diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index 28479f236d..e4fa3c129c 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -77,9 +77,22 @@ jobs: run: | cd build/web && printf "y" | ./build.sh presubmit + validate-docs: + name: validate-docs + runs-on: ubuntu-22.04-4core + steps: + - uses: actions/checkout@v4.1.6 + with: + fetch-depth: 0 + - name: Check for manual edits to /docs + run: | + echo "${{ github.event.pull_request.head.sha }} -- ${{ github.event.pull_request.head.sha }}" + # disable for now + # bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }} + test-renderdiff: name: test-renderdiff - runs-on: ubuntu-22.04-32core + runs-on: ubuntu-22.04-16core steps: - uses: actions/checkout@v4.1.6 diff --git a/CMakeLists.txt b/CMakeLists.txt index b8462d29f1..f9de5b2a5e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -457,10 +457,19 @@ if (NOT WEBGL) set(GC_SECTIONS "-Wl,--gc-sections") endif() +# Prevents stacks from being made for executable by explicitly adding this linker flag. Otherwise, +# it generates warnings newly introduced as of GNU LD 2.39. Modern security practices strongly +# recommend marking the stack as non-executable using the -z noexecstack linker flag to prevent +# stack-based buffer overflow exploits. +# See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=ffcf9c5700e49c0aee42dcba9a12ba21338e8136 +if (LINUX) + set(NO_EXEC_STACK "-Wl,-z,noexecstack") +endif() + set(B_SYMBOLIC_FUNCTIONS "-Wl,-Bsymbolic-functions") if (ANDROID) -set(BINARY_ALIGNMENT "-Wl,-z,max-page-size=16384") + set(BINARY_ALIGNMENT "-Wl,-z,max-page-size=16384") endif() if (APPLE) @@ -475,7 +484,7 @@ if (APPLE) set(CMAKE_CXX_ARCHIVE_CREATE " qc -S ") endif() -set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GC_SECTIONS}") +set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GC_SECTIONS} ${NO_EXEC_STACK}") set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GC_SECTIONS} ${B_SYMBOLIC_FUNCTIONS} ${BINARY_ALIGNMENT}") if (WEBGL_PTHREADS) diff --git a/CODE_STYLE.md b/CODE_STYLE.md index 0a1e785726..41233f2792 100644 --- a/CODE_STYLE.md +++ b/CODE_STYLE.md @@ -121,9 +121,21 @@ private: - other headers are sorted in reverse order of their layering, that is, lower layer headers last - within a layer, headers are sorted alphabetically - strive for implementing one class per file -- `STL` limited in public headers to: - - `type_traits` +- `STL` limited in **filament** public headers to: + - `array` + - `initializer_list` + - `iterator` - `limits` + - `optional` + - `type_traits` + - `utility` + - `variant` + +For **libfilament** the rule of thumb is that STL headers that don't generate code are allowed (e.g. `type_traits`), +conversely containers and algorithms are not allowed. There are exceptions such as `array`. See above for the full list. +- The following `STL` headers are banned entirely, from public and private headers as well as implementation files: + - `iostream` + *Sorting the headers is important to help catching missing `#include` directives.* diff --git a/README.md b/README.md index 625dd40c3a..914a1f3dba 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ repositories { } dependencies { - implementation 'com.google.android.filament:filament-android:1.56.7' + implementation 'com.google.android.filament:filament-android:1.56.8' } ``` @@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`: iOS projects can use CocoaPods to install the latest release: ```shell -pod 'Filament', '~> 1.56.7' +pod 'Filament', '~> 1.56.8' ``` ## Documentation diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index ffccaa339a..09643b5d20 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -7,6 +7,9 @@ A new header is inserted each time a *tag* is created. Instead, if you are authoring a PR for the main branch, add your release note to [NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md). +## v1.56.8 + + ## v1.56.7 diff --git a/android/filament-android/src/main/cpp/Engine.cpp b/android/filament-android/src/main/cpp/Engine.cpp index 56aecc66dd..d6e941209b 100644 --- a/android/filament-android/src/main/cpp/Engine.cpp +++ b/android/filament-android/src/main/cpp/Engine.cpp @@ -392,11 +392,11 @@ Java_com_google_android_filament_Engine_nIsValidSwapChain(JNIEnv*, jclass, return (jboolean)engine->isValid((SwapChain*)nativeSwapChain); } -extern "C" JNIEXPORT void JNICALL +extern "C" JNIEXPORT jboolean JNICALL Java_com_google_android_filament_Engine_nFlushAndWait(JNIEnv*, jclass, - jlong nativeEngine) { + jlong nativeEngine, jlong timeout) { Engine* engine = (Engine*) nativeEngine; - engine->flushAndWait(); + return engine->flushAndWait((uint64_t)timeout); } extern "C" JNIEXPORT void JNICALL diff --git a/android/filament-android/src/main/cpp/RenderableManager.cpp b/android/filament-android/src/main/cpp/RenderableManager.cpp index 4f38e46f82..d9b56e02fb 100644 --- a/android/filament-android/src/main/cpp/RenderableManager.cpp +++ b/android/filament-android/src/main/cpp/RenderableManager.cpp @@ -459,6 +459,13 @@ Java_com_google_android_filament_RenderableManager_nSetMaterialInstanceAt(JNIEnv materialInstance); } +extern "C" JNIEXPORT void JNICALL +Java_com_google_android_filament_RenderableManager_nClearMaterialInstanceAt(JNIEnv*, jclass, + jlong nativeRenderableManager, jint i, jint primitiveIndex) { + RenderableManager *rm = (RenderableManager *) nativeRenderableManager; + rm->clearMaterialInstanceAt((RenderableManager::Instance) i, (size_t) primitiveIndex); +} + extern "C" JNIEXPORT jlong JNICALL Java_com_google_android_filament_RenderableManager_nGetMaterialInstanceAt(JNIEnv*, jclass, jlong nativeRenderableManager, jint i, jint primitiveIndex) { diff --git a/android/filament-android/src/main/java/com/google/android/filament/Engine.java b/android/filament-android/src/main/java/com/google/android/filament/Engine.java index 1e49bf54a3..392497461b 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/Engine.java +++ b/android/filament-android/src/main/java/com/google/android/filament/Engine.java @@ -1271,7 +1271,28 @@ public class Engine { * {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.

*/ public void flushAndWait() { - nFlushAndWait(getNativeObject()); + boolean unused = flushAndWait(Fence.WAIT_FOR_EVER); + } + + /** + * Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until + * all commands to this point are executed. Note that does guarantee that the + * hardware is actually finished. + * + * A timeout can be specified, if for some reason this flushAndWait doesn't complete before the timeout, it will + * return false, true otherwise. + * + *

This is typically used right after destroying the SwapChain, + * in cases where a guarantee about the SwapChain destruction is needed in a + * timely fashion, such as when responding to Android's + * android.view.SurfaceHolder.Callback.surfaceDestroyed

+ * + * @param timeout A timeout in nanoseconds + * @return true if successful, false if flushAndWait timed out, in which case it wasn't successful and commands + * might still be executing on both the CPU and GPU sides. + */ + public boolean flushAndWait(long timeout) { + return nFlushAndWait(getNativeObject(), timeout); } /** @@ -1437,7 +1458,7 @@ public class Engine { private static native boolean nIsValidRenderTarget(long nativeEngine, long nativeTarget); private static native boolean nIsValidSwapChain(long nativeEngine, long nativeSwapChain); private static native void nDestroyEntity(long nativeEngine, int entity); - private static native void nFlushAndWait(long nativeEngine); + private static native boolean nFlushAndWait(long nativeEngine, long timeout); private static native void nFlush(long nativeEngine); private static native boolean nIsPaused(long nativeEngine); private static native void nSetPaused(long nativeEngine, boolean paused); diff --git a/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java b/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java index 0da9a0d6e7..81053197c5 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java +++ b/android/filament-android/src/main/java/com/google/android/filament/RenderableManager.java @@ -869,6 +869,13 @@ public class RenderableManager { nSetMaterialInstanceAt(mNativeObject, i, primitiveIndex, materialInstance.getNativeObject()); } + /** + * Clears the material instance for the given primitive. + */ + public void clearMaterialInstanceAt(@EntityInstance int i, @IntRange(from = 0) int primitiveIndex) { + nClearMaterialInstanceAt(mNativeObject, i, primitiveIndex); + } + /** * Creates a MaterialInstance Java wrapper object for a particular material instance. */ @@ -1012,6 +1019,7 @@ public class RenderableManager { private static native void nGetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float[] center, float[] halfExtent); private static native int nGetPrimitiveCount(long nativeRenderableManager, int i); private static native void nSetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex, long nativeMaterialInstance); + private static native void nClearMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex); private static native long nGetMaterialInstanceAt(long nativeRenderableManager, int i, int primitiveIndex); private static native void nSetGeometryAt(long nativeRenderableManager, int i, int primitiveIndex, int primitiveType, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int count); private static native void nSetBlendOrderAt(long nativeRenderableManager, int i, int primitiveIndex, int blendOrder); diff --git a/android/filament-android/src/main/java/com/google/android/filament/View.java b/android/filament-android/src/main/java/com/google/android/filament/View.java index 0bcd1299b7..bcf6f5378f 100644 --- a/android/filament-android/src/main/java/com/google/android/filament/View.java +++ b/android/filament-android/src/main/java/com/google/android/filament/View.java @@ -1420,10 +1420,10 @@ public class View { /** * Upscaling quality * LOW: bilinear filtered blit. Fastest, poor quality - * MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations + * MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0 * HIGH: AMD FidelityFX FSR1 w/ mobile optimizations * ULTRA: AMD FidelityFX FSR1 - * FSR1 require a well anti-aliased (MSAA or TAA), noise free scene. + * FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene. Avoid FXAA and dithering. * * The default upscaling quality is set to LOW. */ diff --git a/android/gradle.properties b/android/gradle.properties index d1baf95447..6687f3ef9b 100644 --- a/android/gradle.properties +++ b/android/gradle.properties @@ -1,5 +1,5 @@ GROUP=com.google.android.filament -VERSION_NAME=1.56.7 +VERSION_NAME=1.56.8 POM_DESCRIPTION=Real-time physically based rendering engine for Android. diff --git a/build/linux/ci-common.sh b/build/linux/ci-common.sh index eb758bfe0e..bc3abd0fc2 100755 --- a/build/linux/ci-common.sh +++ b/build/linux/ci-common.sh @@ -1,16 +1,16 @@ #!/bin/bash # version of clang we want to use -GITHUB_CLANG_VERSION=14 +export GITHUB_CLANG_VERSION=14 # version of CMake to use instead of the default one -CMAKE_VERSION=3.19.5 +export GITHUB_CMAKE_VERSION=3.19.5 # version of ninja to use -NINJA_VERSION=1.10.2 +export GITHUB_NINJA_VERSION=1.10.2 # Steps for GitHub Workflows if [[ "$GITHUB_WORKFLOW" ]]; then # Install ninja - wget -q https://github.com/ninja-build/ninja/releases/download/v$NINJA_VERSION/ninja-linux.zip + wget -q https://github.com/ninja-build/ninja/releases/download/v$GITHUB_NINJA_VERSION/ninja-linux.zip unzip -q ninja-linux.zip export PATH="$PWD:$PATH" @@ -18,9 +18,9 @@ if [[ "$GITHUB_WORKFLOW" ]]; then mkdir -p cmake cd cmake - sudo wget https://github.com/Kitware/CMake/releases/download/v$CMAKE_VERSION/cmake-$CMAKE_VERSION-Linux-x86_64.sh - sudo chmod +x ./cmake-$CMAKE_VERSION-Linux-x86_64.sh - sudo ./cmake-$CMAKE_VERSION-Linux-x86_64.sh --skip-license > /dev/null + 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 .. diff --git a/docs_src/build/checks.py b/docs_src/build/checks.py new file mode 100644 index 0000000000..738e858f08 --- /dev/null +++ b/docs_src/build/checks.py @@ -0,0 +1,140 @@ +# Copyright (C) 2025 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. + +# This script contains several checks on the current commit, each corresponds to `possible_conditions` +# in the main function below +# - Direct (non-filamentbot) edits of /docs +# - Edits to sources of READMEs that are duplicated to /docs +# or edits to /docs_src sources +# - Commit message has DOCS_BYPASS +# - Commit message has DOCS_FORCE +# - Commit message has DOCS_ALLOW_DIRECT_EDITS + +import json +import sys +import os + +from utils import execute, ArgParseImpl + +CUR_DIR = os.path.dirname(os.path.abspath(__file__)) +ROOT_DIR = os.path.join(CUR_DIR, '../../') + +def get_last_commit_hash(): + res, ret = execute('git rev-parse HEAD', cwd=ROOT_DIR) + assert res == 0, 'Failed to get the last commit hash' + return ret.strip() + +def get_edited_files(commit_hash): + INSERT = '#####?????' + res, ret = execute(f'git show --name-only --pretty=%b{INSERT} {commit_hash}') + assert res == 0, 'Failed to get edited filed' + files = [] + _, after = ret.split(INSERT) + for r in filter(lambda a: len(a) > 0, after.split('\n')): + if r.startswith('commit'): + break + files.append(r) + return files + +# Returns True if there were no direct edits to '/docs' +def check_no_direct_edits(commit_hash, printing=True): + bad = [f'\t{f}' for f in get_edited_files(commit_hash) if f.startswith('docs/')] + if printing and len(bad) > 0: + print(f'Found edits to /docs:\n' + '\n'.join(bad)) + return len(bad) == 0 + +# Returns True if docs sources have been modified +def check_has_source_edits(commit_hash, printing=True): + config = {} + with open(f'{CUR_DIR}/duplicates.json') as config_txt: + config = json.loads(config_txt.read()) + source_files = set(config.keys()) + edited_files = set(get_edited_files(commit_hash)) + overlap = [f'\t{f}' for f in list(source_files & edited_files)] + if printing and len(overlap) > 0: + print(f'Found edited source files:\n' + '\n'.join(overlap)) + return len(overlap) > 0 + +# Returns true in a given TAG is found in the commit msg +def commit_msg_has_tag(commit_hash, tag, printing=True): + res, ret = execute(f'git log --pretty=%B {commit_hash}', cwd=ROOT_DIR) + for l in ret.split('\n'): + if tag == l.strip(): + if printing: + print(f'Found tag={tag} in commit message') + return True + return False + +if __name__ == "__main__": + parser = ArgParseImpl() + + TAG_DOCS_BYPASS = 'DOCS_BYPASS' + TAG_DOCS_FORCE = 'DOCS_FORCE' + TAG_DOCS_ALLOW_DIRECT_EDITS = 'DOCS_ALLOW_DIRECT_EDITS' + + possible_conditions = { + 'no_direct_edits': + check_no_direct_edits, + 'source_edits': + check_has_source_edits, + 'commit_docs_bypass': + lambda h: commit_msg_has_tag(h, TAG_DOCS_BYPASS), + 'commit_docs_force': + lambda h: commit_msg_has_tag(h, TAG_DOCS_FORCE), + 'commit_docs_allow_direct_edits': + lambda h: commit_msg_has_tag(h, TAG_DOCS_ALLOW_DIRECT_EDITS), + } + + possible_str = ', '.join(list(possible_conditions.keys())) + parser.add_argument( + '--do-and', + type=str, + help=( + f'A conjunction of boolean conditions. Possible values are={possible_str}. ' + 'Negation is done with `-`' + ) + ) + parser.add_argument( + '--do-or', + type=str, + help=( + f'A disjunction of boolean conditions. Possible values are={possible_str}. ' + 'Negation is done with `-`' + ) + ) + + args, _ = parser.parse_known_args(sys.argv[1:len(sys.argv) - 1]) + commit_hash = sys.argv[-1] + + assert not (args.do_and and args.do_or), "Must not supply both '--do-and' and '--do-or'" + assert args.do_and or args.do_or, "Must supply argument '--do-and' or '--do-or'" + conds = args.do_and.split(',') if args.do_and else args.do_or.split(',') + conds = [c.strip() for c in conds] + assert all( + [c in possible_conditions.keys() for c in + [(c.replace('-', '') if c.startswith('-') else c) for c in conds]]),\ + f"Not all conditions are valid names. Only {possible_str} are accepted" + + res = [] + for cond in conds: + if cond.startswith('-'): + f = lambda: not possible_conditions[cond.replace('-', '')]() + else: + f = possible_conditions[cond] + res.append(f(commit_hash)) + + if args.do_and: + exit(0 if all(res) else 1) + else: + exit(0 if any(res) else 1) diff --git a/docs_src/build/presubmit_check.sh b/docs_src/build/presubmit_check.sh new file mode 100644 index 0000000000..21bc09a8f3 --- /dev/null +++ b/docs_src/build/presubmit_check.sh @@ -0,0 +1,19 @@ +#!/usr/bin/bash + +# Copyright (C) 2025 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. + +COMMIT_HASH=$1 +python3 docs_src/build/checks.py --do-or="no_direct_edits,commit_docs_allow_direct_edits" $COMMIT_HASH ||\ + (echo "Direct edits to /docs are not allowed. Please see /docs_src/README.md if you need to bypass this check." && exit 1) diff --git a/filament/CMakeLists.txt b/filament/CMakeLists.txt index d218a39170..9f0364f94e 100644 --- a/filament/CMakeLists.txt +++ b/filament/CMakeLists.txt @@ -252,6 +252,7 @@ set(MATERIAL_SRCS src/materials/fsr/fsr_easu_mobile.mat src/materials/fsr/fsr_easu_mobileF.mat src/materials/fsr/fsr_rcas.mat + src/materials/sgsr/sgsr1.mat src/materials/resolveDepth.mat src/materials/separableGaussianBlur.mat src/materials/skybox.mat @@ -504,6 +505,12 @@ add_custom_command( APPEND ) +add_custom_command( + OUTPUT "${MATERIAL_DIR}/sgsr1.filamat" + DEPENDS src/materials/sgsr/sgsr1_shader_mobile.fs + APPEND +) + add_custom_command( OUTPUT "${MATERIAL_DIR}/separableGaussianBlur.filamat" DEPENDS src/materials/separableGaussianBlur.vs diff --git a/filament/backend/CMakeLists.txt b/filament/backend/CMakeLists.txt index 89c29cf53e..208aec0ee0 100644 --- a/filament/backend/CMakeLists.txt +++ b/filament/backend/CMakeLists.txt @@ -139,11 +139,11 @@ if (FILAMENT_SUPPORTS_METAL) src/metal/MetalEnums.mm src/metal/MetalExternalImage.mm src/metal/MetalHandles.mm - src/metal/MetalPlatform.mm src/metal/MetalShaderCompiler.mm src/metal/MetalState.mm src/metal/MetalTimerQuery.mm src/metal/MetalUtils.mm + src/metal/PlatformMetal.mm ) set(METAL_CPP_SRCS diff --git a/filament/backend/include/backend/DriverEnums.h b/filament/backend/include/backend/DriverEnums.h index ea4c41dfd3..2b68ced9c1 100644 --- a/filament/backend/include/backend/DriverEnums.h +++ b/filament/backend/include/backend/DriverEnums.h @@ -33,9 +33,9 @@ #include -#include // FIXME: STL headers are not allowed in public headers -#include // FIXME: STL headers are not allowed in public headers -#include // FIXME: STL headers are not allowed in public headers +#include +#include +#include #include #include diff --git a/filament/backend/include/backend/Handle.h b/filament/backend/include/backend/Handle.h index 5b03df2150..9a96e38939 100644 --- a/filament/backend/include/backend/Handle.h +++ b/filament/backend/include/backend/Handle.h @@ -130,7 +130,7 @@ struct Handle : public HandleBase { bool operator>=(const Handle& rhs) const noexcept { return getId() >= rhs.getId(); } // type-safe Handle cast - template::value> > + template> > Handle(Handle const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions,google-explicit-constructor) private: diff --git a/filament/backend/src/metal/MetalPlatform.h b/filament/backend/include/backend/platforms/PlatformMetal.h similarity index 63% rename from filament/backend/src/metal/MetalPlatform.h rename to filament/backend/include/backend/platforms/PlatformMetal.h index 82730ff6bb..b308935bb9 100644 --- a/filament/backend/src/metal/MetalPlatform.h +++ b/filament/backend/include/backend/platforms/PlatformMetal.h @@ -14,8 +14,8 @@ * limitations under the License. */ -#ifndef TNT_FILAMENT_BACKEND_PRIVATE_METALPLATFORM_H -#define TNT_FILAMENT_BACKEND_PRIVATE_METALPLATFORM_H +#ifndef TNT_FILAMENT_BACKEND_PRIVATE_PLATFORMMETAL_H +#define TNT_FILAMENT_BACKEND_PRIVATE_PLATFORMMETAL_H #include #include @@ -24,9 +24,12 @@ namespace filament::backend { -class MetalPlatform final : public Platform { +struct PlatformMetalImpl; + +class PlatformMetal final : public Platform { public: - ~MetalPlatform() override; + PlatformMetal(); + ~PlatformMetal() noexcept override; Driver* createDriver(void* sharedContext, const Platform::DriverConfig& driverConfig) noexcept override; int getOSVersion() const noexcept override { return 0; } @@ -54,11 +57,30 @@ public: */ id createAndEnqueueCommandBuffer() noexcept; -private: - id mCommandQueue = nil; + /** + * The action to take if a Drawable cannot be acquired. + * + * Each frame rendered requires a CAMetalDrawable texture, which is presented on-screen at the + * completion of each frame. These are limited and provided round-robin style by the system. + */ + enum class DrawableFailureBehavior : uint8_t { + /** + * Terminates the application and reports an error message (default). + */ + PANIC, + /* + * Aborts execution of the current frame. The Metal backend will attempt to acquire a new + * drawable at the next frame. + */ + ABORT_FRAME + }; + void setDrawableFailureBehavior(DrawableFailureBehavior behavior) noexcept; + DrawableFailureBehavior getDrawableFailureBehavior() const noexcept; +private: + PlatformMetalImpl* pImpl = nullptr; }; } // namespace filament::backend -#endif // TNT_FILAMENT_BACKEND_PRIVATE_METALPLATFORM_H +#endif // TNT_FILAMENT_BACKEND_PRIVATE_PLATFORMMETAL_H diff --git a/filament/backend/include/private/backend/HandleAllocator.h b/filament/backend/include/private/backend/HandleAllocator.h index 9333336302..a1c727ecbe 100644 --- a/filament/backend/include/private/backend/HandleAllocator.h +++ b/filament/backend/include/private/backend/HandleAllocator.h @@ -31,6 +31,7 @@ #include #include +#include #include #include #include @@ -44,11 +45,26 @@ namespace filament::backend { +// This is used to not duplicate the code for the Tags management +class DebugTag { +public: + DebugTag(); + void writeHandleTag(HandleBase::HandleId key, utils::CString&& tag) noexcept; + utils::CString findHandleTag(HandleBase::HandleId key) const noexcept; + +private: + // This is used to associate a tag to a handle. mDebugTags is only written the in the main + // driver thread, but it can be accessed from any thread, because it's called from handle_cast<> + // which is used by synchronous calls. + mutable utils::Mutex mDebugTagLock; + tsl::robin_map mDebugTags; +}; + /* * A utility class to efficiently allocate and manage Handle<> */ template -class HandleAllocator { +class HandleAllocator : public DebugTag { public: HandleAllocator(const char* name, size_t size, bool disableUseAfterFreeCheck) noexcept; HandleAllocator(HandleAllocator const& rhs) = delete; @@ -97,7 +113,7 @@ public: * ConcreteTexture* p = reconstruct(h, w, h); */ template - typename std::enable_if_t, D>* + std::enable_if_t, D>* destroyAndConstruct(Handle const& handle, ARGS&& ... args) { assert_invariant(handle); D* addr = handle_cast(const_cast&>(handle)); @@ -116,7 +132,7 @@ public: * ConcreteTexture* p = construct(h, w, h); */ template - typename std::enable_if_t, D>* + std::enable_if_t, D>* construct(Handle const& handle, ARGS&& ... args) noexcept { assert_invariant(handle); D* addr = handle_cast(const_cast&>(handle)); @@ -133,7 +149,7 @@ public: * deallocate(h, p); */ template , D>> + typename = std::enable_if_t, D>> void deallocate(Handle& handle, D const* p) noexcept { // allow to destroy the nullptr, similarly to operator delete if (p) { @@ -161,9 +177,9 @@ public: * ConcreteTexture* p = handle_cast(h); */ template - inline typename std::enable_if_t< + inline std::enable_if_t< std::is_pointer_v && - std::is_base_of_v>, Dp> + std::is_base_of_v>, Dp> handle_cast(Handle& handle) { assert_invariant(handle); auto [p, tag] = handleToPointer(handle.getId()); @@ -200,6 +216,8 @@ public: return static_cast(p); } + utils::CString getHandleTag(HandleBase::HandleId key) const noexcept; + template bool is_valid(Handle& handle) { if (!handle) { @@ -217,9 +235,9 @@ public: } template - inline typename std::enable_if_t< + inline std::enable_if_t< std::is_pointer_v && - std::is_base_of_v>, Dp> + std::is_base_of_v>, Dp> handle_cast(Handle const& handle) { return handle_cast(const_cast&>(handle)); } @@ -227,24 +245,12 @@ public: void associateTagToHandle(HandleBase::HandleId id, utils::CString&& tag) noexcept { // TODO: for now, only pool handles check for use-after-free, so we only keep tags for // those - if (isPoolHandle(id)) { + uint32_t key = id; + if (UTILS_LIKELY(isPoolHandle(id))) { // Truncate the age to get the debug tag - uint32_t const key = id & ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK); - // This line is the costly part. In the future, we could potentially use a custom - // allocator. - mDebugTags[key] = std::move(tag); + key &= ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK); } - } - - utils::CString getHandleTag(HandleBase::HandleId id) const noexcept { - if (!isPoolHandle(id)) { - return "(no tag)"; - } - uint32_t const key = id & ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK); - if (auto pos = mDebugTags.find(key); pos != mDebugTags.end()) { - return pos->second; - } - return "(no tag)"; + writeHandleTag(key, std::move(tag)); } private: @@ -347,9 +353,8 @@ private: if (UTILS_LIKELY(p)) { uint32_t const tag = (uint32_t(age) << HANDLE_AGE_SHIFT) & HANDLE_AGE_MASK; return arenaPointerToHandle(p, tag); - } else { - return allocateHandleSlow(SIZE); } + return allocateHandleSlow(SIZE); } template @@ -421,7 +426,6 @@ private: // Below is only used when running out of space in the HandleArena mutable utils::Mutex mLock; tsl::robin_map mOverflowMap; - tsl::robin_map mDebugTags; HandleBase::HandleId mId = 0; bool mUseAfterFreeCheckDisabled = false; }; diff --git a/filament/backend/src/HandleAllocator.cpp b/filament/backend/src/HandleAllocator.cpp index 6cdcaa4af4..d1d9440af1 100644 --- a/filament/backend/src/HandleAllocator.cpp +++ b/filament/backend/src/HandleAllocator.cpp @@ -19,6 +19,7 @@ #include #include +#include #include #include #include @@ -29,7 +30,9 @@ #include #include #include +#include +#include #include #include @@ -80,9 +83,6 @@ HandleAllocator::HandleAllocator(const char* name, size_t size, bool disableUseAfterFreeCheck) noexcept : mHandleArena(name, size, disableUseAfterFreeCheck), mUseAfterFreeCheckDisabled(disableUseAfterFreeCheck) { - // Reserve initial space for debug tags. This prevents excessive calls to malloc when the first - // few tags are set. - mDebugTags.reserve(512); } template @@ -147,6 +147,42 @@ void HandleAllocator::deallocateHandleSlow(HandleBase::HandleId id, ::free(p); } +template +UTILS_NOINLINE +CString HandleAllocator::getHandleTag(HandleBase::HandleId id) const noexcept { + uint32_t key = id; + if (UTILS_LIKELY(isPoolHandle(id))) { + // Truncate the age to get the debug tag + key &= ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK); + } + return findHandleTag(key); +} + +DebugTag::DebugTag() { + // Reserve initial space for debug tags. This prevents excessive calls to malloc when the first + // few tags are set. + mDebugTags.reserve(512); +} + +UTILS_NOINLINE +CString DebugTag::findHandleTag(HandleBase::HandleId key) const noexcept { + std::unique_lock const lock(mDebugTagLock); + if (auto pos = mDebugTags.find(key); pos != mDebugTags.end()) { + return pos->second; + } + return "(no tag)"; +} + +UTILS_NOINLINE +void DebugTag::writeHandleTag(HandleBase::HandleId key, CString&& tag) noexcept { + // This line is the costly part. In the future, we could potentially use a custom + // allocator. + std::unique_lock const lock(mDebugTagLock); + // Pool based tags will be recycled after a certain age. Heap-based tag will never be recycled, therefore, + // this can grow indefinitely, once we're in the slow mode. + mDebugTags[key] = std::move(tag); +} + // Explicit template instantiations. #if defined (FILAMENT_SUPPORTS_OPENGL) template class HandleAllocatorGL; diff --git a/filament/backend/src/metal/MetalBuffer.h b/filament/backend/src/metal/MetalBuffer.h index ec724a9f0b..b40e6714cd 100644 --- a/filament/backend/src/metal/MetalBuffer.h +++ b/filament/backend/src/metal/MetalBuffer.h @@ -18,9 +18,9 @@ #define TNT_FILAMENT_DRIVER_METALBUFFER_H #include "MetalContext.h" -#include "MetalPlatform.h" #include +#include #include @@ -54,12 +54,12 @@ public: } } - static void setPlatform(MetalPlatform* p) { platform = p; } + static void setPlatform(PlatformMetal* p) { platform = p; } private: typedef std::chrono::steady_clock clock_t; - static MetalPlatform* platform; + static PlatformMetal* platform; std::chrono::time_point mBeginning; const char* mName; @@ -141,7 +141,7 @@ public: assert_invariant(type != Type::NONE); return aliveBuffers[toIndex(type)]; } - static void setPlatform(MetalPlatform* p) { platform = p; } + static void setPlatform(PlatformMetal* p) { platform = p; } private: void swap(TrackedMetalBuffer& other) noexcept { @@ -152,7 +152,7 @@ private: id mBuffer; Type mType = Type::NONE; - static MetalPlatform* platform; + static PlatformMetal* platform; static std::array aliveBuffers; }; diff --git a/filament/backend/src/metal/MetalBuffer.mm b/filament/backend/src/metal/MetalBuffer.mm index 6347ab70c6..13675f2706 100644 --- a/filament/backend/src/metal/MetalBuffer.mm +++ b/filament/backend/src/metal/MetalBuffer.mm @@ -23,8 +23,8 @@ namespace filament { namespace backend { std::array TrackedMetalBuffer::aliveBuffers = { 0 }; -MetalPlatform* TrackedMetalBuffer::platform = nullptr; -MetalPlatform* ScopedAllocationTimer::platform = nullptr; +PlatformMetal* TrackedMetalBuffer::platform = nullptr; +PlatformMetal* ScopedAllocationTimer::platform = nullptr; MetalBuffer::MetalBuffer(MetalContext& context, BufferObjectBinding bindingType, BufferUsage usage, size_t size, bool forceGpuBuffer) diff --git a/filament/backend/src/metal/MetalContext.h b/filament/backend/src/metal/MetalContext.h index f85e08545b..7535acd5e7 100644 --- a/filament/backend/src/metal/MetalContext.h +++ b/filament/backend/src/metal/MetalContext.h @@ -128,6 +128,7 @@ struct MetalContext { std::atomic latestCompletedCommandBufferId = 0; id pendingCommandBuffer = nil; id currentRenderPassEncoder = nil; + uint32_t currentFrame = 0; std::atomic memorylessLimitsReached = false; @@ -156,6 +157,7 @@ struct MetalContext { RenderPassFlags currentRenderPassFlags; MetalRenderTarget* currentRenderTarget = nullptr; bool validPipelineBound = false; + bool currentRenderPassAbandoned = false; // State trackers. PipelineStateTracker pipelineState; diff --git a/filament/backend/src/metal/MetalDriver.h b/filament/backend/src/metal/MetalDriver.h index ca14adf974..3c0aa214d8 100644 --- a/filament/backend/src/metal/MetalDriver.h +++ b/filament/backend/src/metal/MetalDriver.h @@ -37,7 +37,7 @@ namespace filament { namespace backend { -class MetalPlatform; +class PlatformMetal; class MetalBuffer; class MetalProgram; @@ -51,19 +51,19 @@ struct BufferState; #endif class MetalDriver final : public DriverBase { - explicit MetalDriver(MetalPlatform* platform, const Platform::DriverConfig& driverConfig) noexcept; + explicit MetalDriver(PlatformMetal* platform, const Platform::DriverConfig& driverConfig) noexcept; ~MetalDriver() noexcept override; Dispatcher getDispatcher() const noexcept final; public: - static Driver* create(MetalPlatform* platform, const Platform::DriverConfig& driverConfig); + static Driver* create(PlatformMetal* platform, const Platform::DriverConfig& driverConfig); private: friend class MetalSwapChain; friend struct MetalDescriptorSet; - MetalPlatform& mPlatform; + PlatformMetal& mPlatform; MetalContext* mContext; ShaderModel getShaderModel() const noexcept final; diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index a8eee36dcb..246d83dd20 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -30,7 +30,7 @@ #include "MetalState.h" #include "MetalTimerQuery.h" -#include "MetalPlatform.h" +#include #include #include @@ -57,7 +57,7 @@ namespace filament { namespace backend { -Driver* MetalDriverFactory::create(MetalPlatform* const platform, const Platform::DriverConfig& driverConfig) { +Driver* MetalDriverFactory::create(PlatformMetal* const platform, const Platform::DriverConfig& driverConfig) { #if 0 // this is useful for development, but too verbose even for debug builds // For reference on a 64-bits machine in Release mode: @@ -96,7 +96,7 @@ Driver* MetalDriverFactory::create(MetalPlatform* const platform, const Platform } UTILS_NOINLINE -Driver* MetalDriver::create(MetalPlatform* const platform, const Platform::DriverConfig& driverConfig) { +Driver* MetalDriver::create(PlatformMetal* const platform, const Platform::DriverConfig& driverConfig) { assert_invariant(platform); size_t defaultSize = FILAMENT_METAL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U; Platform::DriverConfig validConfig {driverConfig}; @@ -109,7 +109,7 @@ Dispatcher MetalDriver::getDispatcher() const noexcept { } MetalDriver::MetalDriver( - MetalPlatform* platform, const Platform::DriverConfig& driverConfig) noexcept + PlatformMetal* platform, const Platform::DriverConfig& driverConfig) noexcept : mPlatform(*platform), mContext(new MetalContext), mHandleAllocator( @@ -246,6 +246,7 @@ void MetalDriver::tick(int) { void MetalDriver::beginFrame(int64_t monotonic_clock_ns, int64_t refreshIntervalNs, uint32_t frameId) { + mContext->currentFrame = frameId; DEBUG_LOG("beginFrame(monotonic_clock_ns = %lld, refreshIntervalNs = %lld, frameId = %d)\n", monotonic_clock_ns, refreshIntervalNs, frameId); #if defined(FILAMENT_METAL_PROFILING) @@ -631,19 +632,19 @@ void MetalDriver::createFenceR(Handle fh, int dummy) { void MetalDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags) { if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) { CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) nativeWindow; - construct_handle(sch, *mContext, pixelBuffer, flags); + construct_handle(sch, *mContext, mPlatform, pixelBuffer, flags); // This release matches the retain call in setupExternalImage. The MetalSwapchain will have // retained the buffer by now. CVPixelBufferRelease((CVPixelBufferRef)pixelBuffer); } else { auto* metalLayer = (__bridge CAMetalLayer*) nativeWindow; - construct_handle(sch, *mContext, metalLayer, flags); + construct_handle(sch, *mContext, mPlatform, metalLayer, flags); } } void MetalDriver::createSwapChainHeadlessR(Handle sch, uint32_t width, uint32_t height, uint64_t flags) { - construct_handle(sch, *mContext, width, height, flags); + construct_handle(sch, *mContext, mPlatform, width, height, flags); } void MetalDriver::createTimerQueryR(Handle tqh, int) { @@ -1268,6 +1269,13 @@ void MetalDriver::beginRenderPass(Handle rth, MTLRenderPassDescriptor* descriptor = [MTLRenderPassDescriptor renderPassDescriptor]; renderTarget->setUpRenderPassAttachments(descriptor, params); + if (renderTarget->involvesAbandonedSwapChain()) { + mContext->currentRenderPassAbandoned = true; + return; + } else { + mContext->currentRenderPassAbandoned = false; + } + mContext->currentRenderPassEncoder = [getPendingCommandBuffer(mContext) renderCommandEncoderWithDescriptor:descriptor]; if (!mContext->groupMarkers.empty()) { @@ -1329,6 +1337,10 @@ void MetalDriver::endRenderPass(int dummy) { os_signpost_interval_end(mContext->log, OS_SIGNPOST_ID_EXCLUSIVE, "Render pass"); #endif + if (UTILS_UNLIKELY(mContext->currentRenderPassAbandoned)) { + return; + } + [mContext->currentRenderPassEncoder endEncoding]; // Command encoders are one time use. Set it to nil to release the encoder and ensure we don't @@ -1629,6 +1641,11 @@ void MetalDriver::blitDEPRECATED(TargetBufferFlags buffers, auto srcTarget = handle_cast(src); auto dstTarget = handle_cast(dst); + if (UTILS_UNLIKELY(srcTarget->involvesAbandonedSwapChain() || + dstTarget->involvesAbandonedSwapChain())) { + return; + } + FILAMENT_CHECK_PRECONDITION(buffers == TargetBufferFlags::COLOR0) << "blitDEPRECATED only supports COLOR0"; @@ -1913,6 +1930,10 @@ void MetalDriver::bindDescriptorSet( } void MetalDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t instanceCount) { + if (UTILS_UNLIKELY(mContext->currentRenderPassAbandoned)) { + return; + } + FILAMENT_CHECK_PRECONDITION(mContext->currentRenderPassEncoder != nullptr) << "draw() without a valid command encoder."; DEBUG_LOG("draw2(...)\n"); @@ -1956,6 +1977,9 @@ void MetalDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t inst void MetalDriver::draw(PipelineState ps, Handle rph, uint32_t const indexOffset, uint32_t const indexCount, uint32_t const instanceCount) { + if (UTILS_UNLIKELY(mContext->currentRenderPassAbandoned)) { + return; + } MetalRenderPrimitive const* const rp = handle_cast(rph); ps.primitiveType = rp->type; ps.vertexBufferInfo = rp->vertexBuffer->vbih; diff --git a/filament/backend/src/metal/MetalDriverFactory.h b/filament/backend/src/metal/MetalDriverFactory.h index bff7439077..083a592e37 100644 --- a/filament/backend/src/metal/MetalDriverFactory.h +++ b/filament/backend/src/metal/MetalDriverFactory.h @@ -21,12 +21,12 @@ namespace filament { namespace backend { -class MetalPlatform; +class PlatformMetal; class Driver; class MetalDriverFactory { public: - static Driver* create(MetalPlatform* platform, const Platform::DriverConfig& driverConfig); + static Driver* create(PlatformMetal* platform, const Platform::DriverConfig& driverConfig); }; } // namespace backend diff --git a/filament/backend/src/metal/MetalHandles.h b/filament/backend/src/metal/MetalHandles.h index 973e5d19eb..cc17d950d8 100644 --- a/filament/backend/src/metal/MetalHandles.h +++ b/filament/backend/src/metal/MetalHandles.h @@ -30,6 +30,7 @@ #include "MetalState.h" // for MetalState::VertexDescription #include +#include #include #include @@ -51,13 +52,16 @@ class MetalSwapChain : public HwSwapChain { public: // Instantiate a SwapChain from a CAMetalLayer - MetalSwapChain(MetalContext& context, CAMetalLayer* nativeWindow, uint64_t flags); + MetalSwapChain(MetalContext& context, PlatformMetal& platform, CAMetalLayer* nativeWindow, + uint64_t flags); // Instantiate a SwapChain from a CVPixelBuffer - MetalSwapChain(MetalContext& context, CVPixelBufferRef pixelBuffer, uint64_t flags); + MetalSwapChain(MetalContext& context, PlatformMetal& platform, CVPixelBufferRef pixelBuffer, + uint64_t flags); // Instantiate a headless SwapChain. - MetalSwapChain(MetalContext& context, int32_t width, int32_t height, uint64_t flags); + MetalSwapChain(MetalContext& context, PlatformMetal& platform, int32_t width, int32_t height, + uint64_t flags); ~MetalSwapChain(); @@ -86,6 +90,8 @@ public: bool isPixelBuffer() const { return type == SwapChainType::CVPIXELBUFFERREF; } + bool isAbandoned() const; + private: enum class SwapChainType { @@ -103,6 +109,7 @@ private: void ensureDepthStencilTexture(); MetalContext& context; + PlatformMetal& platform; id drawable = nil; id depthStencilTexture = nil; id headlessDrawable = nil; @@ -114,6 +121,8 @@ private: MetalExternalImage externalImage; SwapChainType type; + int64_t abandonedUntilFrame = -1; + // These fields store a callback to notify the client that a frame is ready for presentation. If // !frameScheduled.callback, then the Metal backend automatically calls presentDrawable when the // frame is committed. Otherwise, the Metal backend will not automatically present the frame. @@ -341,6 +350,8 @@ public: void setUpRenderPassAttachments(MTLRenderPassDescriptor* descriptor, const RenderPassParams& params); + bool involvesAbandonedSwapChain() const noexcept; + MTLViewport getViewportFromClientViewport( Viewport rect, float depthRangeNear, float depthRangeFar) { const int32_t height = int32_t(getAttachmentSize().y); diff --git a/filament/backend/src/metal/MetalHandles.mm b/filament/backend/src/metal/MetalHandles.mm index fc12fe0a9a..da10317f51 100644 --- a/filament/backend/src/metal/MetalHandles.mm +++ b/filament/backend/src/metal/MetalHandles.mm @@ -69,8 +69,10 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) { return MTLTextureUsage(u); } -MetalSwapChain::MetalSwapChain(MetalContext& context, CAMetalLayer* nativeWindow, uint64_t flags) +MetalSwapChain::MetalSwapChain( + MetalContext& context, PlatformMetal& platform, CAMetalLayer* nativeWindow, uint64_t flags) : context(context), + platform(platform), depthStencilFormat(decideDepthStencilFormat(flags)), layer(nativeWindow), layerDrawableMutex(std::make_shared()), @@ -94,15 +96,19 @@ MetalSwapChain::MetalSwapChain(MetalContext& context, CAMetalLayer* nativeWindow layer.device = context.device; } -MetalSwapChain::MetalSwapChain(MetalContext& context, int32_t width, int32_t height, uint64_t flags) +MetalSwapChain::MetalSwapChain(MetalContext& context, PlatformMetal& platform, int32_t width, + int32_t height, uint64_t flags) : context(context), + platform(platform), depthStencilFormat(decideDepthStencilFormat(flags)), headlessWidth(width), headlessHeight(height), type(SwapChainType::HEADLESS) {} -MetalSwapChain::MetalSwapChain(MetalContext& context, CVPixelBufferRef pixelBuffer, uint64_t flags) +MetalSwapChain::MetalSwapChain(MetalContext& context, PlatformMetal& platform, + CVPixelBufferRef pixelBuffer, uint64_t flags) : context(context), + platform(platform), depthStencilFormat(decideDepthStencilFormat(flags)), externalImage(MetalExternalImage::createFromImage(context, pixelBuffer)), type(SwapChainType::CVPIXELBUFFERREF) { @@ -140,6 +146,10 @@ NSUInteger MetalSwapChain::getSurfaceHeight() const { return (NSUInteger) layer.drawableSize.height; } +bool MetalSwapChain::isAbandoned() const { + return context.currentFrame < abandonedUntilFrame; +} + id MetalSwapChain::acquireDrawable() { if (drawable) { return drawable.texture; @@ -180,7 +190,18 @@ id MetalSwapChain::acquireDrawable() { drawable = [layer nextDrawable]; } - FILAMENT_CHECK_POSTCONDITION(drawable != nil) << "Could not obtain drawable."; + if (UTILS_UNLIKELY(drawable == nil)) { + switch (platform.getDrawableFailureBehavior()) { + case PlatformMetal::DrawableFailureBehavior::PANIC: + FILAMENT_CHECK_POSTCONDITION(drawable != nil) << "Could not obtain drawable."; + break; + + case PlatformMetal::DrawableFailureBehavior::ABORT_FRAME: + abandonedUntilFrame = context.currentFrame + 1; + return nil; + } + } + return drawable.texture; } @@ -1117,12 +1138,20 @@ void MetalRenderTarget::setUpRenderPassAttachments(MTLRenderPassDescriptor* desc } } +bool MetalRenderTarget::involvesAbandonedSwapChain() const noexcept { + const auto* draw = context->currentDrawSwapChain; + const auto* read = context->currentReadSwapChain; + return (draw && draw->isAbandoned()) || (read && read->isAbandoned()); +} + MetalRenderTarget::Attachment MetalRenderTarget::getDrawColorAttachment(size_t index) { assert_invariant(index < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT); Attachment result = color[index]; if (index == 0 && defaultRenderTarget) { assert_invariant(context->currentDrawSwapChain); result.texture = context->currentDrawSwapChain->acquireDrawable(); + // acquireDrawable may fail to acquire the drawable, in which case result.texture will be + // nil, and an invalid attachment } return result; } @@ -1133,6 +1162,8 @@ MetalRenderTarget::Attachment MetalRenderTarget::getReadColorAttachment(size_t i if (index == 0 && defaultRenderTarget) { assert_invariant(context->currentReadSwapChain); result.texture = context->currentReadSwapChain->acquireDrawable(); + // acquireDrawable may fail to acquire the drawable, in which case result.texture will be + // nil, and an invalid attachment } return result; } diff --git a/filament/backend/src/metal/MetalPlatform.mm b/filament/backend/src/metal/PlatformMetal.mm similarity index 59% rename from filament/backend/src/metal/MetalPlatform.mm rename to filament/backend/src/metal/PlatformMetal.mm index 4979e602ba..e446698b08 100644 --- a/filament/backend/src/metal/MetalPlatform.mm +++ b/filament/backend/src/metal/PlatformMetal.mm @@ -14,7 +14,7 @@ * limitations under the License. */ -#include "MetalPlatform.h" +#include #include "MetalDriverFactory.h" @@ -22,19 +22,32 @@ #import +#include + namespace filament::backend { +struct PlatformMetalImpl { + id mCommandQueue = nil; + // read form driver thread, read/written to from client thread + std::atomic mDrawableFailureBehavior = + PlatformMetal::DrawableFailureBehavior::PANIC; +}; + Platform* createDefaultMetalPlatform() { - return new MetalPlatform(); + return new PlatformMetal(); } -MetalPlatform::~MetalPlatform() = default; +PlatformMetal::PlatformMetal() : pImpl(new PlatformMetalImpl) {} -Driver* MetalPlatform::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept { +PlatformMetal::~PlatformMetal() noexcept { + delete pImpl; +} + +Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept { return MetalDriverFactory::create(this, driverConfig); } -id MetalPlatform::createDevice() noexcept { +id PlatformMetal::createDevice() noexcept { id result; #if !defined(FILAMENT_IOS) @@ -62,16 +75,24 @@ id MetalPlatform::createDevice() noexcept { return result; } -id MetalPlatform::createCommandQueue(id device) noexcept { - mCommandQueue = [device newCommandQueue]; - mCommandQueue.label = @"Filament"; - return mCommandQueue; +id PlatformMetal::createCommandQueue(id device) noexcept { + pImpl->mCommandQueue = [device newCommandQueue]; + pImpl->mCommandQueue.label = @"Filament"; + return pImpl->mCommandQueue; } -id MetalPlatform::createAndEnqueueCommandBuffer() noexcept { - id commandBuffer = [mCommandQueue commandBuffer]; +id PlatformMetal::createAndEnqueueCommandBuffer() noexcept { + id commandBuffer = [pImpl->mCommandQueue commandBuffer]; [commandBuffer enqueue]; return commandBuffer; } +void PlatformMetal::setDrawableFailureBehavior(DrawableFailureBehavior behavior) noexcept { + pImpl->mDrawableFailureBehavior = behavior; +} + +PlatformMetal::DrawableFailureBehavior PlatformMetal::getDrawableFailureBehavior() const noexcept { + return pImpl->mDrawableFailureBehavior; +} + } // namespace filament diff --git a/filament/backend/src/vulkan/VulkanDriver.cpp b/filament/backend/src/vulkan/VulkanDriver.cpp index 3d3ad70038..56c4a7a296 100644 --- a/filament/backend/src/vulkan/VulkanDriver.cpp +++ b/filament/backend/src/vulkan/VulkanDriver.cpp @@ -700,6 +700,11 @@ void VulkanDriver::createFenceR(Handle fh, int) { } void VulkanDriver::createSwapChainR(Handle sch, void* nativeWindow, uint64_t flags) { + // Running gc() to guard against an edge case where the old swapchains need to have been + // destroyed before the new swapchain can be created. Otherwise, we would fail + // vkCreateSwapchainKHR with VK_ERROR_NATIVE_WINDOW_IN_USE_KHR. + mResourceManager.gc(); + if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) { FVK_LOGW << "sRGB swapchain requested, but Platform does not support it" << utils::io::endl; diff --git a/filament/backend/src/vulkan/VulkanTexture.cpp b/filament/backend/src/vulkan/VulkanTexture.cpp index 2180c04fbd..2f30ee20c9 100644 --- a/filament/backend/src/vulkan/VulkanTexture.cpp +++ b/filament/backend/src/vulkan/VulkanTexture.cpp @@ -296,7 +296,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice, imageInfo.samples = (VkSampleCountFlagBits) samples; VkResult result = vkCreateImage(mState->mDevice, &imageInfo, VKALLOC, &mState->mTextureImage); - if (result == VK_SUCCESS || FVK_ENABLED(FVK_DEBUG_TEXTURE)) { + if (result != VK_SUCCESS || FVK_ENABLED(FVK_DEBUG_TEXTURE)) { FVK_LOGD << "vkCreateImage: " << "image = " << mState->mTextureImage << ", " << "result = " << result << ", " diff --git a/filament/backend/src/vulkan/memory/ResourcePointer.h b/filament/backend/src/vulkan/memory/ResourcePointer.h index 25b9737bf7..f6f3578dde 100644 --- a/filament/backend/src/vulkan/memory/ResourcePointer.h +++ b/filament/backend/src/vulkan/memory/ResourcePointer.h @@ -81,7 +81,7 @@ public: inline resource_ptr() = default; // move constructor operator - inline resource_ptr(resource_ptr&& rhs) { + inline resource_ptr(resource_ptr&& rhs) noexcept { (*this) = std::move(rhs); } @@ -98,7 +98,7 @@ public: } // move operator - inline resource_ptr& operator=(resource_ptr && rhs) { + inline resource_ptr& operator=(resource_ptr && rhs) noexcept { std::swap(mRef, rhs.mRef); return *this; } diff --git a/filament/backend/src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp b/filament/backend/src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp index f8b900c6b1..cb80e48985 100644 --- a/filament/backend/src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp +++ b/filament/backend/src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp @@ -117,7 +117,7 @@ void VulkanPlatformSwapChainImpl::destroy() { mSwapChainBundle.colors.clear(); } -VkImage VulkanPlatformSwapChainImpl::createImage(VkExtent2D extent, VkFormat format, +VkImage VulkanPlatformSwapChainImpl::createImage(VkExtent2D extent, VkFormat format, bool isProtected) { auto [image, memory] = createImageAndMemory(mContext, mDevice, extent, format, isProtected); mMemory.insert({image, memory}); @@ -140,9 +140,8 @@ VulkanPlatformSurfaceSwapChain::VulkanPlatformSurfaceSwapChain(VulkanContext con } VulkanPlatformSurfaceSwapChain::~VulkanPlatformSurfaceSwapChain() { - vkDestroySwapchainKHR(mDevice, mSwapchain, VKALLOC); - vkDestroySurfaceKHR(mInstance, mSurface, VKALLOC); destroy(); + vkDestroySurfaceKHR(mInstance, mSurface, VKALLOC); } VkResult VulkanPlatformSurfaceSwapChain::create() { @@ -256,7 +255,7 @@ VkResult VulkanPlatformSurfaceSwapChain::create() { mSwapChainBundle.colorFormat = surfaceFormat.format; mSwapChainBundle.depthFormat = selectDepthFormat(mContext.getAttachmentDepthStencilFormats(), mHasStencil); - mSwapChainBundle.depth = createImage(mSwapChainBundle.extent, + mSwapChainBundle.depth = createImage(mSwapChainBundle.extent, mSwapChainBundle.depthFormat, mIsProtected); mSwapChainBundle.isProtected = mIsProtected; @@ -344,6 +343,22 @@ VkResult VulkanPlatformSurfaceSwapChain::recreate() { } void VulkanPlatformSurfaceSwapChain::destroy() { + // The next part is not ideal. We don't have a good signal on when it's ok to destroy + // a swapchain. This is a spec oversight and mentioned as much: + // https://github.com/KhronosGroup/Vulkan-Docs/issues/1678 + // + // One workaround [1] is: + // https://docs.vulkan.org/samples/latest/samples/api/swapchain_recreation/README.html + // + // The proper fix is to use VK_EXT_swapchain_maintenance1, but availability of this extension is + // unknown (not yet ratified). + // + // Instead of adding too much mechanics, we're taking a hacksaw to the problem - just wait for + // the queue to be idle. The hope is that this only happens on resize, where performance + // degradation is less obvious (until, of course, people complain about lag when rotating their + // phone). If necessary, we can revisit and implement the workaround [1]. + vkQueueWaitIdle(mQueue); + VulkanPlatformSwapChainImpl::destroy(); for (uint32_t i = 0; i < IMAGE_READY_SEMAPHORE_COUNT; ++i) { @@ -352,6 +367,10 @@ void VulkanPlatformSurfaceSwapChain::destroy() { mImageReady[i] = VK_NULL_HANDLE; } } + if (mSwapchain) { + vkDestroySwapchainKHR(mDevice, mSwapchain, VKALLOC); + mSwapchain = VK_NULL_HANDLE; + } } VulkanPlatformHeadlessSwapChain::VulkanPlatformHeadlessSwapChain(VulkanContext const& context, diff --git a/filament/include/filament/Box.h b/filament/include/filament/Box.h index da6638dabd..5faa5b2151 100644 --- a/filament/include/filament/Box.h +++ b/filament/include/filament/Box.h @@ -183,7 +183,7 @@ struct UTILS_PUBLIC Aabb { * Returns the 8 corner vertices of the AABB. */ Corners getCorners() const { - return Aabb::Corners{ .vertices = { + return Corners{ .vertices = { { min.x, min.y, min.z }, { max.x, min.y, min.z }, { min.x, max.y, min.z }, diff --git a/filament/include/filament/BufferObject.h b/filament/include/filament/BufferObject.h index 8c76719c85..b946449afb 100644 --- a/filament/include/filament/BufferObject.h +++ b/filament/include/filament/BufferObject.h @@ -73,7 +73,7 @@ public: /** * The binding type for this buffer object. (defaults to VERTEX) - * @param BindingType Distinguishes between SSBO, VBO, etc. For now this must be VERTEX. + * @param bindingType Distinguishes between SSBO, VBO, etc. For now this must be VERTEX. * @return A reference to this Builder for chaining calls. */ Builder& bindingType(BindingType bindingType) noexcept; @@ -91,7 +91,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the BufferObject and returns a pointer to it. After creation, the buffer diff --git a/filament/include/filament/Camera.h b/filament/include/filament/Camera.h index 91d51377f5..10fe041b7c 100644 --- a/filament/include/filament/Camera.h +++ b/filament/include/filament/Camera.h @@ -400,14 +400,14 @@ public: * engine.getTransformManager().getInstance(camera->getEntity()), model); * ~~~~~~~~~~~ * - * @param model The camera position and orientation provided as a rigid transform matrix. + * @param modelMatrix The camera position and orientation provided as a rigid transform matrix. * * @note The Camera "looks" towards its -z axis * * @warning \p model must be a rigid transform */ - void setModelMatrix(const math::mat4& model) noexcept; - void setModelMatrix(const math::mat4f& model) noexcept; //!< @overload + void setModelMatrix(const math::mat4& modelMatrix) noexcept; + void setModelMatrix(const math::mat4f& modelMatrix) noexcept; //!< @overload /** Set the position of an eye relative to this Camera (head). * diff --git a/filament/include/filament/Color.h b/filament/include/filament/Color.h index 30b77856f2..3793982015 100644 --- a/filament/include/filament/Color.h +++ b/filament/include/filament/Color.h @@ -194,7 +194,7 @@ inline sRGBColorA Color::toSRGB(LinearColorA const& color) { } inline LinearColor Color::toLinear(RgbType type, math::float3 color) { - return (type == RgbType::LINEAR) ? color : Color::toLinear(color); + return (type == RgbType::LINEAR) ? color : toLinear(color); } // converts an RGBA color to linear space @@ -202,11 +202,11 @@ inline LinearColor Color::toLinear(RgbType type, math::float3 color) { inline LinearColorA Color::toLinear(RgbaType type, math::float4 color) { switch (type) { case RgbaType::sRGB: - return Color::toLinear(color) * math::float4{color.a, color.a, color.a, 1.0f}; + return toLinear(color) * math::float4{color.a, color.a, color.a, 1.0f}; case RgbaType::LINEAR: return color * math::float4{color.a, color.a, color.a, 1.0f}; case RgbaType::PREMULTIPLIED_sRGB: - return Color::toLinear(color); + return toLinear(color); case RgbaType::PREMULTIPLIED_LINEAR: return color; } diff --git a/filament/include/filament/Engine.h b/filament/include/filament/Engine.h index 17aaea975f..5092e16c38 100644 --- a/filament/include/filament/Engine.h +++ b/filament/include/filament/Engine.h @@ -537,7 +537,7 @@ public: Platform* UTILS_NULLABLE platform = nullptr, void* UTILS_NULLABLE sharedContext = nullptr, const Config* UTILS_NULLABLE config = nullptr) { - return Engine::Builder() + return Builder() .backend(backend) .platform(platform) .sharedContext(sharedContext) @@ -557,7 +557,7 @@ public: Platform* UTILS_NULLABLE platform = nullptr, void* UTILS_NULLABLE sharedContext = nullptr, const Config* UTILS_NULLABLE config = nullptr) { - Engine::Builder() + Builder() .backend(backend) .platform(platform) .sharedContext(sharedContext) @@ -970,6 +970,25 @@ public: */ void flushAndWait(); + /** + * Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until + * all commands to this point are executed. Note that does guarantee that the + * hardware is actually finished. + * + * A timeout can be specified, if for some reason this flushAndWait doesn't complete before the timeout, it will + * return false, true otherwise. + * + *

This is typically used right after destroying the SwapChain, + * in cases where a guarantee about the SwapChain destruction is needed in a + * timely fashion, such as when responding to Android's + * android.view.SurfaceHolder.Callback.surfaceDestroyed

+ * + * @param timeout A timeout in nanoseconds + * @return true if successful, false if flushAndWait timed out, in which case it wasn't successful and commands + * might still be executing on both the CPU and GPU sides. + */ + bool flushAndWait(uint64_t timeout); + /** * Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) but does not wait * for commands to be either executed or the hardware finished. diff --git a/filament/include/filament/IndexBuffer.h b/filament/include/filament/IndexBuffer.h index ff29e1f44d..57c95921d7 100644 --- a/filament/include/filament/IndexBuffer.h +++ b/filament/include/filament/IndexBuffer.h @@ -96,7 +96,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the IndexBuffer object and returns a pointer to it. After creation, the index diff --git a/filament/include/filament/InstanceBuffer.h b/filament/include/filament/InstanceBuffer.h index 843c7983bb..b744e32c7b 100644 --- a/filament/include/filament/InstanceBuffer.h +++ b/filament/include/filament/InstanceBuffer.h @@ -83,7 +83,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the InstanceBuffer object and returns a pointer to it. diff --git a/filament/include/filament/Material.h b/filament/include/filament/Material.h index 768338a48a..b7333f2937 100644 --- a/filament/include/filament/Material.h +++ b/filament/include/filament/Material.h @@ -118,10 +118,10 @@ public: Builder& package(const void* UTILS_NONNULL payload, size_t size); template - using is_supported_constant_parameter_t = typename std::enable_if< - std::is_same::value || - std::is_same::value || - std::is_same::value>::type; + using is_supported_constant_parameter_t = std::enable_if_t< + std::is_same_v || + std::is_same_v || + std::is_same_v>; /** * Specialize a constant parameter specified in the material definition with a concrete @@ -177,7 +177,7 @@ public: * memory or other resources. * @exception utils::PreConditionPanic if a parameter to a builder function was invalid. */ - Material* UTILS_NULLABLE build(Engine& engine); + Material* UTILS_NULLABLE build(Engine& engine) const; private: friend class FMaterial; }; diff --git a/filament/include/filament/MaterialInstance.h b/filament/include/filament/MaterialInstance.h index 2b8aaa9ac0..72989075f3 100644 --- a/filament/include/filament/MaterialInstance.h +++ b/filament/include/filament/MaterialInstance.h @@ -56,35 +56,35 @@ class UTILS_PUBLIC MaterialInstance : public FilamentAPI { }; public: - using CullingMode = filament::backend::CullingMode; - using TransparencyMode = filament::TransparencyMode; - using DepthFunc = filament::backend::SamplerCompareFunc; - using StencilCompareFunc = filament::backend::SamplerCompareFunc; - using StencilOperation = filament::backend::StencilOperation; - using StencilFace = filament::backend::StencilFace; + using CullingMode = backend::CullingMode; + using TransparencyMode = TransparencyMode; + using DepthFunc = backend::SamplerCompareFunc; + using StencilCompareFunc = backend::SamplerCompareFunc; + using StencilOperation = backend::StencilOperation; + using StencilFace = backend::StencilFace; template - using is_supported_parameter_t = typename std::enable_if< - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || + using is_supported_parameter_t = std::enable_if_t< + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || // these types are slower as they need a layout conversion - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value - >::type; + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v + >; /** * Creates a new MaterialInstance using another MaterialInstance as a template for initialization. @@ -121,13 +121,13 @@ public: /** inline helper to provide the name as a null-terminated string literal */ template> - inline void setParameter(StringLiteral name, T const& value) { + void setParameter(StringLiteral name, T const& value) { setParameter(name.data, name.size, value); } /** inline helper to provide the name as a null-terminated C string */ template> - inline void setParameter(const char* UTILS_NONNULL name, T const& value) { + void setParameter(const char* UTILS_NONNULL name, T const& value) { setParameter(name, strlen(name), value); } @@ -148,14 +148,14 @@ public: /** inline helper to provide the name as a null-terminated string literal */ template> - inline void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) { + void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) { setParameter(name.data, name.size, values, count); } /** inline helper to provide the name as a null-terminated C string */ template> - inline void setParameter(const char* UTILS_NONNULL name, - const T* UTILS_NONNULL values, size_t count) { + void setParameter(const char* UTILS_NONNULL name, + const T* UTILS_NONNULL values, size_t count) { setParameter(name, strlen(name), values, count); } @@ -176,14 +176,14 @@ public: Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler); /** inline helper to provide the name as a null-terminated string literal */ - inline void setParameter(StringLiteral name, - Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) { + void setParameter(StringLiteral name, + Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) { setParameter(name.data, name.size, texture, sampler); } /** inline helper to provide the name as a null-terminated C string */ - inline void setParameter(const char* UTILS_NONNULL name, - Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) { + void setParameter(const char* UTILS_NONNULL name, + Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) { setParameter(name, strlen(name), texture, sampler); } @@ -202,12 +202,12 @@ public: RgbType type, math::float3 color); /** inline helper to provide the name as a null-terminated string literal */ - inline void setParameter(StringLiteral name, RgbType type, math::float3 color) { + void setParameter(StringLiteral name, RgbType type, math::float3 color) { setParameter(name.data, name.size, type, color); } /** inline helper to provide the name as a null-terminated C string */ - inline void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) { + void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) { setParameter(name, strlen(name), type, color); } @@ -226,12 +226,12 @@ public: RgbaType type, math::float4 color); /** inline helper to provide the name as a null-terminated string literal */ - inline void setParameter(StringLiteral name, RgbaType type, math::float4 color) { + void setParameter(StringLiteral name, RgbaType type, math::float4 color) { setParameter(name.data, name.size, type, color); } /** inline helper to provide the name as a null-terminated C string */ - inline void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) { + void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) { setParameter(name, strlen(name), type, color); } @@ -251,13 +251,13 @@ public: /** inline helper to provide the name as a null-terminated C string */ template> - inline T getParameter(StringLiteral name) const { + T getParameter(StringLiteral name) const { return getParameter(name.data, name.size); } /** inline helper to provide the name as a null-terminated C string */ template> - inline T getParameter(const char* UTILS_NONNULL name) const { + T getParameter(const char* UTILS_NONNULL name) const { return getParameter(name, strlen(name)); } diff --git a/filament/include/filament/MorphTargetBuffer.h b/filament/include/filament/MorphTargetBuffer.h index cb77bb79c8..79c2710670 100644 --- a/filament/include/filament/MorphTargetBuffer.h +++ b/filament/include/filament/MorphTargetBuffer.h @@ -76,7 +76,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the MorphTargetBuffer object and returns a pointer to it. diff --git a/filament/include/filament/Options.h b/filament/include/filament/Options.h index 93bba80cd8..dc06143dd4 100644 --- a/filament/include/filament/Options.h +++ b/filament/include/filament/Options.h @@ -86,10 +86,10 @@ struct DynamicResolutionOptions { /** * Upscaling quality * LOW: bilinear filtered blit. Fastest, poor quality - * MEDIUM: AMD FidelityFX FSR1 w/ mobile optimizations + * MEDIUM: Qualcomm Snapdragon Game Super Resolution (SGSR) 1.0 * HIGH: AMD FidelityFX FSR1 w/ mobile optimizations * ULTRA: AMD FidelityFX FSR1 - * FSR1 require a well anti-aliased (MSAA or TAA), noise free scene. + * FSR1 and SGSR require a well anti-aliased (MSAA or TAA), noise free scene. Avoid FXAA and dithering. * * The default upscaling quality is set to LOW. */ diff --git a/filament/include/filament/RenderableManager.h b/filament/include/filament/RenderableManager.h index 1ca238352b..b0cc14baa8 100644 --- a/filament/include/filament/RenderableManager.h +++ b/filament/include/filament/RenderableManager.h @@ -220,7 +220,7 @@ public: * the renderable are immutable. * STATIC geometry has the same restrictions as STATIC_BOUNDS, but in addition disallows * skinning, morphing and changing the VertexBuffer or IndexBuffer in any way. - * @param enable whether this renderable has static bounds. false by default. + * @param type type of geometry. */ Builder& geometryType(GeometryType type) noexcept; @@ -454,7 +454,7 @@ public: * * @param primitiveIndex zero-based index of the primitive, must be less than the primitive * count passed to Builder constructor - * @param indicesAndWeightsVectors pairs of bone index and bone weight for all vertices of + * @param indicesAndWeightsVector pairs of bone index and bone weight for all vertices of * the primitive sequentially * * @return Builder reference for chaining calls. @@ -501,7 +501,7 @@ public: * @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor * @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices) */ - RenderableManager::Builder& morphing(uint8_t level, + Builder& morphing(uint8_t level, size_t primitiveIndex, size_t offset) noexcept; @@ -798,6 +798,13 @@ public: void setMaterialInstanceAt(Instance instance, size_t primitiveIndex, MaterialInstance const* UTILS_NONNULL materialInstance); + /** + * Clear the MaterialInstance for the given primitive. + * @param instance Renderable's instance + * @param primitiveIndex Primitive index + */ + void clearMaterialInstanceAt(Instance instance, size_t primitiveIndex); + /** * Retrieves the material instance that is bound to the given primitive. */ @@ -845,20 +852,20 @@ public: /*! \cond PRIVATE */ template struct is_supported_vector_type { - using type = typename std::enable_if< - std::is_same::value || - std::is_same::value || - std::is_same::value || - std::is_same::value - >::type; + using type = std::enable_if_t< + std::is_same_v || + std::is_same_v || + std::is_same_v || + std::is_same_v + >; }; template struct is_supported_index_type { - using type = typename std::enable_if< - std::is_same::value || - std::is_same::value - >::type; + using type = std::enable_if_t< + std::is_same_v || + std::is_same_v + >; }; /*! \endcond */ diff --git a/filament/include/filament/Renderer.h b/filament/include/filament/Renderer.h index 7e66c898c4..c6033a3db8 100644 --- a/filament/include/filament/Renderer.h +++ b/filament/include/filament/Renderer.h @@ -105,7 +105,7 @@ public: * @param historySize requested history size. The returned vector could be smaller. * @return A vector of FrameInfo. */ - utils::FixedCapacityVector getFrameInfoHistory( + utils::FixedCapacityVector getFrameInfoHistory( size_t historySize = 1) const noexcept; /** diff --git a/filament/include/filament/SkinningBuffer.h b/filament/include/filament/SkinningBuffer.h index 27b13191e5..ac440425cb 100644 --- a/filament/include/filament/SkinningBuffer.h +++ b/filament/include/filament/SkinningBuffer.h @@ -82,7 +82,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the SkinningBuffer object and returns a pointer to it. diff --git a/filament/include/filament/Stream.h b/filament/include/filament/Stream.h index 883a8ccab3..f9e5a60e8e 100644 --- a/filament/include/filament/Stream.h +++ b/filament/include/filament/Stream.h @@ -149,7 +149,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the Stream object and returns a pointer to it. diff --git a/filament/include/filament/Texture.h b/filament/include/filament/Texture.h index 6813b13e73..12b28358a9 100644 --- a/filament/include/filament/Texture.h +++ b/filament/include/filament/Texture.h @@ -94,7 +94,7 @@ public: /** @return whether a backend supports texture swizzling. */ static bool isTextureSwizzleSupported(Engine& engine) noexcept; - static size_t computeTextureDataSize(Texture::Format format, Texture::Type type, + static size_t computeTextureDataSize(Format format, Type type, size_t stride, size_t height, size_t alignment) noexcept; @@ -215,7 +215,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the Texture object and returns a pointer to it. diff --git a/filament/include/filament/VertexBuffer.h b/filament/include/filament/VertexBuffer.h index 64106434ab..b850aab71a 100644 --- a/filament/include/filament/VertexBuffer.h +++ b/filament/include/filament/VertexBuffer.h @@ -171,7 +171,7 @@ public: * @param len Length of name, should be less than or equal to 128 * @return This Builder, for chaining calls. */ - // Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; // inherited + Builder& name(const char* UTILS_NONNULL name, size_t len) noexcept; /** * Creates the VertexBuffer object and returns a pointer to it. diff --git a/filament/src/AtlasAllocator.cpp b/filament/src/AtlasAllocator.cpp index 6b97f1e090..cb12297737 100644 --- a/filament/src/AtlasAllocator.cpp +++ b/filament/src/AtlasAllocator.cpp @@ -22,7 +22,7 @@ namespace filament { using namespace utils; -static inline constexpr std::pair unmorton(uint16_t m) noexcept { +static inline constexpr std::pair unmorton(uint16_t const m) noexcept { uint32_t r = (m | (uint32_t(m) << 15u)) & 0x55555555u; r = (r | (r >> 1u)) & 0x33333333u; r = (r | (r >> 2u)) & 0x0f0f0f0fu; @@ -30,14 +30,14 @@ static inline constexpr std::pair unmorton(uint16_t m) noexcep return { uint8_t(r), uint8_t(r >> 16u) }; } -AtlasAllocator::AtlasAllocator(size_t maxTextureSize) noexcept { +AtlasAllocator::AtlasAllocator(size_t const maxTextureSize) noexcept { // round to power-of-two immediately inferior or equal to the size specified. - mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - utils::clz(maxTextureSize); + mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - clz(maxTextureSize); } -AtlasAllocator::Allocation AtlasAllocator::allocate(size_t textureSize) noexcept { +AtlasAllocator::Allocation AtlasAllocator::allocate(size_t const textureSize) noexcept { Allocation result{}; - const size_t powerOfTwo = (sizeof(textureSize) * 8 - 1u) - utils::clz(textureSize); + const size_t powerOfTwo = (sizeof(textureSize) * 8 - 1u) - clz(textureSize); // asked for a texture size too large if (UTILS_UNLIKELY(powerOfTwo > mMaxTextureSizePot)) { @@ -67,12 +67,12 @@ AtlasAllocator::Allocation AtlasAllocator::allocate(size_t textureSize) noexcept return result; } -void AtlasAllocator::clear(size_t maxTextureSize) noexcept { +void AtlasAllocator::clear(size_t const maxTextureSize) noexcept { std::fill(mQuadTree.begin(), mQuadTree.end(), Node{}); - mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - utils::clz(maxTextureSize); + mMaxTextureSizePot = (sizeof(maxTextureSize) * 8 - 1u) - clz(maxTextureSize); } -AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t maxHeight) noexcept { +AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t const maxHeight) noexcept { using namespace QuadTreeUtils; NodeId candidate{ -1, 0 }; @@ -155,7 +155,7 @@ AtlasAllocator::NodeId AtlasAllocator::allocateInLayer(size_t maxHeight) noexcep if (candidate.l > 0) { // first thing to do is to update our parent's children count (the first node // doesn't have a parent). - size_t const pi = QuadTreeUtils::parent(candidate.l, candidate.code); + size_t const pi = parent(candidate.l, candidate.code); Node& parentNode = mQuadTree[pi]; assert_invariant(!parentNode.isAllocated()); assert_invariant(!parentNode.hasAllChildren()); diff --git a/filament/src/BufferObject.cpp b/filament/src/BufferObject.cpp index 461f6c2968..e37173f250 100644 --- a/filament/src/BufferObject.cpp +++ b/filament/src/BufferObject.cpp @@ -23,7 +23,7 @@ namespace filament { void BufferObject::setBuffer(Engine& engine, - BufferObject::BufferDescriptor&& buffer, uint32_t byteOffset) { + BufferDescriptor&& buffer, uint32_t const byteOffset) { downcast(this)->setBuffer(downcast(engine), std::move(buffer), byteOffset); } diff --git a/filament/src/BufferPoolAllocator.h b/filament/src/BufferPoolAllocator.h index 11f584df87..a7de04b2e8 100644 --- a/filament/src/BufferPoolAllocator.h +++ b/filament/src/BufferPoolAllocator.h @@ -103,7 +103,7 @@ void BufferPoolAllocator:: } template -void* BufferPoolAllocator::get(size_type size) noexcept { +void* BufferPoolAllocator::get(size_type const size) noexcept { std::lock_guard guard(mLock); // if the requested size is larger that our buffers in the pool, we just empty the pool diff --git a/filament/src/Camera.cpp b/filament/src/Camera.cpp index b88080874e..7ae393ebc7 100644 --- a/filament/src/Camera.cpp +++ b/filament/src/Camera.cpp @@ -22,16 +22,16 @@ namespace filament { using namespace math; -void Camera::setProjection(double fovInDegrees, double aspect, double near, double far, - Camera::Fov direction) { +void Camera::setProjection(double const fovInDegrees, double const aspect, double const near, double const far, + Fov const direction) { setCustomProjection( projection(direction, fovInDegrees, aspect, near), projection(direction, fovInDegrees, aspect, near, far), near, far); } -void Camera::setLensProjection(double focalLengthInMillimeters, - double aspect, double near, double far) { +void Camera::setLensProjection(double const focalLengthInMillimeters, + double const aspect, double const near, double const far) { setCustomProjection( projection(focalLengthInMillimeters, aspect, near), projection(focalLengthInMillimeters, aspect, near, far), @@ -46,38 +46,38 @@ mat4 Camera::inverseProjection(const mat4& p) noexcept { return inverse(p); } -void Camera::setEyeModelMatrix(uint8_t eyeId, math::mat4 const& model) { +void Camera::setEyeModelMatrix(uint8_t const eyeId, mat4 const& model) { downcast(this)->setEyeModelMatrix(eyeId, model); } -void Camera::setCustomEyeProjection(math::mat4 const* projection, size_t count, - math::mat4 const& projectionForCulling, double near, double far) { +void Camera::setCustomEyeProjection(mat4 const* projection, size_t const count, + mat4 const& projectionForCulling, double const near, double const far) { downcast(this)->setCustomEyeProjection(projection, count, projectionForCulling, near, far); } -void Camera::setProjection(Camera::Projection projection, double left, double right, double bottom, - double top, double near, double far) { +void Camera::setProjection(Projection const projection, double const left, double const right, double const bottom, + double const top, double const near, double const far) { downcast(this)->setProjection(projection, left, right, bottom, top, near, far); } -void Camera::setCustomProjection(mat4 const& projection, double near, double far) noexcept { +void Camera::setCustomProjection(mat4 const& projection, double const near, double const far) noexcept { downcast(this)->setCustomProjection(projection, near, far); } void Camera::setCustomProjection(mat4 const& projection, mat4 const& projectionForCulling, - double near, double far) noexcept { + double const near, double const far) noexcept { downcast(this)->setCustomProjection(projection, projectionForCulling, near, far); } -void Camera::setScaling(double2 scaling) noexcept { +void Camera::setScaling(double2 const scaling) noexcept { downcast(this)->setScaling(scaling); } -void Camera::setShift(double2 shift) noexcept { +void Camera::setShift(double2 const shift) noexcept { downcast(this)->setShift(shift); } -mat4 Camera::getProjectionMatrix(uint8_t eyeId) const { +mat4 Camera::getProjectionMatrix(uint8_t const eyeId) const { return downcast(this)->getUserProjectionMatrix(eyeId); } @@ -137,7 +137,7 @@ float3 Camera::getForwardVector() const noexcept { return downcast(this)->getForwardVector(); } -float Camera::getFieldOfViewInDegrees(Camera::Fov direction) const noexcept { +float Camera::getFieldOfViewInDegrees(Fov const direction) const noexcept { return downcast(this)->getFieldOfViewInDegrees(direction); } @@ -149,7 +149,7 @@ utils::Entity Camera::getEntity() const noexcept { return downcast(this)->getEntity(); } -void Camera::setExposure(float aperture, float shutterSpeed, float ISO) noexcept { +void Camera::setExposure(float const aperture, float const shutterSpeed, float const ISO) noexcept { downcast(this)->setExposure(aperture, shutterSpeed, ISO); } @@ -165,7 +165,7 @@ float Camera::getSensitivity() const noexcept { return downcast(this)->getSensitivity(); } -void Camera::setFocusDistance(float distance) noexcept { +void Camera::setFocusDistance(float const distance) noexcept { downcast(this)->setFocusDistance(distance); } @@ -177,21 +177,21 @@ double Camera::getFocalLength() const noexcept { return downcast(this)->getFocalLength(); } -double Camera::computeEffectiveFocalLength(double focalLength, double focusDistance) noexcept { +double Camera::computeEffectiveFocalLength(double const focalLength, double const focusDistance) noexcept { return FCamera::computeEffectiveFocalLength(focalLength, focusDistance); } -double Camera::computeEffectiveFov(double fovInDegrees, double focusDistance) noexcept { +double Camera::computeEffectiveFov(double const fovInDegrees, double const focusDistance) noexcept { return FCamera::computeEffectiveFov(fovInDegrees, focusDistance); } -math::mat4 Camera::projection(Fov direction, double fovInDegrees, - double aspect, double near, double far) { +mat4 Camera::projection(Fov const direction, double const fovInDegrees, + double const aspect, double const near, double const far) { return FCamera::projection(direction, fovInDegrees, aspect, near, far); } -math::mat4 Camera::projection(double focalLengthInMillimeters, - double aspect, double near, double far) { +mat4 Camera::projection(double const focalLengthInMillimeters, + double const aspect, double const near, double const far) { return FCamera::projection(focalLengthInMillimeters, aspect, near, far); } diff --git a/filament/src/Color.cpp b/filament/src/Color.cpp index 41c837786d..79adbd63d6 100644 --- a/filament/src/Color.cpp +++ b/filament/src/Color.cpp @@ -25,15 +25,15 @@ namespace filament { using namespace math; -float3 Color::sRGBToLinear(float3 color) noexcept { +float3 Color::sRGBToLinear(float3 const color) noexcept { return EOTF_sRGB(color); } -float3 Color::linearToSRGB(float3 color) noexcept { +float3 Color::linearToSRGB(float3 const color) noexcept { return OETF_sRGB(color); } -LinearColor Color::cct(float K) { +LinearColor Color::cct(float const K) { // temperature to CIE 1960 float const K2 = K * K; float const u = (0.860117757f + 1.54118254e-4f * K + 1.28641212e-7f * K2) / @@ -47,7 +47,7 @@ LinearColor Color::cct(float K) { return saturate(linear / max(1e-5f, max(linear))); } -LinearColor Color::illuminantD(float K) { +LinearColor Color::illuminantD(float const K) { // temperature to xyY const float iK = 1.0f / K; float const iK2 = iK * iK; @@ -61,7 +61,7 @@ LinearColor Color::illuminantD(float K) { return saturate(linear / max(1e-5f, max(linear))); } -LinearColor Color::absorptionAtDistance(LinearColor const& color, float distance) { +LinearColor Color::absorptionAtDistance(LinearColor const& color, float const distance) { return -log(clamp(color, 1e-5f, 1.0f)) / max(1e-5f, distance); } diff --git a/filament/src/ColorSpaceUtils.cpp b/filament/src/ColorSpaceUtils.cpp index 6d8010ec53..415c8c2ac0 100644 --- a/filament/src/ColorSpaceUtils.cpp +++ b/filament/src/ColorSpaceUtils.cpp @@ -52,7 +52,7 @@ using namespace math; // Finds the maximum saturation possible for a given hue that fits in sRGB // Saturation here is defined as S = C/L // a and b must be normalized so a^2 + b^2 == 1 -static float compute_max_saturation(float a, float b) noexcept { +static float compute_max_saturation(float const a, float const b) noexcept { // Max saturation will be when one of r, g or b goes below zero. // Select different coefficients depending on which component goes below zero first @@ -131,7 +131,7 @@ static float compute_max_saturation(float a, float b) noexcept { // finds L_cusp and C_cusp for a given hue // a and b must be normalized so a^2 + b^2 == 1 -static float2 find_cusp(float a, float b) noexcept { +static float2 find_cusp(float const a, float const b) noexcept { // First, find the maximum saturation (saturation S = C/L) float const S_cusp = compute_max_saturation(a, b); @@ -147,7 +147,7 @@ static float2 find_cusp(float a, float b) noexcept { // L = L0 * (1 - t) + t * L1; // C = t * C1; // a and b must be normalized so a^2 + b^2 == 1 -static float find_gamut_intersection(float a, float b, float L1, float C1, float L0) noexcept { +static float find_gamut_intersection(float const a, float const b, float const L1, float const C1, float const L0) noexcept { // Find the cusp of the gamut triangle float2 const cusp = find_cusp(a, b); @@ -231,7 +231,7 @@ static float find_gamut_intersection(float a, float b, float L1, float C1, float return t; } -constexpr float sgn(float x) noexcept { +constexpr float sgn(float const x) noexcept { return (float) (0.f < x) - (float) (x < 0.f); } @@ -266,7 +266,7 @@ inline float3 gamut_clip_adaptive_L0_0_5(float3 rgb, return OkLab_to_sRGB({L_clipped, C_clipped * a_, C_clipped * b_}); } -float3 gamutMapping_sRGB(float3 rgb) noexcept { +float3 gamutMapping_sRGB(float3 const rgb) noexcept { return gamut_clip_adaptive_L0_0_5(rgb); } diff --git a/filament/src/ColorSpaceUtils.h b/filament/src/ColorSpaceUtils.h index 490e79ea9e..3c10888921 100644 --- a/filament/src/ColorSpaceUtils.h +++ b/filament/src/ColorSpaceUtils.h @@ -213,7 +213,7 @@ constexpr float MIDDLE_GRAY_ACEScct = 0.4135884f; // Returns the y chromaticity coordinate in xyY for an illuminant series D, // given its x chromaticity coordinate. -inline constexpr float chromaticityCoordinateIlluminantD(float x) noexcept { +inline constexpr float chromaticityCoordinateIlluminantD(float const x) noexcept { // See http://en.wikipedia.org/wiki/Standard_illuminant#Illuminant_series_D return 2.87f * x - 3.0f * x * x - 0.275f; } @@ -222,7 +222,7 @@ inline constexpr float chromaticityCoordinateIlluminantD(float x) noexcept { // Color space conversions //------------------------------------------------------------------------------ -inline constexpr XYZ xyY_to_XYZ(xyY v) noexcept { +inline constexpr XYZ xyY_to_XYZ(xyY const v) noexcept { const float a = v.z / max(v.y, 1e-5f); return XYZ{v.x * a, v.z, (1.0f - v.x - v.y) * a}; } @@ -231,23 +231,23 @@ inline constexpr xyY XYZ_to_xyY(XYZ v) noexcept { return {v.xy / max(v.x + v.y + v.z, 1e-5f), v.y}; } -inline constexpr float3 pow3(float3 x) noexcept { +inline constexpr float3 pow3(float3 const x) noexcept { return x * x * x; } -inline float3 sRGB_to_OkLab(float3 x) noexcept { +inline float3 sRGB_to_OkLab(float3 const x) noexcept { return OkLab_LMS_to_OkLab * cbrt(sRGB_to_OkLab_LMS * x); } -inline float3 Rec2020_to_OkLab(float3 x) noexcept { +inline float3 Rec2020_to_OkLab(float3 const x) noexcept { return OkLab_LMS_to_OkLab * cbrt(Rec2020_to_OkLab_LMS * x); } -inline float3 OkLab_to_sRGB(float3 x) noexcept { +inline float3 OkLab_to_sRGB(float3 const x) noexcept { return OkLab_LMS_to_sRGB * pow3(OkLab_to_OkLab_LMS * x); } -inline float3 OkLab_to_Rec2020(float3 x) noexcept { +inline float3 OkLab_to_Rec2020(float3 const x) noexcept { return OkLab_LMS_to_Rec2020 * pow3(OkLab_to_OkLab_LMS * x); } @@ -256,7 +256,7 @@ inline float3 OkLab_to_Rec2020(float3 x) noexcept { //------------------------------------------------------------------------------ // Decodes a linear value from LogC using the Alexa LogC EI 1000 curve -inline float3 LogC_to_linear(float3 x) noexcept { +inline float3 LogC_to_linear(float3 const x) noexcept { const float ia = 1.0f / 5.555556f; const float b = 0.047996f; const float ic = 1.0f / 0.244161f; @@ -265,7 +265,7 @@ inline float3 LogC_to_linear(float3 x) noexcept { } // Encodes a linear value in LogC using the Alexa LogC EI 1000 curve -inline float3 linear_to_LogC(float3 x) noexcept { +inline float3 linear_to_LogC(float3 const x) noexcept { const float a = 5.555556f; const float b = 0.047996f; const float c = 0.244161f; @@ -296,7 +296,7 @@ inline float3 linearAP1_to_ACEScct(float3 x) noexcept { return x; } -inline float3 OETF_Linear(float3 x) noexcept { +inline float3 OETF_Linear(float3 const x) noexcept { return x; } diff --git a/filament/src/Culler.cpp b/filament/src/Culler.cpp index bae62063dc..85e8bf03ac 100644 --- a/filament/src/Culler.cpp +++ b/filament/src/Culler.cpp @@ -64,7 +64,7 @@ void Culler::intersects( Frustum const& UTILS_RESTRICT frustum, float3 const* UTILS_RESTRICT center, float3 const* UTILS_RESTRICT extent, - size_t count, size_t bit) noexcept { + size_t count, size_t const bit) noexcept { float4 const * UTILS_RESTRICT const planes = frustum.mPlanes; @@ -101,10 +101,10 @@ bool Culler::intersects(Frustum const& frustum, Box const& box) noexcept { // The main intersection routine assumes multiples of 8 items float3 centers[MODULO]; float3 extents[MODULO]; - Culler::result_type results[MODULO]; + result_type results[MODULO]; centers[0] = box.center; extents[0] = box.halfExtent; - Culler::intersects(results, frustum, centers, extents, MODULO, 0); + intersects(results, frustum, centers, extents, MODULO, 0); return bool(results[0] & 1); } @@ -114,9 +114,9 @@ bool Culler::intersects(Frustum const& frustum, Box const& box) noexcept { bool Culler::intersects(Frustum const& frustum, float4 const& sphere) noexcept { // The main intersection routine assumes multiples of 8 items float4 spheres[MODULO]; - Culler::result_type results[MODULO]; + result_type results[MODULO]; spheres[0] = sphere; - Culler::intersects(results, frustum, spheres, MODULO); + intersects(results, frustum, spheres, MODULO); return bool(results[0] & 1); } @@ -127,14 +127,14 @@ void Culler::Test::intersects( Frustum const& UTILS_RESTRICT frustum, float3 const* UTILS_RESTRICT c, float3 const* UTILS_RESTRICT e, - size_t count) noexcept { + size_t const count) noexcept { Culler::intersects(results, frustum, c, e, count, 0); } void Culler::Test::intersects( result_type* UTILS_RESTRICT results, Frustum const& UTILS_RESTRICT frustum, - float4 const* UTILS_RESTRICT b, size_t count) noexcept { + float4 const* UTILS_RESTRICT b, size_t const count) noexcept { Culler::intersects(results, frustum, b, count); } diff --git a/filament/src/Culler.h b/filament/src/Culler.h index 6f3a0bf9f9..643d69086a 100644 --- a/filament/src/Culler.h +++ b/filament/src/Culler.h @@ -38,7 +38,7 @@ class Culler { public: // Culler can only process buffers with a size multiple of MODULO static constexpr size_t MODULO = 8u; - static inline size_t round(size_t count) noexcept { + static inline size_t round(size_t const count) noexcept { return (count + (MODULO - 1)) & ~(MODULO - 1); } diff --git a/filament/src/DebugRegistry.cpp b/filament/src/DebugRegistry.cpp index a4f93df486..27182dcc51 100644 --- a/filament/src/DebugRegistry.cpp +++ b/filament/src/DebugRegistry.cpp @@ -28,27 +28,27 @@ bool DebugRegistry::hasProperty(const char* name) const noexcept { return downcast(this)->hasProperty(name); } -bool DebugRegistry::setProperty(const char* name, bool v) noexcept { +bool DebugRegistry::setProperty(const char* name, bool const v) noexcept { return downcast(this)->setProperty(name, v); } -bool DebugRegistry::setProperty(const char* name, int v) noexcept { +bool DebugRegistry::setProperty(const char* name, int const v) noexcept { return downcast(this)->setProperty(name, v); } -bool DebugRegistry::setProperty(const char* name, float v) noexcept { +bool DebugRegistry::setProperty(const char* name, float const v) noexcept { return downcast(this)->setProperty(name, v); } -bool DebugRegistry::setProperty(const char* name, float2 v) noexcept { +bool DebugRegistry::setProperty(const char* name, float2 const v) noexcept { return downcast(this)->setProperty(name, v); } -bool DebugRegistry::setProperty(const char* name, float3 v) noexcept { +bool DebugRegistry::setProperty(const char* name, float3 const v) noexcept { return downcast(this)->setProperty(name, v); } -bool DebugRegistry::setProperty(const char* name, float4 v) noexcept { +bool DebugRegistry::setProperty(const char* name, float4 const v) noexcept { return downcast(this)->setProperty(name, v); } diff --git a/filament/src/Engine.cpp b/filament/src/Engine.cpp index c95b944ccf..455067739c 100644 --- a/filament/src/Engine.cpp +++ b/filament/src/Engine.cpp @@ -104,15 +104,15 @@ Scene* Engine::createScene() noexcept { return downcast(this)->createScene(); } -Camera* Engine::createCamera(Entity entity) noexcept { +Camera* Engine::createCamera(Entity const entity) noexcept { return downcast(this)->createCamera(entity); } -Camera* Engine::getCameraComponent(utils::Entity entity) noexcept { +Camera* Engine::getCameraComponent(Entity const entity) noexcept { return downcast(this)->getCameraComponent(entity); } -void Engine::destroyCameraComponent(utils::Entity entity) noexcept { +void Engine::destroyCameraComponent(Entity const entity) noexcept { downcast(this)->destroyCameraComponent(entity); } @@ -120,11 +120,11 @@ Fence* Engine::createFence() noexcept { return downcast(this)->createFence(); } -SwapChain* Engine::createSwapChain(void* nativeWindow, uint64_t flags) noexcept { +SwapChain* Engine::createSwapChain(void* nativeWindow, uint64_t const flags) noexcept { return downcast(this)->createSwapChain(nativeWindow, flags); } -SwapChain* Engine::createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept { +SwapChain* Engine::createSwapChain(uint32_t const width, uint32_t const height, uint64_t const flags) noexcept { return downcast(this)->createSwapChain(width, height, flags); } @@ -204,7 +204,7 @@ bool Engine::destroy(const InstanceBuffer* p) { return downcast(this)->destroy(downcast(p)); } -void Engine::destroy(Entity e) { +void Engine::destroy(Entity const e) { downcast(this)->destroy(e); } @@ -338,11 +338,15 @@ void Engine::flushAndWait() { downcast(this)->flushAndWait(); } +bool Engine::flushAndWait(uint64_t timeout) { + return downcast(this)->flushAndWait(timeout); +} + void Engine::flush() { downcast(this)->flush(); } -utils::EntityManager& Engine::getEntityManager() noexcept { +EntityManager& Engine::getEntityManager() noexcept { return downcast(this)->getEntityManager(); } @@ -362,7 +366,7 @@ void Engine::enableAccurateTranslations() noexcept { getTransformManager().setAccurateTranslationsEnabled(true); } -void* Engine::streamAlloc(size_t size, size_t alignment) noexcept { +void* Engine::streamAlloc(size_t const size, size_t const alignment) noexcept { return downcast(this)->streamAlloc(size, alignment); } @@ -375,7 +379,7 @@ void Engine::execute() { downcast(this)->execute(); } -utils::JobSystem& Engine::getJobSystem() noexcept { +JobSystem& Engine::getJobSystem() noexcept { return downcast(this)->getJobSystem(); } @@ -385,7 +389,7 @@ bool Engine::isPaused() const noexcept { return downcast(this)->isPaused(); } -void Engine::setPaused(bool paused) { +void Engine::setPaused(bool const paused) { FILAMENT_CHECK_PRECONDITION(UTILS_HAS_THREADING) << "Pause is meant for multi-threaded platforms."; downcast(this)->setPaused(paused); @@ -403,7 +407,7 @@ void Engine::unprotected() noexcept { downcast(this)->unprotected(); } -void Engine::setAutomaticInstancingEnabled(bool enable) noexcept { +void Engine::setAutomaticInstancingEnabled(bool const enable) noexcept { downcast(this)->setAutomaticInstancingEnabled(enable); } @@ -415,7 +419,7 @@ FeatureLevel Engine::getSupportedFeatureLevel() const noexcept { return downcast(this)->getSupportedFeatureLevel(); } -FeatureLevel Engine::setActiveFeatureLevel(FeatureLevel featureLevel) { +FeatureLevel Engine::setActiveFeatureLevel(FeatureLevel const featureLevel) { return downcast(this)->setActiveFeatureLevel(featureLevel); } @@ -443,11 +447,11 @@ uint64_t Engine::getSteadyClockTimeNano() noexcept { return std::chrono::steady_clock::now().time_since_epoch().count(); } -utils::Slice Engine::getFeatureFlags() const noexcept { +Slice Engine::getFeatureFlags() const noexcept { return downcast(this)->getFeatureFlags(); } -bool Engine::setFeatureFlag(char const* name, bool value) noexcept { +bool Engine::setFeatureFlag(char const* name, bool const value) noexcept { return downcast(this)->setFeatureFlag(name, value); } diff --git a/filament/src/Exposure.cpp b/filament/src/Exposure.cpp index b2a88a7ce1..9029b59646 100644 --- a/filament/src/Exposure.cpp +++ b/filament/src/Exposure.cpp @@ -28,7 +28,7 @@ float ev100(const Camera& c) noexcept { return ev100(camera.getAperture(), camera.getShutterSpeed(), camera.getSensitivity()); } -float ev100(float aperture, float shutterSpeed, float sensitivity) noexcept { +float ev100(float const aperture, float const shutterSpeed, float const sensitivity) noexcept { // With N = aperture, t = shutter speed and S = sensitivity, // we can compute EV100 knowing that: // @@ -46,7 +46,7 @@ float ev100(float aperture, float shutterSpeed, float sensitivity) noexcept { return std::log2((aperture * aperture) / shutterSpeed * 100.0f / sensitivity); } -float ev100FromLuminance(float luminance) noexcept { +float ev100FromLuminance(float const luminance) noexcept { // With L the average scene luminance, S the sensitivity and K the // reflected-light meter calibration constant: // @@ -61,7 +61,7 @@ float ev100FromLuminance(float luminance) noexcept { return std::log2(luminance * (100.0f / 12.5f)); } -float ev100FromIlluminance(float illuminance) noexcept { +float ev100FromIlluminance(float const illuminance) noexcept { // With E the illuminance, S the sensitivity and C the incident-light meter // calibration constant, the exposure value can be computed as such: // @@ -83,14 +83,14 @@ float exposure(const Camera& c) noexcept { return exposure(camera.getAperture(), camera.getShutterSpeed(), camera.getSensitivity()); } -float exposure(float aperture, float shutterSpeed, float sensitivity) noexcept { +float exposure(float const aperture, float const shutterSpeed, float const sensitivity) noexcept { // This is equivalent to calling exposure(ev100(N, t, S)) // By merging the two calls we can remove extra pow()/log2() calls const float e = (aperture * aperture) / shutterSpeed * 100.0f / sensitivity; return 1.0f / (1.2f * e); } -float exposure(float ev100) noexcept { +float exposure(float const ev100) noexcept { // The photometric exposure H is defined by: // // H = (q * t / (N^2)) * L @@ -140,14 +140,14 @@ float luminance(const Camera& c) noexcept { return luminance(camera.getAperture(), camera.getShutterSpeed(), camera.getSensitivity()); } -float luminance(float aperture, float shutterSpeed, float sensitivity) noexcept { +float luminance(float const aperture, float const shutterSpeed, float const sensitivity) noexcept { // This is equivalent to calling luminance(ev100(N, t, S)) // By merging the two calls we can remove extra pow()/log2() calls const float e = (aperture * aperture) / shutterSpeed * 100.0f / sensitivity; return e * 0.125f; } -float luminance(float ev100) noexcept { +float luminance(float const ev100) noexcept { // With L the average scene luminance, S the sensitivity and K the // reflected-light meter calibration constant: // @@ -172,14 +172,14 @@ float illuminance(const Camera& c) noexcept { return illuminance(camera.getAperture(), camera.getShutterSpeed(), camera.getSensitivity()); } -float illuminance(float aperture, float shutterSpeed, float sensitivity) noexcept { +float illuminance(float const aperture, float const shutterSpeed, float const sensitivity) noexcept { // This is equivalent to calling illuminance(ev100(N, t, S)) // By merging the two calls we can remove extra pow()/log2() calls const float e = (aperture * aperture) / shutterSpeed * 100.0f / sensitivity; return 2.5f * e; } -float illuminance(float ev100) noexcept { +float illuminance(float const ev100) noexcept { // With E the illuminance, S the sensitivity and C the incident-light meter // calibration constant, the exposure value can be computed as such: // diff --git a/filament/src/Fence.cpp b/filament/src/Fence.cpp index 699326b195..12199a0f00 100644 --- a/filament/src/Fence.cpp +++ b/filament/src/Fence.cpp @@ -20,11 +20,11 @@ namespace filament { using namespace backend; -FenceStatus Fence::waitAndDestroy(Fence* fence, Mode mode) { +FenceStatus Fence::waitAndDestroy(Fence* fence, Mode const mode) { return FFence::waitAndDestroy(downcast(fence), mode); } -FenceStatus Fence::wait(Mode mode, uint64_t timeout) { +FenceStatus Fence::wait(Mode const mode, uint64_t const timeout) { return downcast(this)->wait(mode, timeout); } diff --git a/filament/src/FilamentBuilder.cpp b/filament/src/FilamentBuilder.cpp index 08f1cb3231..67631eb4c9 100644 --- a/filament/src/FilamentBuilder.cpp +++ b/filament/src/FilamentBuilder.cpp @@ -20,7 +20,7 @@ namespace filament { -void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept { +void builderMakeName(utils::CString& outName, const char* name, size_t const len) noexcept { if (!name) { return; } diff --git a/filament/src/FrameInfo.cpp b/filament/src/FrameInfo.cpp index 228f8fa671..49a4e2b0d9 100644 --- a/filament/src/FrameInfo.cpp +++ b/filament/src/FrameInfo.cpp @@ -172,9 +172,9 @@ void FrameInfoManager::denoiseFrameTime(FrameHistoryQueue& history, Config const } } -utils::FixedCapacityVector FrameInfoManager::getFrameInfoHistory( +FixedCapacityVector FrameInfoManager::getFrameInfoHistory( size_t historySize) const noexcept { - auto result = utils::FixedCapacityVector::with_capacity(MAX_FRAMETIME_HISTORY); + auto result = FixedCapacityVector::with_capacity(MAX_FRAMETIME_HISTORY); auto const& history = mFrameTimeHistory; size_t i = 0; size_t const c = history.size(); diff --git a/filament/src/FrameInfo.h b/filament/src/FrameInfo.h index 9abda05354..668d8a23fe 100644 --- a/filament/src/FrameInfo.h +++ b/filament/src/FrameInfo.h @@ -57,7 +57,7 @@ struct FrameInfoImpl : public details::FrameInfo { time_point backendBeginFrame; // backend thread beginFrame time (makeCurrent time) time_point backendEndFrame; // backend thread endFrame time (present time) std::atomic_bool ready{}; // true once backend thread has populated its data - explicit FrameInfoImpl(uint32_t frameId) noexcept + explicit FrameInfoImpl(uint32_t const frameId) noexcept : frameId(frameId) { } }; @@ -110,7 +110,7 @@ public: return front(); } - T& operator[](size_t pos) noexcept { + T& operator[](size_t const pos) noexcept { assert_invariant(pos < size()); size_t const index = (mFront + CAPACITY - pos) % CAPACITY; return *std::launder(reinterpret_cast(&mStorage[index])); @@ -135,7 +135,7 @@ private: Storage mStorage[CAPACITY]; uint32_t mFront = 0; // always index 0 uint32_t mSize = 0; - [[nodiscard]] inline uint32_t advance(uint32_t v) noexcept { + [[nodiscard]] inline uint32_t advance(uint32_t const v) noexcept { return (v + 1) % CAPACITY; } }; diff --git a/filament/src/FrameSkipper.cpp b/filament/src/FrameSkipper.cpp index 673e82ef4f..c58f986953 100644 --- a/filament/src/FrameSkipper.cpp +++ b/filament/src/FrameSkipper.cpp @@ -30,7 +30,7 @@ namespace filament { using namespace utils; using namespace backend; -FrameSkipper::FrameSkipper(size_t latency) noexcept +FrameSkipper::FrameSkipper(size_t const latency) noexcept : mLast(std::clamp(latency, size_t(1), MAX_FRAME_LATENCY) - 1) { } diff --git a/filament/src/Froxelizer.cpp b/filament/src/Froxelizer.cpp index 560891ad5a..fe8975276e 100644 --- a/filament/src/Froxelizer.cpp +++ b/filament/src/Froxelizer.cpp @@ -16,27 +16,47 @@ #include "Froxelizer.h" +#include "Allocators.h" #include "Intersections.h" #include "details/Engine.h" #include "details/Scene.h" -#include "private/backend/DriverApi.h" +#include +#include +#include #include +#include + #include +#include #include +#include #include +#include #include -#include #include +#include +#include #include +#include +#include +#include #include +#include +#include +#include +#include +#include +#include #include +#include +#include using namespace filament::math; using namespace utils; @@ -143,7 +163,7 @@ void Froxelizer::terminate(DriverApi& driverApi) noexcept { } } -void Froxelizer::setOptions(float zLightNear, float zLightFar) noexcept { +void Froxelizer::setOptions(float const zLightNear, float const zLightFar) noexcept { if (UTILS_UNLIKELY(mZLightNear != zLightNear || mZLightFar != zLightFar)) { mZLightNear = zLightNear; mZLightFar = zLightFar; @@ -160,7 +180,7 @@ void Froxelizer::setViewport(filament::Viewport const& viewport) noexcept { } void Froxelizer::setProjection(const mat4f& projection, - float near, UTILS_UNUSED float far) noexcept { + float const near, UTILS_UNUSED float far) noexcept { if (UTILS_UNLIKELY(!fuzzyEqual(mProjection, projection))) { mProjection = projection; mNear = near; @@ -171,7 +191,7 @@ void Froxelizer::setProjection(const mat4f& projection, bool Froxelizer::prepare( FEngine::DriverApi& driverApi, RootArenaScope& rootArenaScope, filament::Viewport const& viewport, - const mat4f& projection, float projectionNear, float projectionFar) noexcept { + const mat4f& projection, float const projectionNear, float const projectionFar) noexcept { setViewport(viewport); setProjection(projection, projectionNear, projectionFar); @@ -223,9 +243,9 @@ bool Froxelizer::prepare( void Froxelizer::computeFroxelLayout( uint2* dim, uint16_t* countX, uint16_t* countY, uint16_t* countZ, - size_t froxelBufferEntryCount, filament::Viewport const& viewport) noexcept { + size_t const froxelBufferEntryCount, filament::Viewport const& viewport) noexcept { - auto roundTo8 = [](uint32_t v) { return (v + 7u) & ~7u; }; + auto roundTo8 = [](uint32_t const v) { return (v + 7u) & ~7u; }; const uint32_t width = std::max(16u, viewport.width); const uint32_t height = std::max(16u, viewport.height); @@ -264,10 +284,10 @@ void Froxelizer::computeFroxelLayout( UTILS_NOINLINE void Froxelizer::updateBoundingSpheres( - math::float4* const UTILS_RESTRICT boundingSpheres, + float4* const UTILS_RESTRICT boundingSpheres, size_t froxelCountX, size_t froxelCountY, size_t froxelCountZ, - math::float4 const* UTILS_RESTRICT planesX, - math::float4 const* UTILS_RESTRICT planesY, + float4 const* UTILS_RESTRICT planesX, + float4 const* UTILS_RESTRICT planesY, float const* UTILS_RESTRICT planesZ) noexcept { SYSTRACE_CALL(); @@ -458,7 +478,7 @@ bool Froxelizer::update() noexcept { return uniformsNeedUpdating; } -Froxel Froxelizer::getFroxelAt(size_t x, size_t y, size_t z) const noexcept { +Froxel Froxelizer::getFroxelAt(size_t const x, size_t const y, size_t const z) const noexcept { assert_invariant(x < mFroxelCountX); assert_invariant(y < mFroxelCountY); assert_invariant(z < mFroxelCountZ); @@ -473,7 +493,7 @@ Froxel Froxelizer::getFroxelAt(size_t x, size_t y, size_t z) const noexcept { } UTILS_NOINLINE -size_t Froxelizer::findSliceZ(float z) const noexcept { +size_t Froxelizer::findSliceZ(float const z) const noexcept { // The vastly common case is that z<0, so we always do the math for this case // and we "undo" it below otherwise. This works because we're using fast::log2 which // doesn't care if given a negative number (we'd have to use abs() otherwise). @@ -502,7 +522,7 @@ std::pair Froxelizer::clipToIndices(float2 const& clip) const no } -void Froxelizer::commit(backend::DriverApi& driverApi) { +void Froxelizer::commit(DriverApi& driverApi) { // send data to GPU driverApi.updateBufferObject(mFroxelsBuffer, { mFroxelBufferUser.data(), getFroxelBufferEntryCount() * 16u }, 0); @@ -563,7 +583,7 @@ void Froxelizer::froxelizeLoop(FEngine& engine, auto process = [ this, &froxelThreadData, spheres, directions, instances, &viewMatrix, &lcm ] - (size_t count, size_t offset, size_t stride) { + (size_t const count, size_t const offset, size_t const stride) { SYSTRACE_NAME("FroxelizeLoop Job"); @@ -603,7 +623,7 @@ void Froxelizer::froxelizeLoop(FEngine& engine, JobSystem& js = engine.getJobSystem(); constexpr bool SINGLE_THREADED = false; - if (!SINGLE_THREADED) { + if constexpr (!SINGLE_THREADED) { auto *parent = js.createJob(); for (size_t i = 0; i < GROUP_COUNT; i++) { js.run(jobs::createJob(js, parent, std::cref(process), @@ -629,7 +649,7 @@ void Froxelizer::froxelizeAssignRecordsCompress() noexcept { // this gets very well vectorized... - utils::Slice records(mLightRecords); + Slice records(mLightRecords); for (size_t j = 0, jc = getFroxelBufferEntryCount(); j < jc; j++) { for (size_t i = 0; i < LightRecord::bitset::WORLD_COUNT; i++) { using container_type = LightRecord::bitset::container_type; @@ -737,7 +757,7 @@ out_of_memory: ; } -static inline float2 project(mat4f const& p, float3 const& v) noexcept { +static float2 project(mat4f const& p, float3 const& v) noexcept { const float vx = v[0]; const float vy = v[1]; const float vz = v[2]; @@ -750,7 +770,7 @@ static inline float2 project(mat4f const& p, float3 const& v) noexcept { void Froxelizer::froxelizePointAndSpotLight( FroxelThreadData& froxelThread, size_t bit, mat4f const& UTILS_RESTRICT p, - const Froxelizer::LightParams& UTILS_RESTRICT light) const noexcept { + const LightParams& UTILS_RESTRICT light) const noexcept { if (UTILS_UNLIKELY(light.position.z + light.radius < -mZLightFar)) { // z values are negative // This light is fully behind LightFar, it doesn't light anything @@ -902,7 +922,7 @@ void Froxelizer::froxelizePointAndSpotLight( */ void Froxelizer::computeLightTree( LightTreeNode* lightTree, - utils::Slice const& lightList, + Slice const& lightList, const FScene::LightSoa& lightData, size_t lightRecordsOffset) noexcept { @@ -910,7 +930,7 @@ void Froxelizer::computeLightTree( const size_t count = lightList.size(); // the width of the tree is the next power-of-two (if not already a power of two) - const size_t w = 1u << (log2i(count) + (utils::popcount(count) == 1 ? 0 : 1)); + const size_t w = 1u << (log2i(count) + (popcount(count) == 1 ? 0 : 1)); // height of the tree const size_t h = log2i(w) + 1u; @@ -918,7 +938,7 @@ void Froxelizer::computeLightTree( auto const* UTILS_RESTRICT zrange = lightData.data() + 1; BinaryTreeArray::traverse(h, [lightTree, lightRecordsOffset, zrange, indices = lightList.data(), count] - (size_t index, size_t col, size_t next) { + (size_t const index, size_t const col, size_t const next) { // indices[] cannot be accessed past 'col' const float min = (col < count) ? zrange[indices[col]].x : 1.0f; const float max = (col < count) ? zrange[indices[col]].y : 0.0f; @@ -932,7 +952,7 @@ void Froxelizer::computeLightTree( .reserved = 0, }; }, - [lightTree](size_t index, size_t l, size_t r, size_t next) { + [lightTree](size_t const index, size_t const l, size_t const r, size_t const next) { lightTree[index] = { .min = std::min(lightTree[l].min, lightTree[r].min), .max = std::max(lightTree[l].max, lightTree[r].max), diff --git a/filament/src/Froxelizer.h b/filament/src/Froxelizer.h index 27ba3c5764..d052b7241b 100644 --- a/filament/src/Froxelizer.h +++ b/filament/src/Froxelizer.h @@ -140,7 +140,7 @@ public: */ struct FroxelEntry { - inline FroxelEntry(uint16_t offset, uint8_t count) noexcept + inline FroxelEntry(uint16_t const offset, uint8_t const count) noexcept : u32((offset << 16) | count) { } inline uint8_t count() const noexcept { return u32 & 0xFFu; } inline uint16_t offset() const noexcept { return u32 >> 16u; } @@ -214,12 +214,12 @@ private: math::float4 const* UTILS_RESTRICT planesY, float const* UTILS_RESTRICT planesZ) noexcept; - static size_t getFroxelIndex(size_t ix, size_t iy, size_t iz, - size_t froxelCountX, size_t froxelCountY) noexcept { + static size_t getFroxelIndex(size_t const ix, size_t const iy, size_t const iz, + size_t const froxelCountX, size_t const froxelCountY) noexcept { return ix + (iy * froxelCountX) + (iz * froxelCountX * froxelCountY); } - size_t getFroxelIndex(size_t ix, size_t iy, size_t iz) const noexcept { + size_t getFroxelIndex(size_t const ix, size_t const iy, size_t const iz) const noexcept { return getFroxelIndex(ix, iy, iz, mFroxelCountX, mFroxelCountY); } diff --git a/filament/src/Frustum.cpp b/filament/src/Frustum.cpp index 30f5b970fe..b11f3799e4 100644 --- a/filament/src/Frustum.cpp +++ b/filament/src/Frustum.cpp @@ -19,14 +19,20 @@ #include "Culler.h" #include -#include +#include + +#include +#include +#include + +#include using namespace filament::math; namespace filament { Frustum::Frustum(const mat4f& pv) { - Frustum::setProjection(pv); + setProjection(pv); } // NOTE: if we don't specify noinline here, LLVM inlines this huge function into @@ -68,7 +74,7 @@ void Frustum::setProjection(const mat4f& pv) { mPlanes[5] = n; } -float4 Frustum::getNormalizedPlane(Frustum::Plane plane) const noexcept { +float4 Frustum::getNormalizedPlane(Plane plane) const noexcept { return mPlanes[size_t(plane)]; } @@ -89,7 +95,7 @@ bool Frustum::intersects(const float4& sphere) const noexcept { return Culler::intersects(*this, sphere); } -float Frustum::contains(float3 p) const noexcept { +float Frustum::contains(float3 const p) const noexcept { float const l = dot(mPlanes[0].xyz, p) + mPlanes[0].w; float const b = dot(mPlanes[1].xyz, p) + mPlanes[1].w; float const r = dot(mPlanes[2].xyz, p) + mPlanes[2].w; diff --git a/filament/src/HwDescriptorSetLayoutFactory.cpp b/filament/src/HwDescriptorSetLayoutFactory.cpp index 371ffde4b7..1e2f6301d7 100644 --- a/filament/src/HwDescriptorSetLayoutFactory.cpp +++ b/filament/src/HwDescriptorSetLayoutFactory.cpp @@ -39,9 +39,9 @@ using namespace utils; using namespace backend; size_t HwDescriptorSetLayoutFactory::Parameters::hash() const noexcept { - return utils::hash::murmurSlow( + return hash::murmurSlow( reinterpret_cast(dsl.bindings.data()), - dsl.bindings.size() * sizeof(backend::DescriptorSetLayoutBinding), + dsl.bindings.size() * sizeof(DescriptorSetLayoutBinding), 42); } @@ -68,7 +68,7 @@ void HwDescriptorSetLayoutFactory::terminate(DriverApi&) noexcept { } auto HwDescriptorSetLayoutFactory::create(DriverApi& driver, - backend::DescriptorSetLayout dsl) noexcept -> Handle { + DescriptorSetLayout dsl) noexcept -> Handle { std::sort(dsl.bindings.begin(), dsl.bindings.end(), [](auto&& lhs, auto&& rhs) { diff --git a/filament/src/HwRenderPrimitiveFactory.cpp b/filament/src/HwRenderPrimitiveFactory.cpp index 2c76a3da0a..ae959b5db4 100644 --- a/filament/src/HwRenderPrimitiveFactory.cpp +++ b/filament/src/HwRenderPrimitiveFactory.cpp @@ -34,8 +34,8 @@ using namespace utils; using namespace backend; size_t HwRenderPrimitiveFactory::Parameters::hash() const noexcept { - return utils::hash::combine(vbh.getId(), - utils::hash::combine(ibh.getId(), + return hash::combine(vbh.getId(), + hash::combine(ibh.getId(), (size_t)type)); } @@ -61,9 +61,9 @@ void HwRenderPrimitiveFactory::terminate(DriverApi&) noexcept { } auto HwRenderPrimitiveFactory::create(DriverApi& driver, - backend::VertexBufferHandle vbh, - backend::IndexBufferHandle ibh, - backend::PrimitiveType type) noexcept -> Handle { + VertexBufferHandle vbh, + IndexBufferHandle ibh, + PrimitiveType const type) noexcept -> Handle { // see if we already have seen this RenderPrimitive Key const key({ vbh, ibh, type }); diff --git a/filament/src/HwVertexBufferInfoFactory.cpp b/filament/src/HwVertexBufferInfoFactory.cpp index 44be4301b3..c5e4f7fc41 100644 --- a/filament/src/HwVertexBufferInfoFactory.cpp +++ b/filament/src/HwVertexBufferInfoFactory.cpp @@ -37,7 +37,7 @@ using namespace backend; size_t HwVertexBufferInfoFactory::Parameters::hash() const noexcept { static_assert((sizeof(*this) % sizeof(uint32_t)) == 0); - return utils::hash::murmur3( + return hash::murmur3( reinterpret_cast(this), sizeof(Parameters) / sizeof(uint32_t), 0); } @@ -61,9 +61,9 @@ void HwVertexBufferInfoFactory::terminate(DriverApi&) noexcept { } auto HwVertexBufferInfoFactory::create(DriverApi& driver, - uint8_t bufferCount, - uint8_t attributeCount, - backend::AttributeArray attributes) noexcept -> Handle { + uint8_t const bufferCount, + uint8_t const attributeCount, + AttributeArray attributes) noexcept -> Handle { Key const key({ bufferCount, attributeCount, {}, attributes }); auto pos = mBimap.find(key); diff --git a/filament/src/IndexBuffer.cpp b/filament/src/IndexBuffer.cpp index 129f7b3356..402983b495 100644 --- a/filament/src/IndexBuffer.cpp +++ b/filament/src/IndexBuffer.cpp @@ -21,7 +21,7 @@ namespace filament { void IndexBuffer::setBuffer(Engine& engine, - IndexBuffer::BufferDescriptor&& buffer, uint32_t byteOffset) { + BufferDescriptor&& buffer, uint32_t const byteOffset) { downcast(this)->setBuffer(downcast(engine), std::move(buffer), byteOffset); } diff --git a/filament/src/IndirectLight.cpp b/filament/src/IndirectLight.cpp index 4683c9117c..6e85220355 100644 --- a/filament/src/IndirectLight.cpp +++ b/filament/src/IndirectLight.cpp @@ -22,7 +22,7 @@ namespace filament { using namespace math; -void IndirectLight::setIntensity(float intensity) noexcept { +void IndirectLight::setIntensity(float const intensity) noexcept { downcast(this)->setIntensity(intensity); } @@ -50,7 +50,7 @@ float3 IndirectLight::getDirectionEstimate() const noexcept { return downcast(this)->getDirectionEstimate(); } -float4 IndirectLight::getColorEstimate(float3 direction) const noexcept { +float4 IndirectLight::getColorEstimate(float3 const direction) const noexcept { return downcast(this)->getColorEstimate(direction); } @@ -58,7 +58,7 @@ float3 IndirectLight::getDirectionEstimate(const float3* sh) noexcept { return FIndirectLight::getDirectionEstimate(sh); } -float4 IndirectLight::getColorEstimate(const float3* sh, float3 direction) noexcept { +float4 IndirectLight::getColorEstimate(const float3* sh, float3 const direction) noexcept { return FIndirectLight::getColorEstimate(sh, direction); } diff --git a/filament/src/InstanceBuffer.cpp b/filament/src/InstanceBuffer.cpp index 3fbb28f7fc..93d151e911 100644 --- a/filament/src/InstanceBuffer.cpp +++ b/filament/src/InstanceBuffer.cpp @@ -23,7 +23,7 @@ size_t InstanceBuffer::getInstanceCount() const noexcept { } void InstanceBuffer::setLocalTransforms( - math::mat4f const* localTransforms, size_t count, size_t offset) { + math::mat4f const* localTransforms, size_t const count, size_t const offset) { downcast(this)->setLocalTransforms(localTransforms, count, offset); } diff --git a/filament/src/Intersections.h b/filament/src/Intersections.h index 32417bf679..908471fb06 100644 --- a/filament/src/Intersections.h +++ b/filament/src/Intersections.h @@ -40,7 +40,7 @@ inline constexpr math::float4 spherePlaneIntersection(math::float4 s, math::floa // sphere radius must be squared // plane equation must be normalized and have the form {0,0,1,w}, sphere radius must be squared // return float4.w <= 0 if no intersection -inline constexpr math::float4 spherePlaneIntersection(math::float4 s, float pw) noexcept { +inline constexpr math::float4 spherePlaneIntersection(math::float4 const s, float pw) noexcept { return spherePlaneIntersection(s, { 0.f, 0.f, 1.f, pw }); } @@ -65,8 +65,8 @@ inline constexpr bool sphereConeIntersection( math::float4 const& sphere, math::float3 const& conePosition, math::float3 const& coneAxis, - float coneSinInverse, - float coneCosSquared) noexcept { + float const coneSinInverse, + float const coneCosSquared) noexcept { if (sphereConeIntersectionFast(sphere, conePosition, coneAxis, coneSinInverse, coneCosSquared)) { math::float3 const d = sphere.xyz - conePosition; diff --git a/filament/src/LightManager.cpp b/filament/src/LightManager.cpp index cc6bd083e5..5644f24bc6 100644 --- a/filament/src/LightManager.cpp +++ b/filament/src/LightManager.cpp @@ -22,7 +22,7 @@ namespace filament { using namespace math; -bool LightManager::hasComponent(Entity e) const noexcept { +bool LightManager::hasComponent(Entity const e) const noexcept { return downcast(this)->hasComponent(e); } @@ -34,128 +34,128 @@ bool LightManager::empty() const noexcept { return downcast(this)->empty(); } -utils::Entity LightManager::getEntity(LightManager::Instance i) const noexcept { +Entity LightManager::getEntity(Instance const i) const noexcept { return downcast(this)->getEntity(i); } -utils::Entity const* LightManager::getEntities() const noexcept { +Entity const* LightManager::getEntities() const noexcept { return downcast(this)->getEntities(); } -LightManager::Instance LightManager::getInstance(Entity e) const noexcept { +LightManager::Instance LightManager::getInstance(Entity const e) const noexcept { return downcast(this)->getInstance(e); } -void LightManager::destroy(Entity e) noexcept { +void LightManager::destroy(Entity const e) noexcept { return downcast(this)->destroy(e); } -void LightManager::setLightChannel(Instance i, unsigned int channel, bool enable) noexcept { +void LightManager::setLightChannel(Instance const i, unsigned int const channel, bool const enable) noexcept { downcast(this)->setLightChannel(i, channel, enable); } -bool LightManager::getLightChannel(LightManager::Instance i, unsigned int channel) const noexcept { +bool LightManager::getLightChannel(Instance const i, unsigned int const channel) const noexcept { return downcast(this)->getLightChannel(i, channel); } -void LightManager::setPosition(Instance i, const float3& position) noexcept { +void LightManager::setPosition(Instance const i, const float3& position) noexcept { downcast(this)->setLocalPosition(i, position); } -const float3& LightManager::getPosition(Instance i) const noexcept { +const float3& LightManager::getPosition(Instance const i) const noexcept { return downcast(this)->getLocalPosition(i); } -void LightManager::setDirection(Instance i, const float3& direction) noexcept { +void LightManager::setDirection(Instance const i, const float3& direction) noexcept { downcast(this)->setLocalDirection(i, direction); } -const float3& LightManager::getDirection(Instance i) const noexcept { +const float3& LightManager::getDirection(Instance const i) const noexcept { return downcast(this)->getLocalDirection(i); } -void LightManager::setColor(Instance i, const LinearColor& color) noexcept { +void LightManager::setColor(Instance const i, const LinearColor& color) noexcept { downcast(this)->setColor(i, color); } -const float3& LightManager::getColor(Instance i) const noexcept { +const float3& LightManager::getColor(Instance const i) const noexcept { return downcast(this)->getColor(i); } -void LightManager::setIntensity(Instance i, float intensity) noexcept { +void LightManager::setIntensity(Instance const i, float const intensity) noexcept { downcast(this)->setIntensity(i, intensity, FLightManager::IntensityUnit::LUMEN_LUX); } -void LightManager::setIntensityCandela(Instance i, float intensity) noexcept { +void LightManager::setIntensityCandela(Instance const i, float const intensity) noexcept { downcast(this)->setIntensity(i, intensity, FLightManager::IntensityUnit::CANDELA); } -float LightManager::getIntensity(Instance i) const noexcept { +float LightManager::getIntensity(Instance const i) const noexcept { return downcast(this)->getIntensity(i); } -void LightManager::setFalloff(Instance i, float radius) noexcept { +void LightManager::setFalloff(Instance const i, float const radius) noexcept { downcast(this)->setFalloff(i, radius); } -float LightManager::getFalloff(Instance i) const noexcept { +float LightManager::getFalloff(Instance const i) const noexcept { return downcast(this)->getFalloff(i); } -void LightManager::setSpotLightCone(Instance i, float inner, float outer) noexcept { +void LightManager::setSpotLightCone(Instance const i, float const inner, float const outer) noexcept { downcast(this)->setSpotLightCone(i, inner, outer); } -float LightManager::getSpotLightOuterCone(Instance i) const noexcept { +float LightManager::getSpotLightOuterCone(Instance const i) const noexcept { return downcast(this)->getSpotParams(i).outerClamped; } -float LightManager::getSpotLightInnerCone(Instance i) const noexcept { +float LightManager::getSpotLightInnerCone(Instance const i) const noexcept { return downcast(this)->getSpotLightInnerCone(i); } -void LightManager::setSunAngularRadius(Instance i, float angularRadius) noexcept { +void LightManager::setSunAngularRadius(Instance const i, float const angularRadius) noexcept { downcast(this)->setSunAngularRadius(i, angularRadius); } -float LightManager::getSunAngularRadius(Instance i) const noexcept { +float LightManager::getSunAngularRadius(Instance const i) const noexcept { float radius = downcast(this)->getSunAngularRadius(i); return radius * f::RAD_TO_DEG; } -void LightManager::setSunHaloSize(Instance i, float haloSize) noexcept { +void LightManager::setSunHaloSize(Instance const i, float const haloSize) noexcept { downcast(this)->setSunHaloSize(i, haloSize); } -float LightManager::getSunHaloSize(Instance i) const noexcept { +float LightManager::getSunHaloSize(Instance const i) const noexcept { return downcast(this)->getSunHaloSize(i); } -void LightManager::setSunHaloFalloff(Instance i, float haloFalloff) noexcept { +void LightManager::setSunHaloFalloff(Instance const i, float const haloFalloff) noexcept { downcast(this)->setSunHaloFalloff(i, haloFalloff); } -float LightManager::getSunHaloFalloff(Instance i) const noexcept { +float LightManager::getSunHaloFalloff(Instance const i) const noexcept { return downcast(this)->getSunHaloFalloff(i); } -LightManager::Type LightManager::getType(LightManager::Instance i) const noexcept { +LightManager::Type LightManager::getType(Instance const i) const noexcept { return downcast(this)->getType(i); } -const LightManager::ShadowOptions& LightManager::getShadowOptions(Instance i) const noexcept { +const LightManager::ShadowOptions& LightManager::getShadowOptions(Instance const i) const noexcept { return downcast(this)->getShadowOptions(i); } -void LightManager::setShadowOptions(Instance i, ShadowOptions const& options) noexcept { +void LightManager::setShadowOptions(Instance const i, ShadowOptions const& options) noexcept { downcast(this)->setShadowOptions(i, options); } -bool LightManager::isShadowCaster(Instance i) const noexcept { +bool LightManager::isShadowCaster(Instance const i) const noexcept { return downcast(this)->isShadowCaster(i); } -void LightManager::setShadowCaster(Instance i, bool castShadows) noexcept { +void LightManager::setShadowCaster(Instance const i, bool const castShadows) noexcept { downcast(this)->setShadowCaster(i, castShadows); } diff --git a/filament/src/Material.cpp b/filament/src/Material.cpp index e48de9c0b5..1663de2794 100644 --- a/filament/src/Material.cpp +++ b/filament/src/Material.cpp @@ -16,8 +16,22 @@ #include "details/Material.h" +#include +#include + +#include +#include + +#include + +#include + +#include + namespace filament { +class MaterialInstance; + using namespace backend; MaterialInstance* Material::createInstance(const char* name) const noexcept { @@ -100,7 +114,7 @@ size_t Material::getParameterCount() const noexcept { return downcast(this)->getParameterCount(); } -size_t Material::getParameters(ParameterInfo* parameters, size_t count) const noexcept { +size_t Material::getParameters(ParameterInfo* parameters, size_t const count) const noexcept { return downcast(this)->getParameters(parameters, count); } @@ -140,9 +154,9 @@ MaterialInstance const* Material::getDefaultInstance() const noexcept { return downcast(this)->getDefaultInstance(); } -void Material::compile(CompilerPriorityQueue priority, UserVariantFilterMask variantFilter, - backend::CallbackHandler* handler, utils::Invocable&& callback) noexcept { - downcast(this)->compile(priority, variantFilter, handler, std::move(callback)); +void Material::compile(CompilerPriorityQueue const priority, UserVariantFilterMask const variants, + CallbackHandler* handler, utils::Invocable&& callback) noexcept { + downcast(this)->compile(priority, variants, handler, std::move(callback)); } UserVariantFilterMask Material::getSupportedVariants() const noexcept { diff --git a/filament/src/MaterialInstance.cpp b/filament/src/MaterialInstance.cpp index dd7e28bc99..e141a62aeb 100644 --- a/filament/src/MaterialInstance.cpp +++ b/filament/src/MaterialInstance.cpp @@ -29,7 +29,7 @@ using namespace backend; // vec4. This must not be inlined (this is the whole point). template UTILS_NOINLINE -void FMaterialInstance::setParameterUntypedImpl(std::string_view name, const void* value) { +void FMaterialInstance::setParameterUntypedImpl(std::string_view const name, const void* value) { ssize_t offset = mMaterial->getUniformInterfaceBlock().getFieldOffset(name, 0); if (UTILS_LIKELY(offset >= 0)) { mUniforms.setUniformUntyped(size_t(offset), value); // handles specialization for mat3f @@ -41,14 +41,14 @@ void FMaterialInstance::setParameterUntypedImpl(std::string_view name, const voi // this converts typed calls into the untyped-sized call. template UTILS_ALWAYS_INLINE -inline void FMaterialInstance::setParameterImpl(std::string_view name, T const& value) { - static_assert(!std::is_same_v); +inline void FMaterialInstance::setParameterImpl(std::string_view const name, T const& value) { + static_assert(!std::is_same_v); setParameterUntypedImpl(name, &value); } // specialization for mat3f template<> -inline void FMaterialInstance::setParameterImpl(std::string_view name, mat3f const& value) { +inline void FMaterialInstance::setParameterImpl(std::string_view const name, mat3f const& value) { ssize_t offset = mMaterial->getUniformInterfaceBlock().getFieldOffset(name, 0); if (UTILS_LIKELY(offset >= 0)) { mUniforms.setUniform(size_t(offset), value); @@ -59,8 +59,8 @@ inline void FMaterialInstance::setParameterImpl(std::string_view name, mat3f con template UTILS_NOINLINE -void FMaterialInstance::setParameterUntypedImpl(std::string_view name, - const void* value, size_t count) { +void FMaterialInstance::setParameterUntypedImpl(std::string_view const name, + const void* value, size_t const count) { ssize_t offset = mMaterial->getUniformInterfaceBlock().getFieldOffset(name, 0); if (UTILS_LIKELY(offset >= 0)) { mUniforms.setUniformArrayUntyped(size_t(offset), value, count); @@ -69,9 +69,9 @@ void FMaterialInstance::setParameterUntypedImpl(std::string_view name, template UTILS_ALWAYS_INLINE -inline void FMaterialInstance::setParameterImpl(std::string_view name, - const T* value, size_t count) { - static_assert(!std::is_same_v); +inline void FMaterialInstance::setParameterImpl(std::string_view const name, + const T* value, size_t const count) { + static_assert(!std::is_same_v); setParameterUntypedImpl(name, value, count); } @@ -83,27 +83,27 @@ void MaterialInstance::setParameter(const char* name, size_t nameLength, T const } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, bool const& v) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool const& v) { // this kills tail-call optimization - MaterialInstance::setParameter(name, nameLength, (uint32_t)v); + setParameter(name, nameLength, (uint32_t)v); } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, bool2 const& v) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool2 const& v) { // this kills tail-call optimization - MaterialInstance::setParameter(name, nameLength, uint2(v)); + setParameter(name, nameLength, uint2(v)); } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, bool3 const& v) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool3 const& v) { // this kills tail-call optimization - MaterialInstance::setParameter(name, nameLength, uint3(v)); + setParameter(name, nameLength, uint3(v)); } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, bool4 const& v) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool4 const& v) { // this kills tail-call optimization - MaterialInstance::setParameter(name, nameLength, uint4(v)); + setParameter(name, nameLength, uint4(v)); } // explicit template instantiation of our supported types @@ -130,41 +130,41 @@ void MaterialInstance::setParameter(const char* name, size_t nameLength, const T } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, const bool* v, size_t c) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, const bool* v, size_t const c) { auto* p = new uint32_t[c]; std::copy_n(v, c, p); - MaterialInstance::setParameter(name, nameLength, p, c); + setParameter(name, nameLength, p, c); delete [] p; } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, const bool2* v, size_t c) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, const bool2* v, size_t const c) { auto* p = new uint2[c]; std::copy_n(v, c, p); - MaterialInstance::setParameter(name, nameLength, p, c); + setParameter(name, nameLength, p, c); delete [] p; } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, const bool3* v, size_t c) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, const bool3* v, size_t const c) { auto* p = new uint3[c]; std::copy_n(v, c, p); - MaterialInstance::setParameter(name, nameLength, p, c); + setParameter(name, nameLength, p, c); delete [] p; } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, const bool4* v, size_t c) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, const bool4* v, size_t const c) { auto* p = new uint4[c]; std::copy_n(v, c, p); - MaterialInstance::setParameter(name, nameLength, p, c); + setParameter(name, nameLength, p, c); delete [] p; } template<> -UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t nameLength, const mat3f* v, size_t c) { +UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, const mat3f* v, size_t const c) { // pretend each mat3 is an array of 3 float3 - MaterialInstance::setParameter(name, nameLength, reinterpret_cast(v), c * 3); + setParameter(name, nameLength, reinterpret_cast(v), c * 3); } template UTILS_PUBLIC void MaterialInstance::setParameter (const char* name, size_t nameLength, const float *v, size_t c); @@ -184,7 +184,7 @@ template UTILS_PUBLIC void MaterialInstance::setParameter (const char* // ------------------------------------------------------------------------------------------------ template -T FMaterialInstance::getParameterImpl(std::string_view name) const { +T FMaterialInstance::getParameterImpl(std::string_view const name) const { ssize_t offset = mMaterial->getUniformInterfaceBlock().getFieldOffset(name, 0); assert_invariant(offset>=0); return downcast(this)->getUniformBuffer().getUniform(offset); @@ -226,17 +226,17 @@ void MaterialInstance::setParameter(const char* name, size_t nameLength, Texture } void MaterialInstance::setParameter( - const char* name, size_t nameLength, RgbType type, float3 color) { + const char* name, size_t nameLength, RgbType const type, float3 const color) { downcast(this)->setParameterImpl({ name, nameLength }, Color::toLinear(type, color)); } void MaterialInstance::setParameter( - const char* name, size_t nameLength, RgbaType type, float4 color) { + const char* name, size_t nameLength, RgbaType const type, float4 const color) { downcast(this)->setParameterImpl({ name, nameLength }, Color::toLinear(type, color)); } void MaterialInstance::setScissor( - uint32_t left, uint32_t bottom, uint32_t width, uint32_t height) noexcept { + uint32_t const left, uint32_t const bottom, uint32_t const width, uint32_t const height) noexcept { downcast(this)->setScissor(left, bottom, width, height); } @@ -244,47 +244,47 @@ void MaterialInstance::unsetScissor() noexcept { downcast(this)->unsetScissor(); } -void MaterialInstance::setPolygonOffset(float scale, float constant) noexcept { +void MaterialInstance::setPolygonOffset(float const scale, float const constant) noexcept { downcast(this)->setPolygonOffset(scale, constant); } -void MaterialInstance::setMaskThreshold(float threshold) noexcept { +void MaterialInstance::setMaskThreshold(float const threshold) noexcept { downcast(this)->setMaskThreshold(threshold); } -void MaterialInstance::setSpecularAntiAliasingVariance(float variance) noexcept { +void MaterialInstance::setSpecularAntiAliasingVariance(float const variance) noexcept { downcast(this)->setSpecularAntiAliasingVariance(variance); } -void MaterialInstance::setSpecularAntiAliasingThreshold(float threshold) noexcept { +void MaterialInstance::setSpecularAntiAliasingThreshold(float const threshold) noexcept { downcast(this)->setSpecularAntiAliasingThreshold(threshold); } -void MaterialInstance::setDoubleSided(bool doubleSided) noexcept { +void MaterialInstance::setDoubleSided(bool const doubleSided) noexcept { downcast(this)->setDoubleSided(doubleSided); } -void MaterialInstance::setTransparencyMode(TransparencyMode mode) noexcept { +void MaterialInstance::setTransparencyMode(TransparencyMode const mode) noexcept { downcast(this)->setTransparencyMode(mode); } -void MaterialInstance::setCullingMode(CullingMode culling) noexcept { +void MaterialInstance::setCullingMode(CullingMode const culling) noexcept { downcast(this)->setCullingMode(culling); } -void MaterialInstance::setColorWrite(bool enable) noexcept { +void MaterialInstance::setColorWrite(bool const enable) noexcept { downcast(this)->setColorWrite(enable); } -void MaterialInstance::setDepthWrite(bool enable) noexcept { +void MaterialInstance::setDepthWrite(bool const enable) noexcept { downcast(this)->setDepthWrite(enable); } -void MaterialInstance::setDepthCulling(bool enable) noexcept { +void MaterialInstance::setDepthCulling(bool const enable) noexcept { downcast(this)->setDepthCulling(enable); } -void MaterialInstance::setDepthFunc(DepthFunc depthFunc) noexcept { +void MaterialInstance::setDepthFunc(DepthFunc const depthFunc) noexcept { downcast(this)->setDepthFunc(depthFunc); } @@ -292,35 +292,35 @@ MaterialInstance::DepthFunc MaterialInstance::getDepthFunc() const noexcept { return downcast(this)->getDepthFunc(); } -void MaterialInstance::setStencilWrite(bool enable) noexcept { +void MaterialInstance::setStencilWrite(bool const enable) noexcept { downcast(this)->setStencilWrite(enable); } -void MaterialInstance::setStencilCompareFunction(StencilCompareFunc func, StencilFace face) noexcept { +void MaterialInstance::setStencilCompareFunction(StencilCompareFunc const func, StencilFace const face) noexcept { downcast(this)->setStencilCompareFunction(func, face); } -void MaterialInstance::setStencilOpStencilFail(StencilOperation op, StencilFace face) noexcept { +void MaterialInstance::setStencilOpStencilFail(StencilOperation const op, StencilFace const face) noexcept { downcast(this)->setStencilOpStencilFail(op, face); } -void MaterialInstance::setStencilOpDepthFail(StencilOperation op, StencilFace face) noexcept { +void MaterialInstance::setStencilOpDepthFail(StencilOperation const op, StencilFace const face) noexcept { downcast(this)->setStencilOpDepthFail(op, face); } -void MaterialInstance::setStencilOpDepthStencilPass(StencilOperation op, StencilFace face) noexcept { +void MaterialInstance::setStencilOpDepthStencilPass(StencilOperation const op, StencilFace const face) noexcept { downcast(this)->setStencilOpDepthStencilPass(op, face); } -void MaterialInstance::setStencilReferenceValue(uint8_t value, StencilFace face) noexcept { +void MaterialInstance::setStencilReferenceValue(uint8_t const value, StencilFace const face) noexcept { downcast(this)->setStencilReferenceValue(value, face); } -void MaterialInstance::setStencilReadMask(uint8_t readMask, StencilFace face) noexcept { +void MaterialInstance::setStencilReadMask(uint8_t const readMask, StencilFace const face) noexcept { downcast(this)->setStencilReadMask(readMask, face); } -void MaterialInstance::setStencilWriteMask(uint8_t writeMask, StencilFace face) noexcept { +void MaterialInstance::setStencilWriteMask(uint8_t const writeMask, StencilFace const face) noexcept { downcast(this)->setStencilWriteMask(writeMask, face); } diff --git a/filament/src/MaterialParser.cpp b/filament/src/MaterialParser.cpp index e2e62be505..5c5873726c 100644 --- a/filament/src/MaterialParser.cpp +++ b/filament/src/MaterialParser.cpp @@ -54,26 +54,26 @@ using namespace filamat; namespace filament { -constexpr std::pair shaderLanguageToTags(ShaderLanguage language) { +constexpr std::pair shaderLanguageToTags(ShaderLanguage const language) { switch (language) { case ShaderLanguage::ESSL3: - return { ChunkType::MaterialGlsl, ChunkType::DictionaryText }; + return { MaterialGlsl, DictionaryText }; case ShaderLanguage::ESSL1: - return { ChunkType::MaterialEssl1, ChunkType::DictionaryText }; + return { MaterialEssl1, DictionaryText }; case ShaderLanguage::MSL: - return { ChunkType::MaterialMetal, ChunkType::DictionaryText }; + return { MaterialMetal, DictionaryText }; case ShaderLanguage::SPIRV: - return { ChunkType::MaterialSpirv, ChunkType::DictionarySpirv }; + return { MaterialSpirv, DictionarySpirv }; case ShaderLanguage::METAL_LIBRARY: - return { ChunkType::MaterialMetalLibrary, ChunkType::DictionaryMetalLibrary }; + return { MaterialMetalLibrary, DictionaryMetalLibrary }; } } // ------------------------------------------------------------------------------------------------ MaterialParser::MaterialParserDetails::MaterialParserDetails( - utils::FixedCapacityVector preferredLanguages, const void* data, - size_t size) + FixedCapacityVector preferredLanguages, const void* data, + size_t const size) : mManagedBuffer(data, size), mChunkContainer(mManagedBuffer.data(), mManagedBuffer.size()), mPreferredLanguages(std::move(preferredLanguages)), @@ -83,7 +83,7 @@ MaterialParser::MaterialParserDetails::MaterialParserDetails( template UTILS_NOINLINE bool MaterialParser::MaterialParserDetails::getFromSimpleChunk( - filamat::ChunkType type, T* value) const noexcept { + ChunkType const type, T* value) const noexcept { ChunkContainer const& chunkContainer = mChunkContainer; ChunkContainer::ChunkDesc chunkDesc; if (chunkContainer.hasChunk(type, &chunkDesc)) { @@ -93,7 +93,7 @@ bool MaterialParser::MaterialParserDetails::getFromSimpleChunk( return false; } -MaterialParser::MaterialParserDetails::ManagedBuffer::ManagedBuffer(const void* start, size_t size) +MaterialParser::MaterialParserDetails::ManagedBuffer::ManagedBuffer(const void* start, size_t const size) : mStart(malloc(size)), mSize(size) { memcpy(mStart, start, size); } @@ -108,12 +108,12 @@ template bool MaterialParser::get(typename T::Container* container) const noexcept { auto [start, end] = mImpl.mChunkContainer.getChunkRange(T::tag); if (start == end) return false; - filaflat::Unflattener unflattener{ start, end }; + Unflattener unflattener{ start, end }; return T::unflatten(unflattener, container); } -MaterialParser::MaterialParser(utils::FixedCapacityVector preferredLanguages, - const void* data, size_t size) +MaterialParser::MaterialParser(FixedCapacityVector preferredLanguages, + const void* data, size_t const size) : mImpl(std::move(preferredLanguages), data, size) { } @@ -160,20 +160,20 @@ MaterialParser::ParseResult MaterialParser::parse() noexcept { return ParseResult::SUCCESS; } -backend::ShaderLanguage MaterialParser::getShaderLanguage() const noexcept { +ShaderLanguage MaterialParser::getShaderLanguage() const noexcept { return mImpl.mChosenLanguage; } // Accessors bool MaterialParser::getMaterialVersion(uint32_t* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialVersion, value); + return mImpl.getFromSimpleChunk(MaterialVersion, value); } bool MaterialParser::getFeatureLevel(uint8_t* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialFeatureLevel, value); + return mImpl.getFromSimpleChunk(MaterialFeatureLevel, value); } -bool MaterialParser::getName(utils::CString* cstring) const noexcept { +bool MaterialParser::getName(CString* cstring) const noexcept { auto [start, end] = mImpl.mChunkContainer.getChunkRange(MaterialName); if (start == end) return false; Unflattener unflattener(start, end); @@ -200,11 +200,11 @@ bool MaterialParser::getSubpasses(SubpassInfo* container) const noexcept { } bool MaterialParser::getShaderModels(uint32_t* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialShaderModels, value); + return mImpl.getFromSimpleChunk(MaterialShaderModels, value); } bool MaterialParser::getMaterialProperties(uint64_t* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialProperties, value); + return mImpl.getFromSimpleChunk(MaterialProperties, value); } bool MaterialParser::getBindingUniformInfo(BindingUniformInfoContainer* container) const noexcept { @@ -223,75 +223,75 @@ bool MaterialParser::getDescriptorSetLayout(DescriptorSetLayoutContainer* contai return get(container); } -bool MaterialParser::getConstants(utils::FixedCapacityVector* container) const noexcept { +bool MaterialParser::getConstants(FixedCapacityVector* container) const noexcept { return get(container); } -bool MaterialParser::getPushConstants(utils::CString* structVarName, - utils::FixedCapacityVector* value) const noexcept { - auto [start, end] = mImpl.mChunkContainer.getChunkRange(filamat::MaterialPushConstants); +bool MaterialParser::getPushConstants(CString* structVarName, + FixedCapacityVector* value) const noexcept { + auto [start, end] = mImpl.mChunkContainer.getChunkRange(MaterialPushConstants); if (start == end) return false; Unflattener unflattener(start, end); return ChunkMaterialPushConstants::unflatten(unflattener, structVarName, value); } bool MaterialParser::getDepthWriteSet(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialDepthWriteSet, value); + return mImpl.getFromSimpleChunk(MaterialDepthWriteSet, value); } bool MaterialParser::getDepthWrite(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialDepthWrite, value); + return mImpl.getFromSimpleChunk(MaterialDepthWrite, value); } bool MaterialParser::getDoubleSidedSet(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialDoubleSidedSet, value); + return mImpl.getFromSimpleChunk(MaterialDoubleSidedSet, value); } bool MaterialParser::getDoubleSided(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialDoubleSided, value); + return mImpl.getFromSimpleChunk(MaterialDoubleSided, value); } bool MaterialParser::getColorWrite(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialColorWrite, value); + return mImpl.getFromSimpleChunk(MaterialColorWrite, value); } bool MaterialParser::getDepthTest(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialDepthTest, value); + return mImpl.getFromSimpleChunk(MaterialDepthTest, value); } bool MaterialParser::getInstanced(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialInstanced, value); + return mImpl.getFromSimpleChunk(MaterialInstanced, value); } bool MaterialParser::getCullingMode(CullingMode* value) const noexcept { static_assert(sizeof(CullingMode) == sizeof(uint8_t), "CullingMode expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialCullingMode, reinterpret_cast(value)); + return mImpl.getFromSimpleChunk(MaterialCullingMode, reinterpret_cast(value)); } bool MaterialParser::getTransparencyMode(TransparencyMode* value) const noexcept { static_assert(sizeof(TransparencyMode) == sizeof(uint8_t), "TransparencyMode expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialTransparencyMode, + return mImpl.getFromSimpleChunk(MaterialTransparencyMode, reinterpret_cast(value)); } bool MaterialParser::getInterpolation(Interpolation* value) const noexcept { static_assert(sizeof(Interpolation) == sizeof(uint8_t), "Interpolation expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialInterpolation, reinterpret_cast(value)); + return mImpl.getFromSimpleChunk(MaterialInterpolation, reinterpret_cast(value)); } bool MaterialParser::getVertexDomain(VertexDomain* value) const noexcept { static_assert(sizeof(VertexDomain) == sizeof(uint8_t), "VertexDomain expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialVertexDomain, reinterpret_cast(value)); + return mImpl.getFromSimpleChunk(MaterialVertexDomain, reinterpret_cast(value)); } bool MaterialParser::getMaterialVariantFilterMask(UserVariantFilterMask* value) const noexcept { static_assert(sizeof(UserVariantFilterMask) == sizeof(uint32_t), "UserVariantFilterMask expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialVariantFilterMask, + return mImpl.getFromSimpleChunk(MaterialVariantFilterMask, reinterpret_cast(value)); } @@ -304,12 +304,12 @@ bool MaterialParser::getMaterialDomain(MaterialDomain* value) const noexcept { bool MaterialParser::getBlendingMode(BlendingMode* value) const noexcept { static_assert(sizeof(BlendingMode) == sizeof(uint8_t), "BlendingMode expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialBlendingMode, reinterpret_cast(value)); + return mImpl.getFromSimpleChunk(MaterialBlendingMode, reinterpret_cast(value)); } bool MaterialParser::getCustomBlendFunction(std::array* value) const noexcept { uint32_t blendFunctions = 0; - bool const result = mImpl.getFromSimpleChunk(ChunkType::MaterialBlendFunction, &blendFunctions); + bool const result = mImpl.getFromSimpleChunk(MaterialBlendFunction, &blendFunctions); (*value)[0] = BlendFunction((blendFunctions >> 24) & 0xFF); (*value)[1] = BlendFunction((blendFunctions >> 16) & 0xFF); (*value)[2] = BlendFunction((blendFunctions >> 8) & 0xFF); @@ -318,52 +318,52 @@ bool MaterialParser::getCustomBlendFunction(std::array* value) } bool MaterialParser::getMaskThreshold(float* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialMaskThreshold, value); + return mImpl.getFromSimpleChunk(MaterialMaskThreshold, value); } bool MaterialParser::getAlphaToCoverageSet(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialAlphaToCoverageSet, value); + return mImpl.getFromSimpleChunk(MaterialAlphaToCoverageSet, value); } bool MaterialParser::getAlphaToCoverage(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialAlphaToCoverage, value); + return mImpl.getFromSimpleChunk(MaterialAlphaToCoverage, value); } bool MaterialParser::hasShadowMultiplier(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialShadowMultiplier, value); + return mImpl.getFromSimpleChunk(MaterialShadowMultiplier, value); } bool MaterialParser::getShading(Shading* value) const noexcept { static_assert(sizeof(Shading) == sizeof(uint8_t), "Shading expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialShading, reinterpret_cast(value)); + return mImpl.getFromSimpleChunk(MaterialShading, reinterpret_cast(value)); } bool MaterialParser::hasCustomDepthShader(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialHasCustomDepthShader, value); + return mImpl.getFromSimpleChunk(MaterialHasCustomDepthShader, value); } bool MaterialParser::hasSpecularAntiAliasing(bool* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialSpecularAntiAliasing, value); + return mImpl.getFromSimpleChunk(MaterialSpecularAntiAliasing, value); } bool MaterialParser::getSpecularAntiAliasingVariance(float* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialSpecularAntiAliasingVariance, value); + return mImpl.getFromSimpleChunk(MaterialSpecularAntiAliasingVariance, value); } bool MaterialParser::getSpecularAntiAliasingThreshold(float* value) const noexcept { - return mImpl.getFromSimpleChunk(ChunkType::MaterialSpecularAntiAliasingThreshold, value); + return mImpl.getFromSimpleChunk(MaterialSpecularAntiAliasingThreshold, value); } -bool MaterialParser::getStereoscopicType(backend::StereoscopicType* value) const noexcept { +bool MaterialParser::getStereoscopicType(StereoscopicType* value) const noexcept { static_assert(sizeof(StereoscopicType) == sizeof(uint8_t), "StereoscopicType expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialStereoscopicType, reinterpret_cast(value)); + return mImpl.getFromSimpleChunk(MaterialStereoscopicType, reinterpret_cast(value)); } bool MaterialParser::getRequiredAttributes(AttributeBitset* value) const noexcept { uint32_t rawAttributes = 0; - if (!mImpl.getFromSimpleChunk(ChunkType::MaterialRequiredAttributes, &rawAttributes)) { + if (!mImpl.getFromSimpleChunk(MaterialRequiredAttributes, &rawAttributes)) { return false; } *value = AttributeBitset(); @@ -374,23 +374,23 @@ bool MaterialParser::getRequiredAttributes(AttributeBitset* value) const noexcep bool MaterialParser::getRefractionMode(RefractionMode* value) const noexcept { static_assert(sizeof(RefractionMode) == sizeof(uint8_t), "Refraction expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialRefraction, (uint8_t*)value); + return mImpl.getFromSimpleChunk(MaterialRefraction, (uint8_t*)value); } bool MaterialParser::getRefractionType(RefractionType* value) const noexcept { static_assert(sizeof(RefractionType) == sizeof(uint8_t), "RefractionType expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialRefractionType, (uint8_t*)value); + return mImpl.getFromSimpleChunk(MaterialRefractionType, (uint8_t*)value); } bool MaterialParser::getReflectionMode(ReflectionMode* value) const noexcept { static_assert(sizeof(ReflectionMode) == sizeof(uint8_t), "ReflectionMode expected size is wrong"); - return mImpl.getFromSimpleChunk(ChunkType::MaterialReflectionMode, (uint8_t*)value); + return mImpl.getFromSimpleChunk(MaterialReflectionMode, (uint8_t*)value); } bool MaterialParser::getShader(ShaderContent& shader, - ShaderModel shaderModel, Variant variant, ShaderStage stage) noexcept { + ShaderModel const shaderModel, Variant const variant, ShaderStage const stage) noexcept { return mImpl.mMaterialChunk.getShader(shader, mImpl.mBlobDictionary, shaderModel, variant, stage); } @@ -399,7 +399,7 @@ bool MaterialParser::getShader(ShaderContent& shader, bool ChunkUniformInterfaceBlock::unflatten(Unflattener& unflattener, - filament::BufferInterfaceBlock* uib) { + BufferInterfaceBlock* uib) { BufferInterfaceBlock::Builder builder = BufferInterfaceBlock::Builder(); @@ -450,7 +450,7 @@ bool ChunkUniformInterfaceBlock::unflatten(Unflattener& unflattener, } bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener, - filament::SamplerInterfaceBlock* sib) { + SamplerInterfaceBlock* sib) { SamplerInterfaceBlock::Builder builder = SamplerInterfaceBlock::Builder(); @@ -467,7 +467,7 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener, } for (uint64_t i = 0; i < numFields; i++) { - static_assert(sizeof(backend::descriptor_binding_t) == sizeof(uint8_t)); + static_assert(sizeof(descriptor_binding_t) == sizeof(uint8_t)); CString fieldName; uint8_t fieldBinding = 0; uint8_t fieldType = 0; @@ -512,7 +512,7 @@ bool ChunkSamplerInterfaceBlock::unflatten(Unflattener& unflattener, } bool ChunkSubpassInterfaceBlock::unflatten(Unflattener& unflattener, - filament::SubpassInfo* subpass) { + SubpassInfo* subpass) { CString block; if (!unflattener.read(&block)) { @@ -566,7 +566,7 @@ bool ChunkSubpassInterfaceBlock::unflatten(Unflattener& unflattener, return true; } -bool ChunkBindingUniformInfo::unflatten(filaflat::Unflattener& unflattener, +bool ChunkBindingUniformInfo::unflatten(Unflattener& unflattener, MaterialParser::BindingUniformInfoContainer* bindingUniformInfo) { uint8_t bindingPointCount; if (!unflattener.read(&bindingPointCount)) { @@ -578,7 +578,7 @@ bool ChunkBindingUniformInfo::unflatten(filaflat::Unflattener& unflattener, if (!unflattener.read(&index)) { return false; } - utils::CString uboName; + CString uboName; if (!unflattener.read(&uboName)) { return false; } @@ -589,7 +589,7 @@ bool ChunkBindingUniformInfo::unflatten(filaflat::Unflattener& unflattener, Program::UniformInfo uniforms = Program::UniformInfo::with_capacity(uniformCount); for (size_t j = 0; j < uniformCount; j++) { - utils::CString name; + CString name; if (!unflattener.read(&name)) { return false; } @@ -612,7 +612,7 @@ bool ChunkBindingUniformInfo::unflatten(filaflat::Unflattener& unflattener, return true; } -bool ChunkAttributeInfo::unflatten(filaflat::Unflattener& unflattener, +bool ChunkAttributeInfo::unflatten(Unflattener& unflattener, MaterialParser::AttributeInfoContainer* attributeInfoContainer) { uint8_t attributeCount; @@ -623,7 +623,7 @@ bool ChunkAttributeInfo::unflatten(filaflat::Unflattener& unflattener, attributeInfoContainer->reserve(attributeCount); for (size_t j = 0; j < attributeCount; j++) { - utils::CString name; + CString name; if (!unflattener.read(&name)) { return false; } @@ -637,7 +637,7 @@ bool ChunkAttributeInfo::unflatten(filaflat::Unflattener& unflattener, return true; } -bool ChunkDescriptorBindingsInfo::unflatten(filaflat::Unflattener& unflattener, +bool ChunkDescriptorBindingsInfo::unflatten(Unflattener& unflattener, MaterialParser::DescriptorBindingsContainer* container) { uint8_t setCount; @@ -661,7 +661,7 @@ bool ChunkDescriptorBindingsInfo::unflatten(filaflat::Unflattener& unflattener, auto& descriptors = (*container)[+set]; descriptors.reserve(descriptorCount); for (size_t i = 0; i < descriptorCount; i++) { - utils::CString name; + CString name; if (!unflattener.read(&name)) { return false; } @@ -675,15 +675,15 @@ bool ChunkDescriptorBindingsInfo::unflatten(filaflat::Unflattener& unflattener, } descriptors.push_back({ std::move(name), - backend::DescriptorType(type), - backend::descriptor_binding_t(binding)}); + DescriptorType(type), + descriptor_binding_t(binding)}); } } return true; } -bool ChunkDescriptorSetLayoutInfo::unflatten(filaflat::Unflattener& unflattener, +bool ChunkDescriptorSetLayoutInfo::unflatten(Unflattener& unflattener, MaterialParser::DescriptorSetLayoutContainer* container) { for (size_t j = 0; j < 2; j++) { uint8_t descriptorCount; @@ -714,10 +714,10 @@ bool ChunkDescriptorSetLayoutInfo::unflatten(filaflat::Unflattener& unflattener, return false; } descriptors.push_back({ - backend::DescriptorType(type), - backend::ShaderStageFlags(stageFlags), - backend::descriptor_binding_t(binding), - backend::DescriptorFlags(flags), + DescriptorType(type), + ShaderStageFlags(stageFlags), + descriptor_binding_t(binding), + DescriptorFlags(flags), count, }); } @@ -725,8 +725,8 @@ bool ChunkDescriptorSetLayoutInfo::unflatten(filaflat::Unflattener& unflattener, return true; } -bool ChunkMaterialConstants::unflatten(filaflat::Unflattener& unflattener, - utils::FixedCapacityVector* materialConstants) { +bool ChunkMaterialConstants::unflatten(Unflattener& unflattener, + FixedCapacityVector* materialConstants) { assert_invariant(materialConstants); // Read number of constants. @@ -751,15 +751,15 @@ bool ChunkMaterialConstants::unflatten(filaflat::Unflattener& unflattener, } (*materialConstants)[i].name = constantName; - (*materialConstants)[i].type = static_cast(constantType); + (*materialConstants)[i].type = static_cast(constantType); } return true; } -bool ChunkMaterialPushConstants::unflatten(filaflat::Unflattener& unflattener, - utils::CString* structVarName, - utils::FixedCapacityVector* materialPushConstants) { +bool ChunkMaterialPushConstants::unflatten(Unflattener& unflattener, + CString* structVarName, + FixedCapacityVector* materialPushConstants) { assert_invariant(materialPushConstants); if (!unflattener.read(structVarName)) { @@ -793,8 +793,8 @@ bool ChunkMaterialPushConstants::unflatten(filaflat::Unflattener& unflattener, } (*materialPushConstants)[i].name = constantName; - (*materialPushConstants)[i].type = static_cast(constantType); - (*materialPushConstants)[i].stage = static_cast(shaderStage); + (*materialPushConstants)[i].type = static_cast(constantType); + (*materialPushConstants)[i].stage = static_cast(shaderStage); } return true; } diff --git a/filament/src/MaterialParser.h b/filament/src/MaterialParser.h index 4883a0dbba..761698d526 100644 --- a/filament/src/MaterialParser.h +++ b/filament/src/MaterialParser.h @@ -130,8 +130,8 @@ public: bool getShader(filaflat::ShaderContent& shader, backend::ShaderModel shaderModel, Variant variant, backend::ShaderStage stage) noexcept; - bool hasShader(backend::ShaderModel model, - Variant variant, backend::ShaderStage stage) const noexcept { + bool hasShader(backend::ShaderModel const model, + Variant const variant, backend::ShaderStage const stage) const noexcept { return getMaterialChunk().hasShader(model, variant, stage); } diff --git a/filament/src/MorphTargetBuffer.cpp b/filament/src/MorphTargetBuffer.cpp index 227755a564..4a4f0de490 100644 --- a/filament/src/MorphTargetBuffer.cpp +++ b/filament/src/MorphTargetBuffer.cpp @@ -20,18 +20,18 @@ namespace filament { -void MorphTargetBuffer::setPositionsAt(Engine& engine, size_t targetIndex, - math::float3 const* positions, size_t count, size_t offset) { +void MorphTargetBuffer::setPositionsAt(Engine& engine, size_t const targetIndex, + math::float3 const* positions, size_t const count, size_t const offset) { downcast(this)->setPositionsAt(downcast(engine), targetIndex, positions, count, offset); } -void MorphTargetBuffer::setPositionsAt(Engine& engine, size_t targetIndex, - math::float4 const* positions, size_t count, size_t offset) { +void MorphTargetBuffer::setPositionsAt(Engine& engine, size_t const targetIndex, + math::float4 const* positions, size_t const count, size_t const offset) { downcast(this)->setPositionsAt(downcast(engine), targetIndex, positions, count, offset); } -void MorphTargetBuffer::setTangentsAt(Engine& engine, size_t targetIndex, - math::short4 const* tangents, size_t count, size_t offset) { +void MorphTargetBuffer::setTangentsAt(Engine& engine, size_t const targetIndex, + math::short4 const* tangents, size_t const count, size_t const offset) { downcast(this)->setTangentsAt(downcast(engine), targetIndex, tangents, count, offset); } diff --git a/filament/src/PIDController.h b/filament/src/PIDController.h index db22bb67cd..791a9cecc4 100644 --- a/filament/src/PIDController.h +++ b/filament/src/PIDController.h @@ -27,43 +27,43 @@ class PIDController { public: PIDController() noexcept = default; - void setStandardGains(float Kp, float Ti, float Td) noexcept { + void setStandardGains(float const Kp, float const Ti, float const Td) noexcept { mKp = Kp; mKi = Kp / Ti; mKd = Kp * Td; } - void setParallelGains(float Kp, float Ki, float Kd) noexcept { + void setParallelGains(float const Kp, float const Ki, float const Kd) noexcept { mKp = Kp; mKi = Ki; mKd = Kd; } // output is kept steady in the dead band - void setOutputDeadBand(float low, float high) noexcept { + void setOutputDeadBand(float const low, float const high) noexcept { mDeadBandLow = low; mDeadBandHigh = high; } // integral bounds to prevent windup - void setIntegralLimits(float low, float high) noexcept { + void setIntegralLimits(float const low, float const high) noexcept { mIntegralLimitLow = low; mIntegralLimitHigh = high; } // output bounds - void setOutputLimits(float low, float high) noexcept { + void setOutputLimits(float const low, float const high) noexcept { mOutputLimitLow = low; mOutputLimitHigh = high; } // disable integral term to prevent windup - void setIntegralInhibitionEnabled(bool enabled) noexcept { + void setIntegralInhibitionEnabled(bool const enabled) noexcept { mIntegralInhibition = enabled ? 0.0f : 1.0f; } // update PID output - float update(float measure, float target, float dt) const noexcept { + float update(float const measure, float const target, float const dt) const noexcept { // compute error const float error = target - measure; diff --git a/filament/src/PostProcessManager.cpp b/filament/src/PostProcessManager.cpp index 1a96335f2a..d9ab8b0c16 100644 --- a/filament/src/PostProcessManager.cpp +++ b/filament/src/PostProcessManager.cpp @@ -27,6 +27,7 @@ #include "details/Engine.h" #include "ds/SsrPassDescriptorSet.h" +#include "ds/TypedUniformBuffer.h" #include "fg/FrameGraph.h" #include "fg/FrameGraphId.h" @@ -52,6 +53,7 @@ #include #include +#include #include #include @@ -98,7 +100,7 @@ using namespace backend; static constexpr uint8_t kMaxBloomLevels = 12u; static_assert(kMaxBloomLevels >= 3, "We require at least 3 bloom levels"); -constexpr static float halton(unsigned int i, unsigned int b) noexcept { +constexpr static float halton(unsigned int i, unsigned int const b) noexcept { // skipping a bunch of entries makes the average of the sequence closer to 0.5 i += 409; float f = 1.0f; @@ -120,7 +122,7 @@ PostProcessManager::PostProcessMaterial::PostProcessMaterial(StaticMaterialInfo } PostProcessManager::PostProcessMaterial::PostProcessMaterial( - PostProcessManager::PostProcessMaterial&& rhs) noexcept + PostProcessMaterial&& rhs) noexcept : mData(nullptr), mSize(0), mConstants(rhs.mConstants) { using namespace std; swap(mData, rhs.mData); // aliased to mMaterial @@ -128,7 +130,7 @@ PostProcessManager::PostProcessMaterial::PostProcessMaterial( } PostProcessManager::PostProcessMaterial& PostProcessManager::PostProcessMaterial::operator=( - PostProcessManager::PostProcessMaterial&& rhs) noexcept { + PostProcessMaterial&& rhs) noexcept { if (this != &rhs) { using namespace std; swap(mData, rhs.mData); // aliased to mMaterial @@ -183,7 +185,7 @@ FMaterialInstance* PostProcessManager::PostProcessMaterial::getMaterialInstance( UTILS_NOINLINE FMaterialInstance* PostProcessManager::PostProcessMaterial::getMaterialInstance(FEngine& engine, - PostProcessMaterial const& material, PostProcessVariant variant) noexcept { + PostProcessMaterial const& material, PostProcessVariant const variant) noexcept { FMaterial const* ma = material.getMaterial(engine, variant); return getMaterialInstance(ma); } @@ -209,8 +211,8 @@ static constexpr auto halton() { std::array h; for (size_t i = 0; i < COUNT; i++) { h[i] = { - filament::halton(i, 2), - filament::halton(i, 3) }; + halton(i, 2), + halton(i, 3) }; } return h; } @@ -227,25 +229,25 @@ PostProcessManager::PostProcessManager(FEngine& engine) noexcept PostProcessManager::~PostProcessManager() noexcept = default; -void PostProcessManager::setFrameUniforms(backend::DriverApi& driver, +void PostProcessManager::setFrameUniforms(DriverApi& driver, TypedUniformBuffer& uniforms) noexcept { mPostProcessDescriptorSet.setFrameUniforms(driver, uniforms); mSsrPassDescriptorSet.setFrameUniforms(uniforms); } -void PostProcessManager::bindPostProcessDescriptorSet(backend::DriverApi& driver) const noexcept { +void PostProcessManager::bindPostProcessDescriptorSet(DriverApi& driver) const noexcept { mPostProcessDescriptorSet.bind(driver); } UTILS_NOINLINE -void PostProcessManager::registerPostProcessMaterial(std::string_view name, +void PostProcessManager::registerPostProcessMaterial(std::string_view const name, StaticMaterialInfo const& info) { mMaterialRegistry.try_emplace(name, info); } UTILS_NOINLINE PostProcessManager::PostProcessMaterial& PostProcessManager::getPostProcessMaterial( - std::string_view name) noexcept { + std::string_view const name) noexcept { auto pos = mMaterialRegistry.find(name); assert_invariant(pos != mMaterialRegistry.end()); return pos.value(); @@ -309,6 +311,7 @@ static const PostProcessManager::StaticMaterialInfo sMaterialList[] = { { "fsr_easu_mobile", MATERIAL(FSR_EASU_MOBILE) }, { "fsr_easu_mobileF", MATERIAL(FSR_EASU_MOBILEF) }, { "fsr_rcas", MATERIAL(FSR_RCAS) }, + { "sgsr1", MATERIAL(SGSR1) }, { "debugShadowCascades", MATERIAL(DEBUGSHADOWCASCADES) }, { "resolveDepth", MATERIAL(RESOLVEDEPTH) }, { "shadowmap", MATERIAL(SHADOWMAP) }, @@ -371,7 +374,7 @@ void PostProcessManager::terminate(DriverApi& driver) noexcept { driver.destroyTexture(mStarburstTexture); auto first = mMaterialRegistry.begin(); - auto last = mMaterialRegistry.end(); + auto const last = mMaterialRegistry.end(); while (first != last) { first.value().terminate(engine); ++first; @@ -381,19 +384,19 @@ void PostProcessManager::terminate(DriverApi& driver) noexcept { mSsrPassDescriptorSet.terminate(driver); } -backend::Handle PostProcessManager::getOneTexture() const { +Handle PostProcessManager::getOneTexture() const { return mEngine.getOneTexture(); } -backend::Handle PostProcessManager::getZeroTexture() const { +Handle PostProcessManager::getZeroTexture() const { return mEngine.getZeroTexture(); } -backend::Handle PostProcessManager::getOneTextureArray() const { +Handle PostProcessManager::getOneTextureArray() const { return mEngine.getOneTextureArray(); } -backend::Handle PostProcessManager::getZeroTextureArray() const { +Handle PostProcessManager::getZeroTextureArray() const { return mEngine.getZeroTextureArray(); } @@ -444,9 +447,9 @@ void PostProcessManager::renderFullScreenQuadWithScissor( } UTILS_NOINLINE -void PostProcessManager::commitAndRenderFullScreenQuad(backend::DriverApi& driver, +void PostProcessManager::commitAndRenderFullScreenQuad(DriverApi& driver, FrameGraphResources::RenderPassInfo const& out, FMaterialInstance const* mi, - PostProcessVariant variant) const noexcept { + PostProcessVariant const variant) const noexcept { mi->commit(driver); mi->use(driver); FMaterial const* const ma = mi->getMaterial(); @@ -465,7 +468,7 @@ void PostProcessManager::commitAndRenderFullScreenQuad(backend::DriverApi& drive // ------------------------------------------------------------------------------------------------ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph& fg, - RenderPassBuilder const& passBuilder, uint8_t structureRenderFlags, + RenderPassBuilder const& passBuilder, uint8_t const structureRenderFlags, uint32_t width, uint32_t height, StructurePassConfig const& config) noexcept { @@ -481,15 +484,15 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph }; // sanitize a bit the user provided scaling factor - width = std::max(32u, (uint32_t)std::ceil(float(width) * scale)); - height = std::max(32u, (uint32_t)std::ceil(float(height) * scale)); + width = std::max(32u, uint32_t(std::ceil(float(width) * scale))); + height = std::max(32u, uint32_t(std::ceil(float(height) * scale))); // We limit the lowest lod size to 32 pixels (which is where the -5 comes from) const size_t levelCount = std::min(8, FTexture::maxLevelCount(width, height) - 5); assert_invariant(levelCount >= 1); // generate depth pass at the requested resolution - auto& structurePass = fg.addPass("Structure Pass", + auto const& structurePass = fg.addPass("Structure Pass", [&](FrameGraph::Builder& builder, auto& data) { bool const isES2 = mEngine.getDriverApi().getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0; data.depth = builder.createTexture("Structure Buffer", { @@ -526,13 +529,13 @@ PostProcessManager::StructurePassOutput PostProcessManager::structure(FrameGraph passBuilder.commandTypeFlags(RenderPass::CommandTypeFlags::SSAO); RenderPass const pass{ passBuilder.build(mEngine, driver) }; - auto out = resources.getRenderPassInfo(); + auto const out = resources.getRenderPassInfo(); driver.beginRenderPass(out.target, out.params); pass.getExecutor().execute(mEngine, driver); driver.endRenderPass(); }); - auto depth = structurePass->depth; + auto const depth = structurePass->depth; /* * create depth mipmap chain @@ -588,7 +591,7 @@ FrameGraphId PostProcessManager::ssr(FrameGraph& fg, RenderPassBuilder const& passBuilder, FrameHistory const& frameHistory, CameraInfo const& cameraInfo, - FrameGraphId structure, + FrameGraphId const structure, ScreenSpaceReflectionsOptions const& options, FrameGraphTexture::Descriptor const& desc) noexcept { @@ -608,12 +611,12 @@ FrameGraphId PostProcessManager::ssr(FrameGraph& fg, return {}; } - FrameGraphId history = fg.import("SSR history", previous.desc, + FrameGraphId const history = fg.import("SSR history", previous.desc, FrameGraphTexture::Usage::SAMPLEABLE, previous.color); mat4 const& historyProjection = previous.projection; auto const& uvFromClipMatrix = mEngine.getUvFromClipMatrix(); - auto& ssrPass = fg.addPass("SSR Pass", + auto const& ssrPass = fg.addPass("SSR Pass", [&](FrameGraph::Builder& builder, auto& data) { // Create our reflection buffer. We need an alpha channel, so we have to use RGBA16F @@ -667,7 +670,7 @@ FrameGraphId PostProcessManager::ssr(FrameGraph& fg, mSsrPassDescriptorSet.bind(driver); - auto out = resources.getRenderPassInfo(); + auto const out = resources.getRenderPassInfo(); // Remove the HAS_SHADOWING RenderFlags, since it's irrelevant when rendering reflections passBuilder.renderFlags(RenderPass::HAS_SHADOWING, 0); @@ -690,7 +693,7 @@ FrameGraphId PostProcessManager::ssr(FrameGraph& fg, FrameGraphId PostProcessManager::screenSpaceAmbientOcclusion(FrameGraph& fg, filament::Viewport const&, const CameraInfo& cameraInfo, - FrameGraphId depth, + FrameGraphId const depth, AmbientOcclusionOptions const& options) noexcept { assert_invariant(depth); @@ -790,7 +793,7 @@ FrameGraphId PostProcessManager::screenSpaceAmbientOcclusion( duplicateDepthOutput = blitDepth(fg, depth); } - auto& SSAOPass = fg.addPass( + auto const& SSAOPass = fg.addPass( "SSAO Pass", [&](FrameGraph::Builder& builder, auto& data) { auto const& desc = builder.getDescriptor(depth); @@ -938,9 +941,9 @@ FrameGraphId PostProcessManager::screenSpaceAmbientOcclusion( } FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph& fg, - FrameGraphId input, + FrameGraphId const input, FrameGraphId depth, - math::int2 axis, float zf, TextureFormat format, + int2 const axis, float const zf, TextureFormat const format, BilateralPassConfig const& config) noexcept { assert_invariant(depth); @@ -951,7 +954,7 @@ FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph FrameGraphId bn; }; - auto& blurPass = fg.addPass("Separable Blur Pass", + auto const& blurPass = fg.addPass("Separable Blur Pass", [&](FrameGraph::Builder& builder, auto& data) { auto const& desc = builder.getDescriptor(input); @@ -999,7 +1002,7 @@ FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph // returns number of samples stored in the array (max 16) constexpr size_t kernelArraySize = 16; // limited by bilateralBlur.mat auto gaussianKernel = - [kernelArraySize](float* outKernel, size_t gaussianWidth, float stdDev) -> uint32_t { + [kernelArraySize](float* outKernel, size_t const gaussianWidth, float const stdDev) -> uint32_t { const size_t gaussianSampleCount = std::min(kernelArraySize, (gaussianWidth + 1u) / 2u); for (size_t i = 0; i < gaussianSampleCount; i++) { float const x = float(i); @@ -1036,8 +1039,8 @@ FrameGraphId PostProcessManager::bilateralBlurPass(FrameGraph } FrameGraphId PostProcessManager::generateGaussianMipmap(FrameGraph& fg, - const FrameGraphId input, size_t levels, - bool reinhard, size_t kernelWidth, float sigma) noexcept { + const FrameGraphId input, size_t const levels, + bool reinhard, size_t const kernelWidth, float const sigma) noexcept { auto const subResourceDesc = fg.getSubResourceDescriptor(input); @@ -1046,7 +1049,7 @@ FrameGraphId PostProcessManager::generateGaussianMipmap(Frame struct MipmapPassData { FixedCapacityVector> out; }; - auto& mipmapPass = fg.addPass("Mipmap Pass", + auto const& mipmapPass = fg.addPass("Mipmap Pass", [&](FrameGraph::Builder& builder, auto& data) { data.out.reserve(levels - 1); for (size_t i = 1; i < levels; i++) { @@ -1061,7 +1064,7 @@ FrameGraphId PostProcessManager::generateGaussianMipmap(Frame // Then generate a blur pass for each level, using the previous level as source auto from = input; for (size_t i = 0; i < levels - 1; i++) { - auto output = mipmapPass->out[i]; + auto const output = mipmapPass->out[i]; from = gaussianBlurPass(fg, from, output, reinhard, kernelWidth, sigma); reinhard = false; // only do the reinhard filtering on the first level } @@ -1071,12 +1074,12 @@ FrameGraphId PostProcessManager::generateGaussianMipmap(Frame } FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& fg, - FrameGraphId input, + FrameGraphId const input, FrameGraphId output, - bool reinhard, size_t kernelWidth, const float sigma) noexcept { + bool const reinhard, size_t kernelWidth, const float sigma) noexcept { auto computeGaussianCoefficients = - [kernelWidth, sigma](float2* kernel, size_t size) -> size_t { + [kernelWidth, sigma](float2* kernel, size_t const size) -> size_t { const float alpha = 1.0f / (2.0f * sigma * sigma); // number of positive-side samples needed, using linear sampling @@ -1130,15 +1133,15 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& // and because it's a separable filter, the effective 2D filter kernel size is 17*17 // The total number of samples needed over the two passes is 18. - auto& blurPass = fg.addPass("Gaussian Blur Pass (separable)", + auto const& blurPass = fg.addPass("Gaussian Blur Pass (separable)", [&](FrameGraph::Builder& builder, auto& data) { - auto inDesc = builder.getDescriptor(input); + auto const inDesc = builder.getDescriptor(input); if (!output) { output = builder.createTexture("Blurred texture", inDesc); } - auto outDesc = builder.getDescriptor(output); + auto const outDesc = builder.getDescriptor(output); auto tempDesc = inDesc; tempDesc.width = outDesc.width; // width of the destination level (b/c we're blurring horizontally) tempDesc.levels = 1; @@ -1172,7 +1175,7 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& using namespace std::literals; std::string_view materialName; const bool is2dArray = inDesc.type == SamplerType::SAMPLER_2D_ARRAY; - switch (backend::getFormatComponentCount(outDesc.format)) { + switch (getFormatComponentCount(outDesc.format)) { case 1: materialName = is2dArray ? "separableGaussianBlur1L"sv : "separableGaussianBlur1"sv; break; case 2: materialName = is2dArray ? @@ -1203,7 +1206,7 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& float2 kernel[64]; size_t const m = computeGaussianCoefficients(kernel, - std::min(sizeof(kernel) / sizeof(*kernel), kernelStorageSize)); + std::min(std::size(kernel), kernelStorageSize)); std::string_view const sourceParameterName = is2dArray ? "sourceArray"sv : "source"sv; // horizontal pass @@ -1215,7 +1218,7 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& mi->setParameter("layer", float(inSubDesc.layer)); mi->setParameter("reinhard", reinhard ? uint32_t(1) : uint32_t(0)); mi->setParameter("axis",float2{ 1.0f / inDesc.width, 0 }); - mi->setParameter("count", (int32_t)m); + mi->setParameter("count", int32_t(m)); mi->setParameter("kernel", kernel, m); // The framegraph only computes discard flags at FrameGraphPass boundaries @@ -1244,8 +1247,8 @@ FrameGraphId PostProcessManager::gaussianBlurPass(FrameGraph& } PostProcessManager::ScreenSpaceRefConfig PostProcessManager::prepareMipmapSSR(FrameGraph& fg, - uint32_t width, uint32_t height, backend::TextureFormat format, - float verticalFieldOfView, float2 scale) noexcept { + uint32_t const width, uint32_t const height, TextureFormat const format, + float const verticalFieldOfView, float2 const scale) noexcept { // The kernel-size was determined empirically so that we don't get too many artifacts // due to the down-sampling with a box filter (which happens implicitly). @@ -1386,7 +1389,7 @@ PostProcessManager::ScreenSpaceRefConfig PostProcessManager::prepareMipmapSSR(Fr FrameGraphId refraction; FrameGraphId reflection; }; - auto& pass = fg.addPass("Prepare MipmapSSR Pass", + auto const& pass = fg.addPass("Prepare MipmapSSR Pass", [&](FrameGraph::Builder& builder, auto& data){ // create the SSR 2D array data.ssr = builder.createTexture("ssr", outDesc); @@ -1411,7 +1414,7 @@ FrameGraphId PostProcessManager::generateMipmapSSR( PostProcessManager& ppm, FrameGraph& fg, FrameGraphId input, FrameGraphId output, - bool needInputDuplication, ScreenSpaceRefConfig const& config) noexcept { + bool const needInputDuplication, ScreenSpaceRefConfig const& config) noexcept { // Descriptor of our actual input image (e.g. reflection buffer or refraction framebuffer) auto const& desc = fg.getDescriptor(input); @@ -1461,10 +1464,10 @@ FrameGraphId PostProcessManager::generateMipmapSSR( } FrameGraphId PostProcessManager::dof(FrameGraph& fg, - FrameGraphId input, - FrameGraphId depth, + FrameGraphId const input, + FrameGraphId const depth, const CameraInfo& cameraInfo, - bool translucent, + bool const translucent, float2 bokehScale, const DepthOfFieldOptions& dofOptions) noexcept { @@ -1557,7 +1560,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, const float focusDistance = cameraInfo.d; auto const& desc = fg.getDescriptor(input); const float Kc = (cameraInfo.A * cameraInfo.f) / (focusDistance - cameraInfo.f); - const float Ks = ((float)desc.height) / FCamera::SENSOR_SIZE; + const float Ks = float(desc.height) / FCamera::SENSOR_SIZE; const float K = dofOptions.cocScale * Ks * Kc; auto const& p = cameraInfo.projection; @@ -1577,7 +1580,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, const uint32_t height = colorDesc.height / dofResolution; // at full resolution, 4 "safe" levels are guaranteed - constexpr const uint32_t maxMipLevels = 4u; + constexpr uint32_t maxMipLevels = 4u; // compute numbers of "safe" levels (should be 4, but can be 3 at half res) const uint8_t mipmapCount = std::min(maxMipLevels, ctz(width | height)); @@ -1597,7 +1600,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, FrameGraphId outCoc; }; - auto& ppDoFDownsample = fg.addPass("DoF Downsample", + auto const& ppDoFDownsample = fg.addPass("DoF Downsample", [&](FrameGraph::Builder& builder, auto& data) { data.color = builder.sample(input); data.depth = builder.sample(depth); @@ -1610,8 +1613,8 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, .format = TextureFormat::R16F, .swizzle = { // the next stage expects min/max CoC in the red/green channel - .r = backend::TextureSwizzle::CHANNEL_0, - .g = backend::TextureSwizzle::CHANNEL_0 }, + .r = TextureSwizzle::CHANNEL_0, + .g = TextureSwizzle::CHANNEL_0 }, }); data.outColor = builder.write(data.outColor, FrameGraphTexture::Usage::COLOR_ATTACHMENT); data.outCoc = builder.write(data.outCoc, FrameGraphTexture::Usage::COLOR_ATTACHMENT); @@ -1656,7 +1659,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, assert_invariant(mipmapCount - 1 <= sizeof(PostProcessDofMipmap::rp) / sizeof(uint32_t)); - auto& ppDoFMipmap = fg.addPass("DoF Mipmap", + auto const& ppDoFMipmap = fg.addPass("DoF Mipmap", [&](FrameGraph::Builder& builder, auto& data) { data.inOutColor = builder.sample(ppDoFDownsample->outColor); data.inOutCoc = builder.sample(ppDoFDownsample->outCoc); @@ -1722,7 +1725,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, // TODO: Should the tile size be in real pixels? i.e. always 16px instead of being dependant on // the DoF effect resolution? // Size of a tile in full-resolution pixels -- must match TILE_SIZE in dofDilate.mat - const size_t tileSize = 16; + constexpr size_t tileSize = 16; // we assume the width/height is already multiple of 16 assert_invariant(!(colorDesc.width & 0xF) && !(colorDesc.height & 0xF)); @@ -1737,7 +1740,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, const bool textureSwizzleSupported = Texture::isTextureSwizzleSupported(mEngine); for (size_t i = 0; i < tileReductionCount; i++) { - auto& ppDoFTiling = fg.addPass("DoF Tiling", + auto const& ppDoFTiling = fg.addPass("DoF Tiling", [&](FrameGraph::Builder& builder, auto& data) { // this must be true by construction @@ -1775,14 +1778,14 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, */ // This is a small helper that does one round of dilate - auto dilate = [&](FrameGraphId input) -> FrameGraphId { + auto dilate = [&](FrameGraphId const input) -> FrameGraphId { struct PostProcessDofDilate { FrameGraphId inTilesCocMinMax; FrameGraphId outTilesCocMinMax; }; - auto& ppDoFDilate = fg.addPass("DoF Dilate", + auto const& ppDoFDilate = fg.addPass("DoF Dilate", [&](FrameGraph::Builder& builder, auto& data) { auto const& inputDesc = fg.getDescriptor(input); data.inTilesCocMinMax = builder.sample(input); @@ -1821,7 +1824,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, FrameGraphId outAlpha; }; - auto& ppDoF = fg.addPass("DoF", + auto const& ppDoF = fg.addPass("DoF", [&](FrameGraph::Builder& builder, auto& data) { data.color = builder.sample(ppDoFMipmap->inOutColor); @@ -1893,7 +1896,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, FrameGraphId outAlpha; }; - auto& ppDoFMedian = fg.addPass("DoF Median", + auto const& ppDoFMedian = fg.addPass("DoF Median", [&](FrameGraph::Builder& builder, auto& data) { data.inColor = builder.sample(ppDoF->outColor); @@ -1945,7 +1948,7 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, FrameGraphId output; }; - auto& ppDoFCombine = fg.addPass("DoF combine", + auto const& ppDoFCombine = fg.addPass("DoF combine", [&](FrameGraph::Builder& builder, auto& data) { data.color = builder.sample(input); data.dof = builder.sample(outColor); @@ -1979,14 +1982,14 @@ FrameGraphId PostProcessManager::dof(FrameGraph& fg, } FrameGraphId PostProcessManager::downscalePass(FrameGraph& fg, - FrameGraphId input, + FrameGraphId const input, FrameGraphTexture::Descriptor const& outDesc, - bool threshold, float highlight, bool fireflies) noexcept { + bool const threshold, float const highlight, bool const fireflies) noexcept { struct DownsampleData { FrameGraphId input; FrameGraphId output; }; - auto& downsamplePass = fg.addPass("Downsample", + auto const& downsamplePass = fg.addPass("Downsample", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("Downsample-output", outDesc); @@ -2014,10 +2017,10 @@ FrameGraphId PostProcessManager::downscalePass(FrameGraph& fg } PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, - FrameGraphId input, TextureFormat outFormat, + FrameGraphId input, TextureFormat const outFormat, BloomOptions& inoutBloomOptions, TemporalAntiAliasingOptions const& taaOptions, - float2 scale) noexcept { + float2 const scale) noexcept { // Figure out a good size for the bloom buffer. We must use a fixed bloom buffer size so // that the size/strength of the bloom doesn't vary much with the resolution, otherwise @@ -2106,7 +2109,7 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, // Bloom on these. // See: https://github.com/google/filament/issues/2338 - auto& bloomDownsamplePass = fg.addPass("Bloom Downsample", + auto const& bloomDownsamplePass = fg.addPass("Bloom Downsample", [&](FrameGraph::Builder& builder, auto& data) { data.out = builder.createTexture("Bloom Out Texture", { .width = width, @@ -2168,9 +2171,9 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, input = bloomDownsamplePass->out; // flare pass - auto flare = flarePass(fg, input, width, height, outFormat, inoutBloomOptions); + auto const flare = flarePass(fg, input, width, height, outFormat, inoutBloomOptions); - auto& bloomUpsamplePass = fg.addPass("Bloom Upsample", + auto const& bloomUpsamplePass = fg.addPass("Bloom Upsample", [&](FrameGraph::Builder& builder, auto& data) { data.out = builder.sample(input); for (size_t i = 0; i < inoutBloomOptions.levels; i++) { @@ -2215,16 +2218,16 @@ PostProcessManager::BloomPassOutput PostProcessManager::bloom(FrameGraph& fg, UTILS_NOINLINE FrameGraphId PostProcessManager::flarePass(FrameGraph& fg, - FrameGraphId input, - uint32_t width, uint32_t height, - backend::TextureFormat outFormat, + FrameGraphId const input, + uint32_t const width, uint32_t const height, + TextureFormat const outFormat, BloomOptions const& bloomOptions) noexcept { struct FlarePassData { FrameGraphId in; FrameGraphId out; }; - auto& flarePass = fg.addPass("Flare", + auto const& flarePass = fg.addPass("Flare", [&](FrameGraph::Builder& builder, auto& data) { data.in = builder.sample(input); data.out = builder.createTexture("Flare Texture", { @@ -2238,7 +2241,7 @@ FrameGraphId PostProcessManager::flarePass(FrameGraph& fg, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); auto in = resources.getTexture(data.in); - auto out = resources.getRenderPassInfo(0); + auto const out = resources.getRenderPassInfo(0); const float aspectRatio = float(width) / float(height); auto const& material = getPostProcessMaterial("flare"); @@ -2255,7 +2258,7 @@ FrameGraphId PostProcessManager::flarePass(FrameGraph& fg, mi->setParameter("threshold", float2{ bloomOptions.ghostThreshold, bloomOptions.haloThreshold }); mi->setParameter("chromaticAberration", bloomOptions.chromaticAberration); - mi->setParameter("ghostCount", (float)bloomOptions.ghostCount); + mi->setParameter("ghostCount", float(bloomOptions.ghostCount)); mi->setParameter("ghostSpacing", bloomOptions.ghostSpacing); mi->setParameter("haloRadius", bloomOptions.haloRadius); mi->setParameter("haloThickness", bloomOptions.haloThickness); @@ -2265,13 +2268,13 @@ FrameGraphId PostProcessManager::flarePass(FrameGraph& fg, constexpr float kernelWidth = 9; constexpr float sigma = (kernelWidth + 1.0f) / 6.0f; - auto flare = gaussianBlurPass(fg, flarePass->out, {}, false, kernelWidth, sigma); + auto const flare = gaussianBlurPass(fg, flarePass->out, {}, false, kernelWidth, sigma); return flare; } UTILS_NOINLINE static float4 getVignetteParameters(VignetteOptions const& options, - uint32_t width, uint32_t height) noexcept { + uint32_t const width, uint32_t const height) noexcept { if (options.enabled) { // Vignette params // From 0.0 to 0.5 the vignette is a rounded rect that turns into an oval @@ -2301,7 +2304,7 @@ static float4 getVignetteParameters(VignetteOptions const& options, void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver, const FColorGrading* colorGrading, ColorGradingConfig const& colorGradingConfig, - VignetteOptions const& vignetteOptions, uint32_t width, uint32_t height) noexcept { + VignetteOptions const& vignetteOptions, uint32_t const width, uint32_t const height) noexcept { float4 const vignetteParameters = getVignetteParameters(vignetteOptions, width, height); @@ -2326,7 +2329,7 @@ void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver, mi->setParameter("vignette", vignetteParameters); mi->setParameter("vignetteColor", vignetteOptions.color); mi->setParameter("dithering", colorGradingConfig.dithering); - mi->setParameter("fxaa", colorGradingConfig.fxaa); + mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance); mi->setParameter("temporalNoise", temporalNoise); mi->commit(driver); @@ -2346,7 +2349,7 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver, auto const& material = getPostProcessMaterial("colorGradingAsSubpass"); FMaterial const* const ma = material.getMaterial(mEngine, variant); // the UBO has been set and committed in colorGradingPrepareSubpass() - FMaterialInstance* mi = PostProcessMaterial::getMaterialInstance(ma); + FMaterialInstance const* mi = PostProcessMaterial::getMaterialInstance(ma); mi->use(driver); auto const pipeline = getPipelineState(ma, variant); driver.nextSubpass(); @@ -2354,7 +2357,7 @@ void PostProcessManager::colorGradingSubpass(DriverApi& driver, driver.draw(pipeline, mFullScreenQuadRph, 0, 3, 1); } -void PostProcessManager::customResolvePrepareSubpass(DriverApi& driver, CustomResolveOp op) noexcept { +void PostProcessManager::customResolvePrepareSubpass(DriverApi& driver, CustomResolveOp const op) noexcept { auto const& material = getPostProcessMaterial("customResolveAsSubpass"); FMaterialInstance* const mi = PostProcessMaterial::getMaterialInstance(mEngine, material); mi->setParameter("direction", op == CustomResolveOp::COMPRESS ? 1.0f : -1.0f), @@ -2368,7 +2371,7 @@ void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept { auto const& material = getPostProcessMaterial("customResolveAsSubpass"); FMaterial const* const ma = material.getMaterial(mEngine); // the UBO has been set and committed in colorGradingPrepareSubpass() - FMaterialInstance* mi = PostProcessMaterial::getMaterialInstance(ma); + FMaterialInstance const* mi = PostProcessMaterial::getMaterialInstance(ma); mi->use(driver); auto const pipeline = getPipelineState(ma); driver.nextSubpass(); @@ -2377,11 +2380,11 @@ void PostProcessManager::customResolveSubpass(DriverApi& driver) noexcept { } FrameGraphId PostProcessManager::customResolveUncompressPass(FrameGraph& fg, - FrameGraphId inout) noexcept { + FrameGraphId const inout) noexcept { struct UncompressData { FrameGraphId inout; }; - auto& detonemapPass = fg.addPass("Uncompress Pass", + auto const& detonemapPass = fg.addPass("Uncompress Pass", [&](FrameGraph::Builder& builder, auto& data) { data.inout = builder.read(inout, FrameGraphTexture::Usage::SUBPASS_INPUT); data.inout = builder.write(data.inout, FrameGraphTexture::Usage::COLOR_ATTACHMENT); @@ -2402,9 +2405,9 @@ FrameGraphId PostProcessManager::customResolveUncompressPass( } FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg, - FrameGraphId input, filament::Viewport const& vp, - FrameGraphId bloom, - FrameGraphId flare, + FrameGraphId const input, filament::Viewport const& vp, + FrameGraphId const bloom, + FrameGraphId const flare, FColorGrading const* colorGrading, ColorGradingConfig const& colorGradingConfig, BloomOptions const& bloomOptions, @@ -2417,7 +2420,7 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg, if (bloomOptions.enabled) { bloomStrength = clamp(bloomOptions.strength, 0.0f, 1.0f); if (bloomOptions.dirt) { - FTexture* fdirt = downcast(bloomOptions.dirt); + FTexture const* fdirt = downcast(bloomOptions.dirt); FrameGraphTexture const frameGraphTexture{ .handle = fdirt->getHwHandleForSampling() }; bloomDirt = fg.import("dirt", { .width = (uint32_t)fdirt->getWidth(0u), @@ -2443,7 +2446,7 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg, FrameGraphId starburst; }; - auto& ppColorGrading = fg.addPass("colorGrading", + auto const& ppColorGrading = fg.addPass("colorGrading", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("colorGrading output", { @@ -2542,13 +2545,13 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg, mi->setParameter("bloom", bloomParameters); mi->setParameter("vignette", vignetteParameters); mi->setParameter("vignetteColor", vignetteOptions.color); - mi->setParameter("fxaa", colorGradingConfig.fxaa); + mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance); mi->setParameter("temporalNoise", temporalNoise); mi->setParameter("viewport", float4{ - (float)vp.left / input.width, - (float)vp.bottom / input.height, - (float)vp.width / input.width, - (float)vp.height / input.height + float(vp.left) / input.width, + float(vp.bottom) / input.height, + float(vp.width) / input.width, + float(vp.height) / input.height }); commitAndRenderFullScreenQuad(driver, out, mi, variant); @@ -2559,15 +2562,15 @@ FrameGraphId PostProcessManager::colorGrading(FrameGraph& fg, } FrameGraphId PostProcessManager::fxaa(FrameGraph& fg, - FrameGraphId input, filament::Viewport const& vp, - TextureFormat outFormat, bool translucent) noexcept { + FrameGraphId const input, filament::Viewport const& vp, + TextureFormat const outFormat, bool const preserveAlphaChannel) noexcept { struct PostProcessFXAA { FrameGraphId input; FrameGraphId output; }; - auto& ppFXAA = fg.addPass("fxaa", + auto const& ppFXAA = fg.addPass("fxaa", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("fxaa output", { @@ -2585,7 +2588,7 @@ FrameGraphId PostProcessManager::fxaa(FrameGraph& fg, auto const& material = getPostProcessMaterial("fxaa"); - PostProcessVariant const variant = translucent ? + PostProcessVariant const variant = preserveAlphaChannel ? PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; FMaterialInstance* const mi = @@ -2596,10 +2599,10 @@ FrameGraphId PostProcessManager::fxaa(FrameGraph& fg, .filterMin = SamplerMinFilter::LINEAR }); mi->setParameter("viewport", float4{ - (float)vp.left / inDesc.width, - (float)vp.bottom / inDesc.height, - (float)vp.width / inDesc.width, - (float)vp.height / inDesc.height + float(vp.left) / inDesc.width, + float(vp.bottom) / inDesc.height, + float(vp.width) / inDesc.width, + float(vp.height) / inDesc.height }); mi->setParameter("texelSize", 1.0f / float2{ inDesc.width, inDesc.height }); @@ -2622,7 +2625,7 @@ void PostProcessManager::TaaJitterCamera( current.projection = inoutCameraInfo->projection * inoutCameraInfo->getUserViewMatrix(); current.frameId = previous.frameId + 1; - auto jitterPosition = [pattern = taaOptions.jitterPattern](size_t frameIndex) -> float2 { + auto jitterPosition = [pattern = taaOptions.jitterPattern](size_t const frameIndex) -> float2 { using JitterPattern = TemporalAntiAliasingOptions::JitterPattern; switch (pattern) { case JitterPattern::RGSS_X4: @@ -2669,10 +2672,10 @@ void PostProcessManager::configureTemporalAntiAliasingMaterial( bool dirty = false; auto setConstantParameter = - [&dirty](FMaterial* const ma, std::string_view name, auto value) noexcept { - auto id = ma->getSpecializationConstantId(name); + [&dirty](FMaterial* const material, std::string_view const name, auto value) noexcept { + auto id = material->getSpecializationConstantId(name); if (id.has_value()) { - if (ma->setConstant(id.value(), value)) { + if (material->setConstant(id.value(), value)) { dirty = true; } } @@ -2684,8 +2687,8 @@ void PostProcessManager::configureTemporalAntiAliasingMaterial( setConstantParameter(ma, "filterInput", taaOptions.filterInput); setConstantParameter(ma, "useYCoCg", taaOptions.useYCoCg); setConstantParameter(ma, "preventFlickering", taaOptions.preventFlickering); - setConstantParameter(ma, "boxType", (int32_t)taaOptions.boxType); - setConstantParameter(ma, "boxClipping", (int32_t)taaOptions.boxClipping); + setConstantParameter(ma, "boxType", int32_t(taaOptions.boxType)); + setConstantParameter(ma, "boxClipping", int32_t(taaOptions.boxClipping)); setConstantParameter(ma, "varianceGamma", taaOptions.varianceGamma); if (dirty) { ma->invalidate(); @@ -2696,7 +2699,7 @@ void PostProcessManager::configureTemporalAntiAliasingMaterial( FrameGraphId PostProcessManager::taa(FrameGraph& fg, FrameGraphId input, - FrameGraphId depth, + FrameGraphId const depth, FrameHistory& frameHistory, FrameHistoryEntry::TemporalAA FrameHistoryEntry::*pTaa, TemporalAntiAliasingOptions const& taaOptions, @@ -2723,7 +2726,7 @@ FrameGraphId PostProcessManager::taa(FrameGraph& fg, FrameGraphId output; FrameGraphId tonemappedOutput; }; - auto& taaPass = fg.addPass("TAA", + auto const& taaPass = fg.addPass("TAA", [&](FrameGraph::Builder& builder, auto& data) { auto desc = fg.getDescriptor(input); if (taaOptions.upscaling) { @@ -2773,7 +2776,7 @@ FrameGraphId PostProcessManager::taa(FrameGraph& fg, }; UTILS_UNUSED - auto const lanczos = [](float x, float a) -> float { + auto const lanczos = [](float const x, float const a) -> float { if (x <= std::numeric_limits::epsilon()) { return 1.0f; } @@ -2846,7 +2849,7 @@ FrameGraphId PostProcessManager::taa(FrameGraph& fg, }); input = colorGradingConfig.asSubpass ? taaPass->tonemappedOutput : taaPass->output; - auto history = input; + auto const history = input; // optional sharpen pass from FSR1 if (taaOptions.sharpness > 0.0f) { @@ -2873,17 +2876,17 @@ FrameGraphId PostProcessManager::taa(FrameGraph& fg, FrameGraphId PostProcessManager::rcas( FrameGraph& fg, - float sharpness, - FrameGraphId input, + float const sharpness, + FrameGraphId const input, FrameGraphTexture::Descriptor const& outDesc, - bool translucent) { + bool const translucent) { struct QuadBlitData { FrameGraphId input; FrameGraphId output; }; - auto& ppFsrRcas = fg.addPass("FidelityFX FSR1 Rcas", + auto const& ppFsrRcas = fg.addPass("FidelityFX FSR1 Rcas", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("FFX FSR1 Rcas output", outDesc); @@ -2893,14 +2896,14 @@ FrameGraphId PostProcessManager::rcas( auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); - auto input = resources.getTexture(data.input); - auto out = resources.getRenderPassInfo(); + auto const input = resources.getTexture(data.input); + auto const out = resources.getRenderPassInfo(); auto const& outputDesc = resources.getDescriptor(data.input); PostProcessVariant const variant = translucent ? PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; - auto& material = getPostProcessMaterial("fsr_rcas"); + auto const& material = getPostProcessMaterial("fsr_rcas"); FMaterialInstance* const mi = PostProcessMaterial::getMaterialInstance(mEngine, material, variant); @@ -2918,20 +2921,171 @@ FrameGraphId PostProcessManager::rcas( } FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool translucent, - DynamicResolutionOptions dsrOptions, FrameGraphId input, - filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, - backend::SamplerMagFilter filter) noexcept { - + bool sourceHasLuminance, DynamicResolutionOptions dsrOptions, + FrameGraphId const input, filament::Viewport const& vp, + FrameGraphTexture::Descriptor const& outDesc, SamplerMagFilter filter) noexcept { // The code below cannot handle sub-resources assert_invariant(fg.getSubResourceDescriptor(input).layer == 0); assert_invariant(fg.getSubResourceDescriptor(input).level == 0); - const bool lowQualityFallback = translucent && dsrOptions.quality != QualityLevel::LOW; + const bool lowQualityFallback = translucent; if (lowQualityFallback) { - // FidelityFX-FSR doesn't support the alpha channel currently + // FidelityFX-FSR nor SGSR support the source alpha channel currently dsrOptions.quality = QualityLevel::LOW; } + if (dsrOptions.quality == QualityLevel::LOW) { + return upscaleBilinear(fg, translucent, dsrOptions, input, vp, outDesc, filter); + } + if (dsrOptions.quality == QualityLevel::MEDIUM) { + return upscaleSGSR1(fg, sourceHasLuminance, dsrOptions, input, vp, outDesc); + } + return upscaleFSR1(fg, dsrOptions, input, vp, outDesc); +} + +FrameGraphId PostProcessManager::upscaleBilinear(FrameGraph& fg, bool translucent, + DynamicResolutionOptions dsrOptions, FrameGraphId const input, + filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, + SamplerMagFilter filter) noexcept { + + struct QuadBlitData { + FrameGraphId input; + FrameGraphId output; + }; + + auto const& ppQuadBlit = fg.addPass(dsrOptions.enabled ? "upscaling" : "compositing", + [&](FrameGraph::Builder& builder, auto& data) { + data.input = builder.sample(input); + data.output = builder.createTexture("upscaled output", outDesc); + data.output = builder.write(data.output, FrameGraphTexture::Usage::COLOR_ATTACHMENT); + builder.declareRenderPass(builder.getName(data.output), { + .attachments = { .color = { data.output } }, + .clearFlags = TargetBufferFlags::DEPTH }); + }, + [this, vp, translucent, filter](FrameGraphResources const& resources, + auto const& data, DriverApi& driver) { + bindPostProcessDescriptorSet(driver); + + // helper to enable blending + auto enableTranslucentBlending = [](PipelineState& pipeline) { + pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE; + pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE; + pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA; + pipeline.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA; + }; + + auto color = resources.getTexture(data.input); + auto const& inputDesc = resources.getDescriptor(data.input); + + // -------------------------------------------------------------------------------- + // set uniforms + + auto& material = getPostProcessMaterial("blitLow"); + FMaterialInstance* const mi = + PostProcessMaterial::getMaterialInstance(mEngine, material); + mi->setParameter("color", color, { + .filterMag = filter + }); + + mi->setParameter("levelOfDetail", 0.0f); + + mi->setParameter("viewport", float4{ + float(vp.left) / inputDesc.width, + float(vp.bottom) / inputDesc.height, + float(vp.width) / inputDesc.width, + float(vp.height) / inputDesc.height + }); + mi->commit(driver); + mi->use(driver); + + auto out = resources.getRenderPassInfo(); + + auto pipeline = getPipelineState(material.getMaterial(mEngine)); + if (translucent) { + enableTranslucentBlending(pipeline); + } + renderFullScreenQuad(out, pipeline, driver); + }); + + auto output = ppQuadBlit->output; + + // if we had to take the low quality fallback, we still do the "sharpen pass" + if (dsrOptions.sharpness > 0.0f) { + output = rcas(fg, dsrOptions.sharpness, output, outDesc, translucent); + } + + // we rely on automatic culling of unused render passes + return output; +} + +FrameGraphId PostProcessManager::upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance, + DynamicResolutionOptions dsrOptions, FrameGraphId const input, + filament::Viewport const&, FrameGraphTexture::Descriptor const& outDesc) noexcept { + + struct QuadBlitData { + FrameGraphId input; + FrameGraphId output; + }; + + auto const& ppQuadBlit = fg.addPass(dsrOptions.enabled ? "upscaling" : "compositing", + [&](FrameGraph::Builder& builder, auto& data) { + data.input = builder.sample(input); + data.output = builder.createTexture("upscaled output", outDesc); + data.output = builder.write(data.output, FrameGraphTexture::Usage::COLOR_ATTACHMENT); + builder.declareRenderPass(builder.getName(data.output), { + .attachments = { .color = { data.output } }, + .clearFlags = TargetBufferFlags::DEPTH }); + }, + [this, sourceHasLuminance](FrameGraphResources const& resources, + auto const& data, DriverApi& driver) { + bindPostProcessDescriptorSet(driver); + + auto color = resources.getTexture(data.input); + auto const& inputDesc = resources.getDescriptor(data.input); + + // -------------------------------------------------------------------------------- + // set uniforms + + auto const& material = getPostProcessMaterial("sgsr1"); + + PostProcessVariant const variant = sourceHasLuminance ? + PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE; + + FMaterialInstance* const mi = + PostProcessMaterial::getMaterialInstance(mEngine, material, variant); + + mi->setParameter("color", color, { + // The SGSR documentation doesn't clarify if LINEAR or NEAREST should be used. The + // sample code uses NEAREST, but that doesn't seem right, since it would mean the + // LERP mode would not be a LERP, and the non-edges would be sampled as NEAREST. + .filterMag = SamplerMagFilter::LINEAR + }); + + mi->setParameter("viewport", float4{ + 1.0f / inputDesc.width, + 1.0f / inputDesc.height, + float(inputDesc.width), + float(inputDesc.height), + }); + + mi->commit(driver); + mi->use(driver); + + auto out = resources.getRenderPassInfo(); + commitAndRenderFullScreenQuad(driver, out, mi, variant); + + }); + + auto output = ppQuadBlit->output; + + // we rely on automatic culling of unused render passes + return output; +} + +FrameGraphId PostProcessManager::upscaleFSR1(FrameGraph& fg, + DynamicResolutionOptions dsrOptions, FrameGraphId const input, + filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept { + const bool twoPassesEASU = mWorkaroundSplitEasu && (dsrOptions.quality == QualityLevel::MEDIUM || dsrOptions.quality == QualityLevel::HIGH); @@ -2942,7 +3096,7 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool FrameGraphId depth; }; - auto& ppQuadBlit = fg.addPass(dsrOptions.enabled ? "upscaling" : "compositing", + auto const& ppQuadBlit = fg.addPass(dsrOptions.enabled ? "upscaling" : "compositing", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("upscaled output", outDesc); @@ -2962,7 +3116,7 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool .attachments = { .color = { data.output }, .depth = { data.depth }}, .clearFlags = TargetBufferFlags::DEPTH }); }, - [this, twoPassesEASU, dsrOptions, vp, translucent, filter](FrameGraphResources const& resources, + [this, twoPassesEASU, dsrOptions, vp](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); @@ -2987,14 +3141,6 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool float2{ inputDesc.width, inputDesc.height }); }; - // helper to enable blending - auto enableTranslucentBlending = [](PipelineState& pipeline) { - pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE; - pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE; - pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA; - pipeline.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA; - }; - auto color = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); auto const& outputDesc = resources.getDescriptor(data.output); @@ -3021,35 +3167,27 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool } { // just a scope to not leak local variables - const std::string_view blitterNames[4] = { - "blitLow", "fsr_easu_mobile", "fsr_easu_mobile", "fsr_easu" }; - unsigned const index = std::min(3u, (unsigned)dsrOptions.quality); + const std::string_view blitterNames[2] = { "fsr_easu_mobile", "fsr_easu" }; + unsigned const index = std::min(1u, unsigned(dsrOptions.quality) - 2); easuMaterial = &getPostProcessMaterial(blitterNames[index]); FMaterialInstance* const mi = PostProcessMaterial::getMaterialInstance(mEngine, *easuMaterial); - if (dsrOptions.quality != QualityLevel::LOW) { - setEasuUniforms(mi, inputDesc, outputDesc); - } + + setEasuUniforms(mi, inputDesc, outputDesc); + mi->setParameter("color", color, { - .filterMag = (dsrOptions.quality == QualityLevel::LOW) ? - filter : SamplerMagFilter::LINEAR + .filterMag = SamplerMagFilter::LINEAR }); - if (blitterNames[index] != "blitLow") { - mi->setParameter("resolution", - float4{outputDesc.width, outputDesc.height, 1.0f / outputDesc.width, - 1.0f / outputDesc.height}); - } - - if (blitterNames[index] == "blitLow") { - mi->setParameter("levelOfDetail", 0.0f); - } + mi->setParameter("resolution", + float4{outputDesc.width, outputDesc.height, 1.0f / outputDesc.width, + 1.0f / outputDesc.height}); mi->setParameter("viewport", float4{ - (float)vp.left / inputDesc.width, - (float)vp.bottom / inputDesc.height, - (float)vp.width / inputDesc.width, - (float)vp.height / inputDesc.height + float(vp.left) / inputDesc.width, + float(vp.bottom) / inputDesc.height, + float(vp.width) / inputDesc.width, + float(vp.height) / inputDesc.height }); mi->commit(driver); mi->use(driver); @@ -3063,38 +3201,28 @@ FrameGraphId PostProcessManager::upscale(FrameGraph& fg, bool if (UTILS_UNLIKELY(twoPassesEASU)) { auto pipeline0 = getPipelineState(splitEasuMaterial->getMaterial(mEngine)); auto pipeline1 = getPipelineState(easuMaterial->getMaterial(mEngine)); - pipeline1.rasterState.depthFunc = backend::SamplerCompareFunc::NE; - if (translucent) { - enableTranslucentBlending(pipeline0); - enableTranslucentBlending(pipeline1); - } + pipeline1.rasterState.depthFunc = SamplerCompareFunc::NE; driver.beginRenderPass(out.target, out.params); driver.draw(pipeline0, mFullScreenQuadRph, 0, 3, 1); driver.draw(pipeline1, mFullScreenQuadRph, 0, 3, 1); driver.endRenderPass(); } else { auto pipeline = getPipelineState(easuMaterial->getMaterial(mEngine)); - if (translucent) { - enableTranslucentBlending(pipeline); - } renderFullScreenQuad(out, pipeline, driver); } }); auto output = ppQuadBlit->output; - - // if we had to take the low quality fallback, we still do the "sharpen pass" - if (dsrOptions.sharpness > 0.0f && - (dsrOptions.quality != QualityLevel::LOW || lowQualityFallback)) { - output = rcas(fg, dsrOptions.sharpness, output, outDesc, translucent); + if (dsrOptions.sharpness > 0.0f) { + output = rcas(fg, dsrOptions.sharpness, output, outDesc, false); } // we rely on automatic culling of unused render passes return output; } -FrameGraphId PostProcessManager::blit(FrameGraph& fg, bool translucent, - FrameGraphId input, +FrameGraphId PostProcessManager::blit(FrameGraph& fg, bool const translucent, + FrameGraphId const input, filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, SamplerMagFilter filterMag, SamplerMinFilter filterMin) noexcept { @@ -3107,7 +3235,7 @@ FrameGraphId PostProcessManager::blit(FrameGraph& fg, bool tr FrameGraphId output; }; - auto& ppQuadBlit = fg.addPass("blitting", + auto const& ppQuadBlit = fg.addPass("blitting", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("blit output", outDesc); @@ -3162,7 +3290,7 @@ FrameGraphId PostProcessManager::blit(FrameGraph& fg, bool tr } FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, - FrameGraphId input) noexcept { + FrameGraphId const input) noexcept { auto const& inputDesc = fg.getDescriptor(input); filament::Viewport const vp = {0, 0, inputDesc.width, inputDesc.height}; bool const hardwareBlitSupported = @@ -3174,7 +3302,7 @@ FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, }; if (hardwareBlitSupported) { - auto& depthPass = fg.addPass( + auto const& depthPass = fg.addPass( "Depth Blit", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.read(input, FrameGraphTexture::Usage::BLIT_SRC); @@ -3206,7 +3334,7 @@ FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, } // Otherwise, we would do a shader-based blit. - auto& ppQuadBlit = fg.addPass( + auto const& ppQuadBlit = fg.addPass( "Depth Blit (Shader)", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); @@ -3222,7 +3350,7 @@ FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, bindPostProcessDescriptorSet(driver); auto depth = resources.getTexture(data.input); auto const& inputDesc = resources.getDescriptor(data.input); - auto out = resources.getRenderPassInfo(); + auto const out = resources.getRenderPassInfo(); // -------------------------------------------------------------------------------- // set uniforms @@ -3245,7 +3373,7 @@ FrameGraphId PostProcessManager::blitDepth(FrameGraph& fg, } FrameGraphId PostProcessManager::resolve(FrameGraph& fg, - const char* outputBufferName, FrameGraphId input, + const char* outputBufferName, FrameGraphId const input, FrameGraphTexture::Descriptor outDesc) noexcept { // Don't do anything if we're not a MSAA buffer @@ -3272,7 +3400,7 @@ FrameGraphId PostProcessManager::resolve(FrameGraph& fg, FrameGraphId output; }; - auto& ppResolve = fg.addPass("resolve", + auto const& ppResolve = fg.addPass("resolve", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.read(input, FrameGraphTexture::Usage::BLIT_SRC); data.output = builder.createTexture(outputBufferName, outDesc); @@ -3299,7 +3427,7 @@ FrameGraphId PostProcessManager::resolve(FrameGraph& fg, } FrameGraphId PostProcessManager::resolveDepth(FrameGraph& fg, - const char* outputBufferName, FrameGraphId input, + const char* outputBufferName, FrameGraphId const input, FrameGraphTexture::Descriptor outDesc) noexcept { // Don't do anything if we're not a MSAA buffer @@ -3323,7 +3451,7 @@ FrameGraphId PostProcessManager::resolveDepth(FrameGraph& fg, FrameGraphId output; }; - auto& ppResolve = fg.addPass("resolveDepth", + auto const& ppResolve = fg.addPass("resolveDepth", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture(outputBufferName, outDesc); @@ -3346,14 +3474,14 @@ FrameGraphId PostProcessManager::resolveDepth(FrameGraph& fg, } FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg, - FrameGraphId input, uint8_t layer, size_t level, - math::float4 clearColor) noexcept { + FrameGraphId const input, uint8_t layer, size_t const level, + float4 clearColor) noexcept { struct VsmMipData { FrameGraphId in; }; - auto& depthMipmapPass = fg.addPass("VSM Generate Mipmap Pass", + auto const& depthMipmapPass = fg.addPass("VSM Generate Mipmap Pass", [&](FrameGraph::Builder& builder, auto& data) { const char* name = builder.getName(input); data.in = builder.sample(input); @@ -3407,8 +3535,8 @@ FrameGraphId PostProcessManager::vsmMipmapPass(FrameGraph& fg } FrameGraphId PostProcessManager::debugShadowCascades(FrameGraph& fg, - FrameGraphId input, - FrameGraphId depth) noexcept { + FrameGraphId const input, + FrameGraphId const depth) noexcept { // new pass for showing the cascades struct DebugShadowCascadesData { @@ -3416,20 +3544,20 @@ FrameGraphId PostProcessManager::debugShadowCascades(FrameGra FrameGraphId depth; FrameGraphId output; }; - auto& debugShadowCascadePass = fg.addPass("ShadowCascades", + auto const& debugShadowCascadePass = fg.addPass("ShadowCascades", [&](FrameGraph::Builder& builder, auto& data) { - auto desc = builder.getDescriptor(input); + auto const desc = builder.getDescriptor(input); data.color = builder.sample(input); data.depth = builder.sample(depth); data.output = builder.createTexture("Shadow Cascade Debug", desc); builder.declareRenderPass(data.output); }, - [=](FrameGraphResources const& resources, auto const& data, backend::DriverApi& driver) { + [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); auto color = resources.getTexture(data.color); auto depth = resources.getTexture(data.depth); - auto out = resources.getRenderPassInfo(); - auto& material = getPostProcessMaterial("debugShadowCascades"); + auto const out = resources.getRenderPassInfo(); + auto const& material = getPostProcessMaterial("debugShadowCascades"); FMaterialInstance* const mi = PostProcessMaterial::getMaterialInstance(mEngine, material); mi->setParameter("color", color, {}); // nearest @@ -3441,7 +3569,7 @@ FrameGraphId PostProcessManager::debugShadowCascades(FrameGra } FrameGraphId PostProcessManager::debugCombineArrayTexture(FrameGraph& fg, - bool translucent, FrameGraphId input, + bool const translucent, FrameGraphId const input, filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, SamplerMagFilter filterMag, SamplerMinFilter filterMin) noexcept { @@ -3459,7 +3587,7 @@ FrameGraphId PostProcessManager::debugCombineArrayTexture(Fra FrameGraphId output; }; - auto& ppQuadBlit = fg.addPass("combining array tex", + auto const& ppQuadBlit = fg.addPass("combining array tex", [&](FrameGraph::Builder& builder, auto& data) { data.input = builder.sample(input); data.output = builder.createTexture("upscaled output", outDesc); @@ -3511,8 +3639,8 @@ FrameGraphId PostProcessManager::debugCombineArrayTexture(Fra mi->commit(driver); renderFullScreenQuad(out, pipeline, driver); // From the second draw, don't clear the targetbuffer. - out.params.flags.clear = filament::backend::TargetBufferFlags::NONE; - out.params.flags.discardStart = filament::backend::TargetBufferFlags::NONE; + out.params.flags.clear = TargetBufferFlags::NONE; + out.params.flags.discardStart = TargetBufferFlags::NONE; out.params.viewport.left += out.params.viewport.width; } }); @@ -3523,8 +3651,8 @@ FrameGraphId PostProcessManager::debugCombineArrayTexture(Fra FrameGraphId PostProcessManager::debugDisplayShadowTexture( FrameGraph& fg, FrameGraphId input, - FrameGraphId shadowmap, float scale, - uint8_t layer, uint8_t level, uint8_t channel, float power) noexcept { + FrameGraphId const shadowmap, float const scale, + uint8_t const layer, uint8_t const level, uint8_t const channel, float const power) noexcept { if (shadowmap) { struct ShadowMapData { FrameGraphId color; @@ -3536,7 +3664,7 @@ FrameGraphId PostProcessManager::debugDisplayShadowTexture( float const screenScale = float(fg.getDescriptor(shadowmap).height) / float(desc.height); float2 const s = { screenScale * scale * ratio, screenScale * scale }; - auto& shadomapDebugPass = fg.addPass("shadowmap debug pass", + auto const& shadomapDebugPass = fg.addPass("shadowmap debug pass", [&](FrameGraph::Builder& builder, auto& data) { data.color = builder.read(input, FrameGraphTexture::Usage::COLOR_ATTACHMENT); @@ -3549,7 +3677,7 @@ FrameGraphId PostProcessManager::debugDisplayShadowTexture( }, [=](FrameGraphResources const& resources, auto const& data, DriverApi& driver) { bindPostProcessDescriptorSet(driver); - auto out = resources.getRenderPassInfo(); + auto const out = resources.getRenderPassInfo(); auto in = resources.getTexture(data.depth); auto const& material = getPostProcessMaterial("shadowmap"); FMaterialInstance* const mi = diff --git a/filament/src/PostProcessManager.h b/filament/src/PostProcessManager.h index 7ed4395894..677cec30cb 100644 --- a/filament/src/PostProcessManager.h +++ b/filament/src/PostProcessManager.h @@ -89,7 +89,7 @@ public: bool asSubpass{}; bool customResolve{}; bool translucent{}; - bool fxaa{}; + bool outputLuminance{}; // Whether to output luminance in the alpha channel. Ignored by the TRANSLUCENT variant. bool dithering{}; backend::TextureFormat ldrFormat{}; }; @@ -130,8 +130,8 @@ public: // SSAO FrameGraphId screenSpaceAmbientOcclusion(FrameGraph& fg, - filament::Viewport const& svp, const CameraInfo& cameraInfo, - FrameGraphId structure, + Viewport const& svp, const CameraInfo& cameraInfo, + FrameGraphId depth, AmbientOcclusionOptions const& options) noexcept; // Gaussian mipmap @@ -201,7 +201,7 @@ public: // Color grading, tone mapping, dithering and bloom FrameGraphId colorGrading(FrameGraph& fg, - FrameGraphId input, filament::Viewport const& vp, + FrameGraphId input, Viewport const& vp, FrameGraphId bloom, FrameGraphId flare, const FColorGrading* colorGrading, @@ -226,12 +226,12 @@ public: // Anti-aliasing FrameGraphId fxaa(FrameGraph& fg, - FrameGraphId input, filament::Viewport const& vp, - backend::TextureFormat outFormat, bool translucent) noexcept; + FrameGraphId input, Viewport const& vp, + backend::TextureFormat outFormat, bool preserveAlphaChannel) noexcept; // Temporal Anti-aliasing void TaaJitterCamera( - filament::Viewport const& svp, + Viewport const& svp, TemporalAntiAliasingOptions const& taaOptions, FrameHistory& frameHistory, FrameHistoryEntry::TemporalAA FrameHistoryEntry::*pTaa, @@ -251,12 +251,25 @@ public: // high quality upscaler // - when translucent, reverts to LINEAR - // - doens't handle sub-resouces + // - doesn't handle sub-resouces FrameGraphId upscale(FrameGraph& fg, bool translucent, + bool sourceHasLuminance, DynamicResolutionOptions dsrOptions, + FrameGraphId input, Viewport const& vp, + FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filter) noexcept; + + FrameGraphId upscaleBilinear(FrameGraph& fg, bool translucent, DynamicResolutionOptions dsrOptions, FrameGraphId input, - filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, + Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filter) noexcept; + FrameGraphId upscaleFSR1(FrameGraph& fg, + DynamicResolutionOptions dsrOptions, FrameGraphId input, + filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept; + + FrameGraphId upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance, + DynamicResolutionOptions dsrOptions, FrameGraphId input, + filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept; + FrameGraphId rcas( FrameGraph& fg, float sharpness, @@ -267,7 +280,7 @@ public: // color blitter using shaders FrameGraphId blit(FrameGraph& fg, bool translucent, FrameGraphId input, - filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, + Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filterMag, backend::SamplerMinFilter filterMin) noexcept; @@ -311,7 +324,7 @@ public: // is not expected to be used in normal cases. FrameGraphId debugCombineArrayTexture(FrameGraph& fg, bool translucent, FrameGraphId input, - filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, + Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filterMag, backend::SamplerMinFilter filterMin) noexcept; @@ -428,7 +441,7 @@ private: template struct JitterSequence { - math::float2 operator()(size_t i) const noexcept { return positions[i % SIZE] - 0.5f; } + math::float2 operator()(size_t const i) const noexcept { return positions[i % SIZE] - 0.5f; } const std::array positions; }; diff --git a/filament/src/RenderPass.cpp b/filament/src/RenderPass.cpp index 5b9d94613e..58d417466b 100644 --- a/filament/src/RenderPass.cpp +++ b/filament/src/RenderPass.cpp @@ -26,8 +26,6 @@ #include "components/RenderableManager.h" -#include "ds/DescriptorSet.h" - #include #include #include @@ -81,7 +79,7 @@ RenderPassBuilder& RenderPassBuilder::customCommand( return *this; } -RenderPass RenderPassBuilder::build(FEngine const& engine, backend::DriverApi& driver) const { +RenderPass RenderPassBuilder::build(FEngine const& engine, DriverApi& driver) const { assert_invariant(mRenderableSoa); assert_invariant(mScissorViewport.width <= std::numeric_limits::max()); assert_invariant(mScissorViewport.height <= std::numeric_limits::max()); @@ -90,15 +88,14 @@ RenderPass RenderPassBuilder::build(FEngine const& engine, backend::DriverApi& d // ------------------------------------------------------------------------------------------------ -void RenderPass::BufferObjectHandleDeleter::operator()( - backend::BufferObjectHandle handle) noexcept { +void RenderPass::BufferObjectHandleDeleter::operator()(BufferObjectHandle handle) noexcept { if (handle) { // this is common case driver.get().destroyBufferObject(handle); } } void RenderPass::DescriptorSetHandleDeleter::operator()( - backend::DescriptorSetHandle handle) noexcept { + DescriptorSetHandle handle) noexcept { if (handle) { // this is common case driver.get().destroyDescriptorSet(handle); } @@ -106,7 +103,7 @@ void RenderPass::DescriptorSetHandleDeleter::operator()( // ------------------------------------------------------------------------------------------------ -RenderPass::RenderPass(FEngine const& engine, backend::DriverApi& driver, +RenderPass::RenderPass(FEngine const& engine, DriverApi& driver, RenderPassBuilder const& builder) noexcept : mRenderableSoa(*builder.mRenderableSoa), mColorPassDescriptorSet(builder.mColorPassDescriptorSet), @@ -160,7 +157,7 @@ RenderPass::RenderPass(FEngine const& engine, backend::DriverApi& driver, // sort commands once we're done adding commands commandEnd = resize(builder.mArena, - RenderPass::sortCommands(commandBegin, commandEnd)); + sortCommands(commandBegin, commandEnd)); if (engine.isAutomaticInstancingEnabled()) { int32_t stereoscopicEyeCount = 1; @@ -188,19 +185,19 @@ RenderPass::Command* RenderPass::resize(Arena& arena, Command* const last) noexc void RenderPass::appendCommands(FEngine const& engine, Slice commands, - utils::Range const vr, + Range const visibleRenderables, CommandTypeFlags const commandTypeFlags, RenderFlags const renderFlags, FScene::VisibleMaskType const visibilityMask, Variant const variant, float3 const cameraPosition, - float3 const cameraForwardVector) noexcept { + float3 const cameraForwardVector) const noexcept { SYSTRACE_CALL(); SYSTRACE_CONTEXT(); // trace the number of visible renderables - SYSTRACE_VALUE32("visibleRenderables", vr.size()); - if (UTILS_UNLIKELY(vr.empty())) { + SYSTRACE_VALUE32("visibleRenderables", visibleRenderables.size()); + if (UTILS_UNLIKELY(visibleRenderables.empty())) { // no renderables, we still need the sentinel and the command buffer size should be // exactly 1. assert_invariant(commands.size() == 1); @@ -222,17 +219,18 @@ void RenderPass::appendCommands(FEngine const& engine, auto work = [commandTypeFlags, curr, &soa, variant, renderFlags, visibilityMask, cameraPosition, cameraForwardVector, stereoscopicEyeCount] - (uint32_t startIndex, uint32_t indexCount) { - RenderPass::generateCommands(commandTypeFlags, curr, + (uint32_t const startIndex, uint32_t const indexCount) { + generateCommands(commandTypeFlags, curr, soa, { startIndex, startIndex + indexCount }, variant, renderFlags, visibilityMask, cameraPosition, cameraForwardVector, stereoscopicEyeCount); }; - if (vr.size() <= JOBS_PARALLEL_FOR_COMMANDS_COUNT) { - work(vr.first, vr.size()); + if (visibleRenderables.size() <= JOBS_PARALLEL_FOR_COMMANDS_COUNT) { + work(visibleRenderables.first, visibleRenderables.size()); } else { - auto* jobCommandsParallel = jobs::parallel_for(js, nullptr, vr.first, (uint32_t)vr.size(), + auto* jobCommandsParallel = parallel_for(js, nullptr, + visibleRenderables.first, uint32_t(visibleRenderables.size()), std::cref(work), jobs::CountSplitter()); js.runAndWait(jobCommandsParallel); } @@ -253,7 +251,7 @@ void RenderPass::appendCommands(FEngine const& engine, } void RenderPass::appendCustomCommand(Command* commands, - uint8_t channel, Pass pass, CustomCommand custom, uint32_t order, + uint8_t channel, Pass pass, CustomCommand custom, uint32_t const order, Executor::CustomCommandFn command) { assert_invariant((uint64_t(order) << CUSTOM_ORDER_SHIFT) <= CUSTOM_ORDER_MASK); @@ -287,10 +285,10 @@ RenderPass::Command* RenderPass::sortCommands( return last; } -RenderPass::Command* RenderPass::instanceify(backend::DriverApi& driver, +RenderPass::Command* RenderPass::instanceify(DriverApi& driver, DescriptorSetLayoutHandle perRenderableDescriptorSetLayoutHandle, Command* curr, Command* const last, - int32_t eyeCount) const noexcept { + int32_t const eyeCount) const noexcept { SYSTRACE_NAME("instanceify"); // instanceify works by scanning the **sorted** command stream, looking for repeat draw @@ -365,7 +363,7 @@ RenderPass::Command* RenderPass::instanceify(backend::DriverApi& driver, // TODO: use a pool for larger heap buffers // buffer large enough for all instances data stagingBufferSize = count * sizeof(PerRenderableData); - stagingBuffer = (PerRenderableData*)::malloc(stagingBufferSize); + stagingBuffer = static_cast(malloc(stagingBufferSize)); uboData = mRenderableSoa.data(); assert_invariant(uboData); @@ -415,14 +413,14 @@ RenderPass::Command* RenderPass::instanceify(backend::DriverApi& driver, driver.updateBufferObjectUnsynchronized(mInstancedUboHandle, { stagingBuffer, sizeof(PerRenderableData) * instancedPrimitiveOffset, +[](void* buffer, size_t, void*) { - ::free(buffer); + free(buffer); } }, 0); stagingBuffer = nullptr; // remove all the canceled commands - auto lastCommand = std::remove_if(firstSentinel, last, [](auto const& command) { + auto const lastCommand = std::remove_if(firstSentinel, last, [](auto const& command) { return command.key == uint64_t(Pass::SENTINEL); }); @@ -439,7 +437,7 @@ UTILS_ALWAYS_INLINE // This function exists only to make the code more readable. inline // and we don't need it in the compilation unit void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant, FMaterialInstance const* const UTILS_RESTRICT mi, - bool inverseFrontFaces, bool hasDepthClamp) noexcept { + bool const inverseFrontFaces, bool const hasDepthClamp) noexcept { FMaterial const * const UTILS_RESTRICT ma = mi->getMaterial(); variant = Variant::filterVariant(variant, ma->isVariantLit()); @@ -492,7 +490,7 @@ void RenderPass::generateCommands(CommandTypeFlags commandTypeFlags, Command* co Variant const variant, RenderFlags const renderFlags, FScene::VisibleMaskType const visibilityMask, float3 const cameraPosition, float3 const cameraForward, - uint8_t stereoEyeCount) noexcept { + uint8_t instancedStereoEyeCount) noexcept { SYSTRACE_CALL(); @@ -525,13 +523,13 @@ void RenderPass::generateCommands(CommandTypeFlags commandTypeFlags, Command* co curr = generateCommandsImpl(commandTypeFlags, curr, soa, range, variant, renderFlags, visibilityMask, cameraPosition, cameraForward, - stereoEyeCount); + instancedStereoEyeCount); break; case CommandTypeFlags::DEPTH: curr = generateCommandsImpl(commandTypeFlags, curr, soa, range, variant, renderFlags, visibilityMask, cameraPosition, cameraForward, - stereoEyeCount); + instancedStereoEyeCount); break; default: // we should never end-up here @@ -550,11 +548,11 @@ void RenderPass::generateCommands(CommandTypeFlags commandTypeFlags, Command* co /* static */ template UTILS_NOINLINE -RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFlags extraFlags, +RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlags, Command* UTILS_RESTRICT curr, FScene::RenderableSoa const& UTILS_RESTRICT soa, Range range, Variant const variant, RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, - float3 cameraPosition, float3 cameraForward, uint8_t stereoEyeCount) noexcept { + float3 cameraPosition, float3 cameraForward, uint8_t instancedStereoEyeCount) noexcept { constexpr bool isColorPass = bool(commandTypeFlags & CommandTypeFlags::COLOR); constexpr bool isDepthPass = bool(commandTypeFlags & CommandTypeFlags::DEPTH); @@ -675,16 +673,16 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla cmd.key |= makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT); cmd.key |= makeField(soaVisibility[i].channel, CHANNEL_MASK, CHANNEL_SHIFT); cmd.info.index = i; - cmd.info.hasHybridInstancing = (bool)soaInstanceInfo[i].handle; + cmd.info.hasHybridInstancing = bool(soaInstanceInfo[i].handle); cmd.info.instanceCount = soaInstanceInfo[i].count; - cmd.info.hasMorphing = (bool)morphing.handle; - cmd.info.hasSkinning = (bool)skinning.handle; + cmd.info.hasMorphing = bool(morphing.handle); + cmd.info.hasSkinning = bool(skinning.handle); // soaInstanceInfo[i].count is the number of instances the user has requested, either for // manual or hybrid instancing. Instanced stereo multiplies the number of instances by the // eye count. if (hasInstancedStereo) { - cmd.info.instanceCount *= stereoEyeCount; + cmd.info.instanceCount *= instancedStereoEyeCount; } // soaDescriptorSet[i] is either populated with a common descriptor-set or truly with @@ -704,11 +702,22 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla */ for (auto const& primitive: primitives) { FMaterialInstance const* const mi = primitive.getMaterialInstance(); - FMaterial const* const ma = mi->getMaterial(); + if (UTILS_UNLIKELY(!mi)) { + // This can happen because RenderPrimitives can be initialized with + // a null MaterialInstance. In this case, skip the primitive. + if constexpr (isColorPass) { + curr->key = uint64_t(Pass::SENTINEL); + ++curr; + } + curr->key = uint64_t(Pass::SENTINEL); + ++curr; + continue; + } // TODO: we should disable the SKN variant if this primitive doesn't have either // skinning or morphing. + FMaterial const* const ma = mi->getMaterial(); cmd.info.mi = mi; cmd.info.rph = primitive.getHwHandle(); cmd.info.vbih = primitive.getVertexBufferInfoHandle(); @@ -721,7 +730,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla // morphing.morphTargetBuffer->getHwHandle() : SamplerGroupHandle{}; if constexpr (isColorPass) { - RenderPass::setupColorCommand(cmd, renderableVariant, mi, + setupColorCommand(cmd, renderableVariant, mi, inverseFrontFaces, hasDepthClamp); const bool blendPass = Pass(cmd.key & PASS_MASK) == Pass::BLENDED; if (blendPass) { @@ -842,7 +851,7 @@ void RenderPass::updateSummedPrimitiveCounts( // ------------------------------------------------------------------------------------------------ -void RenderPass::Executor::overridePolygonOffset(backend::PolygonOffset const* polygonOffset) noexcept { +void RenderPass::Executor::overridePolygonOffset(PolygonOffset const* polygonOffset) noexcept { if ((mPolygonOffsetOverride = (polygonOffset != nullptr))) { // NOLINT(*-assignment-in-if-condition) mPolygonOffset = *polygonOffset; } @@ -853,7 +862,7 @@ void RenderPass::Executor::overrideScissor(backend::Viewport const& scissor) noe mScissor = scissor; } -void RenderPass::Executor::execute(FEngine const& engine, backend::DriverApi& driver) const noexcept { +void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver) const noexcept { execute(engine, driver, mCommands.begin(), mCommands.end()); } @@ -903,7 +912,7 @@ backend::Viewport RenderPass::Executor::applyScissorViewport( } UTILS_NOINLINE // no need to be inlined -void RenderPass::Executor::execute(FEngine const& engine, backend::DriverApi& driver, +void RenderPass::Executor::execute(FEngine const& engine, DriverApi& driver, Command const* first, Command const* last) const noexcept { SYSTRACE_CALL(); @@ -947,7 +956,7 @@ void RenderPass::Executor::execute(FEngine const& engine, backend::DriverApi& dr // CommandStream protocol. Currently, the maximum is 248 bytes. // The batch size is calculated by adding the size of all commands that can possibly be // emitted per draw call: - constexpr size_t const maxCommandSizeInBytes = + constexpr size_t maxCommandSizeInBytes = sizeof(COMMAND_TYPE(scissor)) + sizeof(COMMAND_TYPE(bindDescriptorSet)) + sizeof(COMMAND_TYPE(bindDescriptorSet)) + diff --git a/filament/src/RenderPass.h b/filament/src/RenderPass.h index c48bd9be44..de536fcb19 100644 --- a/filament/src/RenderPass.h +++ b/filament/src/RenderPass.h @@ -219,14 +219,14 @@ public: * * The variant is inserted while building the commands, because we don't know it before that */ - static CommandKey makeMaterialSortingKey(uint32_t materialId, uint32_t instanceId) noexcept { + static CommandKey makeMaterialSortingKey(uint32_t const materialId, uint32_t const instanceId) noexcept { CommandKey const key = ((materialId << MATERIAL_ID_SHIFT) & MATERIAL_ID_MASK) | ((instanceId << MATERIAL_INSTANCE_ID_SHIFT) & MATERIAL_INSTANCE_ID_MASK); return (key << MATERIAL_SHIFT) & MATERIAL_MASK; } template - static CommandKey makeField(T value, uint64_t mask, unsigned shift) noexcept { + static CommandKey makeField(T value, uint64_t const mask, unsigned const shift) noexcept { assert_invariant(!((uint64_t(value) << shift) & ~mask)); return uint64_t(value) << shift; } @@ -273,7 +273,7 @@ public: PrimitiveInfo info; // 56 bytes bool operator < (Command const& rhs) const noexcept { return key < rhs.key; } // placement new declared as "throw" to avoid the compiler's null-check - inline void* operator new (size_t, void* ptr) { + void* operator new (size_t, void* ptr) { assert_invariant(ptr); return ptr; } @@ -412,7 +412,7 @@ private: FScene::VisibleMaskType visibilityMask, Variant variant, math::float3 cameraPosition, - math::float3 cameraForwardVector) noexcept; + math::float3 cameraForwardVector) const noexcept; // Appends a custom command. void appendCustomCommand(Command* commands, @@ -426,7 +426,7 @@ private: Command* begin, Command* end) noexcept; // instanceify commands then trims sentinels - RenderPass::Command* instanceify(backend::DriverApi& driver, + Command* instanceify(backend::DriverApi& driver, backend::DescriptorSetLayoutHandle perRenderableDescriptorSetLayoutHandle, Command* begin, Command* end, int32_t eyeCount) const noexcept; @@ -446,8 +446,8 @@ private: math::float3 cameraPosition, math::float3 cameraForward, uint8_t instancedStereoEyeCount) noexcept; - template - static inline RenderPass::Command* generateCommandsImpl(RenderPass::CommandTypeFlags extraFlags, + template + static Command* generateCommandsImpl(CommandTypeFlags extraFlags, Command* curr, FScene::RenderableSoa const& soa, utils::Range range, Variant variant, RenderFlags renderFlags, FScene::VisibleMaskType visibilityMask, math::float3 cameraPosition, math::float3 cameraForward, @@ -502,21 +502,21 @@ class RenderPassBuilder { public: explicit RenderPassBuilder(RenderPass::Arena& arena) : mArena(arena) { } - RenderPassBuilder& commandTypeFlags(RenderPass::CommandTypeFlags commandTypeFlags) noexcept { + RenderPassBuilder& commandTypeFlags(RenderPass::CommandTypeFlags const commandTypeFlags) noexcept { mCommandTypeFlags = commandTypeFlags; return *this; } // Specifies the viewport for the scissor rectangle, that is, the final scissor rect is // offset by the viewport's left-top and clipped to the viewport's width/height. - RenderPassBuilder& scissorViewport(backend::Viewport viewport) noexcept { + RenderPassBuilder& scissorViewport(backend::Viewport const viewport) noexcept { mScissorViewport = viewport; return *this; } // specifies the geometry to generate commands for RenderPassBuilder& geometry( - FScene::RenderableSoa const& soa, utils::Range vr) noexcept { + FScene::RenderableSoa const& soa, utils::Range const vr) noexcept { mRenderableSoa = &soa; mVisibleRenderables = vr; return *this; @@ -530,14 +530,14 @@ public: } // flags controlling how commands are generated - RenderPassBuilder& renderFlags(RenderPass::RenderFlags flags) noexcept { + RenderPassBuilder& renderFlags(RenderPass::RenderFlags const flags) noexcept { mFlags = flags; return *this; } // like above but allows to set specific flags RenderPassBuilder& renderFlags( - RenderPass::RenderFlags mask, RenderPass::RenderFlags value) noexcept { + RenderPass::RenderFlags const mask, RenderPass::RenderFlags value) noexcept { value &= mask; mFlags &= ~mask; mFlags |= value; @@ -545,7 +545,7 @@ public: } // variant to use - RenderPassBuilder& variant(Variant variant) noexcept { + RenderPassBuilder& variant(Variant const variant) noexcept { mVariant = variant; return *this; } @@ -559,7 +559,7 @@ public: // Sets the visibility mask, which is AND-ed against each Renderable's VISIBLE_MASK to // determine if the renderable is visible for this pass. // Defaults to all 1's, which means all renderables in this render pass will be rendered. - RenderPassBuilder& visibilityMask(FScene::VisibleMaskType mask) noexcept { + RenderPassBuilder& visibilityMask(FScene::VisibleMaskType const mask) noexcept { mVisibilityMask = mask; return *this; } diff --git a/filament/src/RenderPrimitive.cpp b/filament/src/RenderPrimitive.cpp index 42918c0b42..1ffb53d660 100644 --- a/filament/src/RenderPrimitive.cpp +++ b/filament/src/RenderPrimitive.cpp @@ -41,8 +41,8 @@ void FRenderPrimitive::init(HwRenderPrimitiveFactory& factory, backend::DriverAp mBlendOrder = entry.blendOrder; if (entry.indices && entry.vertices) { - FVertexBuffer* vertexBuffer = downcast(entry.vertices); - FIndexBuffer* indexBuffer = downcast(entry.indices); + FVertexBuffer const* vertexBuffer = downcast(entry.vertices); + FIndexBuffer const* indexBuffer = downcast(entry.indices); set(factory, driver, entry.type, vertexBuffer, indexBuffer, entry.offset, entry.count); } } @@ -54,9 +54,9 @@ void FRenderPrimitive::terminate(HwRenderPrimitiveFactory& factory, backend::Dri } void FRenderPrimitive::set(HwRenderPrimitiveFactory& factory, backend::DriverApi& driver, - RenderableManager::PrimitiveType type, - FVertexBuffer* vertexBuffer, FIndexBuffer* indexBuffer, - size_t offset, size_t count) noexcept { + RenderableManager::PrimitiveType const type, + FVertexBuffer const* vertexBuffer, FIndexBuffer const* indexBuffer, + size_t const offset, size_t const count) noexcept { if (mHandle) { factory.destroy(driver, mHandle); } diff --git a/filament/src/RenderPrimitive.h b/filament/src/RenderPrimitive.h index a4716399e1..5c6eb5fef9 100644 --- a/filament/src/RenderPrimitive.h +++ b/filament/src/RenderPrimitive.h @@ -45,7 +45,7 @@ public: void set(HwRenderPrimitiveFactory& factory, backend::DriverApi& driver, RenderableManager::PrimitiveType type, - FVertexBuffer* vertexBuffer, FIndexBuffer* indexBuffer, size_t offset, + FVertexBuffer const* vertexBuffer, FIndexBuffer const* indexBuffer, size_t offset, size_t count) noexcept; // frees driver resources, object becomes invalid @@ -65,15 +65,15 @@ public: void setMaterialInstance(FMaterialInstance const* mi) noexcept { mMaterialInstance = mi; } - void setBlendOrder(uint16_t order) noexcept { + void setBlendOrder(uint16_t const order) noexcept { mBlendOrder = static_cast(order & 0x7FFF); } - void setGlobalBlendOrderEnabled(bool enabled) noexcept { + void setGlobalBlendOrderEnabled(bool const enabled) noexcept { mGlobalBlendOrderEnabled = enabled; } - void setMorphingBufferOffset(uint32_t offset) noexcept { + void setMorphingBufferOffset(uint32_t const offset) noexcept { mMorphingBufferOffset = offset; } diff --git a/filament/src/RenderTarget.cpp b/filament/src/RenderTarget.cpp index a17818bcba..50d67824c0 100644 --- a/filament/src/RenderTarget.cpp +++ b/filament/src/RenderTarget.cpp @@ -22,19 +22,19 @@ namespace filament { using namespace backend; -Texture* RenderTarget::getTexture(AttachmentPoint attachment) const noexcept { +Texture* RenderTarget::getTexture(AttachmentPoint const attachment) const noexcept { return downcast(this)->getAttachment(attachment).texture; } -uint8_t RenderTarget::getMipLevel(AttachmentPoint attachment) const noexcept { +uint8_t RenderTarget::getMipLevel(AttachmentPoint const attachment) const noexcept { return downcast(this)->getAttachment(attachment).mipLevel; } -RenderTarget::CubemapFace RenderTarget::getFace(AttachmentPoint attachment) const noexcept { +RenderTarget::CubemapFace RenderTarget::getFace(AttachmentPoint const attachment) const noexcept { return downcast(this)->getAttachment(attachment).face; } -uint32_t RenderTarget::getLayer(AttachmentPoint attachment) const noexcept { +uint32_t RenderTarget::getLayer(AttachmentPoint const attachment) const noexcept { return downcast(this)->getAttachment(attachment).layer; } diff --git a/filament/src/RenderableManager.cpp b/filament/src/RenderableManager.cpp index 87ea0d0e46..8a8f10f6d6 100644 --- a/filament/src/RenderableManager.cpp +++ b/filament/src/RenderableManager.cpp @@ -27,7 +27,7 @@ namespace filament { using namespace backend; using namespace math; -bool RenderableManager::hasComponent(utils::Entity e) const noexcept { +bool RenderableManager::hasComponent(Entity const e) const noexcept { return downcast(this)->hasComponent(e); } @@ -39,152 +39,156 @@ bool RenderableManager::empty() const noexcept { return downcast(this)->empty(); } -utils::Entity RenderableManager::getEntity(RenderableManager::Instance i) const noexcept { +Entity RenderableManager::getEntity(Instance const i) const noexcept { return downcast(this)->getEntity(i); } -utils::Entity const* RenderableManager::getEntities() const noexcept { +Entity const* RenderableManager::getEntities() const noexcept { return downcast(this)->getEntities(); } RenderableManager::Instance -RenderableManager::getInstance(utils::Entity e) const noexcept { +RenderableManager::getInstance(Entity const e) const noexcept { return downcast(this)->getInstance(e); } -void RenderableManager::destroy(utils::Entity e) noexcept { +void RenderableManager::destroy(Entity const e) noexcept { return downcast(this)->destroy(e); } -void RenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& aabb) { +void RenderableManager::setAxisAlignedBoundingBox(Instance const instance, const Box& aabb) { downcast(this)->setAxisAlignedBoundingBox(instance, aabb); } -void RenderableManager::setLayerMask(Instance instance, uint8_t select, uint8_t values) noexcept { +void RenderableManager::setLayerMask(Instance const instance, uint8_t const select, uint8_t const values) noexcept { downcast(this)->setLayerMask(instance, select, values); } -void RenderableManager::setPriority(Instance instance, uint8_t priority) noexcept { +void RenderableManager::setPriority(Instance const instance, uint8_t const priority) noexcept { downcast(this)->setPriority(instance, priority); } -void RenderableManager::setChannel(Instance instance, uint8_t channel) noexcept{ +void RenderableManager::setChannel(Instance const instance, uint8_t const channel) noexcept{ downcast(this)->setChannel(instance, channel); } -void RenderableManager::setCulling(Instance instance, bool enable) noexcept { +void RenderableManager::setCulling(Instance const instance, bool const enable) noexcept { downcast(this)->setCulling(instance, enable); } -void RenderableManager::setCastShadows(Instance instance, bool enable) noexcept { +void RenderableManager::setCastShadows(Instance const instance, bool const enable) noexcept { downcast(this)->setCastShadows(instance, enable); } -void RenderableManager::setReceiveShadows(Instance instance, bool enable) noexcept { +void RenderableManager::setReceiveShadows(Instance const instance, bool const enable) noexcept { downcast(this)->setReceiveShadows(instance, enable); } -void RenderableManager::setScreenSpaceContactShadows(Instance instance, bool enable) noexcept { +void RenderableManager::setScreenSpaceContactShadows(Instance const instance, bool const enable) noexcept { downcast(this)->setScreenSpaceContactShadows(instance, enable); } -bool RenderableManager::isShadowCaster(Instance instance) const noexcept { +bool RenderableManager::isShadowCaster(Instance const instance) const noexcept { return downcast(this)->isShadowCaster(instance); } -bool RenderableManager::isShadowReceiver(Instance instance) const noexcept { +bool RenderableManager::isShadowReceiver(Instance const instance) const noexcept { return downcast(this)->isShadowReceiver(instance); } -const Box& RenderableManager::getAxisAlignedBoundingBox(Instance instance) const noexcept { +const Box& RenderableManager::getAxisAlignedBoundingBox(Instance const instance) const noexcept { return downcast(this)->getAxisAlignedBoundingBox(instance); } -uint8_t RenderableManager::getLayerMask(Instance instance) const noexcept { +uint8_t RenderableManager::getLayerMask(Instance const instance) const noexcept { return downcast(this)->getLayerMask(instance); } -size_t RenderableManager::getPrimitiveCount(Instance instance) const noexcept { +size_t RenderableManager::getPrimitiveCount(Instance const instance) const noexcept { return downcast(this)->getPrimitiveCount(instance, 0); } -void RenderableManager::setMaterialInstanceAt(Instance instance, - size_t primitiveIndex, MaterialInstance const* materialInstance) { +void RenderableManager::setMaterialInstanceAt(Instance const instance, + size_t const primitiveIndex, MaterialInstance const* materialInstance) { downcast(this)->setMaterialInstanceAt(instance, 0, primitiveIndex, downcast(materialInstance)); } +void RenderableManager::clearMaterialInstanceAt(Instance instance, size_t primitiveIndex) { + downcast(this)->clearMaterialInstanceAt(instance, 0, primitiveIndex); +} + MaterialInstance* RenderableManager::getMaterialInstanceAt( - Instance instance, size_t primitiveIndex) const noexcept { + Instance const instance, size_t const primitiveIndex) const noexcept { return downcast(this)->getMaterialInstanceAt(instance, 0, primitiveIndex); } -void RenderableManager::setBlendOrderAt(Instance instance, size_t primitiveIndex, uint16_t order) noexcept { +void RenderableManager::setBlendOrderAt(Instance const instance, size_t const primitiveIndex, uint16_t const order) noexcept { downcast(this)->setBlendOrderAt(instance, 0, primitiveIndex, order); } -void RenderableManager::setGlobalBlendOrderEnabledAt(RenderableManager::Instance instance, - size_t primitiveIndex, bool enabled) noexcept { +void RenderableManager::setGlobalBlendOrderEnabledAt(Instance const instance, + size_t const primitiveIndex, bool const enabled) noexcept { downcast(this)->setGlobalBlendOrderEnabledAt(instance, 0, primitiveIndex, enabled); } -AttributeBitset RenderableManager::getEnabledAttributesAt(Instance instance, size_t primitiveIndex) const noexcept { +AttributeBitset RenderableManager::getEnabledAttributesAt(Instance const instance, size_t const primitiveIndex) const noexcept { return downcast(this)->getEnabledAttributesAt(instance, 0, primitiveIndex); } -void RenderableManager::setGeometryAt(Instance instance, size_t primitiveIndex, - PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, - size_t offset, size_t count) noexcept { +void RenderableManager::setGeometryAt(Instance const instance, size_t const primitiveIndex, + PrimitiveType const type, VertexBuffer* vertices, IndexBuffer* indices, + size_t const offset, size_t const count) noexcept { downcast(this)->setGeometryAt(instance, 0, primitiveIndex, type, downcast(vertices), downcast(indices), offset, count); } -void RenderableManager::setBones(Instance instance, - RenderableManager::Bone const* transforms, size_t boneCount, size_t offset) { +void RenderableManager::setBones(Instance const instance, + Bone const* transforms, size_t const boneCount, size_t const offset) { downcast(this)->setBones(instance, transforms, boneCount, offset); } -void RenderableManager::setBones(Instance instance, - mat4f const* transforms, size_t boneCount, size_t offset) { +void RenderableManager::setBones(Instance const instance, + mat4f const* transforms, size_t const boneCount, size_t const offset) { downcast(this)->setBones(instance, transforms, boneCount, offset); } -void RenderableManager::setSkinningBuffer(Instance instance, - SkinningBuffer* skinningBuffer, size_t count, size_t offset) { +void RenderableManager::setSkinningBuffer(Instance const instance, + SkinningBuffer* skinningBuffer, size_t const count, size_t const offset) { downcast(this)->setSkinningBuffer(instance, downcast(skinningBuffer), count, offset); } -void RenderableManager::setMorphWeights(Instance instance, float const* weights, - size_t count, size_t offset) { +void RenderableManager::setMorphWeights(Instance const instance, float const* weights, + size_t const count, size_t const offset) { downcast(this)->setMorphWeights(instance, weights, count, offset); } -void RenderableManager::setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, - size_t primitiveIndex, - size_t offset) { +void RenderableManager::setMorphTargetBufferOffsetAt(Instance const instance, uint8_t const level, + size_t const primitiveIndex, + size_t const offset) { downcast(this)->setMorphTargetBufferOffsetAt(instance, level, primitiveIndex, offset); } -MorphTargetBuffer* RenderableManager::getMorphTargetBuffer(Instance instance) const noexcept { +MorphTargetBuffer* RenderableManager::getMorphTargetBuffer(Instance const instance) const noexcept { return downcast(this)->getMorphTargetBuffer(instance); } -size_t RenderableManager::getMorphTargetCount(Instance instance) const noexcept { +size_t RenderableManager::getMorphTargetCount(Instance const instance) const noexcept { return downcast(this)->getMorphTargetCount(instance); } -void RenderableManager::setLightChannel(Instance instance, unsigned int channel, bool enable) noexcept { +void RenderableManager::setLightChannel(Instance const instance, unsigned int const channel, bool const enable) noexcept { downcast(this)->setLightChannel(instance, channel, enable); } -bool RenderableManager::getLightChannel(Instance instance, unsigned int channel) const noexcept { +bool RenderableManager::getLightChannel(Instance const instance, unsigned int const channel) const noexcept { return downcast(this)->getLightChannel(instance, channel); } -void RenderableManager::setFogEnabled(RenderableManager::Instance instance, bool enable) noexcept { +void RenderableManager::setFogEnabled(Instance const instance, bool const enable) noexcept { downcast(this)->setFogEnabled(instance, enable); } -bool RenderableManager::getFogEnabled(RenderableManager::Instance instance) const noexcept { +bool RenderableManager::getFogEnabled(Instance const instance) const noexcept { return downcast(this)->getFogEnabled(instance); } diff --git a/filament/src/Renderer.cpp b/filament/src/Renderer.cpp index 155a5877e8..836e4255be 100644 --- a/filament/src/Renderer.cpp +++ b/filament/src/Renderer.cpp @@ -42,30 +42,30 @@ void Renderer::render(View const* view) { downcast(this)->render(downcast(view)); } -void Renderer::setPresentationTime(int64_t monotonic_clock_ns) { +void Renderer::setPresentationTime(int64_t const monotonic_clock_ns) { downcast(this)->setPresentationTime(monotonic_clock_ns); } -void Renderer::skipFrame(uint64_t vsyncSteadyClockTimeNano) { +void Renderer::skipFrame(uint64_t const vsyncSteadyClockTimeNano) { downcast(this)->skipFrame(vsyncSteadyClockTimeNano); } -bool Renderer::beginFrame(SwapChain* swapChain, uint64_t vsyncSteadyClockTimeNano) { +bool Renderer::beginFrame(SwapChain* swapChain, uint64_t const vsyncSteadyClockTimeNano) { return downcast(this)->beginFrame(downcast(swapChain), vsyncSteadyClockTimeNano); } void Renderer::copyFrame(SwapChain* dstSwapChain, filament::Viewport const& dstViewport, - filament::Viewport const& srcViewport, CopyFrameFlag flags) { + filament::Viewport const& srcViewport, CopyFrameFlag const flags) { downcast(this)->copyFrame(downcast(dstSwapChain), dstViewport, srcViewport, flags); } -void Renderer::readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height, +void Renderer::readPixels(uint32_t const xoffset, uint32_t const yoffset, uint32_t const width, uint32_t const height, PixelBufferDescriptor&& buffer) { downcast(this)->readPixels(xoffset, yoffset, width, height, std::move(buffer)); } void Renderer::readPixels(RenderTarget* renderTarget, - uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height, + uint32_t const xoffset, uint32_t const yoffset, uint32_t const width, uint32_t const height, PixelBufferDescriptor&& buffer) { downcast(this)->readPixels(downcast(renderTarget), xoffset, yoffset, width, height, std::move(buffer)); @@ -103,11 +103,11 @@ void Renderer::renderStandaloneView(View const* view) { downcast(this)->renderStandaloneView(downcast(view)); } -void Renderer::setVsyncTime(uint64_t steadyClockTimeNano) noexcept { +void Renderer::setVsyncTime(uint64_t const steadyClockTimeNano) noexcept { downcast(this)->setVsyncTime(steadyClockTimeNano); } -utils::FixedCapacityVector Renderer::getFrameInfoHistory(size_t historySize) const noexcept { +utils::FixedCapacityVector Renderer::getFrameInfoHistory(size_t const historySize) const noexcept { return downcast(this)->getFrameInfoHistory(historySize); } diff --git a/filament/src/RendererUtils.cpp b/filament/src/RendererUtils.cpp index 5b671dda97..4d6b6b6898 100644 --- a/filament/src/RendererUtils.cpp +++ b/filament/src/RendererUtils.cpp @@ -55,7 +55,7 @@ RendererUtils::ColorPassOutput RendererUtils::colorPass( FrameGraph& fg, const char* name, FEngine& engine, FView const& view, ColorPassInput const& colorPassInput, FrameGraphTexture::Descriptor const& colorBufferDesc, - ColorPassConfig const& config, PostProcessManager::ColorGradingConfig colorGradingConfig, + ColorPassConfig const& config, PostProcessManager::ColorGradingConfig const colorGradingConfig, RenderPass::Executor passExecutor) noexcept { struct ColorPassData { @@ -273,7 +273,7 @@ std::optional RendererUtils::refractionPass( ColorPassInput colorPassInput, ColorPassConfig config, PostProcessManager::ScreenSpaceRefConfig const& ssrConfig, - PostProcessManager::ColorGradingConfig colorGradingConfig, + PostProcessManager::ColorGradingConfig const colorGradingConfig, RenderPass const& pass) noexcept { // find the first refractive object in channel 2 @@ -295,7 +295,7 @@ std::optional RendererUtils::refractionPass( config.hasScreenSpaceReflectionsOrRefractions = true; PostProcessManager& ppm = engine.getPostProcessManager(); - auto const opaquePassOutput = RendererUtils::colorPass(fg, + auto const opaquePassOutput = colorPass(fg, "Color Pass (opaque)", engine, view, colorPassInput, { // When rendering the opaques, we need to conserve the sample buffer, // so create a config that specifies the sample count. @@ -330,7 +330,7 @@ std::optional RendererUtils::refractionPass( // and we'd end up clearing the opaque pass. This scenario never happens because it is // prevented in Renderer.cpp's final blit. config.clearFlags = TargetBufferFlags::NONE; - auto transparentPassOutput = RendererUtils::colorPass(fg, "Color Pass (transparent)", + auto transparentPassOutput = colorPass(fg, "Color Pass (transparent)", engine, view, colorPassInput, { .width = config.physicalViewport.width, .height = config.physicalViewport.height }, @@ -352,9 +352,9 @@ std::optional RendererUtils::refractionPass( } UTILS_NOINLINE -void RendererUtils::readPixels(backend::DriverApi& driver, Handle renderTargetHandle, - uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height, - backend::PixelBufferDescriptor&& buffer) { +void RendererUtils::readPixels(DriverApi& driver, Handle renderTargetHandle, + uint32_t const xoffset, uint32_t const yoffset, uint32_t const width, uint32_t const height, + PixelBufferDescriptor&& buffer) { FILAMENT_CHECK_PRECONDITION(buffer.type != PixelDataType::COMPRESSED) << "buffer.format cannot be COMPRESSED"; diff --git a/filament/src/RendererUtils.h b/filament/src/RendererUtils.h index 34ea7b0eda..cd13721fd1 100644 --- a/filament/src/RendererUtils.h +++ b/filament/src/RendererUtils.h @@ -99,7 +99,7 @@ public: PostProcessManager::ColorGradingConfig colorGradingConfig, RenderPass::Executor passExecutor) noexcept; - static std::optional refractionPass( + static std::optional refractionPass( FrameGraph& fg, FEngine& engine, FView const& view, ColorPassInput colorPassInput, ColorPassConfig config, diff --git a/filament/src/ResourceAllocator.cpp b/filament/src/ResourceAllocator.cpp index 4335efa11a..6abefdb347 100644 --- a/filament/src/ResourceAllocator.cpp +++ b/filament/src/ResourceAllocator.cpp @@ -144,30 +144,30 @@ void ResourceAllocator::terminate() noexcept { } RenderTargetHandle ResourceAllocator::createRenderTarget(const char* name, - TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height, - uint8_t samples, uint8_t layerCount, MRT color, TargetBufferInfo depth, - TargetBufferInfo stencil) noexcept { + TargetBufferFlags const targetBufferFlags, uint32_t const width, uint32_t const height, + uint8_t const samples, uint8_t const layerCount, MRT const color, TargetBufferInfo const depth, + TargetBufferInfo const stencil) noexcept { auto handle = mBackend.createRenderTarget(targetBufferFlags, width, height, samples ? samples : 1u, layerCount, color, depth, stencil); mBackend.setDebugTag(handle.getId(), CString{ name }); return handle; } -void ResourceAllocator::destroyRenderTarget(RenderTargetHandle h) noexcept { +void ResourceAllocator::destroyRenderTarget(RenderTargetHandle const h) noexcept { mBackend.destroyRenderTarget(h); } -backend::TextureHandle ResourceAllocator::createTexture(const char* name, - backend::SamplerType target, uint8_t levels, backend::TextureFormat format, uint8_t samples, - uint32_t width, uint32_t height, uint32_t depth, - std::array swizzle, - backend::TextureUsage usage) noexcept { +TextureHandle ResourceAllocator::createTexture(const char* name, + SamplerType const target, uint8_t const levels, TextureFormat const format, uint8_t samples, + uint32_t const width, uint32_t const height, uint32_t const depth, + std::array const swizzle, + TextureUsage const usage) noexcept { // The frame graph descriptor uses "0" to mean "auto" but the sample count that is passed to the // backend should always be 1 or greater. samples = samples ? samples : uint8_t(1); - using TS = backend::TextureSwizzle; - constexpr const auto defaultSwizzle = std::array{ + using TS = TextureSwizzle; + constexpr const auto defaultSwizzle = std::array{ TS::CHANNEL_0, TS::CHANNEL_1, TS::CHANNEL_2, TS::CHANNEL_3}; // do we have a suitable texture in the cache? @@ -207,7 +207,7 @@ backend::TextureHandle ResourceAllocator::createTexture(const char* name, return handle; } -void ResourceAllocator::destroyTexture(TextureHandle h) noexcept { +void ResourceAllocator::destroyTexture(TextureHandle const h) noexcept { auto const key = mDisposer->checkin(h); if constexpr (mEnabled) { if (UTILS_LIKELY(key.has_value())) { @@ -225,7 +225,7 @@ ResourceAllocatorDisposerInterface& ResourceAllocator::getDisposer() noexcept { return *mDisposer; } -void ResourceAllocator::gc(bool skippedFrame) noexcept { +void ResourceAllocator::gc(bool const skippedFrame) noexcept { // this is called regularly -- usually once per frame // increase our age at each (non-skipped) frame @@ -253,7 +253,7 @@ void ResourceAllocator::gc(bool skippedFrame) noexcept { // maximum number of unique ages in the cache constexpr size_t MAX_UNIQUE_AGE_COUNT = 3; - utils::bitset32 ages; + bitset32 ages; uint32_t evictedCount = 0; for (auto it = textureCache.begin(); it != textureCache.end();) { size_t const ageDiff = age - it->second.age; @@ -274,9 +274,9 @@ void ResourceAllocator::gc(bool skippedFrame) noexcept { uint32_t bits = ages.getValue(); // remove from the set the ages we keep for (size_t i = 0; i < MAX_UNIQUE_AGE_COUNT - 1; i++) { - bits &= ~(1 << utils::ctz(bits)); + bits &= ~(1 << ctz(bits)); } - size_t const maxAge = utils::ctz(bits); + size_t const maxAge = ctz(bits); for (auto it = textureCache.begin(); it != textureCache.end();) { const size_t ageDiff = age - it->second.age; if (ageDiff >= maxAge) { @@ -289,7 +289,7 @@ void ResourceAllocator::gc(bool skippedFrame) noexcept { } UTILS_NOINLINE -void ResourceAllocator::dump(bool brief) const noexcept { +void ResourceAllocator::dump(bool const brief) const noexcept { constexpr float MiB = 1.0f / float(1u << 20u); slog.d << "# entries=" << mTextureCache.size() << ", sz=" << (float)mCacheSize * MiB << " MiB" @@ -308,7 +308,7 @@ void ResourceAllocator::dump(bool brief) const noexcept { ResourceAllocator::CacheContainer::iterator ResourceAllocator::purge( - ResourceAllocator::CacheContainer::iterator const& pos) { + CacheContainer::iterator const& pos) { //slog.d << "purging " << pos->second.handle.getId() << ", age=" << pos->second.age << io::endl; mBackend.destroyTexture(pos->second.handle); mCacheSize -= pos->second.size; @@ -329,7 +329,7 @@ void ResourceAllocatorDisposer::terminate() noexcept { assert_invariant(mInUseTextures.empty()); } -void ResourceAllocatorDisposer::destroy(backend::TextureHandle handle) noexcept { +void ResourceAllocatorDisposer::destroy(TextureHandle const handle) noexcept { if (handle) { auto r = checkin(handle); if (r.has_value()) { @@ -338,13 +338,13 @@ void ResourceAllocatorDisposer::destroy(backend::TextureHandle handle) noexcept } } -void ResourceAllocatorDisposer::checkout(backend::TextureHandle handle, +void ResourceAllocatorDisposer::checkout(TextureHandle handle, ResourceAllocator::TextureKey key) { mInUseTextures.emplace(handle, key); } std::optional ResourceAllocatorDisposer::checkin( - backend::TextureHandle handle) { + TextureHandle handle) { // find the texture in the in-use list (it must be there!) auto it = mInUseTextures.find(handle); assert_invariant(it != mInUseTextures.end()); diff --git a/filament/src/ResourceAllocator.h b/filament/src/ResourceAllocator.h index 04825a237c..69eca3aa71 100644 --- a/filament/src/ResourceAllocator.h +++ b/filament/src/ResourceAllocator.h @@ -215,8 +215,8 @@ private: using CacheContainer = AssociativeContainer; - ResourceAllocator::CacheContainer::iterator - purge(ResourceAllocator::CacheContainer::iterator const& pos); + CacheContainer::iterator + purge(CacheContainer::iterator const& pos); backend::DriverApi& mBackend; std::shared_ptr mDisposer; diff --git a/filament/src/Scene.cpp b/filament/src/Scene.cpp index 1cc7496723..93cd014cdd 100644 --- a/filament/src/Scene.cpp +++ b/filament/src/Scene.cpp @@ -39,19 +39,19 @@ IndirectLight* Scene::getIndirectLight() const noexcept { return downcast(this)->getIndirectLight(); } -void Scene::addEntity(Entity entity) { +void Scene::addEntity(Entity const entity) { downcast(this)->addEntity(entity); } -void Scene::addEntities(const Entity* entities, size_t count) { +void Scene::addEntities(const Entity* entities, size_t const count) { downcast(this)->addEntities(entities, count); } -void Scene::remove(Entity entity) { +void Scene::remove(Entity const entity) { downcast(this)->remove(entity); } -void Scene::removeEntities(const Entity* entities, size_t count) { +void Scene::removeEntities(const Entity* entities, size_t const count) { downcast(this)->removeEntities(entities, count); } @@ -67,11 +67,11 @@ size_t Scene::getLightCount() const noexcept { return downcast(this)->getLightCount(); } -bool Scene::hasEntity(Entity entity) const noexcept { +bool Scene::hasEntity(Entity const entity) const noexcept { return downcast(this)->hasEntity(entity); } -void Scene::forEach(Invocable&& functor) const noexcept { +void Scene::forEach(Invocable&& functor) const noexcept { downcast(this)->forEach(std::move(functor)); } diff --git a/filament/src/ShadowMap.cpp b/filament/src/ShadowMap.cpp index 1115bbcba2..b71345458d 100644 --- a/filament/src/ShadowMap.cpp +++ b/filament/src/ShadowMap.cpp @@ -84,8 +84,8 @@ void ShadowMap::terminate(FEngine& engine) { ShadowMap::~ShadowMap() = default; -void ShadowMap::initialize(size_t lightIndex, ShadowType shadowType, - uint16_t shadowIndex, uint8_t face, +void ShadowMap::initialize(size_t const lightIndex, ShadowType const shadowType, + uint16_t const shadowIndex, uint8_t const face, LightManager::ShadowOptions const* options) { mLightIndex = lightIndex; mShadowIndex = shadowIndex; @@ -94,8 +94,8 @@ void ShadowMap::initialize(size_t lightIndex, ShadowType shadowType, mFace = face; } -math::mat4f ShadowMap::getDirectionalLightViewMatrix(math::float3 direction, math::float3 up, - math::float3 position) noexcept { +mat4f ShadowMap::getDirectionalLightViewMatrix(float3 direction, float3 up, + float3 position) noexcept { // 1. we use the x-axis as the "up" reference so that the math is stable when the light // is pointing down, which is a common case for lights. // 2. we do the math in double to avoid some precision issues when the light is almost @@ -104,8 +104,8 @@ math::mat4f ShadowMap::getDirectionalLightViewMatrix(math::float3 direction, mat return FCamera::rigidTransformInverse(Mm); } -math::mat4f ShadowMap::getPointLightViewMatrix(backend::TextureCubemapFace face, - math::float3 position) noexcept { +mat4f ShadowMap::getPointLightViewMatrix(TextureCubemapFace face, + float3 position) noexcept { float3 direction; switch (TextureCubemapFace(face)) { case TextureCubemapFace::POSITIVE_X: direction = { 1, 0, 0 }; break; @@ -121,7 +121,7 @@ math::mat4f ShadowMap::getPointLightViewMatrix(backend::TextureCubemapFace face, ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine, FScene::LightSoa const& lightData, size_t index, - filament::CameraInfo const& camera, + CameraInfo const& camera, ShadowMapInfo const& shadowMapInfo, SceneInfo const& sceneInfo, bool useDepthClamp) noexcept { @@ -217,10 +217,10 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine, // Computes St the transform to use in the shader to access the shadow map texture // i.e. it transforms a world-space vertex to a texture coordinate in the shadowmap - const auto [Mt, Mn] = ShadowMap::getTextureCoordsMapping(shadowMapInfo, getViewport()); - const mat4f St = math::highPrecisionMultiply(Mt, S); + const auto [Mt, Mn] = getTextureCoordsMapping(shadowMapInfo, getViewport()); + const mat4f St = highPrecisionMultiply(Mt, S); - ShadowMap::ShaderParameters shaderParameters; + ShaderParameters shaderParameters; shaderParameters.scissorNormalized = getClampToEdgeCoords(shadowMapInfo); // note: in texelSizeWorldSpace() below, we can use Mb * Mt * F * W because @@ -254,7 +254,7 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine, // The model matrix below is in fact inverted to get the view matrix and passed to the // shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric. // (see depth_main.fs). Note that in the case of VSM, 'b' below is identity. - mCamera->setModelMatrix(FCamera::rigidTransformInverse(math::highPrecisionMultiplyd(Mv, b))); + mCamera->setModelMatrix(FCamera::rigidTransformInverse(highPrecisionMultiplyd(Mv, b))); mCamera->setCustomProjection(mat4(Mn * F * WLMp), znear, zfar); // for the debug camera, we need to undo the world origin @@ -266,7 +266,7 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine, } ShadowMap::ShaderParameters ShadowMap::updatePunctual( - mat4f const& Mv, float outerConeAngle, float nearPlane, float farPlane, + mat4f const& Mv, float const outerConeAngle, float const nearPlane, float const farPlane, const ShadowMapInfo& shadowMapInfo, const FLightManager::ShadowParams& params) noexcept { const mat4f Mp = mat4f::perspective( outerConeAngle * f::RAD_TO_DEG * 2.0f, 1.0f, nearPlane, farPlane); @@ -274,9 +274,9 @@ ShadowMap::ShaderParameters ShadowMap::updatePunctual( assert_invariant(shadowMapInfo.textureDimension == mOptions->mapSize); // Final shadow transform - const mat4f S = math::highPrecisionMultiply(Mp, Mv); - const auto [Mt, Mn] = ShadowMap::getTextureCoordsMapping(shadowMapInfo, getViewport()); - const mat4f St = math::highPrecisionMultiply(Mt, S); + const mat4f S = highPrecisionMultiply(Mp, Mv); + const auto [Mt, Mn] = getTextureCoordsMapping(shadowMapInfo, getViewport()); + const mat4f St = highPrecisionMultiply(Mt, S); // TODO: focus projection // 1) focus on the casters @@ -316,15 +316,15 @@ ShadowMap::ShaderParameters ShadowMap::updatePunctual( // The model matrix below is in fact inverted to get the view matrix and passed to the // shader as 'viewFromWorldMatrix', and is used in the VSM case to compute the depth metric. // (see depth_main.fs). Note that in the case of VSM, 'b' below is identity. - mCamera->setModelMatrix(FCamera::rigidTransformInverse(math::highPrecisionMultiplyd(Mv, b))); - mCamera->setCustomProjection(math::highPrecisionMultiplyd(Mn, Mp), nearPlane, farPlane); + mCamera->setModelMatrix(FCamera::rigidTransformInverse(highPrecisionMultiplyd(Mv, b))); + mCamera->setCustomProjection(highPrecisionMultiplyd(Mn, Mp), nearPlane, farPlane); return shaderParameters; } ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine, const FScene::LightSoa& lightData, size_t index, - filament::CameraInfo const&, + CameraInfo const&, const ShadowMapInfo& shadowMapInfo, FScene const& scene, SceneInfo sceneInfo) noexcept { @@ -343,7 +343,7 @@ ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine, // by the light -- which should be much smaller. if constexpr (false) { // find decent near/far - ShadowMap::updateSceneInfoSpot(Mv, scene, sceneInfo); + updateSceneInfoSpot(Mv, scene, sceneInfo); } else { sceneInfo.lsCastersNearFar = { -0.01f, -radius }; } @@ -363,7 +363,7 @@ ShadowMap::ShaderParameters ShadowMap::updateSpot(FEngine& engine, } ShadowMap::ShaderParameters ShadowMap::updatePoint(FEngine& engine, - const FScene::LightSoa& lightData, size_t index, filament::CameraInfo const&, + const FScene::LightSoa& lightData, size_t const index, CameraInfo const&, const ShadowMapInfo& shadowMapInfo, FScene const& scene, uint8_t face) noexcept { // check if this shadow map has anything to render @@ -394,7 +394,7 @@ ShadowMap::DirectionalShadowBounds ShadowMap::computeDirectionalShadowBounds( FEngine& engine, float3 const direction, FLightManager::ShadowParams params, - filament::CameraInfo const& camera, + CameraInfo const& camera, SceneInfo const& sceneInfo, bool useDepthClamp) noexcept { @@ -439,7 +439,7 @@ ShadowMap::DirectionalShadowBounds ShadowMap::computeDirectionalShadowBounds( // We compute the directional light's model matrix using the origin's as the light position. // The choice of the light's origin initially doesn't matter for a directional light. // This will be adjusted later because of how we compute the depth metric for VSM. - mat4f const MvAtOrigin = ShadowMap::getDirectionalLightViewMatrix(direction, + mat4f const MvAtOrigin = getDirectionalLightViewMatrix(direction, normalize(camera.worldTransform[0].xyz)); @@ -530,7 +530,7 @@ ShadowMap::DirectionalShadowBounds ShadowMap::computeDirectionalShadowBounds( } mat4f ShadowMap::applyLISPSM(mat4f& Wp, - filament::CameraInfo const& camera, FLightManager::ShadowParams const& params, + CameraInfo const& camera, FLightManager::ShadowParams const& params, mat4f const& LMp, mat4f const& Mv, mat4f const& LMpMv, @@ -612,7 +612,7 @@ mat4f ShadowMap::applyLISPSM(mat4f& Wp, return W; } -math::mat4f ShadowMap::computeLightRotation(math::float3 const& lsDirection) noexcept { +mat4f ShadowMap::computeLightRotation(float3 const& lsDirection) noexcept { mat4f L; // Orient the shadow map in the direction of the view vector by constructing a // rotation matrix in light space around the z-axis, that aligns the y-axis with the camera's @@ -630,11 +630,11 @@ math::mat4f ShadowMap::computeLightRotation(math::float3 const& lsDirection) noe return L; } -math::float4 ShadowMap::computeFocusParams( +float4 ShadowMap::computeFocusParams( mat4f const& LMpMv, mat4f const& WLMp, FrustumBoxIntersection const& lsShadowVolume, size_t vertexCount, - filament::CameraInfo const& camera, + CameraInfo const& camera, float shadowFar, bool stable) noexcept { float2 s, o; if (stable) { @@ -712,7 +712,7 @@ ShadowMap::TextureCoordsMapping ShadowMap::getTextureCoordsMapping(ShadowMapInfo } mat4f ShadowMap::computeVsmLightSpaceMatrix(const mat4f& lightSpacePcf, - const mat4f& Mv, float znear, float zfar) noexcept { + const mat4f& Mv, float const znear, float const zfar) noexcept { // The lightSpacePcf matrix transforms coordinates from world space into (u, v, z) coordinates, // where (u, v) are used to access the shadow map, and z is the (non-linear) PCF comparison // value [0, 1]. @@ -732,7 +732,7 @@ mat4f ShadowMap::computeVsmLightSpaceMatrix(const mat4f& lightSpacePcf, // This construct a frustum (similar to glFrustum or frustum), except // it looks towards the +y axis, and assumes -1,1 for the left/right and bottom/top planes. -mat4f ShadowMap::warpFrustum(float n, float f) noexcept { +mat4f ShadowMap::warpFrustum(float const n, float const f) noexcept { assert_invariant(f > n); const float d = 1 / (f - n); const float A = (f + n) * d; @@ -746,7 +746,7 @@ mat4f ShadowMap::warpFrustum(float n, float f) noexcept { return Wp; } -mat4f ShadowMap::directionalLightFrustum(float near, float far) noexcept { +mat4f ShadowMap::directionalLightFrustum(float const near, float const far) noexcept { const float d = far - near; mat4f m; m[2][2] = -2 / d; @@ -755,7 +755,7 @@ mat4f ShadowMap::directionalLightFrustum(float near, float far) noexcept { } float2 ShadowMap::computeNearFar(const mat4f& view, - float3 const* wsVertices, size_t count) noexcept { + float3 const* wsVertices, size_t const count) noexcept { float2 nearFar = { std::numeric_limits::lowest(), std::numeric_limits::max() }; for (size_t i = 0; i < count; i++) { // we're on the z axis in light space (looking down to -z) @@ -767,7 +767,7 @@ float2 ShadowMap::computeNearFar(const mat4f& view, } float2 ShadowMap::computeNearFarOfWarpSpace(mat4f const& lightView, - float3 const* wsVertices, size_t count) noexcept { + float3 const* wsVertices, size_t const count) noexcept { float2 nearFar = { std::numeric_limits::max(), std::numeric_limits::lowest() }; #pragma nounroll for (size_t i = 0; i < count; i++) { @@ -793,9 +793,9 @@ float4 ShadowMap::computeBoundingSphere(float3 const* vertices, size_t count) no } Aabb ShadowMap::compute2DBounds(const mat4f& lightView, - float3 const* wsVertices, size_t count) noexcept { + float3 const* wsVertices, size_t const count) noexcept { Aabb bounds{}; - utils::Slice const vertices{ wsVertices, count }; + Slice const vertices{ wsVertices, count }; for (auto const& vertice : vertices) { const float3 v = mat4f::project(lightView, vertice); bounds.min.xy = min(bounds.min.xy, v.xy); @@ -848,8 +848,8 @@ ShadowMap::Corners ShadowMap::computeFrustumCorners( Aabb ShadowMap::computeLightFrustumBounds(mat4f const& lightView, Aabb const& wsShadowReceiversVolume, Aabb const& wsShadowCastersVolume, - ShadowMap::SceneInfo const& sceneInfo, - bool stable, bool focusShadowCasters, bool farUsesShadowCasters) noexcept { + SceneInfo const& sceneInfo, + bool const stable, bool const focusShadowCasters, bool const farUsesShadowCasters) noexcept { Aabb lsLightFrustumBounds{}; float const receiversFar = sceneInfo.lsReceiversNearFar[1]; @@ -880,9 +880,9 @@ Aabb ShadowMap::computeLightFrustumBounds(mat4f const& lightView, } void ShadowMap::snapLightFrustum(float2& s, float2& o, - double2 lsRef, int2 resolution) noexcept { + double2 const lsRef, int2 const resolution) noexcept { - auto proj2 = [](mat4 m, double2 v) -> double2 { + auto proj2 = [](mat4 m, double2 const v) -> double2 { double2 p; p.x = dot(double2{ m[0].x, m[1].x }, v) + m[3].x; p.y = dot(double2{ m[0].y, m[1].y }, v) + m[3].y; @@ -1198,7 +1198,7 @@ float ShadowMap::texelSizeWorldSpace(const mat4f& Wp, const mat4f& MbMtF, } template -void ShadowMap::visitScene(const FScene& scene, uint32_t visibleLayers, +void ShadowMap::visitScene(const FScene& scene, uint32_t const visibleLayers, Casters casters, Receivers receivers) noexcept { SYSTRACE_CALL(); @@ -1225,7 +1225,7 @@ void ShadowMap::visitScene(const FScene& scene, uint32_t visibleLayers, } ShadowMap::SceneInfo::SceneInfo( - FScene const& scene, uint8_t visibleLayers) noexcept + FScene const& scene, uint8_t const visibleLayers) noexcept : visibleLayers(visibleLayers) { // the code below only works with affine transforms @@ -1237,7 +1237,7 @@ ShadowMap::SceneInfo::SceneInfo( // Compute scene bounds in world space, as well as the light-space and view-space near/far planes wsShadowCastersVolume = {}; wsShadowReceiversVolume = {}; - ShadowMap::visitScene(scene, visibleLayers, + visitScene(scene, visibleLayers, [&](Aabb caster, Culler::result_type) { wsShadowCastersVolume.min = min(wsShadowCastersVolume.min, caster.min); wsShadowCastersVolume.max = max(wsShadowCastersVolume.max, caster.max); @@ -1263,7 +1263,7 @@ void ShadowMap::updateSceneInfoDirectional(mat4f const& Mv, FScene const& scene, sceneInfo.lsCastersNearFar.x = max(sceneInfo.lsCastersNearFar.x, r.max.z); sceneInfo.lsCastersNearFar.y = min(sceneInfo.lsCastersNearFar.y, r.min.z); }, - [&](Aabb receiver, Culler::result_type vis) { + [&](Aabb receiver, Culler::result_type const vis) { // account only for objects that are visible by the camera auto mask = 1u << VISIBLE_RENDERABLE_BIT; if ((vis & mask) == mask) { @@ -1284,7 +1284,7 @@ void ShadowMap::updateSceneInfoSpot(mat4f const& Mv, FScene const& scene, sceneInfo.lsCastersNearFar = { std::numeric_limits::lowest(), std::numeric_limits::max() }; // account only for objects that are visible by both the camera and the light visitScene(scene, sceneInfo.visibleLayers, - [&](Aabb caster, Culler::result_type vis) { + [&](Aabb caster, Culler::result_type const vis) { auto mask = VISIBLE_DYN_SHADOW_RENDERABLE; if ((vis & mask) == mask) { auto r = Aabb::transform(Mv.upperLeft(), Mv[3].xyz, caster); @@ -1296,7 +1296,7 @@ void ShadowMap::updateSceneInfoSpot(mat4f const& Mv, FScene const& scene, } ); } -void ShadowMap::setAllocation(uint8_t layer, backend::Viewport viewport) noexcept { +void ShadowMap::setAllocation(uint8_t const layer, backend::Viewport viewport) noexcept { mLayer = layer; mOffset = { viewport.left, viewport.bottom }; } @@ -1330,7 +1330,7 @@ backend::Viewport ShadowMap::getScissor() const noexcept { } } -math::float4 ShadowMap::getClampToEdgeCoords(ShadowMapInfo const& shadowMapInfo) const noexcept { +float4 ShadowMap::getClampToEdgeCoords(ShadowMapInfo const& shadowMapInfo) const noexcept { float border; // shadowmap border in texels switch (mShadowType) { case ShadowType::DIRECTIONAL: @@ -1365,7 +1365,7 @@ math::float4 ShadowMap::getClampToEdgeCoords(ShadowMapInfo const& shadowMapInfo) // ------------------------------------------------------------------------------------------------ void ShadowMap::prepareCamera(Transaction const& transaction, - backend::DriverApi& driver, const CameraInfo& cameraInfo) noexcept { + DriverApi& driver, const CameraInfo& cameraInfo) noexcept { ShadowMapDescriptorSet::prepareCamera(transaction, driver, cameraInfo); ShadowMapDescriptorSet::prepareLodBias(transaction, 0.0f); } @@ -1376,12 +1376,12 @@ void ShadowMap::prepareViewport(Transaction const& transaction, } void ShadowMap::prepareTime(Transaction const& transaction, - FEngine const& engine, math::float4 const& userTime) noexcept { + FEngine const& engine, float4 const& userTime) noexcept { ShadowMapDescriptorSet::prepareTime(transaction, engine, userTime); } void ShadowMap::prepareShadowMapping(Transaction const& transaction, - bool highPrecision) noexcept { + bool const highPrecision) noexcept { ShadowMapDescriptorSet::prepareShadowMapping(transaction, highPrecision); } @@ -1390,11 +1390,11 @@ ShadowMapDescriptorSet::Transaction ShadowMap::open(DriverApi& driver) noexcept } void ShadowMap::commit(Transaction& transaction, - FEngine& engine, backend::DriverApi& driver) const noexcept { + FEngine& engine, DriverApi& driver) const noexcept { mPerShadowMapUniforms.commit(transaction, engine, driver); } -void ShadowMap::bind(backend::DriverApi& driver) const noexcept { +void ShadowMap::bind(DriverApi& driver) const noexcept { mPerShadowMapUniforms.bind(driver); } diff --git a/filament/src/ShadowMap.h b/filament/src/ShadowMap.h index e997dce14c..764f02553b 100644 --- a/filament/src/ShadowMap.h +++ b/filament/src/ShadowMap.h @@ -145,19 +145,19 @@ public: // This computes the light's camera. ShaderParameters updateDirectional(FEngine& engine, const FScene::LightSoa& lightData, size_t index, - filament::CameraInfo const& camera, + CameraInfo const& camera, ShadowMapInfo const& shadowMapInfo, SceneInfo const& sceneInfo, bool useDepthClamp) noexcept; ShaderParameters updateSpot(FEngine& engine, const FScene::LightSoa& lightData, size_t index, - filament::CameraInfo const& camera, + CameraInfo const& camera, const ShadowMapInfo& shadowMapInfo, FScene const& scene, SceneInfo sceneInfo) noexcept; - ShadowMap::ShaderParameters updatePoint(FEngine& engine, - const FScene::LightSoa& lightData, size_t index, filament::CameraInfo const& camera, + ShaderParameters updatePoint(FEngine& engine, + const FScene::LightSoa& lightData, size_t index, CameraInfo const& camera, const ShadowMapInfo& shadowMapInfo, FScene const& scene, uint8_t face) noexcept; // Do we have visible shadows. Valid after calling update(). @@ -237,12 +237,12 @@ private: FEngine& engine, math::float3 direction, FLightManager::ShadowParams params, - filament::CameraInfo const& camera, + CameraInfo const& camera, SceneInfo const& sceneInfo, bool useDepthClamp) noexcept; static math::mat4f applyLISPSM(math::mat4f& Wp, - filament::CameraInfo const& camera, FLightManager::ShadowParams const& params, + CameraInfo const& camera, FLightManager::ShadowParams const& params, const math::mat4f& LMp, const math::mat4f& Mv, const math::mat4f& LMpMv, @@ -255,7 +255,7 @@ private: math::mat4f const& LMpMv, math::mat4f const& WLMp, FrustumBoxIntersection const& lsShadowVolume, size_t vertexCount, - filament::CameraInfo const& camera, + CameraInfo const& camera, float shadowFar, bool stable) noexcept; static inline void snapLightFrustum(math::float2& s, math::float2& o, diff --git a/filament/src/ShadowMapManager.cpp b/filament/src/ShadowMapManager.cpp index b6ae94ab82..ac8c70d8d9 100644 --- a/filament/src/ShadowMapManager.cpp +++ b/filament/src/ShadowMapManager.cpp @@ -175,7 +175,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::update( return shadowTechnique; } -ShadowMapManager::Builder& ShadowMapManager::Builder::directionalShadowMap(size_t lightIndex, +ShadowMapManager::Builder& ShadowMapManager::Builder::directionalShadowMap(size_t const lightIndex, LightManager::ShadowOptions const* options) noexcept { assert_invariant(options->shadowCascades <= CONFIG_MAX_SHADOW_CASCADES); // this updates getCascadedShadowMap() @@ -191,7 +191,7 @@ ShadowMapManager::Builder& ShadowMapManager::Builder::directionalShadowMap(size_ return *this; } -ShadowMapManager::Builder& ShadowMapManager::Builder::shadowMap(size_t lightIndex, bool spotlight, +ShadowMapManager::Builder& ShadowMapManager::Builder::shadowMap(size_t const lightIndex, bool const spotlight, LightManager::ShadowOptions const* options) noexcept { if (spotlight) { const size_t c = mSpotShadowMapCount++; @@ -770,7 +770,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng } void ShadowMapManager::updateSpotVisibilityMasks( - uint8_t visibleLayers, + uint8_t const visibleLayers, uint8_t const* UTILS_RESTRICT layers, FRenderableManager::Visibility const* UTILS_RESTRICT visibility, Culler::result_type* UTILS_RESTRICT visibleMask, size_t count) { @@ -795,7 +795,7 @@ void ShadowMapManager::updateSpotVisibilityMasks( void ShadowMapManager::prepareSpotShadowMap(ShadowMap& shadowMap, FEngine& engine, FView& view, CameraInfo const& mainCameraInfo, - FScene::LightSoa& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept { + FScene::LightSoa const& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept { const size_t lightIndex = shadowMap.getLightIndex(); FLightManager::ShadowOptions const* const options = shadowMap.getShadowOptions(); @@ -858,7 +858,7 @@ void ShadowMapManager::cullSpotShadowMap(ShadowMap const& shadowMap, // compute shadow map frustum for culling const mat4f Mv = ShadowMap::getDirectionalLightViewMatrix(direction, { 0, 1, 0 }, position); const mat4f Mp = mat4f::perspective(outerConeAngle * f::RAD_TO_DEG * 2.0f, 1.0f, 0.01f, radius); - const mat4f MpMv = math::highPrecisionMultiply(Mp, Mv); + const mat4f MpMv = highPrecisionMultiply(Mp, Mv); const Frustum frustum(MpMv); // Cull shadow casters @@ -886,7 +886,7 @@ void ShadowMapManager::cullSpotShadowMap(ShadowMap const& shadowMap, void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap, FEngine& engine, FView& view, CameraInfo const& mainCameraInfo, - FScene::LightSoa& lightData) noexcept { + FScene::LightSoa const& lightData) const noexcept { const uint8_t face = shadowMap.getFace(); const size_t lightIndex = shadowMap.getLightIndex(); @@ -930,7 +930,7 @@ void ShadowMapManager::preparePointShadowMap(ShadowMap& shadowMap, } void ShadowMapManager::cullPointShadowMap(ShadowMap const& shadowMap, FView const& view, - FScene::RenderableSoa& renderableData, utils::Range range, + FScene::RenderableSoa& renderableData, utils::Range const range, FScene::LightSoa const& lightData) noexcept { uint8_t const face = shadowMap.getFace(); @@ -945,7 +945,7 @@ void ShadowMapManager::cullPointShadowMap(ShadowMap const& shadowMap, FView cons // compute shadow map frustum for culling mat4f const Mv = ShadowMap::getPointLightViewMatrix(TextureCubemapFace(face), position); mat4f const Mp = mat4f::perspective(90.0f, 1.0f, 0.01f, radius); - Frustum const frustum{ math::highPrecisionMultiply(Mp, Mv) }; + Frustum const frustum{ highPrecisionMultiply(Mp, Mv) }; // Cull shadow casters float3 const* worldAABBCenter = renderableData.data(); @@ -971,7 +971,7 @@ void ShadowMapManager::cullPointShadowMap(ShadowMap const& shadowMap, FView cons } ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine& engine, - FScene::LightSoa const& lightData) noexcept { + FScene::LightSoa const& lightData) const noexcept { // The const_cast here is a little ugly, but conceptually lightData should be const, // it's just that we're using it to store some temporary data. With SoA we can't have @@ -1088,7 +1088,7 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view if (useMipmapping) { // Limit the lowest mipmap level to 256x256. // This avoids artifacts on high derivative tangent surfaces. - int const lowMipmapLevel = 7; // log2(256) - 1 + constexpr int lowMipmapLevel = 7; // log2(256) - 1 mipLevels = std::max(1, FTexture::maxLevelCount(maxDimension) - lowMipmapLevel); } diff --git a/filament/src/ShadowMapManager.h b/filament/src/ShadowMapManager.h index 6949ddb727..ba606c6eb4 100644 --- a/filament/src/ShadowMapManager.h +++ b/filament/src/ShadowMapManager.h @@ -77,7 +77,7 @@ struct ShadowMappingUniforms { class ShadowMapManager { public: - using ShadowMappingUniforms = filament::ShadowMappingUniforms; + using ShadowMappingUniforms = ShadowMappingUniforms; using ShadowType = ShadowMap::ShadowType; @@ -123,7 +123,7 @@ public: // Updates all the shadow maps and performs culling. // Returns true if any of the shadow maps have visible shadows. - ShadowMapManager::ShadowTechnique update(Builder const& builder, + ShadowTechnique update(Builder const& builder, FEngine& engine, FView& view, CameraInfo const& cameraInfo, FScene::RenderableSoa& renderableData, FScene::LightSoa const& lightData) noexcept; @@ -153,19 +153,19 @@ private: static void updateNearFarPlanes(math::mat4f* projection, float nearDistance, float farDistance) noexcept; - ShadowMapManager::ShadowTechnique updateCascadeShadowMaps(FEngine& engine, + ShadowTechnique updateCascadeShadowMaps(FEngine& engine, FView& view, CameraInfo cameraInfo, FScene::RenderableSoa& renderableData, FScene::LightSoa const& lightData, ShadowMap::SceneInfo sceneInfo) noexcept; - ShadowMapManager::ShadowTechnique updateSpotShadowMaps(FEngine& engine, - FScene::LightSoa const& lightData) noexcept; + ShadowTechnique updateSpotShadowMaps(FEngine& engine, + FScene::LightSoa const& lightData) const noexcept; void calculateTextureRequirements(FEngine&, FView& view, FScene::LightSoa const&) noexcept; void prepareSpotShadowMap(ShadowMap& shadowMap, FEngine& engine, FView& view, CameraInfo const& mainCameraInfo, - FScene::LightSoa& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept; + FScene::LightSoa const& lightData, ShadowMap::SceneInfo const& sceneInfo) noexcept; static void cullSpotShadowMap(ShadowMap const& map, FEngine const& engine, FView const& view, @@ -174,7 +174,7 @@ private: void preparePointShadowMap(ShadowMap& map, FEngine& engine, FView& view, CameraInfo const& mainCameraInfo, - FScene::LightSoa& lightData) noexcept; + FScene::LightSoa const& lightData) const noexcept; static void cullPointShadowMap(ShadowMap const& shadowMap, FView const& view, FScene::RenderableSoa& renderableData, utils::Range range, @@ -239,12 +239,12 @@ private: bool mInitialized = false; bool mFeatureShadowAllocator = false; - ShadowMap& getShadowMap(size_t index) noexcept { + ShadowMap& getShadowMap(size_t const index) noexcept { assert_invariant(index < mShadowMapCache.size()); return *std::launder(reinterpret_cast(&mShadowMapCache[index])); } - ShadowMap const& getShadowMap(size_t index) const noexcept { + ShadowMap const& getShadowMap(size_t const index) const noexcept { return const_cast(this)->getShadowMap(index); } diff --git a/filament/src/SkinningBuffer.cpp b/filament/src/SkinningBuffer.cpp index df40f8ce2f..ec196f9a14 100644 --- a/filament/src/SkinningBuffer.cpp +++ b/filament/src/SkinningBuffer.cpp @@ -24,12 +24,12 @@ using namespace backend; using namespace math; void SkinningBuffer::setBones(Engine& engine, - RenderableManager::Bone const* transforms, size_t count, size_t offset) { + RenderableManager::Bone const* transforms, size_t const count, size_t const offset) { downcast(this)->setBones(downcast(engine), transforms, count, offset); } void SkinningBuffer::setBones(Engine& engine, - math::mat4f const* transforms, size_t count, size_t offset) { + mat4f const* transforms, size_t const count, size_t const offset) { downcast(this)->setBones(downcast(engine), transforms, count, offset); } diff --git a/filament/src/Skybox.cpp b/filament/src/Skybox.cpp index b9eee10e8f..f9488f6017 100644 --- a/filament/src/Skybox.cpp +++ b/filament/src/Skybox.cpp @@ -20,7 +20,7 @@ namespace filament { -void Skybox::setLayerMask(uint8_t select, uint8_t values) noexcept { +void Skybox::setLayerMask(uint8_t const select, uint8_t const values) noexcept { downcast(this)->setLayerMask(select, values); } @@ -32,7 +32,7 @@ float Skybox::getIntensity() const noexcept { return downcast(this)->getIntensity(); } -void Skybox::setColor(math::float4 color) noexcept { +void Skybox::setColor(math::float4 const color) noexcept { downcast(this)->setColor(color); } diff --git a/filament/src/Stream.cpp b/filament/src/Stream.cpp index 8bba0dd6b5..bcd9c1777b 100644 --- a/filament/src/Stream.cpp +++ b/filament/src/Stream.cpp @@ -24,16 +24,16 @@ StreamType Stream::getStreamType() const noexcept { return downcast(this)->getStreamType(); } -void Stream::setAcquiredImage(void* image, Callback callback, void* userdata) noexcept { +void Stream::setAcquiredImage(void* image, Callback const callback, void* userdata) noexcept { downcast(this)->setAcquiredImage(image, callback, userdata); } void Stream::setAcquiredImage(void* image, - backend::CallbackHandler* handler, Callback callback, void* userdata) noexcept { + CallbackHandler* handler, Callback const callback, void* userdata) noexcept { downcast(this)->setAcquiredImage(image, handler, callback, userdata); } -void Stream::setDimensions(uint32_t width, uint32_t height) noexcept { +void Stream::setDimensions(uint32_t const width, uint32_t const height) noexcept { downcast(this)->setDimensions(width, height); } diff --git a/filament/src/SwapChain.cpp b/filament/src/SwapChain.cpp index 66502931e7..8bac3e4dba 100644 --- a/filament/src/SwapChain.cpp +++ b/filament/src/SwapChain.cpp @@ -29,7 +29,7 @@ void* SwapChain::getNativeWindow() const noexcept { } void SwapChain::setFrameScheduledCallback( - backend::CallbackHandler* handler, FrameScheduledCallback&& callback, uint64_t flags) { + backend::CallbackHandler* handler, FrameScheduledCallback&& callback, uint64_t const flags) { downcast(this)->setFrameScheduledCallback(handler, std::move(callback), flags); } diff --git a/filament/src/Texture.cpp b/filament/src/Texture.cpp index f4c381927a..eb67f5b43c 100644 --- a/filament/src/Texture.cpp +++ b/filament/src/Texture.cpp @@ -21,15 +21,15 @@ namespace filament { -size_t Texture::getWidth(size_t level) const noexcept { +size_t Texture::getWidth(size_t const level) const noexcept { return downcast(this)->getWidth(level); } -size_t Texture::getHeight(size_t level) const noexcept { +size_t Texture::getHeight(size_t const level) const noexcept { return downcast(this)->getHeight(level); } -size_t Texture::getDepth(size_t level) const noexcept { +size_t Texture::getDepth(size_t const level) const noexcept { return downcast(this)->getDepth(level); } @@ -45,16 +45,16 @@ Texture::InternalFormat Texture::getFormat() const noexcept { return downcast(this)->getFormat(); } -void Texture::setImage(Engine& engine, size_t level, - uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, - uint32_t width, uint32_t height, uint32_t depth, +void Texture::setImage(Engine& engine, size_t const level, + uint32_t const xoffset, uint32_t const yoffset, uint32_t const zoffset, + uint32_t const width, uint32_t const height, uint32_t const depth, PixelBufferDescriptor&& buffer) const { downcast(this)->setImage(downcast(engine), level, xoffset, yoffset, zoffset, width, height, depth, std::move(buffer)); } -void Texture::setImage(Engine& engine, size_t level, - Texture::PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const { +void Texture::setImage(Engine& engine, size_t const level, + PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const { downcast(this)->setImage(downcast(engine), level, std::move(buffer), faceOffsets); } @@ -62,7 +62,7 @@ void Texture::setExternalImage(Engine& engine, void* image) noexcept { downcast(this)->setExternalImage(downcast(engine), image); } -void Texture::setExternalImage(Engine& engine, void* image, size_t plane) noexcept { +void Texture::setExternalImage(Engine& engine, void* image, size_t const plane) noexcept { downcast(this)->setExternalImage(downcast(engine), image, plane); } @@ -74,7 +74,7 @@ void Texture::generateMipmaps(Engine& engine) const noexcept { downcast(this)->generateMipmaps(downcast(engine)); } -bool Texture::isTextureFormatSupported(Engine& engine, InternalFormat format) noexcept { +bool Texture::isTextureFormatSupported(Engine& engine, InternalFormat const format) noexcept { return FTexture::isTextureFormatSupported(downcast(engine), format); } @@ -86,13 +86,13 @@ bool Texture::isTextureSwizzleSupported(Engine& engine) noexcept { return FTexture::isTextureSwizzleSupported(downcast(engine)); } -size_t Texture::computeTextureDataSize(Texture::Format format, Texture::Type type, size_t stride, - size_t height, size_t alignment) noexcept { +size_t Texture::computeTextureDataSize(Format const format, Type const type, size_t const stride, + size_t const height, size_t const alignment) noexcept { return FTexture::computeTextureDataSize(format, type, stride, height, alignment); } -void Texture::generatePrefilterMipmap(Engine& engine, Texture::PixelBufferDescriptor&& buffer, - const Texture::FaceOffsets& faceOffsets, PrefilterOptions const* options) { +void Texture::generatePrefilterMipmap(Engine& engine, PixelBufferDescriptor&& buffer, + const FaceOffsets& faceOffsets, PrefilterOptions const* options) { downcast(this)->generatePrefilterMipmap(downcast(engine), std::move(buffer), faceOffsets, options); } diff --git a/filament/src/ToneMapper.cpp b/filament/src/ToneMapper.cpp index 9c5a191210..e6f9fc8c14 100644 --- a/filament/src/ToneMapper.cpp +++ b/filament/src/ToneMapper.cpp @@ -27,7 +27,7 @@ using namespace math; namespace aces { -inline float rgb_2_saturation(float3 rgb) { +inline float rgb_2_saturation(float3 const rgb) { // Input: ACES // Output: OCES constexpr float TINY = 1e-5f; @@ -36,7 +36,7 @@ inline float rgb_2_saturation(float3 rgb) { return (max(ma, TINY) - max(mi, TINY)) / max(ma, 1e-2f); } -inline float rgb_2_yc(float3 rgb) { +inline float rgb_2_yc(float3 const rgb) { constexpr float ycRadiusWeight = 1.75f; // Converts RGB to a luminance proxy, here called YC @@ -61,14 +61,14 @@ inline float rgb_2_yc(float3 rgb) { return (b + g + r + ycRadiusWeight * chroma) / 3.0f; } -inline float sigmoid_shaper(float x) { +inline float sigmoid_shaper(float const x) { // Sigmoid function in the range 0 to 1 spanning -2 to +2. float t = max(1.0f - std::abs(x / 2.0f), 0.0f); float y = 1.0f + sign(x) * (1.0f - t * t); return y / 2.0f; } -inline float glow_fwd(float ycIn, float glowGainIn, float glowMid) { +inline float glow_fwd(float const ycIn, float const glowGainIn, float const glowMid) { float glowGainOut; if (ycIn <= 2.0f / 3.0f * glowMid) { @@ -82,7 +82,7 @@ inline float glow_fwd(float ycIn, float glowGainIn, float glowMid) { return glowGainOut; } -inline float rgb_2_hue(float3 rgb) { +inline float rgb_2_hue(float3 const rgb) { // Returns a geometric hue angle in degrees (0-360) based on RGB values. // For neutral colors, hue is undefined and the function will return a quiet NaN value. float hue = 0.0f; @@ -95,7 +95,7 @@ inline float rgb_2_hue(float3 rgb) { return (hue < 0.0f) ? hue + 360.0f : hue; } -inline float center_hue(float hue, float centerH) { +inline float center_hue(float const hue, float const centerH) { float hueCentered = hue - centerH; if (hueCentered < -180.0f) { hueCentered = hueCentered + 360.0f; @@ -198,7 +198,7 @@ DEFAULT_CONSTRUCTORS(ToneMapper) DEFAULT_CONSTRUCTORS(LinearToneMapper) -float3 LinearToneMapper::operator()(float3 v) const noexcept { +float3 LinearToneMapper::operator()(float3 const v) const noexcept { return saturate(v); } @@ -208,19 +208,19 @@ float3 LinearToneMapper::operator()(float3 v) const noexcept { DEFAULT_CONSTRUCTORS(ACESToneMapper) -float3 ACESToneMapper::operator()(math::float3 c) const noexcept { +float3 ACESToneMapper::operator()(float3 const c) const noexcept { return aces::ACES(c, 1.0f); } DEFAULT_CONSTRUCTORS(ACESLegacyToneMapper) -float3 ACESLegacyToneMapper::operator()(math::float3 c) const noexcept { +float3 ACESLegacyToneMapper::operator()(float3 const c) const noexcept { return aces::ACES(c, 1.0f / 0.6f); } DEFAULT_CONSTRUCTORS(FilmicToneMapper) -float3 FilmicToneMapper::operator()(math::float3 x) const noexcept { +float3 FilmicToneMapper::operator()(float3 const x) const noexcept { // Narkowicz 2015, "ACES Filmic Tone Mapping Curve" constexpr float a = 2.51f; constexpr float b = 0.03f; @@ -236,7 +236,7 @@ float3 FilmicToneMapper::operator()(math::float3 x) const noexcept { DEFAULT_CONSTRUCTORS(PBRNeutralToneMapper) -float3 PBRNeutralToneMapper::operator()(math::float3 color) const noexcept { +float3 PBRNeutralToneMapper::operator()(float3 color) const noexcept { // PBR Tone Mapping, https://modelviewer.dev/examples/tone-mapping.html constexpr float startCompression = 0.8f - 0.04f; constexpr float desaturation = 0.15f; @@ -260,7 +260,7 @@ float3 PBRNeutralToneMapper::operator()(math::float3 color) const noexcept { // AgX tone mapper //------------------------------------------------------------------------------ -AgxToneMapper::AgxToneMapper(AgxToneMapper::AgxLook look) noexcept : look(look) {} +AgxToneMapper::AgxToneMapper(AgxLook const look) noexcept : look(look) {} AgxToneMapper::~AgxToneMapper() noexcept = default; // These matrices taken from Blender's implementation of AgX, which works with Rec.2020 primaries. @@ -362,7 +362,7 @@ float3 AgxToneMapper::operator()(float3 v) const noexcept { DEFAULT_CONSTRUCTORS(DisplayRangeToneMapper) -float3 DisplayRangeToneMapper::operator()(math::float3 c) const noexcept { +float3 DisplayRangeToneMapper::operator()(float3 const c) const noexcept { // 16 debug colors + 1 duplicated at the end for easy indexing constexpr float3 debugColors[17] = { {0.0, 0.0, 0.0}, // black @@ -437,10 +437,10 @@ struct GenericToneMapper::Options { }; GenericToneMapper::GenericToneMapper( - float contrast, - float midGrayIn, - float midGrayOut, - float hdrMax + float const contrast, + float const midGrayIn, + float const midGrayOut, + float const hdrMax ) noexcept { mOptions = new Options(); mOptions->setParameters(contrast, midGrayIn, midGrayOut, hdrMax); @@ -460,7 +460,7 @@ GenericToneMapper& GenericToneMapper::operator=(GenericToneMapper&& rhs) noexcep return *this; } -float3 GenericToneMapper::operator()(math::float3 x) const noexcept { +float3 GenericToneMapper::operator()(float3 x) const noexcept { x = pow(x, mOptions->contrast); return mOptions->outputScale * x / (x + mOptions->inputScale); } @@ -470,7 +470,7 @@ float GenericToneMapper::getMidGrayIn() const noexcept { return mOptions->midGr float GenericToneMapper::getMidGrayOut() const noexcept { return mOptions->midGrayOut; } float GenericToneMapper::getHdrMax() const noexcept { return mOptions->hdrMax; } -void GenericToneMapper::setContrast(float contrast) noexcept { +void GenericToneMapper::setContrast(float const contrast) noexcept { mOptions->setParameters( contrast, mOptions->midGrayIn, @@ -478,7 +478,7 @@ void GenericToneMapper::setContrast(float contrast) noexcept { mOptions->hdrMax ); } -void GenericToneMapper::setMidGrayIn(float midGrayIn) noexcept { +void GenericToneMapper::setMidGrayIn(float const midGrayIn) noexcept { mOptions->setParameters( mOptions->contrast, midGrayIn, @@ -487,7 +487,7 @@ void GenericToneMapper::setMidGrayIn(float midGrayIn) noexcept { ); } -void GenericToneMapper::setMidGrayOut(float midGrayOut) noexcept { +void GenericToneMapper::setMidGrayOut(float const midGrayOut) noexcept { mOptions->setParameters( mOptions->contrast, mOptions->midGrayIn, @@ -496,7 +496,7 @@ void GenericToneMapper::setMidGrayOut(float midGrayOut) noexcept { ); } -void GenericToneMapper::setHdrMax(float hdrMax) noexcept { +void GenericToneMapper::setHdrMax(float const hdrMax) noexcept { mOptions->setParameters( mOptions->contrast, mOptions->midGrayIn, diff --git a/filament/src/TransformManager.cpp b/filament/src/TransformManager.cpp index 384b930c50..c9af857785 100644 --- a/filament/src/TransformManager.cpp +++ b/filament/src/TransformManager.cpp @@ -22,7 +22,7 @@ namespace filament { using namespace math; -bool TransformManager::hasComponent(Entity e) const noexcept { +bool TransformManager::hasComponent(Entity const e) const noexcept { return downcast(this)->hasComponent(e); } @@ -34,72 +34,72 @@ bool TransformManager::empty() const noexcept { return downcast(this)->empty(); } -utils::Entity TransformManager::getEntity(TransformManager::Instance i) const noexcept { +Entity TransformManager::getEntity(Instance const i) const noexcept { return downcast(this)->getEntity(i); } -utils::Entity const* TransformManager::getEntities() const noexcept { +Entity const* TransformManager::getEntities() const noexcept { return downcast(this)->getEntities(); } -TransformManager::Instance TransformManager::getInstance(Entity e) const noexcept { +TransformManager::Instance TransformManager::getInstance(Entity const e) const noexcept { return downcast(this)->getInstance(e); } -void TransformManager::create(Entity entity, Instance parent, const mat4f& worldTransform) { +void TransformManager::create(Entity const entity, Instance const parent, const mat4f& worldTransform) { downcast(this)->create(entity, parent, worldTransform); } -void TransformManager::create(Entity entity, Instance parent, const mat4& worldTransform) { +void TransformManager::create(Entity const entity, Instance const parent, const mat4& worldTransform) { downcast(this)->create(entity, parent, worldTransform); } -void TransformManager::create(Entity entity, Instance parent) { +void TransformManager::create(Entity const entity, Instance const parent) { downcast(this)->create(entity, parent, mat4f{}); } -void TransformManager::destroy(Entity e) noexcept { +void TransformManager::destroy(Entity const e) noexcept { downcast(this)->destroy(e); } -void TransformManager::setTransform(Instance ci, const mat4f& model) noexcept { +void TransformManager::setTransform(Instance const ci, const mat4f& model) noexcept { downcast(this)->setTransform(ci, model); } -void TransformManager::setTransform(Instance ci, const mat4& model) noexcept { +void TransformManager::setTransform(Instance const ci, const mat4& model) noexcept { downcast(this)->setTransform(ci, model); } -const mat4f& TransformManager::getTransform(Instance ci) const noexcept { +const mat4f& TransformManager::getTransform(Instance const ci) const noexcept { return downcast(this)->getTransform(ci); } -mat4 TransformManager::getTransformAccurate(Instance ci) const noexcept { +mat4 TransformManager::getTransformAccurate(Instance const ci) const noexcept { return downcast(this)->getTransformAccurate(ci); } -const mat4f& TransformManager::getWorldTransform(Instance ci) const noexcept { +const mat4f& TransformManager::getWorldTransform(Instance const ci) const noexcept { return downcast(this)->getWorldTransform(ci); } -mat4 TransformManager::getWorldTransformAccurate(Instance ci) const noexcept { +mat4 TransformManager::getWorldTransformAccurate(Instance const ci) const noexcept { return downcast(this)->getWorldTransformAccurate(ci); } -void TransformManager::setParent(Instance i, Instance newParent) noexcept { +void TransformManager::setParent(Instance const i, Instance const newParent) noexcept { downcast(this)->setParent(i, newParent); } -utils::Entity TransformManager::getParent(Instance i) const noexcept { +Entity TransformManager::getParent(Instance const i) const noexcept { return downcast(this)->getParent(i); } -size_t TransformManager::getChildCount(Instance i) const noexcept { +size_t TransformManager::getChildCount(Instance const i) const noexcept { return downcast(this)->getChildCount(i); } -size_t TransformManager::getChildren(Instance i, utils::Entity* children, - size_t count) const noexcept { +size_t TransformManager::getChildren(Instance const i, Entity* children, + size_t const count) const noexcept { return downcast(this)->getChildren(i, children, count); } @@ -112,16 +112,16 @@ void TransformManager::commitLocalTransformTransaction() noexcept { } TransformManager::children_iterator TransformManager::getChildrenBegin( - TransformManager::Instance parent) const noexcept { + Instance const parent) const noexcept { return downcast(this)->getChildrenBegin(parent); } TransformManager::children_iterator TransformManager::getChildrenEnd( - TransformManager::Instance parent) const noexcept { + Instance const parent) const noexcept { return downcast(this)->getChildrenEnd(parent); } -void TransformManager::setAccurateTranslationsEnabled(bool enable) noexcept { +void TransformManager::setAccurateTranslationsEnabled(bool const enable) noexcept { downcast(this)->setAccurateTranslationsEnabled(enable); } diff --git a/filament/src/UniformBuffer.cpp b/filament/src/UniformBuffer.cpp index acbce78bf0..e61ddc4f9d 100644 --- a/filament/src/UniformBuffer.cpp +++ b/filament/src/UniformBuffer.cpp @@ -23,12 +23,12 @@ using namespace filament::math; namespace filament { -UniformBuffer::UniformBuffer(size_t size) noexcept +UniformBuffer::UniformBuffer(size_t const size) noexcept : mBuffer(mStorage), mSize(uint32_t(size)), mSomethingDirty(true) { if (UTILS_LIKELY(size > sizeof(mStorage))) { - mBuffer = UniformBuffer::alloc(size); + mBuffer = alloc(size); } memset(mBuffer, 0, size); } @@ -65,13 +65,13 @@ UniformBuffer& UniformBuffer::setUniforms(const UniformBuffer& rhs) noexcept { if (UTILS_UNLIKELY(mSize != rhs.mSize)) { // first free our storage if any if (mBuffer && !isLocalStorage()) { - UniformBuffer::free(mBuffer, mSize); + free(mBuffer, mSize); } // and allocate new storage mBuffer = mStorage; mSize = rhs.mSize; if (mSize > sizeof(mStorage)) { - mBuffer = UniformBuffer::alloc(mSize); + mBuffer = alloc(mSize); } } memcpy(mBuffer, rhs.mBuffer, rhs.mSize); @@ -81,9 +81,9 @@ UniformBuffer& UniformBuffer::setUniforms(const UniformBuffer& rhs) noexcept { return *this; } -void* UniformBuffer::alloc(size_t size) noexcept { +void* UniformBuffer::alloc(size_t const size) noexcept { // these allocations have a long life span - return ::malloc(size); + return malloc(size); } void UniformBuffer::free(void* addr, size_t) noexcept { @@ -93,7 +93,7 @@ void UniformBuffer::free(void* addr, size_t) noexcept { // ------------------------------------------------------------------------------------------------ template -void UniformBuffer::setUniformUntyped(size_t offset, void const* UTILS_RESTRICT v) noexcept{ +void UniformBuffer::setUniformUntyped(size_t const offset, void const* UTILS_RESTRICT v) noexcept{ setUniformUntyped(invalidateUniforms(offset, Size), 0ul, v); } @@ -109,7 +109,7 @@ template void UniformBuffer::setUniformUntyped<64ul>(size_t offset, void const* UTILS_RESTRICT v) noexcept; template -void UniformBuffer::setUniformArrayUntyped(size_t offset, void const* UTILS_RESTRICT begin, size_t count) noexcept { +void UniformBuffer::setUniformArrayUntyped(size_t const offset, void const* UTILS_RESTRICT begin, size_t const count) noexcept { constexpr size_t stride = (Size + 0xFu) & ~0xFu; size_t arraySize = stride * count - stride + Size; void* UTILS_RESTRICT p = invalidateUniforms(offset, arraySize); @@ -133,7 +133,7 @@ void UniformBuffer::setUniformArrayUntyped<64ul>(size_t offset, void const* UTIL // specialization for mat3f (which has a different alignment, see std140 layout rules) template<> UTILS_NOINLINE -void UniformBuffer::setUniform(void* addr, size_t offset, const math::mat3f& v) noexcept { +void UniformBuffer::setUniform(void* addr, size_t const offset, const mat3f& v) noexcept { struct mat43 { float v[3][4]; }; @@ -157,7 +157,7 @@ void UniformBuffer::setUniform(void* addr, size_t offset, const math::mat3f& v) } template<> -void UniformBuffer::setUniform(size_t offset, const math::mat3f& v) noexcept { +void UniformBuffer::setUniform(size_t const offset, const mat3f& v) noexcept { setUniform(invalidateUniforms(offset, sizeof(v)), 0, v); } diff --git a/filament/src/UniformBuffer.h b/filament/src/UniformBuffer.h index 090ee76eec..0499479ff6 100644 --- a/filament/src/UniformBuffer.h +++ b/filament/src/UniformBuffer.h @@ -60,14 +60,14 @@ public: // immediately jump into libc's free() if (mBuffer && !isLocalStorage()) { // test not necessary but avoids a call to libc (and this is a common enough case) - UniformBuffer::free(mBuffer, mSize); + free(mBuffer, mSize); } } UniformBuffer& setUniforms(const UniformBuffer& rhs) noexcept; // invalidate a range of uniforms and return a pointer to it. offset and size given in bytes - void* invalidateUniforms(size_t offset, size_t size) { + void* invalidateUniforms(size_t const offset, size_t const size) { assert_invariant(offset + size <= mSize); mSomethingDirty = true; return static_cast(mBuffer) + offset; @@ -133,7 +133,7 @@ public: // The "x" symbols represent dummy words. template::type> UTILS_ALWAYS_INLINE - void setUniformArray(size_t offset, T const* UTILS_RESTRICT begin, size_t count) noexcept { + void setUniformArray(size_t const offset, T const* UTILS_RESTRICT begin, size_t const count) noexcept { static_assert(!std::is_same_v); setUniformArrayUntyped(offset, begin, count); } @@ -141,21 +141,21 @@ public: // (see specialization for mat3f below) template::type> UTILS_ALWAYS_INLINE - static inline void setUniform(void* addr, size_t offset, const T& v) noexcept { + static inline void setUniform(void* addr, size_t const offset, const T& v) noexcept { static_assert(!std::is_same_v); setUniformUntyped(addr, offset, &v); } template::type> UTILS_ALWAYS_INLINE - inline void setUniform(size_t offset, const T& v) noexcept { + inline void setUniform(size_t const offset, const T& v) noexcept { static_assert(!std::is_same_v); setUniformUntyped(offset, &v); } // get uniform of known types from the proper offset (e.g.: use offsetof()) template::type> - T getUniform(size_t offset) const noexcept { + T getUniform(size_t const offset) const noexcept { static_assert(!std::is_same_v); return *reinterpret_cast(static_cast(mBuffer) + offset); } @@ -168,7 +168,7 @@ public: // copy the UBO data and cleans the dirty bits backend::BufferDescriptor toBufferDescriptor( - backend::DriverApi& driver, size_t offset, size_t size) const noexcept { + backend::DriverApi& driver, size_t const offset, size_t const size) const noexcept { backend::BufferDescriptor p; p.size = size; p.buffer = driver.allocate(p.size); // TODO: use out-of-line buffer if too large @@ -194,7 +194,7 @@ private: template = true> UTILS_ALWAYS_INLINE - static void setUniformUntyped(void* addr, size_t offset, void const* v) noexcept { + static void setUniformUntyped(void* addr, size_t const offset, void const* v) noexcept { memcpy(static_cast(addr) + offset, v, Size); // inlined } @@ -215,13 +215,13 @@ void UniformBuffer::setUniform(size_t offset, const math::mat3f& v) noexcept; template<> inline void UniformBuffer::setUniformArray( - size_t offset, math::mat3f const* UTILS_RESTRICT begin, size_t count) noexcept { + size_t const offset, math::mat3f const* UTILS_RESTRICT begin, size_t const count) noexcept { // pretend each mat3 is an array of 3 float3 setUniformArray(offset, reinterpret_cast(begin), count * 3); } template<> -inline math::mat3f UniformBuffer::getUniform(size_t offset) const noexcept { +inline math::mat3f UniformBuffer::getUniform(size_t const offset) const noexcept { math::float4 const* p = reinterpret_cast( static_cast(mBuffer) + offset); return { p[0].xyz, p[1].xyz, p[2].xyz }; diff --git a/filament/src/VertexBuffer.cpp b/filament/src/VertexBuffer.cpp index 37e8f63f81..6c6243be73 100644 --- a/filament/src/VertexBuffer.cpp +++ b/filament/src/VertexBuffer.cpp @@ -24,12 +24,12 @@ size_t VertexBuffer::getVertexCount() const noexcept { return downcast(this)->getVertexCount(); } -void VertexBuffer::setBufferAt(Engine& engine, uint8_t bufferIndex, - backend::BufferDescriptor&& buffer, uint32_t byteOffset) { +void VertexBuffer::setBufferAt(Engine& engine, uint8_t const bufferIndex, + backend::BufferDescriptor&& buffer, uint32_t const byteOffset) { downcast(this)->setBufferAt(downcast(engine), bufferIndex, std::move(buffer), byteOffset); } -void VertexBuffer::setBufferObjectAt(Engine& engine, uint8_t bufferIndex, +void VertexBuffer::setBufferObjectAt(Engine& engine, uint8_t const bufferIndex, BufferObject const* bufferObject) { downcast(this)->setBufferObjectAt(downcast(engine), bufferIndex, downcast(bufferObject)); } diff --git a/filament/src/View.cpp b/filament/src/View.cpp index 7bd4f718ad..4bf4e53348 100644 --- a/filament/src/View.cpp +++ b/filament/src/View.cpp @@ -41,15 +41,15 @@ Camera& View::getCamera() noexcept { return downcast(this)->getCameraUser(); } -void View::setViewport(filament::Viewport const& viewport) noexcept { +void View::setViewport(Viewport const& viewport) noexcept { downcast(this)->setViewport(viewport); } -filament::Viewport const& View::getViewport() const noexcept { +Viewport const& View::getViewport() const noexcept { return downcast(this)->getViewport(); } -void View::setFrustumCullingEnabled(bool culling) noexcept { +void View::setFrustumCullingEnabled(bool const culling) noexcept { downcast(this)->setFrustumCullingEnabled(culling); } @@ -61,7 +61,7 @@ void View::setDebugCamera(Camera* camera) noexcept { downcast(this)->setViewingCamera(downcast(camera)); } -void View::setVisibleLayers(uint8_t select, uint8_t values) noexcept { +void View::setVisibleLayers(uint8_t const select, uint8_t const values) noexcept { downcast(this)->setVisibleLayers(select, values); } @@ -77,7 +77,7 @@ utils::FixedCapacityVector View::getDirectionalShadowCameras() co return downcast(this)->getDirectionalShadowCameras(); } -void View::setShadowingEnabled(bool enabled) noexcept { +void View::setShadowingEnabled(bool const enabled) noexcept { downcast(this)->setShadowingEnabled(enabled); } @@ -89,7 +89,7 @@ RenderTarget* View::getRenderTarget() const noexcept { return downcast(this)->getRenderTarget(); } -void View::setSampleCount(uint8_t count) noexcept { +void View::setSampleCount(uint8_t const count) noexcept { downcast(this)->setSampleCount(count); } @@ -97,7 +97,7 @@ uint8_t View::getSampleCount() const noexcept { return downcast(this)->getSampleCount(); } -void View::setAntiAliasing(AntiAliasing type) noexcept { +void View::setAntiAliasing(AntiAliasing const type) noexcept { downcast(this)->setAntiAliasing(type); } @@ -113,7 +113,7 @@ const View::TemporalAntiAliasingOptions& View::getTemporalAntiAliasingOptions() return downcast(this)->getTemporalAntiAliasingOptions(); } -void View::setMultiSampleAntiAliasingOptions(MultiSampleAntiAliasingOptions options) noexcept { +void View::setMultiSampleAntiAliasingOptions(MultiSampleAntiAliasingOptions const options) noexcept { downcast(this)->setMultiSampleAntiAliasingOptions(options); } @@ -129,7 +129,7 @@ const View::ScreenSpaceReflectionsOptions& View::getScreenSpaceReflectionsOption return downcast(this)->getScreenSpaceReflectionsOptions(); } -void View::setGuardBandOptions(GuardBandOptions options) noexcept { +void View::setGuardBandOptions(GuardBandOptions const options) noexcept { downcast(this)->setGuardBandOptions(options); } @@ -145,7 +145,7 @@ const ColorGrading* View::getColorGrading() const noexcept { return downcast(this)->getColorGrading(); } -void View::setDithering(Dithering dithering) noexcept { +void View::setDithering(Dithering const dithering) noexcept { downcast(this)->setDithering(dithering); } @@ -169,7 +169,7 @@ View::RenderQuality View::getRenderQuality() const noexcept { return downcast(this)->getRenderQuality(); } -void View::setPostProcessingEnabled(bool enabled) noexcept { +void View::setPostProcessingEnabled(bool const enabled) noexcept { downcast(this)->setPostProcessingEnabled(enabled); } @@ -177,7 +177,7 @@ bool View::isPostProcessingEnabled() const noexcept { return downcast(this)->hasPostProcessPass(); } -void View::setFrontFaceWindingInverted(bool inverted) noexcept { +void View::setFrontFaceWindingInverted(bool const inverted) noexcept { downcast(this)->setFrontFaceWindingInverted(inverted); } @@ -185,7 +185,7 @@ bool View::isFrontFaceWindingInverted() const noexcept { return downcast(this)->isFrontFaceWindingInverted(); } -void View::setTransparentPickingEnabled(bool enabled) noexcept { +void View::setTransparentPickingEnabled(bool const enabled) noexcept { downcast(this)->setTransparentPickingEnabled(enabled); } @@ -193,11 +193,11 @@ bool View::isTransparentPickingEnabled() const noexcept { return downcast(this)->isTransparentPickingEnabled(); } -void View::setDynamicLightingOptions(float zLightNear, float zLightFar) noexcept { +void View::setDynamicLightingOptions(float const zLightNear, float const zLightFar) noexcept { downcast(this)->setDynamicLightingOptions(zLightNear, zLightFar); } -void View::setShadowType(View::ShadowType shadow) noexcept { +void View::setShadowType(ShadowType const shadow) noexcept { downcast(this)->setShadowType(shadow); } @@ -221,7 +221,7 @@ SoftShadowOptions View::getSoftShadowOptions() const noexcept { return downcast(this)->getSoftShadowOptions(); } -void View::setAmbientOcclusion(View::AmbientOcclusion ambientOcclusion) noexcept { +void View::setAmbientOcclusion(AmbientOcclusion const ambientOcclusion) noexcept { downcast(this)->setAmbientOcclusion(ambientOcclusion); } @@ -229,7 +229,7 @@ View::AmbientOcclusion View::getAmbientOcclusion() const noexcept { return downcast(this)->getAmbientOcclusion(); } -void View::setAmbientOcclusionOptions(View::AmbientOcclusionOptions const& options) noexcept { +void View::setAmbientOcclusionOptions(AmbientOcclusionOptions const& options) noexcept { downcast(this)->setAmbientOcclusionOptions(options); } @@ -237,7 +237,7 @@ View::AmbientOcclusionOptions const& View::getAmbientOcclusionOptions() const no return downcast(this)->getAmbientOcclusionOptions(); } -void View::setBloomOptions(View::BloomOptions options) noexcept { +void View::setBloomOptions(BloomOptions options) noexcept { downcast(this)->setBloomOptions(options); } @@ -245,7 +245,7 @@ View::BloomOptions View::getBloomOptions() const noexcept { return downcast(this)->getBloomOptions(); } -void View::setFogOptions(View::FogOptions options) noexcept { +void View::setFogOptions(FogOptions options) noexcept { downcast(this)->setFogOptions(options); } @@ -261,7 +261,7 @@ View::DepthOfFieldOptions View::getDepthOfFieldOptions() const noexcept { return downcast(this)->getDepthOfFieldOptions(); } -void View::setVignetteOptions(View::VignetteOptions options) noexcept { +void View::setVignetteOptions(VignetteOptions options) noexcept { downcast(this)->setVignetteOptions(options); } @@ -269,7 +269,7 @@ View::VignetteOptions View::getVignetteOptions() const noexcept { return downcast(this)->getVignetteOptions(); } -void View::setBlendMode(BlendMode blendMode) noexcept { +void View::setBlendMode(BlendMode const blendMode) noexcept { downcast(this)->setBlendMode(blendMode); } @@ -285,7 +285,7 @@ bool View::isShadowingEnabled() const noexcept { return downcast(this)->isShadowingEnabled(); } -void View::setScreenSpaceRefractionEnabled(bool enabled) noexcept { +void View::setScreenSpaceRefractionEnabled(bool const enabled) noexcept { downcast(this)->setScreenSpaceRefractionEnabled(enabled); } @@ -293,7 +293,7 @@ bool View::isScreenSpaceRefractionEnabled() const noexcept { return downcast(this)->isScreenSpaceRefractionEnabled(); } -void View::setStencilBufferEnabled(bool enabled) noexcept { +void View::setStencilBufferEnabled(bool const enabled) noexcept { downcast(this)->setStencilBufferEnabled(enabled); } @@ -309,16 +309,16 @@ const View::StereoscopicOptions& View::getStereoscopicOptions() const noexcept { return downcast(this)->getStereoscopicOptions(); } -View::PickingQuery& View::pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler, - View::PickingQueryResultCallback callback) noexcept { +View::PickingQuery& View::pick(uint32_t const x, uint32_t const y, backend::CallbackHandler* handler, + PickingQueryResultCallback const callback) noexcept { return downcast(this)->pick(x, y, handler, callback); } -void View::setMaterialGlobal(uint32_t index, math::float4 const& value) { +void View::setMaterialGlobal(uint32_t const index, math::float4 const& value) { downcast(this)->setMaterialGlobal(index, value); } -math::float4 View::getMaterialGlobal(uint32_t index) const { +math::float4 View::getMaterialGlobal(uint32_t const index) const { return downcast(this)->getMaterialGlobal(index); } diff --git a/filament/src/components/CameraManager.cpp b/filament/src/components/CameraManager.cpp index b48742eae6..8e9b41dd14 100644 --- a/filament/src/components/CameraManager.cpp +++ b/filament/src/components/CameraManager.cpp @@ -40,16 +40,16 @@ void FCameraManager::terminate(FEngine& engine) noexcept { slog.d << "cleaning up " << manager.getComponentCount() << " leaked Camera components" << io::endl; #endif - utils::Slice const entities{ manager.getEntities(), manager.getComponentCount() }; + Slice const entities{ manager.getEntities(), manager.getComponentCount() }; for (Entity const e : entities) { destroy(engine, e); } } } -void FCameraManager::gc(FEngine& engine, utils::EntityManager& em) noexcept { +void FCameraManager::gc(FEngine& engine, EntityManager& em) noexcept { auto& manager = mManager; - manager.gc(em, [this, &engine](Entity e) { + manager.gc(em, [this, &engine](Entity const e) { destroy(engine, e); }); } @@ -79,7 +79,7 @@ FCamera* FCameraManager::create(FEngine& engine, Entity entity) { return camera; } -void FCameraManager::destroy(FEngine& engine, Entity e) noexcept { +void FCameraManager::destroy(FEngine& engine, Entity const e) noexcept { auto& manager = mManager; if (Instance const i = manager.getInstance(e) ; i) { // destroy the FCamera object diff --git a/filament/src/components/CameraManager.h b/filament/src/components/CameraManager.h index 67bbfcb9ae..a3d23f6995 100644 --- a/filament/src/components/CameraManager.h +++ b/filament/src/components/CameraManager.h @@ -37,7 +37,7 @@ class FCamera; class UTILS_PRIVATE FCameraManager : public CameraManager { public: - using Instance = CameraManager::Instance; + using Instance = Instance; explicit FCameraManager(FEngine& engine) noexcept; @@ -52,11 +52,11 @@ public: * Component Manager APIs */ - bool hasComponent(utils::Entity e) const noexcept { + bool hasComponent(utils::Entity const e) const noexcept { return mManager.hasComponent(e); } - Instance getInstance(utils::Entity e) const noexcept { + Instance getInstance(utils::Entity const e) const noexcept { return { mManager.getInstance(e) }; } @@ -68,7 +68,7 @@ public: return mManager.empty(); } - utils::Entity getEntity(Instance i) const noexcept { + utils::Entity getEntity(Instance const i) const noexcept { return mManager.getEntity(i); } @@ -76,7 +76,7 @@ public: return mManager.getEntities(); } - FCamera* getCamera(Instance i) noexcept { + FCamera* getCamera(Instance const i) noexcept { return mManager.elementAt(i); } diff --git a/filament/src/components/LightManager.cpp b/filament/src/components/LightManager.cpp index cc9a539413..4b677bc754 100644 --- a/filament/src/components/LightManager.cpp +++ b/filament/src/components/LightManager.cpp @@ -64,7 +64,7 @@ struct LightManager::BuilderDetails { float mSunHaloFalloff = 80.0f; ShadowOptions mShadowOptions; - explicit BuilderDetails(Type type) noexcept : mType(type) { } + explicit BuilderDetails(Type const type) noexcept : mType(type) { } // this is only needed for the explicit instantiation below BuilderDetails() = default; }; @@ -77,7 +77,7 @@ BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -LightManager::Builder& LightManager::Builder::castShadows(bool enable) noexcept { +LightManager::Builder& LightManager::Builder::castShadows(bool const enable) noexcept { mImpl->mCastShadows = enable; return *this; } @@ -87,7 +87,7 @@ LightManager::Builder& LightManager::Builder::shadowOptions(const ShadowOptions& return *this; } -LightManager::Builder& LightManager::Builder::castLight(bool enable) noexcept { +LightManager::Builder& LightManager::Builder::castLight(bool const enable) noexcept { mImpl->mCastLight = enable; return *this; } @@ -107,25 +107,25 @@ LightManager::Builder& LightManager::Builder::color(const LinearColor& color) no return *this; } -LightManager::Builder& LightManager::Builder::intensity(float intensity) noexcept { +LightManager::Builder& LightManager::Builder::intensity(float const intensity) noexcept { mImpl->mIntensity = intensity; mImpl->mIntensityUnit = FLightManager::IntensityUnit::LUMEN_LUX; return *this; } -LightManager::Builder& LightManager::Builder::intensityCandela(float intensity) noexcept { +LightManager::Builder& LightManager::Builder::intensityCandela(float const intensity) noexcept { mImpl->mIntensity = intensity; mImpl->mIntensityUnit = FLightManager::IntensityUnit::CANDELA; return *this; } -LightManager::Builder& LightManager::Builder::intensity(float watts, float efficiency) noexcept { +LightManager::Builder& LightManager::Builder::intensity(float const watts, float const efficiency) noexcept { mImpl->mIntensity = efficiency * 683.0f * watts; mImpl->mIntensityUnit = FLightManager::IntensityUnit::LUMEN_LUX; return *this; } -LightManager::Builder& LightManager::Builder::falloff(float radius) noexcept { +LightManager::Builder& LightManager::Builder::falloff(float const radius) noexcept { mImpl->mFalloff = radius; return *this; } @@ -135,22 +135,22 @@ LightManager::Builder& LightManager::Builder::spotLightCone(float inner, float o return *this; } -LightManager::Builder& LightManager::Builder::sunAngularRadius(float sunAngle) noexcept { +LightManager::Builder& LightManager::Builder::sunAngularRadius(float const sunAngle) noexcept { mImpl->mSunAngle = sunAngle; return *this; } -LightManager::Builder& LightManager::Builder::sunHaloSize(float haloSize) noexcept { +LightManager::Builder& LightManager::Builder::sunHaloSize(float const haloSize) noexcept { mImpl->mSunHaloSize = haloSize; return *this; } -LightManager::Builder& LightManager::Builder::sunHaloFalloff(float haloFalloff) noexcept { +LightManager::Builder& LightManager::Builder::sunHaloFalloff(float const haloFalloff) noexcept { mImpl->mSunHaloFalloff = haloFalloff; return *this; } -LightManager::Builder& LightManager::Builder::lightChannel(unsigned int channel, bool enable) noexcept { +LightManager::Builder& LightManager::Builder::lightChannel(unsigned int const channel, bool const enable) noexcept { if (channel < 8) { const uint8_t mask = 1u << channel; mImpl->mChannels &= ~mask; @@ -159,7 +159,7 @@ LightManager::Builder& LightManager::Builder::lightChannel(unsigned int channel, return *this; } -LightManager::Builder::Result LightManager::Builder::build(Engine& engine, Entity entity) { +LightManager::Builder::Result LightManager::Builder::build(Engine& engine, Entity const entity) { downcast(engine).createLight(*this, entity); return Success; } @@ -179,7 +179,7 @@ FLightManager::~FLightManager() { void FLightManager::init(FEngine&) noexcept { } -void FLightManager::create(const Builder& builder, Entity entity) { +void FLightManager::create(const Builder& builder, Entity const entity) { auto& manager = mManager; if (UTILS_UNLIKELY(manager.hasComponent(entity))) { @@ -218,7 +218,7 @@ void FLightManager::create(const Builder& builder, Entity entity) { void FLightManager::prepare(backend::DriverApi&) const noexcept { } -void FLightManager::destroy(Entity e) noexcept { +void FLightManager::destroy(Entity const e) noexcept { Instance const i = getInstance(e); if (i) { auto& manager = mManager; @@ -240,7 +240,7 @@ void FLightManager::terminate() noexcept { } } void FLightManager::gc(EntityManager& em) noexcept { - mManager.gc(em, [this](Entity e) { + mManager.gc(em, [this](Entity const e) { destroy(e); }); } @@ -258,7 +258,7 @@ void FLightManager::setShadowOptions(Instance const i, ShadowOptions const& opti params.options.vsm.blurWidth = std::max(0.0f, options.vsm.blurWidth); } -void FLightManager::setLightChannel(Instance i, unsigned int channel, bool enable) noexcept { +void FLightManager::setLightChannel(Instance const i, unsigned int const channel, bool const enable) noexcept { if (i) { if (channel < 8) { auto& manager = mManager; @@ -269,7 +269,7 @@ void FLightManager::setLightChannel(Instance i, unsigned int channel, bool enabl } } -bool FLightManager::getLightChannel(Instance i, unsigned int channel) const noexcept { +bool FLightManager::getLightChannel(Instance const i, unsigned int const channel) const noexcept { if (i) { if (channel < 8) { auto& manager = mManager; @@ -280,28 +280,28 @@ bool FLightManager::getLightChannel(Instance i, unsigned int channel) const noex return false; } -void FLightManager::setLocalPosition(Instance i, const float3& position) noexcept { +void FLightManager::setLocalPosition(Instance const i, const float3& position) noexcept { if (i) { auto& manager = mManager; manager[i].position = position; } } -void FLightManager::setLocalDirection(Instance i, float3 direction) noexcept { +void FLightManager::setLocalDirection(Instance const i, float3 const direction) noexcept { if (i) { auto& manager = mManager; manager[i].direction = direction; } } -void FLightManager::setColor(Instance i, const LinearColor& color) noexcept { +void FLightManager::setColor(Instance const i, const LinearColor& color) noexcept { if (i) { auto& manager = mManager; manager[i].color = color; } } -void FLightManager::setIntensity(Instance i, float intensity, IntensityUnit unit) noexcept { +void FLightManager::setIntensity(Instance const i, float const intensity, IntensityUnit const unit) noexcept { auto& manager = mManager; if (i) { Type const type = getLightType(i).type; @@ -356,7 +356,7 @@ void FLightManager::setIntensity(Instance i, float intensity, IntensityUnit unit } } -void FLightManager::setFalloff(Instance i, float falloff) noexcept { +void FLightManager::setFalloff(Instance const i, float const falloff) noexcept { auto& manager = mManager; if (i && !isDirectionalLight(i)) { float const sqFalloff = falloff * falloff; @@ -366,7 +366,7 @@ void FLightManager::setFalloff(Instance i, float falloff) noexcept { } } -void FLightManager::setSpotLightCone(Instance i, float inner, float outer) noexcept { +void FLightManager::setSpotLightCone(Instance const i, float const inner, float const outer) noexcept { auto& manager = mManager; if (i && isSpotLight(i)) { // clamp the inner/outer angles to [0.5 degrees, 90 degrees] @@ -399,33 +399,33 @@ void FLightManager::setSpotLightCone(Instance i, float inner, float outer) noexc } } -void FLightManager::setSunAngularRadius(Instance i, float angularRadius) noexcept { +void FLightManager::setSunAngularRadius(Instance const i, float angularRadius) noexcept { if (i && isSunLight(i)) { angularRadius = clamp(angularRadius, 0.25f, 20.0f); mManager[i].sunAngularRadius = angularRadius * f::DEG_TO_RAD; } } -void FLightManager::setSunHaloSize(Instance i, float haloSize) noexcept { +void FLightManager::setSunHaloSize(Instance const i, float const haloSize) noexcept { if (i && isSunLight(i)) { mManager[i].sunHaloSize = haloSize; } } -void FLightManager::setSunHaloFalloff(Instance i, float haloFalloff) noexcept { +void FLightManager::setSunHaloFalloff(Instance const i, float const haloFalloff) noexcept { if (i && isSunLight(i)) { mManager[i].sunHaloFalloff = haloFalloff; } } -void FLightManager::setShadowCaster(Instance i, bool shadowCaster) noexcept { +void FLightManager::setShadowCaster(Instance const i, bool const shadowCaster) noexcept { if (i) { LightType& lightType = mManager[i].lightType; lightType.shadowCaster = shadowCaster; } } -float FLightManager::getSpotLightInnerCone(Instance i) const noexcept { +float FLightManager::getSpotLightInnerCone(Instance const i) const noexcept { const auto& spotParams = getSpotParams(i); float const cosOuter = std::cos(spotParams.outerClamped); float const scale = spotParams.scaleOffset.x; @@ -446,7 +446,7 @@ void LightManager::ShadowCascades::computeUniformSplits(float splitPositions[3], } void LightManager::ShadowCascades::computeLogSplits(float splitPositions[3], uint8_t cascades, - float near, float far) { + float const near, float const far) { size_t s = 0; cascades = min(cascades, (uint8_t) 4u); for (size_t c = 1; c < cascades; c++) { @@ -456,7 +456,7 @@ void LightManager::ShadowCascades::computeLogSplits(float splitPositions[3], uin } void LightManager::ShadowCascades::computePracticalSplits(float splitPositions[3], uint8_t cascades, - float near, float far, float lambda) { + float const near, float const far, float const lambda) { float uniformSplits[3]; float logSplits[3]; cascades = min(cascades, (uint8_t) 4u); diff --git a/filament/src/components/LightManager.h b/filament/src/components/LightManager.h index 317ec723f7..19826e54ac 100644 --- a/filament/src/components/LightManager.h +++ b/filament/src/components/LightManager.h @@ -35,7 +35,7 @@ class FScene; class FLightManager : public LightManager { public: - using Instance = LightManager::Instance; + using Instance = Instance; explicit FLightManager(FEngine& engine) noexcept; ~FLightManager(); @@ -50,11 +50,11 @@ public: * Component Manager APIs */ - bool hasComponent(utils::Entity e) const noexcept { + bool hasComponent(utils::Entity const e) const noexcept { return mManager.hasComponent(e); } - Instance getInstance(utils::Entity e) const noexcept { + Instance getInstance(utils::Entity const e) const noexcept { return { mManager.getInstance(e) }; } @@ -66,7 +66,7 @@ public: return mManager.empty(); } - utils::Entity getEntity(Instance i) const noexcept { + utils::Entity getEntity(Instance const i) const noexcept { return mManager.getEntity(i); } @@ -74,7 +74,7 @@ public: return mManager.getEntities(); } - void create(const FLightManager::Builder& builder, utils::Entity entity); + void create(const Builder& builder, utils::Entity entity); void destroy(utils::Entity e) noexcept; @@ -101,7 +101,7 @@ public: }; struct ShadowParams { // TODO: get rid of this struct - LightManager::ShadowOptions options; + ShadowOptions options; }; UTILS_NOINLINE void setLocalPosition(Instance i, const math::float3& position) noexcept; @@ -118,32 +118,32 @@ public: UTILS_NOINLINE bool getLightChannel(Instance i, unsigned int channel) const noexcept; - LightType const& getLightType(Instance i) const noexcept { + LightType const& getLightType(Instance const i) const noexcept { return mManager[i].lightType; } - Type getType(Instance i) const noexcept { + Type getType(Instance const i) const noexcept { return getLightType(i).type; } - bool isShadowCaster(Instance i) const noexcept { + bool isShadowCaster(Instance const i) const noexcept { return getLightType(i).shadowCaster; } - bool isLightCaster(Instance i) const noexcept { + bool isLightCaster(Instance const i) const noexcept { return getLightType(i).lightCaster; } - bool isPointLight(Instance i) const noexcept { + bool isPointLight(Instance const i) const noexcept { return getType(i) == Type::POINT; } - bool isSpotLight(Instance i) const noexcept { + bool isSpotLight(Instance const i) const noexcept { Type const type = getType(i); return type == Type::FOCUSED_SPOT || type == Type::SPOT; } - bool isDirectionalLight(Instance i) const noexcept { + bool isDirectionalLight(Instance const i) const noexcept { Type const type = getType(i); return type == Type::DIRECTIONAL || type == Type::SUN; } @@ -152,89 +152,89 @@ public: return false; // TODO: change this when we support IES lights } - bool isSunLight(Instance i) const noexcept { + bool isSunLight(Instance const i) const noexcept { return getType(i) == Type::SUN; } - uint32_t getShadowMapSize(Instance i) const noexcept { + uint32_t getShadowMapSize(Instance const i) const noexcept { return getShadowParams(i).options.mapSize; } - ShadowParams const& getShadowParams(Instance i) const noexcept { + ShadowParams const& getShadowParams(Instance const i) const noexcept { return mManager[i].shadowParams; } - float getShadowConstantBias(Instance i) const noexcept { + float getShadowConstantBias(Instance const i) const noexcept { return getShadowParams(i).options.constantBias; } - float getShadowNormalBias(Instance i) const noexcept { + float getShadowNormalBias(Instance const i) const noexcept { return getShadowParams(i).options.normalBias; } - float getShadowFar(Instance i) const noexcept { + float getShadowFar(Instance const i) const noexcept { return getShadowParams(i).options.shadowFar; } - const math::float3& getColor(Instance i) const noexcept { + const math::float3& getColor(Instance const i) const noexcept { return mManager[i].color; } - float getIntensity(Instance i) const noexcept { + float getIntensity(Instance const i) const noexcept { return mManager[i].intensity; } - float getSunAngularRadius(Instance i) const noexcept { + float getSunAngularRadius(Instance const i) const noexcept { return mManager[i].sunAngularRadius; } - float getSunHaloSize(Instance i) const noexcept { + float getSunHaloSize(Instance const i) const noexcept { return mManager[i].sunHaloSize; } - float getSunHaloFalloff(Instance i) const noexcept { + float getSunHaloFalloff(Instance const i) const noexcept { return mManager[i].sunHaloFalloff; } - float getSquaredFalloffInv(Instance i) const noexcept { + float getSquaredFalloffInv(Instance const i) const noexcept { return mManager[i].squaredFallOffInv; } - float getFalloff(Instance i) const noexcept { + float getFalloff(Instance const i) const noexcept { return getRadius(i); } - SpotParams const& getSpotParams(Instance i) const noexcept { + SpotParams const& getSpotParams(Instance const i) const noexcept { return mManager[i].spotParams; } float getSpotLightInnerCone(Instance i) const noexcept; - float getCosOuterSquared(Instance i) const noexcept { + float getCosOuterSquared(Instance const i) const noexcept { return getSpotParams(i).cosOuterSquared; } - float getSinInverse(Instance i) const noexcept { + float getSinInverse(Instance const i) const noexcept { return getSpotParams(i).sinInverse; } - float getRadius(Instance i) const noexcept { + float getRadius(Instance const i) const noexcept { return getSpotParams(i).radius; } - uint8_t getLightChannels(Instance i) const noexcept { + uint8_t getLightChannels(Instance const i) const noexcept { return mManager[i].channels; } - const math::float3& getLocalPosition(Instance i) const noexcept { + const math::float3& getLocalPosition(Instance const i) const noexcept { return mManager[i].position; } - const math::float3& getLocalDirection(Instance i) const noexcept { + const math::float3& getLocalDirection(Instance const i) const noexcept { return mManager[i].direction; } - const ShadowOptions& getShadowOptions(Instance i) const noexcept { + const ShadowOptions& getShadowOptions(Instance const i) const noexcept { return getShadowParams(i).options; } diff --git a/filament/src/components/RenderableManager.cpp b/filament/src/components/RenderableManager.cpp index 8dfd56b449..41381667d0 100644 --- a/filament/src/components/RenderableManager.cpp +++ b/filament/src/components/RenderableManager.cpp @@ -76,7 +76,7 @@ struct RenderableManager::BuilderDetails { Box mAABB; uint8_t mLayerMask = 0x1; uint8_t mPriority = 0x4; - uint8_t mCommandChannel = RenderableManager::Builder::DEFAULT_CHANNEL; + uint8_t mCommandChannel = Builder::DEFAULT_CHANNEL; uint8_t mLightChannels = 1; uint16_t mInstanceCount = 1; bool mCulling : 1; @@ -85,7 +85,7 @@ struct RenderableManager::BuilderDetails { bool mScreenSpaceContactShadows : 1; bool mSkinningBufferMode : 1; bool mFogEnabled : 1; - RenderableManager::Builder::GeometryType mGeometryType : 2; + Builder::GeometryType mGeometryType : 2; size_t mSkinningBoneCount = 0; size_t mMorphTargetCount = 0; FMorphTargetBuffer* mMorphTargetBuffer = nullptr; @@ -94,53 +94,53 @@ struct RenderableManager::BuilderDetails { FSkinningBuffer* mSkinningBuffer = nullptr; FInstanceBuffer* mInstanceBuffer = nullptr; uint32_t mSkinningBufferOffset = 0; - utils::FixedCapacityVector mBoneIndicesAndWeights; + FixedCapacityVector mBoneIndicesAndWeights; size_t mBoneIndicesAndWeightsCount = 0; // bone indices and weights defined for primitive index - std::unordered_map>> mBonePairs; + std::unordered_map>> mBonePairs; - explicit BuilderDetails(size_t count) + explicit BuilderDetails(size_t const count) : mEntries(count), mCulling(true), mCastShadows(false), mReceiveShadows(true), mScreenSpaceContactShadows(false), mSkinningBufferMode(false), mFogEnabled(true), - mGeometryType(RenderableManager::Builder::GeometryType::DYNAMIC), + mGeometryType(Builder::GeometryType::DYNAMIC), mBonePairs() { } // this is only needed for the explicit instantiation below BuilderDetails() = default; - void processBoneIndicesAndWights(Engine& engine, utils::Entity entity); + void processBoneIndicesAndWights(Engine& engine, Entity entity); }; using BuilderType = RenderableManager; BuilderType::Builder::Builder(size_t count) noexcept - : BuilderBase(count) { + : BuilderBase(count) { assert_invariant(mImpl->mEntries.size() == count); } BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -RenderableManager::Builder& RenderableManager::Builder::geometry(size_t index, - PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices) noexcept { +RenderableManager::Builder& RenderableManager::Builder::geometry(size_t const index, + PrimitiveType const type, VertexBuffer* vertices, IndexBuffer* indices) noexcept { return geometry(index, type, vertices, indices, 0, 0, vertices->getVertexCount() - 1, indices->getIndexCount()); } -RenderableManager::Builder& RenderableManager::Builder::geometry(size_t index, - PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, - size_t offset, size_t count) noexcept { +RenderableManager::Builder& RenderableManager::Builder::geometry(size_t const index, + PrimitiveType const type, VertexBuffer* vertices, IndexBuffer* indices, + size_t const offset, size_t const count) noexcept { return geometry(index, type, vertices, indices, offset, 0, vertices->getVertexCount() - 1, count); } -RenderableManager::Builder& RenderableManager::Builder::geometry(size_t index, - PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, - size_t offset, UTILS_UNUSED size_t minIndex, UTILS_UNUSED size_t maxIndex, size_t count) noexcept { +RenderableManager::Builder& RenderableManager::Builder::geometry(size_t const index, + PrimitiveType const type, VertexBuffer* vertices, IndexBuffer* indices, + size_t const offset, UTILS_UNUSED size_t minIndex, UTILS_UNUSED size_t maxIndex, size_t const count) noexcept { std::vector& entries = mImpl->mEntries; if (index < entries.size()) { entries[index].vertices = vertices; @@ -152,12 +152,12 @@ RenderableManager::Builder& RenderableManager::Builder::geometry(size_t index, return *this; } -RenderableManager::Builder& RenderableManager::Builder::geometryType(GeometryType type) noexcept { +RenderableManager::Builder& RenderableManager::Builder::geometryType(GeometryType const type) noexcept { mImpl->mGeometryType = type; return *this; } -RenderableManager::Builder& RenderableManager::Builder::material(size_t index, +RenderableManager::Builder& RenderableManager::Builder::material(size_t const index, MaterialInstance const* materialInstance) noexcept { if (index < mImpl->mEntries.size()) { mImpl->mEntries[index].materialInstance = materialInstance; @@ -170,27 +170,27 @@ RenderableManager::Builder& RenderableManager::Builder::boundingBox(const Box& a return *this; } -RenderableManager::Builder& RenderableManager::Builder::layerMask(uint8_t select, uint8_t values) noexcept { +RenderableManager::Builder& RenderableManager::Builder::layerMask(uint8_t const select, uint8_t const values) noexcept { mImpl->mLayerMask = (mImpl->mLayerMask & ~select) | (values & select); return *this; } -RenderableManager::Builder& RenderableManager::Builder::priority(uint8_t priority) noexcept { +RenderableManager::Builder& RenderableManager::Builder::priority(uint8_t const priority) noexcept { mImpl->mPriority = std::min(priority, uint8_t(0x7)); return *this; } -RenderableManager::Builder& RenderableManager::Builder::channel(uint8_t channel) noexcept { +RenderableManager::Builder& RenderableManager::Builder::channel(uint8_t const channel) noexcept { mImpl->mCommandChannel = std::min(channel, uint8_t(0x3)); return *this; } -RenderableManager::Builder& RenderableManager::Builder::culling(bool enable) noexcept { +RenderableManager::Builder& RenderableManager::Builder::culling(bool const enable) noexcept { mImpl->mCulling = enable; return *this; } -RenderableManager::Builder& RenderableManager::Builder::lightChannel(unsigned int channel, bool enable) noexcept { +RenderableManager::Builder& RenderableManager::Builder::lightChannel(unsigned int const channel, bool const enable) noexcept { if (channel < 8) { const uint8_t mask = 1u << channel; mImpl->mLightChannels &= ~mask; @@ -199,59 +199,59 @@ RenderableManager::Builder& RenderableManager::Builder::lightChannel(unsigned in return *this; } -RenderableManager::Builder& RenderableManager::Builder::castShadows(bool enable) noexcept { +RenderableManager::Builder& RenderableManager::Builder::castShadows(bool const enable) noexcept { mImpl->mCastShadows = enable; return *this; } -RenderableManager::Builder& RenderableManager::Builder::receiveShadows(bool enable) noexcept { +RenderableManager::Builder& RenderableManager::Builder::receiveShadows(bool const enable) noexcept { mImpl->mReceiveShadows = enable; return *this; } -RenderableManager::Builder& RenderableManager::Builder::screenSpaceContactShadows(bool enable) noexcept { +RenderableManager::Builder& RenderableManager::Builder::screenSpaceContactShadows(bool const enable) noexcept { mImpl->mScreenSpaceContactShadows = enable; return *this; } -RenderableManager::Builder& RenderableManager::Builder::skinning(size_t boneCount) noexcept { +RenderableManager::Builder& RenderableManager::Builder::skinning(size_t const boneCount) noexcept { mImpl->mSkinningBoneCount = boneCount; return *this; } RenderableManager::Builder& RenderableManager::Builder::skinning( - size_t boneCount, Bone const* bones) noexcept { + size_t const boneCount, Bone const* bones) noexcept { mImpl->mSkinningBoneCount = boneCount; mImpl->mUserBones = bones; return *this; } RenderableManager::Builder& RenderableManager::Builder::skinning( - size_t boneCount, mat4f const* transforms) noexcept { + size_t const boneCount, mat4f const* transforms) noexcept { mImpl->mSkinningBoneCount = boneCount; mImpl->mUserBoneMatrices = transforms; return *this; } RenderableManager::Builder& RenderableManager::Builder::skinning( - SkinningBuffer* skinningBuffer, size_t count, size_t offset) noexcept { + SkinningBuffer* skinningBuffer, size_t const count, size_t const offset) noexcept { mImpl->mSkinningBuffer = downcast(skinningBuffer); mImpl->mSkinningBoneCount = count; mImpl->mSkinningBufferOffset = offset; return *this; } -RenderableManager::Builder& RenderableManager::Builder::enableSkinningBuffers(bool enabled) noexcept { +RenderableManager::Builder& RenderableManager::Builder::enableSkinningBuffers(bool const enabled) noexcept { mImpl->mSkinningBufferMode = enabled; return *this; } -RenderableManager::Builder& RenderableManager::Builder::boneIndicesAndWeights(size_t primitiveIndex, - math::float2 const* indicesAndWeights, size_t count, size_t bonesPerVertex) noexcept { +RenderableManager::Builder& RenderableManager::Builder::boneIndicesAndWeights(size_t const primitiveIndex, + float2 const* indicesAndWeights, size_t const count, size_t const bonesPerVertex) noexcept { size_t const vertexCount = count / bonesPerVertex; - utils::FixedCapacityVector> bonePairs(vertexCount); + FixedCapacityVector> bonePairs(vertexCount); for (size_t iVertex = 0; iVertex < vertexCount; iVertex++) { - utils::FixedCapacityVector vertexData(bonesPerVertex); + FixedCapacityVector vertexData(bonesPerVertex); std::copy_n(indicesAndWeights + iVertex * bonesPerVertex, bonesPerVertex, vertexData.data()); bonePairs[iVertex] = std::move(vertexData); @@ -259,19 +259,19 @@ RenderableManager::Builder& RenderableManager::Builder::boneIndicesAndWeights(si return boneIndicesAndWeights(primitiveIndex, bonePairs); } -RenderableManager::Builder& RenderableManager::Builder::boneIndicesAndWeights(size_t primitiveIndex, - utils::FixedCapacityVector< - utils::FixedCapacityVector> indicesAndWeightsVector) noexcept { +RenderableManager::Builder& RenderableManager::Builder::boneIndicesAndWeights(size_t const primitiveIndex, + FixedCapacityVector< + FixedCapacityVector> indicesAndWeightsVector) noexcept { mImpl->mBonePairs[primitiveIndex] = std::move(indicesAndWeightsVector); return *this; } -RenderableManager::Builder& RenderableManager::Builder::fog(bool enabled) noexcept { +RenderableManager::Builder& RenderableManager::Builder::fog(bool const enabled) noexcept { mImpl->mFogEnabled = enabled; return *this; } -RenderableManager::Builder& RenderableManager::Builder::morphing(size_t targetCount) noexcept { +RenderableManager::Builder& RenderableManager::Builder::morphing(size_t const targetCount) noexcept { mImpl->mMorphTargetCount = targetCount; return *this; } @@ -284,7 +284,7 @@ RenderableManager::Builder& RenderableManager::Builder::morphing( } RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, - size_t primitiveIndex, size_t offset) noexcept { + size_t const primitiveIndex, size_t const offset) noexcept { // the last parameter "count" is unused, because it must be equal to the primitive's vertex count std::vector& entries = mImpl->mEntries; if (primitiveIndex < entries.size()) { @@ -295,7 +295,7 @@ RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, } RenderableManager::Builder& RenderableManager::Builder::blendOrder( - size_t index, uint16_t blendOrder) noexcept { + size_t const index, uint16_t const blendOrder) noexcept { if (index < mImpl->mEntries.size()) { mImpl->mEntries[index].blendOrder = blendOrder; } @@ -303,7 +303,7 @@ RenderableManager::Builder& RenderableManager::Builder::blendOrder( } RenderableManager::Builder& RenderableManager::Builder::globalBlendOrderEnabled( - size_t index, bool enabled) noexcept { + size_t const index, bool const enabled) noexcept { if (index < mImpl->mEntries.size()) { mImpl->mEntries[index].globalBlendOrderEnabled = enabled; } @@ -311,7 +311,7 @@ RenderableManager::Builder& RenderableManager::Builder::globalBlendOrderEnabled( } UTILS_NOINLINE -void RenderableManager::BuilderDetails::processBoneIndicesAndWights(Engine& engine, Entity entity) { +void RenderableManager::BuilderDetails::processBoneIndicesAndWights(Engine& engine, Entity const entity) { size_t maxPairsCount = 0; //size of texture, number of bone pairs size_t maxPairsCountPerVertex = 0; //maximum of number of bone per vertex @@ -396,10 +396,10 @@ void RenderableManager::BuilderDetails::processBoneIndicesAndWights(Engine& engi } #ifndef NDEBUG else { - utils::slog.w << "Warning of skinning: [entity=%" << entity.getId() + slog.w << "Warning of skinning: [entity=%" << entity.getId() << ", primitive @ %" << primitiveIndex << "] sum of bone weights of vertex=" << iVertex << " is " << boneWeightsSum - << ", it should be one. Weights will be normalized." << utils::io::endl; + << ", it should be one. Weights will be normalized." << io::endl; } #endif @@ -432,7 +432,7 @@ void RenderableManager::BuilderDetails::processBoneIndicesAndWights(Engine& engi mBoneIndicesAndWeightsCount = pairsCount; // only part of mBoneIndicesAndWeights is used for real data } -RenderableManager::Builder::Result RenderableManager::Builder::build(Engine& engine, Entity entity) { +RenderableManager::Builder::Result RenderableManager::Builder::build(Engine& engine, Entity const entity) { bool isEmpty = true; FILAMENT_CHECK_PRECONDITION(mImpl->mSkinningBoneCount <= CONFIG_MAX_BONE_COUNT) @@ -517,13 +517,13 @@ RenderableManager::Builder::Result RenderableManager::Builder::build(Engine& eng return Success; } -RenderableManager::Builder& RenderableManager::Builder::instances(size_t instanceCount) noexcept { +RenderableManager::Builder& RenderableManager::Builder::instances(size_t const instanceCount) noexcept { mImpl->mInstanceCount = clamp((unsigned int)instanceCount, 1u, 32767u); return *this; } RenderableManager::Builder& RenderableManager::Builder::instances( - size_t instanceCount, InstanceBuffer* instanceBuffer) noexcept { + size_t const instanceCount, InstanceBuffer* instanceBuffer) noexcept { mImpl->mInstanceCount = clamp(instanceCount, (size_t)1, CONFIG_MAX_INSTANCES); mImpl->mInstanceBuffer = downcast(instanceBuffer); return *this; @@ -542,7 +542,7 @@ FRenderableManager::~FRenderableManager() { } void FRenderableManager::create( - const RenderableManager::Builder& UTILS_RESTRICT builder, Entity entity) { + const Builder& UTILS_RESTRICT builder, Entity const entity) { FEngine& engine = mEngine; auto& manager = mManager; FEngine::DriverApi& driver = engine.getDriverApi(); @@ -589,7 +589,7 @@ void FRenderableManager::create( // will get bound to the PER_RENDERABLE UBO, and we can't bind a buffer smaller than the // full size of the UBO. instances.handle = driver.createBufferObject(sizeof(PerRenderableUib), - BufferObjectBinding::UNIFORM, backend::BufferUsage::DYNAMIC); + BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC); if (auto name = instances.buffer->getName(); !name.empty()) { driver.setDebugTag(instances.handle.getId(), std::move(name)); } @@ -627,7 +627,7 @@ void FRenderableManager::create( .handle = driver.createBufferObject( sizeof(PerRenderableBoneUib), BufferObjectBinding::UNIFORM, - backend::BufferUsage::DYNAMIC), + BufferUsage::DYNAMIC), .count = (uint16_t)boneCount, .offset = 0, .skinningBufferMode = false }; @@ -689,7 +689,7 @@ void FRenderableManager::create( .handle = driver.createBufferObject( sizeof(PerRenderableMorphingUib), BufferObjectBinding::UNIFORM, - backend::BufferUsage::DYNAMIC), + BufferUsage::DYNAMIC), .count = targetCount }; Slice& primitives = mManager[ci].primitives; @@ -714,7 +714,7 @@ void FRenderableManager::create( } // this destroys a single component from an entity -void FRenderableManager::destroy(utils::Entity e) noexcept { +void FRenderableManager::destroy(Entity const e) noexcept { Instance const ci = getInstance(e); if (ci) { destroyComponent(ci); @@ -739,14 +739,14 @@ void FRenderableManager::terminate() noexcept { mHwRenderPrimitiveFactory.terminate(mEngine.getDriverApi()); } -void FRenderableManager::gc(utils::EntityManager& em) noexcept { - mManager.gc(em, [this](Entity e) { +void FRenderableManager::gc(EntityManager& em) noexcept { + mManager.gc(em, [this](Entity const e) { destroy(e); }); } // This is basically a Renderable's destructor. -void FRenderableManager::destroyComponent(Instance ci) noexcept { +void FRenderableManager::destroyComponent(Instance const ci) noexcept { auto& manager = mManager; FEngine& engine = mEngine; @@ -782,7 +782,7 @@ void FRenderableManager::destroyComponent(Instance ci) noexcept { } void FRenderableManager::destroyComponentPrimitives( - HwRenderPrimitiveFactory& factory, backend::DriverApi& driver, + HwRenderPrimitiveFactory& factory, DriverApi& driver, Slice& primitives) noexcept { for (auto& primitive : primitives) { primitive.terminate(factory, driver); @@ -790,12 +790,12 @@ void FRenderableManager::destroyComponentPrimitives( delete[] primitives.data(); } -void FRenderableManager::setMaterialInstanceAt(Instance instance, uint8_t level, - size_t primitiveIndex, FMaterialInstance const* mi) { +void FRenderableManager::setMaterialInstanceAt(Instance const instance, uint8_t const level, + size_t const primitiveIndex, FMaterialInstance const* mi) { + assert_invariant(mi); if (instance) { Slice& primitives = getRenderPrimitives(instance, level); - if (primitiveIndex < primitives.size()) { - assert_invariant(mi); + if (primitiveIndex < primitives.size() && mi) { FMaterial const* material = mi->getMaterial(); // we want a feature level violation to be a hard error (exception if enabled, or crash) @@ -819,8 +819,18 @@ void FRenderableManager::setMaterialInstanceAt(Instance instance, uint8_t level, } } +void FRenderableManager::clearMaterialInstanceAt(Instance instance, uint8_t level, + size_t primitiveIndex) { + if (instance) { + Slice& primitives = getRenderPrimitives(instance, level); + if (primitiveIndex < primitives.size()) { + primitives[primitiveIndex].setMaterialInstance(nullptr); + } + } +} + MaterialInstance* FRenderableManager::getMaterialInstanceAt( - Instance instance, uint8_t level, size_t primitiveIndex) const noexcept { + Instance const instance, uint8_t const level, size_t const primitiveIndex) const noexcept { if (instance) { const Slice& primitives = getRenderPrimitives(instance, level); if (primitiveIndex < primitives.size()) { @@ -832,8 +842,8 @@ MaterialInstance* FRenderableManager::getMaterialInstanceAt( return nullptr; } -void FRenderableManager::setBlendOrderAt(Instance instance, uint8_t level, - size_t primitiveIndex, uint16_t order) noexcept { +void FRenderableManager::setBlendOrderAt(Instance const instance, uint8_t const level, + size_t const primitiveIndex, uint16_t const order) noexcept { if (instance) { Slice& primitives = getRenderPrimitives(instance, level); if (primitiveIndex < primitives.size()) { @@ -842,8 +852,8 @@ void FRenderableManager::setBlendOrderAt(Instance instance, uint8_t level, } } -void FRenderableManager::setGlobalBlendOrderEnabledAt(Instance instance, uint8_t level, - size_t primitiveIndex, bool enabled) noexcept { +void FRenderableManager::setGlobalBlendOrderEnabledAt(Instance const instance, uint8_t const level, + size_t const primitiveIndex, bool const enabled) noexcept { if (instance) { Slice& primitives = getRenderPrimitives(instance, level); if (primitiveIndex < primitives.size()) { @@ -853,7 +863,7 @@ void FRenderableManager::setGlobalBlendOrderEnabledAt(Instance instance, uint8_t } AttributeBitset FRenderableManager::getEnabledAttributesAt( - Instance instance, uint8_t level, size_t primitiveIndex) const noexcept { + Instance const instance, uint8_t const level, size_t const primitiveIndex) const noexcept { if (instance) { Slice const& primitives = getRenderPrimitives(instance, level); if (primitiveIndex < primitives.size()) { @@ -863,9 +873,9 @@ AttributeBitset FRenderableManager::getEnabledAttributesAt( return AttributeBitset{}; } -void FRenderableManager::setGeometryAt(Instance instance, uint8_t level, size_t primitiveIndex, - PrimitiveType type, FVertexBuffer* vertices, FIndexBuffer* indices, - size_t offset, size_t count) noexcept { +void FRenderableManager::setGeometryAt(Instance const instance, uint8_t const level, size_t const primitiveIndex, + PrimitiveType const type, FVertexBuffer* vertices, FIndexBuffer* indices, + size_t const offset, size_t const count) noexcept { if (instance) { Slice& primitives = getRenderPrimitives(instance, level); if (primitiveIndex < primitives.size()) { @@ -875,8 +885,8 @@ void FRenderableManager::setGeometryAt(Instance instance, uint8_t level, size_t } } -void FRenderableManager::setBones(Instance ci, - Bone const* UTILS_RESTRICT transforms, size_t boneCount, size_t offset) { +void FRenderableManager::setBones(Instance const ci, + Bone const* UTILS_RESTRICT transforms, size_t boneCount, size_t const offset) { if (ci) { Bones const& bones = mManager[ci].bones; @@ -891,8 +901,8 @@ void FRenderableManager::setBones(Instance ci, } } -void FRenderableManager::setBones(Instance ci, - mat4f const* UTILS_RESTRICT transforms, size_t boneCount, size_t offset) { +void FRenderableManager::setBones(Instance const ci, + mat4f const* UTILS_RESTRICT transforms, size_t boneCount, size_t const offset) { if (ci) { Bones const& bones = mManager[ci].bones; @@ -907,8 +917,8 @@ void FRenderableManager::setBones(Instance ci, } } -void FRenderableManager::setSkinningBuffer(FRenderableManager::Instance ci, - FSkinningBuffer* skinningBuffer, size_t count, size_t offset) { +void FRenderableManager::setSkinningBuffer(Instance const ci, + FSkinningBuffer* skinningBuffer, size_t count, size_t const offset) { Bones& bones = mManager[ci].bones; @@ -937,18 +947,18 @@ void FRenderableManager::setSkinningBuffer(FRenderableManager::Instance ci, bones.offset = uint16_t(offset); } -static void updateMorphWeights(FEngine& engine, backend::Handle handle, - float const* weights, size_t count, size_t offset) noexcept { +static void updateMorphWeights(FEngine& engine, Handle handle, + float const* weights, size_t const count, size_t const offset) noexcept { auto& driver = engine.getDriverApi(); auto size = sizeof(float4) * count; auto* UTILS_RESTRICT out = (float4*)driver.allocate(size); std::transform(weights, weights + count, out, - [](float value) { return float4(value, 0, 0, 0); }); + [](float const value) { return float4(value, 0, 0, 0); }); driver.updateBufferObject(handle, { out, size }, sizeof(float4) * offset); } -void FRenderableManager::setMorphWeights(Instance instance, float const* weights, - size_t count, size_t offset) { +void FRenderableManager::setMorphWeights(Instance const instance, float const* weights, + size_t const count, size_t const offset) { if (instance) { FILAMENT_CHECK_PRECONDITION(count + offset <= CONFIG_MAX_MORPH_TARGET_COUNT) << "Only " << CONFIG_MAX_MORPH_TARGET_COUNT @@ -961,9 +971,9 @@ void FRenderableManager::setMorphWeights(Instance instance, float const* weights } } -void FRenderableManager::setMorphTargetBufferOffsetAt(Instance instance, uint8_t level, - size_t primitiveIndex, - size_t offset) { +void FRenderableManager::setMorphTargetBufferOffsetAt(Instance const instance, uint8_t level, + size_t const primitiveIndex, + size_t const offset) { if (instance) { assert_invariant(mManager[instance].morphTargetBuffer); Slice& primitives = mManager[instance].primitives; @@ -973,14 +983,14 @@ void FRenderableManager::setMorphTargetBufferOffsetAt(Instance instance, uint8_t } } -MorphTargetBuffer* FRenderableManager::getMorphTargetBuffer(Instance instance) const noexcept { +MorphTargetBuffer* FRenderableManager::getMorphTargetBuffer(Instance const instance) const noexcept { if (instance) { return mManager[instance].morphTargetBuffer; } return nullptr; } -size_t FRenderableManager::getMorphTargetCount(Instance instance) const noexcept { +size_t FRenderableManager::getMorphTargetCount(Instance const instance) const noexcept { if (instance) { const MorphWeights& morphWeights = mManager[instance].morphWeights; return morphWeights.count; @@ -988,7 +998,7 @@ size_t FRenderableManager::getMorphTargetCount(Instance instance) const noexcept return 0; } -void FRenderableManager::setLightChannel(Instance ci, unsigned int channel, bool enable) noexcept { +void FRenderableManager::setLightChannel(Instance const ci, unsigned int const channel, bool const enable) noexcept { if (ci) { if (channel < 8) { const uint8_t mask = 1u << channel; @@ -998,7 +1008,7 @@ void FRenderableManager::setLightChannel(Instance ci, unsigned int channel, bool } } -bool FRenderableManager::getLightChannel(Instance ci, unsigned int channel) const noexcept { +bool FRenderableManager::getLightChannel(Instance const ci, unsigned int const channel) const noexcept { if (ci) { if (channel < 8) { const uint8_t mask = 1u << channel; @@ -1008,7 +1018,7 @@ bool FRenderableManager::getLightChannel(Instance ci, unsigned int channel) cons return false; } -size_t FRenderableManager::getPrimitiveCount(Instance instance, uint8_t level) const noexcept { +size_t FRenderableManager::getPrimitiveCount(Instance const instance, uint8_t const level) const noexcept { return getRenderPrimitives(instance, level).size(); } diff --git a/filament/src/components/RenderableManager.h b/filament/src/components/RenderableManager.h index d774996f27..45846bba77 100644 --- a/filament/src/components/RenderableManager.h +++ b/filament/src/components/RenderableManager.h @@ -61,8 +61,8 @@ class MorphTargetBuffer; class FRenderableManager : public RenderableManager { public: - using Instance = RenderableManager::Instance; - using GeometryType = RenderableManager::Builder::GeometryType; + using Instance = Instance; + using GeometryType = Builder::GeometryType; // TODO: consider renaming, this pertains to material variants, not strictly visibility. struct Visibility { @@ -94,11 +94,11 @@ public: * Component Manager APIs */ - bool hasComponent(utils::Entity e) const noexcept { + bool hasComponent(utils::Entity const e) const noexcept { return mManager.hasComponent(e); } - Instance getInstance(utils::Entity e) const noexcept { + Instance getInstance(utils::Entity const e) const noexcept { return { mManager.getInstance(e) }; } @@ -110,7 +110,7 @@ public: return mManager.empty(); } - utils::Entity getEntity(Instance i) const noexcept { + utils::Entity getEntity(Instance const i) const noexcept { return mManager.getEntity(i); } @@ -118,7 +118,7 @@ public: return mManager.getEntities(); } - void create(const RenderableManager::Builder& builder, utils::Entity entity); + void create(const Builder& builder, utils::Entity entity); void destroy(utils::Entity e) noexcept; @@ -165,7 +165,7 @@ public: inline Box const& getAABB(Instance instance) const noexcept; - inline Box const& getAxisAlignedBoundingBox(Instance instance) const noexcept { return getAABB(instance); } + inline Box const& getAxisAlignedBoundingBox(Instance const instance) const noexcept { return getAABB(instance); } inline Visibility getVisibility(Instance instance) const noexcept; inline uint8_t getLayerMask(Instance instance) const noexcept; inline uint8_t getPriority(Instance instance) const noexcept; @@ -204,6 +204,7 @@ public: size_t getPrimitiveCount(Instance instance, uint8_t level) const noexcept; void setMaterialInstanceAt(Instance instance, uint8_t level, size_t primitiveIndex, FMaterialInstance const* materialInstance); + void clearMaterialInstanceAt(Instance instance, uint8_t level, size_t primitiveIndex); MaterialInstance* getMaterialInstanceAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept; void setGeometryAt(Instance instance, uint8_t level, size_t primitiveIndex, PrimitiveType type, FVertexBuffer* vertices, FIndexBuffer* indices, @@ -272,7 +273,7 @@ private: utils::Slice, // PRIMITIVES Bones, // BONES FMorphTargetBuffer*, // MORPHTARGET_BUFFER - filament::DescriptorSet // DESCRIPTOR_SET + DescriptorSet // DESCRIPTOR_SET >; struct Sim : public Base { @@ -315,7 +316,7 @@ private: FILAMENT_DOWNCAST(RenderableManager) -void FRenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& aabb) { +void FRenderableManager::setAxisAlignedBoundingBox(Instance const instance, const Box& aabb) { if (instance) { FILAMENT_CHECK_PRECONDITION( static_cast(mManager[instance].visibility).geometryType == @@ -325,74 +326,74 @@ void FRenderableManager::setAxisAlignedBoundingBox(Instance instance, const Box& } } -void FRenderableManager::setLayerMask(Instance instance, - uint8_t select, uint8_t values) noexcept { +void FRenderableManager::setLayerMask(Instance const instance, + uint8_t const select, uint8_t const values) noexcept { if (instance) { uint8_t& layers = mManager[instance].layers; layers = (layers & ~select) | (values & select); } } -void FRenderableManager::setLayerMask(Instance instance, uint8_t layerMask) noexcept { +void FRenderableManager::setLayerMask(Instance const instance, uint8_t const layerMask) noexcept { if (instance) { mManager[instance].layers = layerMask; } } -void FRenderableManager::setPriority(Instance instance, uint8_t priority) noexcept { +void FRenderableManager::setPriority(Instance const instance, uint8_t const priority) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.priority = std::min(priority, uint8_t(0x7)); } } -void FRenderableManager::setChannel(Instance instance, uint8_t channel) noexcept { +void FRenderableManager::setChannel(Instance const instance, uint8_t const channel) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.channel = std::min(channel, uint8_t(0x3)); } } -void FRenderableManager::setCastShadows(Instance instance, bool enable) noexcept { +void FRenderableManager::setCastShadows(Instance const instance, bool const enable) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.castShadows = enable; } } -void FRenderableManager::setReceiveShadows(Instance instance, bool enable) noexcept { +void FRenderableManager::setReceiveShadows(Instance const instance, bool const enable) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.receiveShadows = enable; } } -void FRenderableManager::setScreenSpaceContactShadows(Instance instance, bool enable) noexcept { +void FRenderableManager::setScreenSpaceContactShadows(Instance const instance, bool const enable) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.screenSpaceContactShadows = enable; } } -void FRenderableManager::setCulling(Instance instance, bool enable) noexcept { +void FRenderableManager::setCulling(Instance const instance, bool const enable) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.culling = enable; } } -void FRenderableManager::setFogEnabled(Instance instance, bool enable) noexcept { +void FRenderableManager::setFogEnabled(Instance const instance, bool const enable) noexcept { if (instance) { Visibility& visibility = mManager[instance].visibility; visibility.fog = enable; } } -bool FRenderableManager::getFogEnabled(RenderableManager::Instance instance) const noexcept { +bool FRenderableManager::getFogEnabled(RenderableManager::Instance const instance) const noexcept { return getVisibility(instance).fog; } -void FRenderableManager::setSkinning(Instance instance, bool enable) { +void FRenderableManager::setSkinning(Instance const instance, bool const enable) { if (instance) { Visibility& visibility = mManager[instance].visibility; @@ -403,7 +404,7 @@ void FRenderableManager::setSkinning(Instance instance, bool enable) { } } -void FRenderableManager::setMorphing(Instance instance, bool enable) { +void FRenderableManager::setMorphing(Instance const instance, bool const enable) { if (instance) { Visibility& visibility = mManager[instance].visibility; @@ -414,7 +415,7 @@ void FRenderableManager::setMorphing(Instance instance, bool enable) { } } -void FRenderableManager::setPrimitives(Instance instance, +void FRenderableManager::setPrimitives(Instance const instance, utils::Slice const& primitives) noexcept { if (instance) { mManager[instance].primitives = primitives; @@ -422,72 +423,72 @@ void FRenderableManager::setPrimitives(Instance instance, } FRenderableManager::Visibility -FRenderableManager::getVisibility(Instance instance) const noexcept { +FRenderableManager::getVisibility(Instance const instance) const noexcept { return mManager[instance].visibility; } -bool FRenderableManager::isShadowCaster(Instance instance) const noexcept { +bool FRenderableManager::isShadowCaster(Instance const instance) const noexcept { return getVisibility(instance).castShadows; } -bool FRenderableManager::isShadowReceiver(Instance instance) const noexcept { +bool FRenderableManager::isShadowReceiver(Instance const instance) const noexcept { return getVisibility(instance).receiveShadows; } -bool FRenderableManager::isCullingEnabled(Instance instance) const noexcept { +bool FRenderableManager::isCullingEnabled(Instance const instance) const noexcept { return getVisibility(instance).culling; } -uint8_t FRenderableManager::getLayerMask(Instance instance) const noexcept { +uint8_t FRenderableManager::getLayerMask(Instance const instance) const noexcept { return mManager[instance].layers; } -uint8_t FRenderableManager::getPriority(Instance instance) const noexcept { +uint8_t FRenderableManager::getPriority(Instance const instance) const noexcept { return getVisibility(instance).priority; } -uint8_t FRenderableManager::getChannels(Instance instance) const noexcept { +uint8_t FRenderableManager::getChannels(Instance const instance) const noexcept { return mManager[instance].channels; } -Box const& FRenderableManager::getAABB(Instance instance) const noexcept { +Box const& FRenderableManager::getAABB(Instance const instance) const noexcept { return mManager[instance].aabb; } FRenderableManager::SkinningBindingInfo -FRenderableManager::getSkinningBufferInfo(Instance instance) const noexcept { +FRenderableManager::getSkinningBufferInfo(Instance const instance) const noexcept { Bones const& bones = mManager[instance].bones; return { bones.handle, bones.offset, bones.handleTexture }; } -inline uint32_t FRenderableManager::getBoneCount(Instance instance) const noexcept { +inline uint32_t FRenderableManager::getBoneCount(Instance const instance) const noexcept { Bones const& bones = mManager[instance].bones; return bones.count; } FRenderableManager::MorphingBindingInfo -FRenderableManager::getMorphingBufferInfo(Instance instance) const noexcept { +FRenderableManager::getMorphingBufferInfo(Instance const instance) const noexcept { MorphWeights const& morphWeights = mManager[instance].morphWeights; FMorphTargetBuffer const* const buffer = mManager[instance].morphTargetBuffer; return { morphWeights.handle, morphWeights.count, buffer }; } FRenderableManager::InstancesInfo -FRenderableManager::getInstancesInfo(Instance instance) const noexcept { +FRenderableManager::getInstancesInfo(Instance const instance) const noexcept { return mManager[instance].instances; } utils::Slice const& FRenderableManager::getRenderPrimitives( - Instance instance, UTILS_UNUSED uint8_t level) const noexcept { + Instance const instance, UTILS_UNUSED uint8_t level) const noexcept { return mManager[instance].primitives; } utils::Slice& FRenderableManager::getRenderPrimitives( - Instance instance, UTILS_UNUSED uint8_t level) noexcept { + Instance const instance, UTILS_UNUSED uint8_t level) noexcept { return mManager[instance].primitives; } -DescriptorSet& FRenderableManager::getDescriptorSet(Instance instance) noexcept { +DescriptorSet& FRenderableManager::getDescriptorSet(Instance const instance) noexcept { return mManager[instance].descriptorSet; } diff --git a/filament/src/components/TransformManager.cpp b/filament/src/components/TransformManager.cpp index 7806e41f02..6a90c19599 100644 --- a/filament/src/components/TransformManager.cpp +++ b/filament/src/components/TransformManager.cpp @@ -34,7 +34,7 @@ FTransformManager::~FTransformManager() noexcept = default; void FTransformManager::terminate() noexcept { } -void FTransformManager::setAccurateTranslationsEnabled(bool enable) noexcept { +void FTransformManager::setAccurateTranslationsEnabled(bool const enable) noexcept { if (enable != mAccurateTranslations) { mAccurateTranslations = enable; // when enabling accurate translations, we have to recompute all world transforms @@ -44,11 +44,11 @@ void FTransformManager::setAccurateTranslationsEnabled(bool enable) noexcept { } } -void FTransformManager::create(Entity entity) { +void FTransformManager::create(Entity const entity) { create(entity, 0, mat4f{}); } -void FTransformManager::create(Entity entity, Instance parent, const mat4f& localTransform) { +void FTransformManager::create(Entity const entity, Instance const parent, const mat4f& localTransform) { // this always adds at the end, so all existing instances stay valid auto& manager = mManager; @@ -70,7 +70,7 @@ void FTransformManager::create(Entity entity, Instance parent, const mat4f& loca } } -void FTransformManager::create(Entity entity, Instance parent, const mat4& localTransform) { +void FTransformManager::create(Entity const entity, Instance const parent, const mat4& localTransform) { // this always adds at the end, so all existing instances stay valid auto& manager = mManager; @@ -92,7 +92,7 @@ void FTransformManager::create(Entity entity, Instance parent, const mat4& local } } -void FTransformManager::setParent(Instance i, Instance parent) noexcept { +void FTransformManager::setParent(Instance const i, Instance const parent) noexcept { validateNode(i); if (i) { auto& manager = mManager; @@ -115,14 +115,14 @@ Entity FTransformManager::getParent(Instance i) const noexcept { return i ? mManager.getEntity(i) : Entity(); } -size_t FTransformManager::getChildCount(Instance i) const noexcept { +size_t FTransformManager::getChildCount(Instance const i) const noexcept { size_t count = 0; for (Instance ci = mManager[i].firstChild; ci; ci = mManager[ci].next, ++count); return count; } -size_t FTransformManager::getChildren(Instance i, utils::Entity* children, - size_t count) const noexcept { +size_t FTransformManager::getChildren(Instance const i, Entity* children, + size_t const count) const noexcept { Instance ci = mManager[i].firstChild; size_t numWritten = 0; while (ci && numWritten < count) { @@ -133,7 +133,7 @@ size_t FTransformManager::getChildren(Instance i, utils::Entity* children, } TransformManager::children_iterator FTransformManager::getChildrenBegin( - Instance parent) const noexcept { + Instance const parent) const noexcept { return { *this, mManager[parent].firstChild }; } @@ -141,7 +141,7 @@ TransformManager::children_iterator FTransformManager::getChildrenEnd(Instance) return { *this, 0 }; } -void FTransformManager::destroy(Entity e) noexcept { +void FTransformManager::destroy(Entity const e) noexcept { // update the reference of the element we're removing auto& manager = mManager; Instance const i = manager.getInstance(e); @@ -167,7 +167,7 @@ void FTransformManager::destroy(Entity e) noexcept { } } -void FTransformManager::setTransform(Instance ci, const mat4f& model) noexcept { +void FTransformManager::setTransform(Instance const ci, const mat4f& model) noexcept { validateNode(ci); if (ci) { auto& manager = mManager; @@ -178,7 +178,7 @@ void FTransformManager::setTransform(Instance ci, const mat4f& model) noexcept { } } -void FTransformManager::setTransform(Instance ci, const mat4& model) noexcept { +void FTransformManager::setTransform(Instance const ci, const mat4& model) noexcept { validateNode(ci); if (ci) { auto& manager = mManager; @@ -189,7 +189,7 @@ void FTransformManager::setTransform(Instance ci, const mat4& model) noexcept { } } -void FTransformManager::updateNodeTransform(Instance i) noexcept { +void FTransformManager::updateNodeTransform(Instance const i) noexcept { if (UTILS_UNLIKELY(mLocalTransformTransactionOpen)) { return; } @@ -201,7 +201,7 @@ void FTransformManager::updateNodeTransform(Instance i) noexcept { // find our parent's world transform, if any // note: by using the raw_array() we don't need to check that parent is valid. Instance const parent = manager[i].parent; - FTransformManager::computeWorldTransform( + computeWorldTransform( manager[i].world, manager[i].worldTranslationLo, manager[parent].world, manager[i].local, manager[parent].worldTranslationLo, manager[i].localTranslationLo, @@ -241,7 +241,7 @@ void FTransformManager::computeAllWorldTransforms() noexcept { Instance const parent = manager[i].parent; assert_invariant(parent < i); - FTransformManager::computeWorldTransform( + computeWorldTransform( manager[i].world, manager[i].worldTranslationLo, manager[parent].world, manager[i].local, manager[parent].worldTranslationLo, manager[i].localTranslationLo, @@ -250,7 +250,7 @@ void FTransformManager::computeAllWorldTransforms() noexcept { } // Inserts a parentless node in the hierarchy -void FTransformManager::insertNode(Instance i, Instance parent) noexcept { +void FTransformManager::insertNode(Instance const i, Instance const parent) noexcept { auto& manager = mManager; assert_invariant(manager[i].parent == Instance{}); @@ -274,7 +274,7 @@ void FTransformManager::insertNode(Instance i, Instance parent) noexcept { validateNode(parent); } -void FTransformManager::swapNode(Instance i, Instance j) noexcept { +void FTransformManager::swapNode(Instance const i, Instance const j) noexcept { validateNode(i); validateNode(j); @@ -316,7 +316,7 @@ void FTransformManager::swapNode(Instance i, Instance j) noexcept { // removes a node from the graph, but doesn't remove it or its children from the array // (making everybody orphaned). -void FTransformManager::removeNode(Instance i) noexcept { +void FTransformManager::removeNode(Instance const i) noexcept { auto& manager = mManager; Instance const parent = manager[i].parent; Instance const prev = manager[i].prev; @@ -342,7 +342,7 @@ void FTransformManager::removeNode(Instance i) noexcept { } // update references to this node after it has been moved in the array -void FTransformManager::updateNode(Instance i) noexcept { +void FTransformManager::updateNode(Instance const i) noexcept { auto& manager = mManager; // update our preview sibling's next reference (to ourselves) Instance const parent = manager[i].parent; @@ -376,7 +376,7 @@ void FTransformManager::transformChildren(Sim& manager, Instance i) noexcept { while (i) { // update child's world transform Instance const parent = manager[i].parent; - FTransformManager::computeWorldTransform( + computeWorldTransform( manager[i].world, manager[i].worldTranslationLo, manager[parent].world, manager[i].local, manager[parent].worldTranslationLo, manager[i].localTranslationLo, @@ -400,7 +400,7 @@ void FTransformManager::computeWorldTransform( mat4f const& UTILS_RESTRICT local, float3 const& UTILS_RESTRICT ptTranslationLo, // reference to avoid unneeded access float3 const& UTILS_RESTRICT localTranslationLo, // reference to avoid unneeded access - bool accurate) { + bool const accurate) { outWorld[0] = pt * local[0]; outWorld[1] = pt * local[1]; @@ -428,7 +428,7 @@ void FTransformManager::computeWorldTransform( } -void FTransformManager::validateNode(UTILS_UNUSED_IN_RELEASE Instance i) noexcept { +void FTransformManager::validateNode(UTILS_UNUSED_IN_RELEASE Instance const i) noexcept { #ifndef NDEBUG auto& manager = mManager; if (i) { @@ -470,8 +470,8 @@ void FTransformManager::validateNode(UTILS_UNUSED_IN_RELEASE Instance i) noexcep #endif } -void FTransformManager::gc(utils::EntityManager& em) noexcept { - mManager.gc(em, [this](Entity e) { +void FTransformManager::gc(EntityManager& em) noexcept { + mManager.gc(em, [this](Entity const e) { destroy(e); }); } diff --git a/filament/src/components/TransformManager.h b/filament/src/components/TransformManager.h index 6e42103370..b985d471f8 100644 --- a/filament/src/components/TransformManager.h +++ b/filament/src/components/TransformManager.h @@ -32,7 +32,7 @@ namespace filament { class UTILS_PRIVATE FTransformManager : public TransformManager { public: - using Instance = TransformManager::Instance; + using Instance = Instance; FTransformManager() noexcept; ~FTransformManager() noexcept; @@ -45,11 +45,11 @@ public: * Component Manager APIs */ - bool hasComponent(utils::Entity e) const noexcept { + bool hasComponent(utils::Entity const e) const noexcept { return mManager.hasComponent(e); } - Instance getInstance(utils::Entity e) const noexcept { + Instance getInstance(utils::Entity const e) const noexcept { return { mManager.getInstance(e) }; } @@ -61,7 +61,7 @@ public: return mManager.empty(); } - utils::Entity getEntity(Instance i) const noexcept { + utils::Entity getEntity(Instance const i) const noexcept { return mManager.getEntity(i); } @@ -109,15 +109,15 @@ public: void setTransform(Instance ci, const math::mat4& model) noexcept; - const math::mat4f& getTransform(Instance ci) const noexcept { + const math::mat4f& getTransform(Instance const ci) const noexcept { return mManager[ci].local; } - const math::mat4f& getWorldTransform(Instance ci) const noexcept { + const math::mat4f& getWorldTransform(Instance const ci) const noexcept { return mManager[ci].world; } - math::mat4 getTransformAccurate(Instance ci) const noexcept { + math::mat4 getTransformAccurate(Instance const ci) const noexcept { math::mat4f const& local = mManager[ci].local; math::float3 const localTranslationLo = mManager[ci].localTranslationLo; math::mat4 r(local); @@ -125,7 +125,7 @@ public: return r; } - math::mat4 getWorldTransformAccurate(Instance ci) const noexcept { + math::mat4 getWorldTransformAccurate(Instance const ci) const noexcept { math::mat4f const& world = mManager[ci].world; math::float3 const worldTranslationLo = mManager[ci].worldTranslationLo; math::mat4 r(world); @@ -151,7 +151,7 @@ private: math::float3 const& ptTranslationLo, math::float3 const& localTranslationLo, bool accurate); - friend class TransformManager::children_iterator; + friend class children_iterator; enum { LOCAL, // local transform (relative to parent), world if no parent @@ -179,7 +179,7 @@ private: using Base::gc; using Base::swap; - typename Base::SoA& getSoA() { return mData; } + SoA& getSoA() { return mData; } struct Proxy { // all of these gets inlined diff --git a/filament/src/details/BufferObject.cpp b/filament/src/details/BufferObject.cpp index a462e42a42..a41725295b 100644 --- a/filament/src/details/BufferObject.cpp +++ b/filament/src/details/BufferObject.cpp @@ -32,28 +32,32 @@ struct BufferObject::BuilderDetails { using BuilderType = BufferObject; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -BufferObject::Builder& BufferObject::Builder::size(uint32_t byteCount) noexcept { +BufferObject::Builder& BufferObject::Builder::size(uint32_t const byteCount) noexcept { mImpl->mByteCount = byteCount; return *this; } -BufferObject::Builder& BufferObject::Builder::bindingType(BindingType bindingType) noexcept { +BufferObject::Builder& BufferObject::Builder::bindingType(BindingType const bindingType) noexcept { mImpl->mBindingType = bindingType; return *this; } +BufferObject::Builder& BufferObject::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + BufferObject* BufferObject::Builder::build(Engine& engine) { return downcast(engine).createBufferObject(*this); } // ------------------------------------------------------------------------------------------------ -FBufferObject::FBufferObject(FEngine& engine, const BufferObject::Builder& builder) +FBufferObject::FBufferObject(FEngine& engine, const Builder& builder) : mByteCount(builder->mByteCount), mBindingType(builder->mBindingType) { FEngine::DriverApi& driver = engine.getDriverApi(); mHandle = driver.createBufferObject(builder->mByteCount, builder->mBindingType, @@ -68,7 +72,7 @@ void FBufferObject::terminate(FEngine& engine) { driver.destroyBufferObject(mHandle); } -void FBufferObject::setBuffer(FEngine& engine, BufferDescriptor&& buffer, uint32_t byteOffset) { +void FBufferObject::setBuffer(FEngine& engine, BufferDescriptor&& buffer, uint32_t const byteOffset) { engine.getDriverApi().updateBufferObject(mHandle, std::move(buffer), byteOffset); } diff --git a/filament/src/details/Camera.cpp b/filament/src/details/Camera.cpp index 1c333d4b63..775e3f175e 100644 --- a/filament/src/details/Camera.cpp +++ b/filament/src/details/Camera.cpp @@ -42,16 +42,16 @@ static constexpr const float MAX_SHUTTER_SPEED = 60.0f; static constexpr const float MIN_SENSITIVITY = 10.0f; static constexpr const float MAX_SENSITIVITY = 204800.0f; -FCamera::FCamera(FEngine& engine, Entity e) +FCamera::FCamera(FEngine& engine, Entity const e) : mEngine(engine), mEntity(e) { } -math::mat4 FCamera::projection(Fov direction, double fovInDegrees, - double aspect, double near, double far) { +mat4 FCamera::projection(Fov const direction, double const fovInDegrees, + double const aspect, double const near, double const far) { double w; double h; - double const s = std::tan(fovInDegrees * math::d::DEG_TO_RAD / 2.0) * near; + double const s = std::tan(fovInDegrees * d::DEG_TO_RAD / 2.0) * near; if (direction == Fov::VERTICAL) { w = s * aspect; h = s; @@ -59,7 +59,7 @@ math::mat4 FCamera::projection(Fov direction, double fovInDegrees, w = s; h = s / aspect; } - mat4 p = math::mat4::frustum(-w, w, -h, h, near, far); + mat4 p = mat4::frustum(-w, w, -h, h, near, far); if (far == std::numeric_limits::infinity()) { p[2][2] = -1.0f; // lim(far->inf) = -1 p[3][2] = -2.0f * near; // lim(far->inf) = -2*near @@ -67,12 +67,12 @@ math::mat4 FCamera::projection(Fov direction, double fovInDegrees, return p; } -math::mat4 FCamera::projection(double focalLengthInMillimeters, - double aspect, double near, double far) { +mat4 FCamera::projection(double const focalLengthInMillimeters, + double const aspect, double const near, double const far) { // a 35mm camera has a 36x24mm wide frame size double const h = (0.5 * near) * ((SENSOR_SIZE * 1000.0) / focalLengthInMillimeters); double const w = h * aspect; - mat4 p = math::mat4::frustum(-w, w, -h, h, near, far); + mat4 p = mat4::frustum(-w, w, -h, h, near, far); if (far == std::numeric_limits::infinity()) { p[2][2] = -1.0f; // lim(far->inf) = -1 p[3][2] = -2.0f * near; // lim(far->inf) = -2*near @@ -85,7 +85,7 @@ math::mat4 FCamera::projection(double focalLengthInMillimeters, */ void UTILS_NOINLINE FCamera::setCustomProjection(mat4 const& p, - mat4 const& c, double near, double far) noexcept { + mat4 const& c, double const near, double const far) noexcept { for (auto& eyeProjection: mEyeProjection) { eyeProjection = p; } @@ -94,8 +94,8 @@ void UTILS_NOINLINE FCamera::setCustomProjection(mat4 const& p, mFar = far; } -void UTILS_NOINLINE FCamera::setCustomEyeProjection(math::mat4 const* projection, size_t count, - math::mat4 const& projectionForCulling, double near, double far) { +void UTILS_NOINLINE FCamera::setCustomEyeProjection(mat4 const* projection, size_t const count, + mat4 const& projectionForCulling, double const near, double const far) { const Engine::Config& config = mEngine.getConfig(); FILAMENT_CHECK_PRECONDITION(count >= config.stereoscopicEyeCount) << "All eye projections must be supplied together, count must be >= " @@ -109,16 +109,16 @@ void UTILS_NOINLINE FCamera::setCustomEyeProjection(math::mat4 const* projection mFar = far; } -void UTILS_NOINLINE FCamera::setProjection(Camera::Projection projection, - double left, double right, - double bottom, double top, - double near, double far) { +void UTILS_NOINLINE FCamera::setProjection(Projection const projection, + double const left, double const right, + double const bottom, double const top, + double const near, double const far) { FILAMENT_CHECK_PRECONDITION(!(left == right || bottom == top || (projection == Projection::PERSPECTIVE && (near <= 0 || far <= near)) || (projection == Projection::ORTHO && (near == far)))) << "Camera preconditions not met in setProjection(" - << (projection == Camera::Projection::PERSPECTIVE ? "PERSPECTIVE" : "ORTHO") << ", " + << (projection == Projection::PERSPECTIVE ? "PERSPECTIVE" : "ORTHO") << ", " << left << ", " << right << ", " << bottom << ", " << top << ", " << near << ", " << far << ")"; @@ -161,10 +161,10 @@ void UTILS_NOINLINE FCamera::setProjection(Camera::Projection projection, p = c; break; } - FCamera::setCustomProjection(p, c, near, far); + setCustomProjection(p, c, near, far); } -math::mat4 FCamera::getProjectionMatrix(uint8_t eye) const noexcept { +mat4 FCamera::getProjectionMatrix(uint8_t const eye) const noexcept { UTILS_UNUSED_IN_RELEASE const Engine::Config& config = mEngine.getConfig(); assert_invariant(eye < config.stereoscopicEyeCount); // This is where we transform the user clip-space (GL convention) to our virtual clip-space @@ -180,7 +180,7 @@ math::mat4 FCamera::getProjectionMatrix(uint8_t eye) const noexcept { return m * mEyeProjection[eye]; } -math::mat4 FCamera::getCullingProjectionMatrix() const noexcept { +mat4 FCamera::getCullingProjectionMatrix() const noexcept { // The culling projection matrix stays in the GL convention const mat4 m{ mat4::row_major_init{ mScalingCS.x, 0.0, 0.0, mShiftCS.x, @@ -191,7 +191,7 @@ math::mat4 FCamera::getCullingProjectionMatrix() const noexcept { return m * mProjectionForCulling; } -const math::mat4& FCamera::getUserProjectionMatrix(uint8_t eyeId) const { +const mat4& FCamera::getUserProjectionMatrix(uint8_t const eyeId) const { const Engine::Config& config = mEngine.getConfig(); FILAMENT_CHECK_PRECONDITION(eyeId < config.stereoscopicEyeCount) << "eyeId must be < config.stereoscopicEyeCount (" << config.stereoscopicEyeCount @@ -209,7 +209,7 @@ void UTILS_NOINLINE FCamera::setModelMatrix(const mat4& modelMatrix) noexcept { transformManager.setTransform(transformManager.getInstance(mEntity), modelMatrix); } -void UTILS_NOINLINE FCamera::setEyeModelMatrix(uint8_t eyeId, math::mat4 const& model) { +void UTILS_NOINLINE FCamera::setEyeModelMatrix(uint8_t const eyeId, mat4 const& model) { const Engine::Config& config = mEngine.getConfig(); FILAMENT_CHECK_PRECONDITION(eyeId < config.stereoscopicEyeCount) << "eyeId must be < config.stereoscopicEyeCount (" << config.stereoscopicEyeCount @@ -237,7 +237,7 @@ Frustum FCamera::getCullingFrustum() const noexcept { return Frustum(mat4f{ getCullingProjectionMatrix() * getViewMatrix() }); } -void FCamera::setExposure(float aperture, float shutterSpeed, float sensitivity) noexcept { +void FCamera::setExposure(float const aperture, float const shutterSpeed, float const sensitivity) noexcept { mAperture = clamp(aperture, MIN_APERTURE, MAX_APERTURE); mShutterSpeed = clamp(shutterSpeed, MIN_SHUTTER_SPEED, MAX_SHUTTER_SPEED); mSensitivity = clamp(sensitivity, MIN_SENSITIVITY, MAX_SENSITIVITY); @@ -245,19 +245,19 @@ void FCamera::setExposure(float aperture, float shutterSpeed, float sensitivity) double FCamera::getFocalLength() const noexcept { auto const& monoscopicEyeProjection = mEyeProjection[0]; - return (FCamera::SENSOR_SIZE * monoscopicEyeProjection[1][1]) * 0.5; + return (SENSOR_SIZE * monoscopicEyeProjection[1][1]) * 0.5; } -double FCamera::computeEffectiveFocalLength(double focalLength, double focusDistance) noexcept { +double FCamera::computeEffectiveFocalLength(double const focalLength, double focusDistance) noexcept { focusDistance = std::max(focalLength, focusDistance); return (focusDistance * focalLength) / (focusDistance - focalLength); } -double FCamera::computeEffectiveFov(double fovInDegrees, double focusDistance) noexcept { - double const f = 0.5 * FCamera::SENSOR_SIZE / std::tan(fovInDegrees * math::d::DEG_TO_RAD * 0.5); +double FCamera::computeEffectiveFov(double const fovInDegrees, double focusDistance) noexcept { + double const f = 0.5 * SENSOR_SIZE / std::tan(fovInDegrees * d::DEG_TO_RAD * 0.5); focusDistance = std::max(f, focusDistance); - double const fov = 2.0 * std::atan(FCamera::SENSOR_SIZE * (focusDistance - f) / (2.0 * focusDistance * f)); - return fov * math::d::RAD_TO_DEG; + double const fov = 2.0 * std::atan(SENSOR_SIZE * (focusDistance - f) / (2.0 * focusDistance * f)); + return fov * d::RAD_TO_DEG; } uint8_t FCamera::getStereoscopicEyeCount() const noexcept { @@ -271,7 +271,7 @@ CameraInfo::CameraInfo(FCamera const& camera) noexcept : CameraInfo(camera, {}, camera.getModelMatrix()) { } -CameraInfo::CameraInfo(FCamera const& camera, math::mat4 const& inWorldTransform) noexcept +CameraInfo::CameraInfo(FCamera const& camera, mat4 const& inWorldTransform) noexcept : CameraInfo(camera, inWorldTransform, inWorldTransform * camera.getModelMatrix()) { } @@ -280,8 +280,8 @@ CameraInfo::CameraInfo(FCamera const& camera, CameraInfo const& mainCameraInfo) } CameraInfo::CameraInfo(FCamera const& camera, - math::mat4 const& inWorldTransform, - math::mat4 const& modelMatrix) noexcept { + mat4 const& inWorldTransform, + mat4 const& modelMatrix) noexcept { for (size_t i = 0; i < camera.getStereoscopicEyeCount(); i++) { eyeProjection[i] = mat4f{ camera.getProjectionMatrix(i) }; eyeFromView[i] = mat4f{ camera.getEyeFromViewMatrix(i) }; diff --git a/filament/src/details/Camera.h b/filament/src/details/Camera.h index cb03363658..34c986d615 100644 --- a/filament/src/details/Camera.h +++ b/filament/src/details/Camera.h @@ -59,7 +59,7 @@ public: math::mat4 const& projectionForCulling, double near, double far) noexcept; inline void setCustomProjection(math::mat4 const& projection, - double near, double far) noexcept { + double const near, double const far) noexcept { setCustomProjection(projection, projection, near, far); } @@ -67,11 +67,11 @@ public: math::mat4 const& projectionForCulling, double near, double far); - void setScaling(math::double2 scaling) noexcept { mScalingCS = scaling; } + void setScaling(math::double2 const scaling) noexcept { mScalingCS = scaling; } math::double4 getScaling() const noexcept { return math::double4{ mScalingCS, 1.0, 1.0 }; } - void setShift(math::double2 shift) noexcept { mShiftCS = shift * 2.0; } + void setShift(math::double2 const shift) noexcept { mShiftCS = shift * 2.0; } math::double2 getShift() const noexcept { return mShiftCS * 0.5; } @@ -82,7 +82,7 @@ public: // culling the projection matrix to be used for culling, contains scaling/shift math::mat4 getCullingProjectionMatrix() const noexcept; - math::mat4 getEyeFromViewMatrix(uint8_t eye) const noexcept { return mEyeFromView[eye]; } + math::mat4 getEyeFromViewMatrix(uint8_t const eye) const noexcept { return mEyeFromView[eye]; } // viewing projection matrix set by the user const math::mat4& getUserProjectionMatrix(uint8_t eyeId) const; @@ -135,7 +135,7 @@ public: return normalize(-getModelMatrix()[2].xyz); } - float getFieldOfView(Camera::Fov direction) const noexcept { + float getFieldOfView(Fov const direction) const noexcept { // note: this is meaningless for an orthographic projection auto const& p = getProjectionMatrix(); switch (direction) { @@ -146,7 +146,7 @@ public: } } - float getFieldOfViewInDegrees(Camera::Fov direction) const noexcept { + float getFieldOfViewInDegrees(Fov const direction) const noexcept { return getFieldOfView(direction) * math::f::RAD_TO_DEG; } @@ -171,7 +171,7 @@ public: return mSensitivity; } - void setFocusDistance(float distance) noexcept { + void setFocusDistance(float const distance) noexcept { mFocusDistance = distance; } diff --git a/filament/src/details/ColorGrading.cpp b/filament/src/details/ColorGrading.cpp index e02f029080..b3c577c2d6 100644 --- a/filament/src/details/ColorGrading.cpp +++ b/filament/src/details/ColorGrading.cpp @@ -133,26 +133,26 @@ struct ColorGrading::BuilderDetails { using BuilderType = ColorGrading; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -ColorGrading::Builder& ColorGrading::Builder::quality(ColorGrading::QualityLevel qualityLevel) noexcept { +ColorGrading::Builder& ColorGrading::Builder::quality(QualityLevel const qualityLevel) noexcept { switch (qualityLevel) { - case ColorGrading::QualityLevel::LOW: + case QualityLevel::LOW: mImpl->format = LutFormat::INTEGER; mImpl->dimension = 16; break; - case ColorGrading::QualityLevel::MEDIUM: + case QualityLevel::MEDIUM: mImpl->format = LutFormat::INTEGER; mImpl->dimension = 32; break; - case ColorGrading::QualityLevel::HIGH: + case QualityLevel::HIGH: mImpl->format = LutFormat::FLOAT; mImpl->dimension = 32; break; - case ColorGrading::QualityLevel::ULTRA: + case QualityLevel::ULTRA: mImpl->format = LutFormat::FLOAT; mImpl->dimension = 64; break; @@ -160,13 +160,13 @@ ColorGrading::Builder& ColorGrading::Builder::quality(ColorGrading::QualityLevel return *this; } -ColorGrading::Builder& ColorGrading::Builder::format(LutFormat format) noexcept { +ColorGrading::Builder& ColorGrading::Builder::format(LutFormat const format) noexcept { mImpl->format = format; return *this; } -ColorGrading::Builder& ColorGrading::Builder::dimensions(uint8_t dim) noexcept { - mImpl->dimension = math::clamp(+dim, 16, 64); +ColorGrading::Builder& ColorGrading::Builder::dimensions(uint8_t const dim) noexcept { + mImpl->dimension = clamp(+dim, 16, 64); return *this; } @@ -175,32 +175,32 @@ ColorGrading::Builder& ColorGrading::Builder::toneMapper(const ToneMapper* toneM return *this; } -ColorGrading::Builder& ColorGrading::Builder::toneMapping(ToneMapping toneMapping) noexcept { +ColorGrading::Builder& ColorGrading::Builder::toneMapping(ToneMapping const toneMapping) noexcept { mImpl->toneMapping = toneMapping; return *this; } -ColorGrading::Builder& ColorGrading::Builder::luminanceScaling(bool luminanceScaling) noexcept { +ColorGrading::Builder& ColorGrading::Builder::luminanceScaling(bool const luminanceScaling) noexcept { mImpl->luminanceScaling = luminanceScaling; return *this; } -ColorGrading::Builder& ColorGrading::Builder::gamutMapping(bool gamutMapping) noexcept { +ColorGrading::Builder& ColorGrading::Builder::gamutMapping(bool const gamutMapping) noexcept { mImpl->gamutMapping = gamutMapping; return *this; } -ColorGrading::Builder& ColorGrading::Builder::exposure(float exposure) noexcept { +ColorGrading::Builder& ColorGrading::Builder::exposure(float const exposure) noexcept { mImpl->exposure = exposure; return *this; } -ColorGrading::Builder& ColorGrading::Builder::nightAdaptation(float adaptation) noexcept { +ColorGrading::Builder& ColorGrading::Builder::nightAdaptation(float const adaptation) noexcept { mImpl->nightAdaptation = saturate(adaptation); return *this; } -ColorGrading::Builder& ColorGrading::Builder::whiteBalance(float temperature, float tint) noexcept { +ColorGrading::Builder& ColorGrading::Builder::whiteBalance(float const temperature, float const tint) noexcept { mImpl->whiteBalance = float2{ clamp(temperature, -1.0f, 1.0f), clamp(tint, -1.0f, 1.0f) @@ -239,17 +239,17 @@ ColorGrading::Builder& ColorGrading::Builder::slopeOffsetPower( return *this; } -ColorGrading::Builder& ColorGrading::Builder::contrast(float contrast) noexcept { +ColorGrading::Builder& ColorGrading::Builder::contrast(float const contrast) noexcept { mImpl->contrast = clamp(contrast, 0.0f, 2.0f); return *this; } -ColorGrading::Builder& ColorGrading::Builder::vibrance(float vibrance) noexcept { +ColorGrading::Builder& ColorGrading::Builder::vibrance(float const vibrance) noexcept { mImpl->vibrance = clamp(vibrance, 0.0f, 2.0f); return *this; } -ColorGrading::Builder& ColorGrading::Builder::saturation(float saturation) noexcept { +ColorGrading::Builder& ColorGrading::Builder::saturation(float const saturation) noexcept { mImpl->saturation = clamp(saturation, 0.0f, 2.0f); return *this; } @@ -316,7 +316,7 @@ ColorGrading* ColorGrading::Builder::build(Engine& engine) { //------------------------------------------------------------------------------ UTILS_ALWAYS_INLINE -inline float3 adjustExposure(float3 v, float exposure) { +inline float3 adjustExposure(float3 const v, float const exposure) { return v * std::exp2(exposure); } @@ -437,7 +437,7 @@ float3 scotopicAdaptation(float3 v, float nightAdaptation) noexcept { // the von Kries method, using the CIECAT16 transform. // See https://en.wikipedia.org/wiki/Chromatic_adaptation // See https://en.wikipedia.org/wiki/CIECAM02#Chromatic_adaptation -constexpr mat3f adaptationTransform(float2 whiteBalance) noexcept { +constexpr mat3f adaptationTransform(float2 const whiteBalance) noexcept { // See Mathematica notebook in docs/math/White Balance.nb float k = whiteBalance.x; // temperature float t = whiteBalance.y; // tint @@ -450,7 +450,7 @@ constexpr mat3f adaptationTransform(float2 whiteBalance) noexcept { } UTILS_ALWAYS_INLINE -inline float3 chromaticAdaptation(float3 v, mat3f adaptationTransform) { +inline float3 chromaticAdaptation(float3 const v, mat3f adaptationTransform) { return adaptationTransform * v; } @@ -499,7 +499,7 @@ inline float3 colorDecisionList(float3 v, float3 slope, float3 offset, float3 po } UTILS_ALWAYS_INLINE -inline constexpr float3 contrast(float3 v, float contrast) { +inline constexpr float3 contrast(float3 const v, float const contrast) { // Matches contrast as applied in DaVinci Resolve return MIDDLE_GRAY_ACEScct + contrast * (v - MIDDLE_GRAY_ACEScct); } @@ -574,7 +574,7 @@ static float3 luminanceScaling(float3 x, //------------------------------------------------------------------------------ static std::tuple - selectLutTextureParams(ColorGrading::LutFormat lutFormat) noexcept { + selectLutTextureParams(ColorGrading::LutFormat const lutFormat) noexcept { // We use RGBA16F for high quality modes instead of RGB16F because RGB16F // is not supported everywhere switch (lutFormat) { @@ -592,21 +592,21 @@ static std::tuple // forces post-processing to be performed in sRGB to guarantee that the inverse tone // mapping function in the shaders will match the forward tone mapping step exactly. -static mat3f selectColorGradingTransformIn(ColorGrading::ToneMapping toneMapping) noexcept { +static mat3f selectColorGradingTransformIn(ColorGrading::ToneMapping const toneMapping) noexcept { if (toneMapping == ColorGrading::ToneMapping::FILMIC) { return mat3f{}; } return sRGB_to_Rec2020; } -static mat3f selectColorGradingTransformOut(ColorGrading::ToneMapping toneMapping) noexcept { +static mat3f selectColorGradingTransformOut(ColorGrading::ToneMapping const toneMapping) noexcept { if (toneMapping == ColorGrading::ToneMapping::FILMIC) { return mat3f{}; } return Rec2020_to_sRGB; } -static float3 selectColorGradingLuminance(ColorGrading::ToneMapping toneMapping) noexcept { +static float3 selectColorGradingLuminance(ColorGrading::ToneMapping const toneMapping) noexcept { if (toneMapping == ColorGrading::ToneMapping::FILMIC) { return LUMINANCE_Rec709; } @@ -649,9 +649,9 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { Config c; // This lock protects the data inside Config, which is written to by the Filament thread, // and read from multiple Job threads. - utils::Mutex configLock; + Mutex configLock; { - std::lock_guard const lock(configLock); + std::lock_guard const lock(configLock); c.lutDimension = builder->dimension; c.adaptationTransform = adaptationTransform(builder->whiteBalance); c.colorGradingIn = selectColorGradingTransformIn(builder->toneMapping); @@ -688,7 +688,7 @@ FColorGrading::FColorGrading(FEngine& engine, const Builder& builder) { [data, converted, b, &c, &configLock, builder](JobSystem&, JobSystem::Job*) { Config config; { - std::lock_guard lock(configLock); + std::lock_guard lock(configLock); config = c; } half4* UTILS_RESTRICT p = (half4*) data + b * config.lutDimension * config.lutDimension; diff --git a/filament/src/details/DebugRegistry.cpp b/filament/src/details/DebugRegistry.cpp index 8915cf312e..9bd24f8386 100644 --- a/filament/src/details/DebugRegistry.cpp +++ b/filament/src/details/DebugRegistry.cpp @@ -59,7 +59,7 @@ void const* FDebugRegistry::getPropertyAddress(const char* name) const noexcept return info.first; } -void FDebugRegistry::registerProperty(std::string_view name, void* p, Type, +void FDebugRegistry::registerProperty(std::string_view const name, void* p, Type, std::function fn) noexcept { auto& propertyMap = mPropertyMap; if (propertyMap.find(name) == propertyMap.end()) { @@ -110,8 +110,8 @@ template bool FDebugRegistry::getProperty(const char* name, float2* v) c template bool FDebugRegistry::getProperty(const char* name, float3* v) const noexcept; template bool FDebugRegistry::getProperty(const char* name, float4* v) const noexcept; -bool FDebugRegistry::registerDataSource(std::string_view name, - void const* data, size_t count) noexcept { +bool FDebugRegistry::registerDataSource(std::string_view const name, + void const* data, size_t const count) noexcept { auto& dataSourceMap = mDataSourceMap; bool const found = dataSourceMap.find(name) == dataSourceMap.end(); if (found) { @@ -120,8 +120,8 @@ bool FDebugRegistry::registerDataSource(std::string_view name, return found; } -bool FDebugRegistry::registerDataSource(std::string_view name, - utils::Invocable&& creator) noexcept { +bool FDebugRegistry::registerDataSource(std::string_view const name, + Invocable&& creator) noexcept { auto& dataSourceCreatorMap = mDataSourceCreatorMap; bool const found = dataSourceCreatorMap.find(name) == dataSourceCreatorMap.end(); if (found) { @@ -130,7 +130,7 @@ bool FDebugRegistry::registerDataSource(std::string_view name, return found; } -void FDebugRegistry::unregisterDataSource(std::string_view name) noexcept { +void FDebugRegistry::unregisterDataSource(std::string_view const name) noexcept { mDataSourceCreatorMap.erase(name); mDataSourceMap.erase(name); } diff --git a/filament/src/details/DebugRegistry.h b/filament/src/details/DebugRegistry.h index 92a25b82e9..53d04255ce 100644 --- a/filament/src/details/DebugRegistry.h +++ b/filament/src/details/DebugRegistry.h @@ -45,57 +45,57 @@ public: FDebugRegistry() noexcept; - void registerProperty(std::string_view name, bool* p) noexcept { + void registerProperty(std::string_view const name, bool* p) noexcept { registerProperty(name, p, BOOL); } - void registerProperty(std::string_view name, int* p) noexcept { + void registerProperty(std::string_view const name, int* p) noexcept { registerProperty(name, p, INT); } - void registerProperty(std::string_view name, float* p) noexcept { + void registerProperty(std::string_view const name, float* p) noexcept { registerProperty(name, p, FLOAT); } - void registerProperty(std::string_view name, math::float2* p) noexcept { + void registerProperty(std::string_view const name, math::float2* p) noexcept { registerProperty(name, p, FLOAT2); } - void registerProperty(std::string_view name, math::float3* p) noexcept { + void registerProperty(std::string_view const name, math::float3* p) noexcept { registerProperty(name, p, FLOAT3); } - void registerProperty(std::string_view name, math::float4* p) noexcept { + void registerProperty(std::string_view const name, math::float4* p) noexcept { registerProperty(name, p, FLOAT4); } - void registerProperty(std::string_view name, bool* p, + void registerProperty(std::string_view const name, bool* p, std::function fn) noexcept { registerProperty(name, p, BOOL, std::move(fn)); } - void registerProperty(std::string_view name, int* p, + void registerProperty(std::string_view const name, int* p, std::function fn) noexcept { registerProperty(name, p, INT, std::move(fn)); } - void registerProperty(std::string_view name, float* p, + void registerProperty(std::string_view const name, float* p, std::function fn) noexcept { registerProperty(name, p, FLOAT, std::move(fn)); } - void registerProperty(std::string_view name, math::float2* p, + void registerProperty(std::string_view const name, math::float2* p, std::function fn) noexcept { registerProperty(name, p, FLOAT2, std::move(fn)); } - void registerProperty(std::string_view name, math::float3* p, + void registerProperty(std::string_view const name, math::float3* p, std::function fn) noexcept { registerProperty(name, p, FLOAT3, std::move(fn)); } - void registerProperty(std::string_view name, math::float4* p, + void registerProperty(std::string_view const name, math::float4* p, std::function fn) noexcept { registerProperty(name, p, FLOAT4, std::move(fn)); } diff --git a/filament/src/details/Engine.cpp b/filament/src/details/Engine.cpp index 1b20b06ac9..2116fae4c1 100644 --- a/filament/src/details/Engine.cpp +++ b/filament/src/details/Engine.cpp @@ -81,7 +81,7 @@ using namespace filaflat; struct Engine::BuilderDetails { Backend mBackend = Backend::DEFAULT; Platform* mPlatform = nullptr; - Engine::Config mConfig; + Config mConfig; FeatureLevel mFeatureLevel = FeatureLevel::FEATURE_LEVEL_1; void* mSharedContext = nullptr; bool mPaused = false; @@ -90,7 +90,7 @@ struct Engine::BuilderDetails { static Config validateConfig(Config config) noexcept; }; -Engine* FEngine::create(Engine::Builder const& builder) { +Engine* FEngine::create(Builder const& builder) { SYSTRACE_ENABLE(); SYSTRACE_CALL(); @@ -153,7 +153,7 @@ Engine* FEngine::create(Engine::Builder const& builder) { #if UTILS_HAS_THREADING -void FEngine::create(Engine::Builder const& builder, Invocable&& callback) { +void FEngine::create(Builder const& builder, Invocable&& callback) { SYSTRACE_ENABLE(); SYSTRACE_CALL(); @@ -208,7 +208,7 @@ static constexpr float4 sFullScreenTriangleVertices[3] = { // these must be static because only a pointer is copied to the render stream static const uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 }; -FEngine::FEngine(Engine::Builder const& builder) : +FEngine::FEngine(Builder const& builder) : mBackend(builder->mBackend), mActiveFeatureLevel(builder->mFeatureLevel), mPlatform(builder->mPlatform), @@ -235,7 +235,7 @@ FEngine::FEngine(Engine::Builder const& builder) : { // update a feature flag from Engine::Config if the flag is not specified in the Builder auto const featureFlagsBackwardCompatibility = - [this, &builder](std::string_view name, bool value) { + [this, &builder](std::string_view const name, bool const value) { if (builder->mFeatureFlags.find(name) == builder->mFeatureFlags.end()) { auto* const p = getFeatureFlagPtr(name, true); if (p) { @@ -268,7 +268,7 @@ FEngine::FEngine(Engine::Builder const& builder) : << "(threading is " << (UTILS_HAS_THREADING ? "enabled)" : "disabled)") << io::endl; } -uint32_t FEngine::getJobSystemThreadPoolSize(Engine::Config const& config) noexcept { +uint32_t FEngine::getJobSystemThreadPoolSize(Config const& config) noexcept { if (config.jobSystemThreadCount > 0) { return config.jobSystemThreadCount; } @@ -309,7 +309,7 @@ void FEngine::init() { mFullScreenTriangleVb = downcast(VertexBuffer::Builder() .vertexCount(3) .bufferCount(1) - .attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT4, 0) + .attribute(POSITION, 0, VertexBuffer::AttributeType::FLOAT4, 0) .build(*this)); mFullScreenTriangleVb->setBufferAt(*this, 0, @@ -635,7 +635,7 @@ void FEngine::prepare() { // prepare() is called once per Renderer frame. Ideally we would upload the content of // UBOs that are visible only. It's not such a big issue because the actual upload() is // skipped if the UBO hasn't changed. Still we could have a lot of these. - FEngine::DriverApi& driver = getDriverApi(); + DriverApi& driver = getDriverApi(); for (auto& materialInstanceList: mMaterialInstances) { materialInstanceList.second.forEach([&driver](FMaterialInstance* item) { @@ -665,50 +665,28 @@ void FEngine::flush() { } void FEngine::flushAndWait() { - FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused()) - << "Cannot call flushAndWait() when rendering thread is paused!"; + flushAndWait(FENCE_WAIT_FOR_EVER); +} -#if defined(__ANDROID__) +bool FEngine::flushAndWait(uint64_t timeout) { + FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused()) + << "Cannot call Engine::flushAndWait() when rendering thread is paused!"; // first make sure we've not terminated filament FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isExitRequested()) - << "calling Engine::flushAndWait() after Engine::shutdown()!"; - -#endif + << "Calling Engine::flushAndWait() after Engine::shutdown()!"; // enqueue finish command -- this will stall in the driver until the GPU is done getDriverApi().finish(); -#if defined(__ANDROID__) && !defined(NDEBUG) - - // then create a fence that will trigger when we're past the finish() above - size_t tryCount = 8; - FFence* fence = FEngine::createFence(); - UTILS_NOUNROLL - do { - FenceStatus status = fence->wait(FFence::Mode::FLUSH,250000000u); - // if the fence didn't trigger after 250ms, check that the command queue thread is still - // running (otherwise indicating a precondition violation). - if (UTILS_UNLIKELY(status == FenceStatus::TIMEOUT_EXPIRED)) { - FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isExitRequested()) - << "called Engine::shutdown() WHILE in Engine::flushAndWait()!"; - tryCount--; - FILAMENT_CHECK_POSTCONDITION(tryCount) << "flushAndWait() failed inexplicably after 2s"; - // if the thread is still running, maybe we just need to give it more time - continue; - } - break; - } while (true); + FFence* fence = createFence(); + FenceStatus const status = fence->wait(FFence::Mode::FLUSH, timeout); destroy(fence); -#else - - FFence::waitAndDestroy(FEngine::createFence(), FFence::Mode::FLUSH); - -#endif - // finally, execute callbacks that might have been scheduled getDriver().purge(); + + return status == FenceStatus::CONDITION_SATISFIED; } // ----------------------------------------------------------------------------------------------- @@ -956,21 +934,21 @@ FSwapChain* FEngine::createSwapChain(uint32_t width, uint32_t height, uint64_t f */ -FCamera* FEngine::createCamera(Entity entity) noexcept { +FCamera* FEngine::createCamera(Entity const entity) noexcept { return mCameraManager.create(*this, entity); } -FCamera* FEngine::getCameraComponent(Entity entity) noexcept { +FCamera* FEngine::getCameraComponent(Entity const entity) noexcept { auto ci = mCameraManager.getInstance(entity); return ci ? mCameraManager.getCamera(ci) : nullptr; } -void FEngine::destroyCameraComponent(utils::Entity entity) noexcept { +void FEngine::destroyCameraComponent(Entity const entity) noexcept { mCameraManager.destroy(*this, entity); } -void FEngine::createRenderable(const RenderableManager::Builder& builder, Entity entity) { +void FEngine::createRenderable(const RenderableManager::Builder& builder, Entity const entity) { mRenderableManager.create(builder, entity); auto& tcm = mTransformManager; // if this entity doesn't have a transform component, add one. @@ -979,7 +957,7 @@ void FEngine::createRenderable(const RenderableManager::Builder& builder, Entity } } -void FEngine::createLight(const LightManager::Builder& builder, Entity entity) { +void FEngine::createLight(const LightManager::Builder& builder, Entity const entity) { mLightManager.create(builder, entity); } @@ -1154,19 +1132,9 @@ UTILS_NOINLINE bool FEngine::destroy(const FMaterial* ptr) { if (ptr == nullptr) return true; bool const success = terminateAndDestroy(ptr, mMaterials); - if (success) { + if (UTILS_LIKELY(success)) { auto pos = mMaterialInstances.find(ptr); - if (pos != mMaterialInstances.cend()) { - // ensure we've destroyed all instances before destroying the material - if (!ASSERT_PRECONDITION_NON_FATAL(pos->second.empty(), - "destroying material \"%s\" but %u instances still alive", - ptr->getName().c_str(), (*pos).second.size())) { - // We return true here, because the material has been destroyed. However, this - // leaks this material's ResourceList until the engine - // is shut down. Note that it's still possible for the MaterialInstances to be - // destroyed manually. - return true; - } + if (UTILS_LIKELY(pos != mMaterialInstances.cend())) { mMaterialInstances.erase(pos); } } @@ -1176,6 +1144,39 @@ bool FEngine::destroy(const FMaterial* ptr) { UTILS_NOINLINE bool FEngine::destroy(const FMaterialInstance* ptr) { if (ptr == nullptr) return true; + + // Check that the material instance we're destroying is not in use in the RenderableManager + // To do this, we currently need to inspect all render primitives in the RenderableManager + EntityManager const& em = mEntityManager; + FRenderableManager const& rcm = mRenderableManager; + Entity const* entities = rcm.getEntities(); + size_t const count = rcm.getComponentCount(); + for (size_t i = 0; i < count; i++) { + Entity const entity = entities[i]; + if (em.isAlive(entity)) { + RenderableManager::Instance const ri = rcm.getInstance(entity); + size_t const primitiveCount = rcm.getPrimitiveCount(ri, 0); + for (size_t j = 0; j < primitiveCount; j++) { + auto const* const mi = rcm.getMaterialInstanceAt(ri, 0, j); + if (features.engine.debug.assert_material_instance_in_use) { + FILAMENT_CHECK_PRECONDITION(mi != ptr) + << "destroying MaterialInstance \"" + << mi->getName() << "\" which is still in use by Renderable (entity=" + << entity.getId() << ", instance=" + << ri.asValue() << ", index=" << j << ")"; + } else { + if (UTILS_UNLIKELY(mi == ptr)) { + slog.e << "destroying MaterialInstance \"" + << mi->getName() << "\" which is still in use by Renderable (entity=" + << entity.getId() << ", instance=" + << ri.asValue() << ", index=" << j << ")" + << io::endl; + } + } + } + } + } + if (ptr->isDefaultInstance()) return false; auto pos = mMaterialInstances.find(ptr->getMaterial()); assert_invariant(pos != mMaterialInstances.cend()); @@ -1187,7 +1188,7 @@ bool FEngine::destroy(const FMaterialInstance* ptr) { } UTILS_NOINLINE -void FEngine::destroy(Entity e) { +void FEngine::destroy(Entity const e) { mRenderableManager.destroy(e); mLightManager.destroy(e); mTransformManager.destroy(e); @@ -1312,7 +1313,7 @@ size_t FEngine::getMaxShadowMapCount() const noexcept { CONFIG_MAX_SHADOWMAPS : CONFIG_MAX_SHADOW_LAYERS; } -void* FEngine::streamAlloc(size_t size, size_t alignment) noexcept { +void* FEngine::streamAlloc(size_t const size, size_t const alignment) noexcept { // we allow this only for small allocations if (size > 65536) { return nullptr; @@ -1350,12 +1351,12 @@ bool FEngine::isPaused() const noexcept { return mCommandBufferQueue.isPaused(); } -void FEngine::setPaused(bool paused) { +void FEngine::setPaused(bool const paused) { mCommandBufferQueue.setPaused(paused); } Engine::FeatureLevel FEngine::getSupportedFeatureLevel() const noexcept { - FEngine::DriverApi& driver = const_cast(this)->getDriverApi(); + DriverApi& driver = const_cast(this)->getDriverApi(); return driver.getFeatureLevel(); } @@ -1380,7 +1381,7 @@ void FEngine::unprotected() noexcept { mUnprotectedDummySwapchain->makeCurrent(getDriverApi()); } -bool FEngine::setFeatureFlag(char const* name, bool value) noexcept { +bool FEngine::setFeatureFlag(char const* name, bool const value) noexcept { auto* const p = getFeatureFlagPtr(name); if (p) { *p = value; @@ -1396,7 +1397,7 @@ std::optional FEngine::getFeatureFlag(char const* name) const noexcept { return std::nullopt; } -bool* FEngine::getFeatureFlagPtr(std::string_view name, bool allowConstant) const noexcept { +bool* FEngine::getFeatureFlagPtr(std::string_view name, bool const allowConstant) const noexcept { auto pos = std::find_if(mFeatures.begin(), mFeatures.end(), [name](FeatureFlag const& entry) { return name == entry.name; @@ -1410,12 +1411,12 @@ bool* FEngine::getFeatureFlagPtr(std::string_view name, bool allowConstant) cons Engine::Builder::Builder() noexcept = default; Engine::Builder::~Builder() noexcept = default; -Engine::Builder::Builder(Engine::Builder const& rhs) noexcept = default; -Engine::Builder::Builder(Engine::Builder&& rhs) noexcept = default; -Engine::Builder& Engine::Builder::operator=(Engine::Builder const& rhs) noexcept = default; -Engine::Builder& Engine::Builder::operator=(Engine::Builder&& rhs) noexcept = default; +Engine::Builder::Builder(Builder const& rhs) noexcept = default; +Engine::Builder::Builder(Builder&& rhs) noexcept = default; +Engine::Builder& Engine::Builder::operator=(Builder const& rhs) noexcept = default; +Engine::Builder& Engine::Builder::operator=(Builder&& rhs) noexcept = default; -Engine::Builder& Engine::Builder::backend(Backend backend) noexcept { +Engine::Builder& Engine::Builder::backend(Backend const backend) noexcept { mImpl->mBackend = backend; return *this; } @@ -1425,12 +1426,12 @@ Engine::Builder& Engine::Builder::platform(Platform* platform) noexcept { return *this; } -Engine::Builder& Engine::Builder::config(Engine::Config const* config) noexcept { - mImpl->mConfig = config ? *config : Engine::Config{}; +Engine::Builder& Engine::Builder::config(Config const* config) noexcept { + mImpl->mConfig = config ? *config : Config{}; return *this; } -Engine::Builder& Engine::Builder::featureLevel(FeatureLevel featureLevel) noexcept { +Engine::Builder& Engine::Builder::featureLevel(FeatureLevel const featureLevel) noexcept { mImpl->mFeatureLevel = featureLevel; return *this; } @@ -1440,17 +1441,17 @@ Engine::Builder& Engine::Builder::sharedContext(void* sharedContext) noexcept { return *this; } -Engine::Builder& Engine::Builder::paused(bool paused) noexcept { +Engine::Builder& Engine::Builder::paused(bool const paused) noexcept { mImpl->mPaused = paused; return *this; } -Engine::Builder& Engine::Builder::feature(char const* name, bool value) noexcept { +Engine::Builder& Engine::Builder::feature(char const* name, bool const value) noexcept { mImpl->mFeatureFlags[name] = value; return *this; } -Engine::Builder& Engine::Builder::features(std::initializer_list list) noexcept { +Engine::Builder& Engine::Builder::features(std::initializer_list const list) noexcept { for (auto name : list) { if (name) { feature(name, true); diff --git a/filament/src/details/Engine.h b/filament/src/details/Engine.h index 7a394d14db..a59b66c1c2 100644 --- a/filament/src/details/Engine.h +++ b/filament/src/details/Engine.h @@ -115,7 +115,7 @@ class ResourceAllocator; class FEngine : public Engine { public: - inline void* operator new(std::size_t size) noexcept { + inline void* operator new(std::size_t const size) noexcept { return utils::aligned_alloc(size, alignof(FEngine)); } @@ -394,6 +394,7 @@ public: void setPaused(bool paused); void flushAndWait(); + bool flushAndWait(uint64_t timeout); // flush the current buffer void flush(); @@ -453,7 +454,7 @@ public: void unprotected() noexcept; - void setAutomaticInstancingEnabled(bool enable) noexcept { + void setAutomaticInstancingEnabled(bool const enable) noexcept { // instancing is not allowed at feature level 0 if (hasFeatureLevel(FeatureLevel::FEATURE_LEVEL_1)) { mAutomaticInstancingEnabled = enable; @@ -497,8 +498,12 @@ public: size_t getRequestedDriverHandleArenaSize() const noexcept { return mConfig.driverHandleArenaSizeMB * MiB; } Config const& getConfig() const noexcept { return mConfig; } - bool hasFeatureLevel(backend::FeatureLevel neededFeatureLevel) const noexcept { - return FEngine::getActiveFeatureLevel() >= neededFeatureLevel; + bool hasFeatureLevel(backend::FeatureLevel const neededFeatureLevel) const noexcept { + return getActiveFeatureLevel() >= neededFeatureLevel; + } + + auto const& getMaterialInstanceResourceList() const noexcept { + return mMaterialInstances; } #if defined(__EMSCRIPTEN__) @@ -506,7 +511,7 @@ public: #endif private: - explicit FEngine(Engine::Builder const& builder); + explicit FEngine(Builder const& builder); void init(); void shutdown(); @@ -598,7 +603,7 @@ private: HeapAllocatorArena mHeapAllocator; utils::JobSystem mJobSystem; - static uint32_t getJobSystemThreadPoolSize(Engine::Config const& config) noexcept; + static uint32_t getJobSystemThreadPoolSize(Config const& config) noexcept; std::default_random_engine mRandomEngine; @@ -683,6 +688,11 @@ public: struct { bool use_shadow_atlas = false; } shadows; + struct { + // TODO: default the following two flags to true. + bool assert_material_instance_in_use = false; + bool assert_destroy_material_before_material_instance = false; + } debug; } engine; struct { struct { @@ -705,7 +715,13 @@ public: &features.backend.opengl.assert_native_window_is_valid, true }, { "engine.shadows.use_shadow_atlas", "Uses an array of atlases to store shadow maps.", - &features.engine.shadows.use_shadow_atlas, false } + &features.engine.shadows.use_shadow_atlas, false }, + { "features.engine.debug.assert_material_instance_in_use", + "Assert when a MaterialInstance is destroyed while it is in use by RenderableManager.", + &features.engine.debug.assert_material_instance_in_use, false }, + { "features.engine.debug.assert_destroy_material_before_material_instance", + "Assert when a Material is destroyed but its instances are still alive.", + &features.engine.debug.assert_destroy_material_before_material_instance, false }, }}; utils::Slice getFeatureFlags() const noexcept { diff --git a/filament/src/details/Fence.cpp b/filament/src/details/Fence.cpp index b05cab44f7..8c7a2c81a4 100644 --- a/filament/src/details/Fence.cpp +++ b/filament/src/details/Fence.cpp @@ -52,7 +52,7 @@ void FFence::terminate(FEngine&) noexcept { } UTILS_NOINLINE -FenceStatus FFence::waitAndDestroy(FFence* fence, Mode mode) noexcept { +FenceStatus FFence::waitAndDestroy(FFence* fence, Mode const mode) noexcept { assert_invariant(fence); FenceStatus const status = fence->wait(mode, FENCE_WAIT_FOR_EVER); fence->mEngine.destroy(fence); @@ -60,7 +60,7 @@ FenceStatus FFence::waitAndDestroy(FFence* fence, Mode mode) noexcept { } UTILS_NOINLINE -FenceStatus FFence::wait(Mode mode, uint64_t timeout) noexcept { +FenceStatus FFence::wait(Mode const mode, uint64_t const timeout) noexcept { FILAMENT_CHECK_PRECONDITION(UTILS_HAS_THREADING || timeout == 0) << "Non-zero timeout requires threads."; @@ -102,21 +102,21 @@ FenceStatus FFence::wait(Mode mode, uint64_t timeout) noexcept { } UTILS_NOINLINE -void FFence::FenceSignal::signal(State s) noexcept { - std::lock_guard const lock(FFence::sLock); +void FFence::FenceSignal::signal(State const s) noexcept { + std::lock_guard const lock(sLock); mState = s; - FFence::sCondition.notify_all(); + sCondition.notify_all(); } UTILS_NOINLINE -Fence::FenceStatus FFence::FenceSignal::wait(uint64_t timeout) noexcept { - std::unique_lock lock(FFence::sLock); +Fence::FenceStatus FFence::FenceSignal::wait(uint64_t const timeout) noexcept { + std::unique_lock lock(sLock); while (mState == UNSIGNALED) { if (mState == DESTROYED) { return FenceStatus::ERROR; } if (timeout == FENCE_WAIT_FOR_EVER) { - FFence::sCondition.wait(lock); + sCondition.wait(lock); } else { if (timeout == 0 || sCondition.wait_for(lock, ns(timeout)) == std::cv_status::timeout) { diff --git a/filament/src/details/IndexBuffer.cpp b/filament/src/details/IndexBuffer.cpp index ee19154023..27775bde49 100644 --- a/filament/src/details/IndexBuffer.cpp +++ b/filament/src/details/IndexBuffer.cpp @@ -32,28 +32,32 @@ struct IndexBuffer::BuilderDetails { using BuilderType = IndexBuffer; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -IndexBuffer::Builder& IndexBuffer::Builder::indexCount(uint32_t indexCount) noexcept { +IndexBuffer::Builder& IndexBuffer::Builder::indexCount(uint32_t const indexCount) noexcept { mImpl->mIndexCount = indexCount; return *this; } -IndexBuffer::Builder& IndexBuffer::Builder::bufferType(IndexType indexType) noexcept { +IndexBuffer::Builder& IndexBuffer::Builder::bufferType(IndexType const indexType) noexcept { mImpl->mIndexType = indexType; return *this; } +IndexBuffer::Builder& IndexBuffer::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + IndexBuffer* IndexBuffer::Builder::build(Engine& engine) { return downcast(engine).createIndexBuffer(*this); } // ------------------------------------------------------------------------------------------------ -FIndexBuffer::FIndexBuffer(FEngine& engine, const IndexBuffer::Builder& builder) +FIndexBuffer::FIndexBuffer(FEngine& engine, const Builder& builder) : mIndexCount(builder->mIndexCount) { auto& name = builder.getName(); const char* const tag = name.empty() ? "(no tag)" : name.c_str_safe(); @@ -75,7 +79,7 @@ void FIndexBuffer::terminate(FEngine& engine) { driver.destroyIndexBuffer(mHandle); } -void FIndexBuffer::setBuffer(FEngine& engine, BufferDescriptor&& buffer, uint32_t byteOffset) { +void FIndexBuffer::setBuffer(FEngine& engine, BufferDescriptor&& buffer, uint32_t const byteOffset) { engine.getDriverApi().updateIndexBuffer(mHandle, std::move(buffer), byteOffset); } diff --git a/filament/src/details/IndirectLight.cpp b/filament/src/details/IndirectLight.cpp index 6d78d56408..371c66f478 100644 --- a/filament/src/details/IndirectLight.cpp +++ b/filament/src/details/IndirectLight.cpp @@ -52,10 +52,10 @@ struct IndirectLight::BuilderDetails { using BuilderType = IndirectLight; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; IndirectLight::Builder& IndirectLight::Builder::reflections(Texture const* cubemap) noexcept { mImpl->mReflectionsMap = cubemap; @@ -110,7 +110,7 @@ IndirectLight::Builder& IndirectLight::Builder::radiance(uint8_t bands, float3 c // this is a way to "document" the actual value of these coefficients and at the same // time make sure the expression and values are always in sync. struct Debug { - static constexpr bool almost(float a, float b) { + static constexpr bool almost(float const a, float const b) { constexpr float e = 1e-6f; return (a > b - e) && (a < b + e); } @@ -138,7 +138,7 @@ IndirectLight::Builder& IndirectLight::Builder::irradiance(Texture const* cubema return *this; } -IndirectLight::Builder& IndirectLight::Builder::intensity(float envIntensity) noexcept { +IndirectLight::Builder& IndirectLight::Builder::intensity(float const envIntensity) noexcept { mImpl->mIntensity = envIntensity; return *this; } @@ -209,7 +209,7 @@ backend::Handle FIndirectLight::getIrradianceHwHandle() cons : backend::Handle{}; } -math::float3 FIndirectLight::getDirectionEstimate(math::float3 const* f) noexcept { +float3 FIndirectLight::getDirectionEstimate(float3 const* f) noexcept { // The linear direction is found as normalize(-sh[3], -sh[1], sh[2]), but the coefficients // we store are already pre-normalized, so the negative sign disappears. // Note: we normalize the directions only after blending, this matches code used elsewhere -- @@ -221,7 +221,7 @@ math::float3 FIndirectLight::getDirectionEstimate(math::float3 const* f) noexcep return -normalize(r * 0.2126f + g * 0.7152f + b * 0.0722f); } -math::float4 FIndirectLight::getColorEstimate(math::float3 const* Le, math::float3 direction) noexcept { +float4 FIndirectLight::getColorEstimate(float3 const* Le, float3 direction) noexcept { // See: https://www.gamasutra.com/view/news/129689/Indepth_Extracting_dominant_light_from_Spherical_Harmonics.php // note Le is our pre-convolved, pre-scaled SH coefficients for the environment @@ -261,11 +261,11 @@ math::float4 FIndirectLight::getColorEstimate(math::float3 const* Le, math::floa return { LdDotLe / intensity, intensity }; } -math::float3 FIndirectLight::getDirectionEstimate() const noexcept { +float3 FIndirectLight::getDirectionEstimate() const noexcept { return getDirectionEstimate(mIrradianceCoefs.data()); } -float4 FIndirectLight::getColorEstimate(float3 direction) const noexcept { +float4 FIndirectLight::getColorEstimate(float3 const direction) const noexcept { return getColorEstimate(mIrradianceCoefs.data(), direction); } diff --git a/filament/src/details/IndirectLight.h b/filament/src/details/IndirectLight.h index db30c517ec..04c757b04b 100644 --- a/filament/src/details/IndirectLight.h +++ b/filament/src/details/IndirectLight.h @@ -46,7 +46,7 @@ public: backend::Handle getIrradianceHwHandle() const noexcept; math::float3 const* getSH() const noexcept{ return mIrradianceCoefs.data(); } float getIntensity() const noexcept { return mIntensity; } - void setIntensity(float intensity) noexcept { mIntensity = intensity; } + void setIntensity(float const intensity) noexcept { mIntensity = intensity; } void setRotation(math::mat3f const& rotation) noexcept { mRotation = rotation; } const math::mat3f& getRotation() const noexcept { return mRotation; } FTexture const* getReflectionsTexture() const noexcept { return mReflectionsTexture; } diff --git a/filament/src/details/InstanceBuffer.cpp b/filament/src/details/InstanceBuffer.cpp index 89fdd0e5d9..955711ab75 100644 --- a/filament/src/details/InstanceBuffer.cpp +++ b/filament/src/details/InstanceBuffer.cpp @@ -34,15 +34,15 @@ struct InstanceBuffer::BuilderDetails { }; using BuilderType = InstanceBuffer; -BuilderType::Builder::Builder(size_t instanceCount) noexcept { +BuilderType::Builder::Builder(size_t const instanceCount) noexcept { mImpl->mInstanceCount = instanceCount; } BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; InstanceBuffer::Builder& InstanceBuffer::Builder::localTransforms( math::mat4f const* localTransforms) noexcept { @@ -50,6 +50,10 @@ InstanceBuffer::Builder& InstanceBuffer::Builder::localTransforms( return *this; } +InstanceBuffer::Builder& InstanceBuffer::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + InstanceBuffer* InstanceBuffer::Builder::build(Engine& engine) { FILAMENT_CHECK_PRECONDITION(mImpl->mInstanceCount >= 1) << "instanceCount must be >= 1."; FILAMENT_CHECK_PRECONDITION(mImpl->mInstanceCount <= engine.getMaxAutomaticInstances()) @@ -75,7 +79,7 @@ FInstanceBuffer::FInstanceBuffer(FEngine& engine, const Builder& builder) } void FInstanceBuffer::setLocalTransforms( - math::mat4f const* localTransforms, size_t count, size_t offset) { + math::mat4f const* localTransforms, size_t const count, size_t const offset) { FILAMENT_CHECK_PRECONDITION(offset + count <= mInstanceCount) << "setLocalTransforms overflow. InstanceBuffer has only " << mInstanceCount << " instances, but trying to set " << count @@ -89,7 +93,7 @@ void FInstanceBuffer::prepare(FEngine& engine, math::mat4f rootTransform, // TODO: allocate this staging buffer from a pool. uint32_t stagingBufferSize = sizeof(PerRenderableUib); - PerRenderableData* stagingBuffer = (PerRenderableData*)::malloc(stagingBufferSize); + PerRenderableData* stagingBuffer = (PerRenderableData*)malloc(stagingBufferSize); // TODO: consider using JobSystem to parallelize this. for (size_t i = 0, c = mInstanceCount; i < c; i++) { stagingBuffer[i] = ubo; @@ -102,7 +106,7 @@ void FInstanceBuffer::prepare(FEngine& engine, math::mat4f rootTransform, driver.updateBufferObject(handle, { stagingBuffer, stagingBufferSize, +[](void* buffer, size_t, void*) { - ::free(buffer); + free(buffer); } }, 0); } diff --git a/filament/src/details/Material.cpp b/filament/src/details/Material.cpp index be8ca04be2..4347e1aa28 100644 --- a/filament/src/details/Material.cpp +++ b/filament/src/details/Material.cpp @@ -78,8 +78,8 @@ using namespace backend; using namespace filaflat; using namespace utils; -static std::unique_ptr createParser(Backend backend, - utils::FixedCapacityVector languages, const void* data, size_t size) { +static std::unique_ptr createParser(Backend const backend, + FixedCapacityVector languages, const void* data, size_t size) { // unique_ptr so we don't leak MaterialParser on failures below auto materialParser = std::make_unique(languages, data, size); @@ -125,35 +125,35 @@ struct Material::BuilderDetails { int32_t mShBandsCount = 3; Builder::ShadowSamplingQuality mShadowSamplingQuality = Builder::ShadowSamplingQuality::LOW; std::unordered_map< - utils::CString, + CString, std::variant, CString::Hasher> mConstantSpecializations; }; -FMaterial::DefaultMaterialBuilder::DefaultMaterialBuilder() : Material::Builder() { +FMaterial::DefaultMaterialBuilder::DefaultMaterialBuilder() { mImpl->mDefaultMaterial = true; } using BuilderType = Material; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -Material::Builder& Material::Builder::package(const void* payload, size_t size) { +Material::Builder& Material::Builder::package(const void* payload, size_t const size) { mImpl->mPayload = payload; mImpl->mSize = size; return *this; } -Material::Builder& Material::Builder::sphericalHarmonicsBandCount(size_t shBandCount) noexcept { +Material::Builder& Material::Builder::sphericalHarmonicsBandCount(size_t const shBandCount) noexcept { mImpl->mShBandsCount = math::clamp(shBandCount, size_t(1), size_t(3)); return *this; } -Material::Builder& Material::Builder::shadowSamplingQuality(ShadowSamplingQuality quality) noexcept { +Material::Builder& Material::Builder::shadowSamplingQuality(ShadowSamplingQuality const quality) noexcept { mImpl->mShadowSamplingQuality = quality; return *this; } @@ -169,7 +169,7 @@ template Material::Builder& Material::Builder::constant(const char*, si template Material::Builder& Material::Builder::constant(const char*, size_t, float); template Material::Builder& Material::Builder::constant(const char*, size_t, bool); -Material* Material::Builder::build(Engine& engine) { +Material* Material::Builder::build(Engine& engine) const { std::unique_ptr materialParser = createParser( downcast(engine).getBackend(), downcast(engine).getShaderLanguage(), mImpl->mPayload, mImpl->mSize); @@ -180,7 +180,7 @@ Material* Material::Builder::build(Engine& engine) { uint32_t v = 0; materialParser->getShaderModels(&v); - utils::bitset32 shaderModels; + bitset32 shaderModels; shaderModels.setValue(v); ShaderModel const shaderModel = downcast(engine).getShaderModel(); @@ -228,7 +228,7 @@ Material* Material::Builder::build(Engine& engine) { return downcast(engine).createMaterial(*this, std::move(materialParser)); } -FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder, +FMaterial::FMaterial(FEngine& engine, const Builder& builder, std::unique_ptr materialParser) : mIsDefaultMaterial(builder->mDefaultMaterial), mEngine(engine), @@ -345,7 +345,7 @@ FMaterial::FMaterial(FEngine& engine, const Material::Builder& builder, // Register the material with matdbg. matdbg::DebugServer* server = downcast(engine).debug.server; if (UTILS_UNLIKELY(server)) { - auto details = builder.mImpl; + auto const details = builder.mImpl; mDebuggerId = server->addMaterial(mName, details->mPayload, details->mSize, this); } #endif @@ -373,6 +373,27 @@ void FMaterial::invalidate(Variant::type_t variantMask, Variant::type_t variantV void FMaterial::terminate(FEngine& engine) { + if (mDefaultMaterialInstance) { + mDefaultMaterialInstance->setDefaultInstance(false); + engine.destroy(mDefaultMaterialInstance); + mDefaultMaterialInstance = nullptr; + } + + // ensure we've destroyed all instances before destroying the material + auto const& materialInstanceResourceList = engine.getMaterialInstanceResourceList(); + auto pos = materialInstanceResourceList.find(this); + if (UTILS_LIKELY(pos != materialInstanceResourceList.cend())) { + if (engine.features.engine.debug.assert_destroy_material_before_material_instance) { + FILAMENT_CHECK_PRECONDITION(pos->second.empty()) + << "destroying material \"" << this->getName().c_str_safe() << "\" but " + << pos->second.size() << " instances still alive."; + } else { + utils::slog.e << "destroying material \"" << this->getName().c_str_safe() << "\" but " + << pos->second.size() << " instances still alive."; + } + } + + #if FILAMENT_ENABLE_MATDBG // Unregister the material with matdbg. matdbg::DebugServer* server = engine.debug.server; @@ -383,22 +404,15 @@ void FMaterial::terminate(FEngine& engine) { destroyPrograms(engine); - if (mDefaultMaterialInstance) { - mDefaultMaterialInstance->setDefaultInstance(false); - engine.destroy(mDefaultMaterialInstance); - mDefaultMaterialInstance = nullptr; - } - - mPerViewDescriptorSetLayout.terminate( - engine.getDescriptorSetLayoutFactory(), engine.getDriverApi()); - mDescriptorSetLayout.terminate( - engine.getDescriptorSetLayoutFactory(), engine.getDriverApi()); + DriverApi& driver = engine.getDriverApi(); + mPerViewDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver); + mDescriptorSetLayout.terminate(engine.getDescriptorSetLayoutFactory(), driver); } -void FMaterial::compile(CompilerPriorityQueue priority, +void FMaterial::compile(CompilerPriorityQueue const priority, UserVariantFilterMask variantSpec, - backend::CallbackHandler* handler, - utils::Invocable&& callback) noexcept { + CallbackHandler* handler, + Invocable&& callback) noexcept { // Turn off the STE variant if stereo is not supported. if (!mEngine.getDriverApi().isStereoSupported()) { @@ -425,7 +439,7 @@ void FMaterial::compile(CompilerPriorityQueue priority, Invocable f; Material* m; static void func(void* user) { - auto* const c = reinterpret_cast(user); + auto* const c = static_cast(user); c->f(c->m); delete c; } @@ -458,7 +472,7 @@ FMaterialInstance* FMaterial::getDefaultInstance() noexcept { bool FMaterial::hasParameter(const char* name) const noexcept { return mUniformInterfaceBlock.hasField(name) || mSamplerInterfaceBlock.hasSampler(name) || - mSubpassInfo.name == utils::CString(name); + mSubpassInfo.name == CString(name); } bool FMaterial::isSampler(const char* name) const noexcept { @@ -466,11 +480,11 @@ bool FMaterial::isSampler(const char* name) const noexcept { } BufferInterfaceBlock::FieldInfo const* FMaterial::reflect( - std::string_view name) const noexcept { + std::string_view const name) const noexcept { return mUniformInterfaceBlock.getFieldInfo(name); } -bool FMaterial::hasVariant(Variant variant) const noexcept { +bool FMaterial::hasVariant(Variant const variant) const noexcept { Variant vertexVariant, fragmentVariant; switch (getMaterialDomain()) { case MaterialDomain::SURFACE: @@ -494,8 +508,8 @@ bool FMaterial::hasVariant(Variant variant) const noexcept { return true; } -void FMaterial::prepareProgramSlow(Variant variant, - backend::CompilerPriorityQueue priorityQueue) const noexcept { +void FMaterial::prepareProgramSlow(Variant const variant, + backend::CompilerPriorityQueue const priorityQueue) const noexcept { assert_invariant(mEngine.hasFeatureLevel(mFeatureLevel)); switch (getMaterialDomain()) { case MaterialDomain::SURFACE: @@ -510,8 +524,8 @@ void FMaterial::prepareProgramSlow(Variant variant, } } -void FMaterial::getSurfaceProgramSlow(Variant variant, - CompilerPriorityQueue priorityQueue) const noexcept { +void FMaterial::getSurfaceProgramSlow(Variant const variant, + CompilerPriorityQueue const priorityQueue) const noexcept { // filterVariant() has already been applied in generateCommands(), shouldn't be needed here // if we're unlit, we don't have any bits that correspond to lit materials assert_invariant(variant == Variant::filterVariant(variant, isVariantLit()) ); @@ -529,8 +543,8 @@ void FMaterial::getSurfaceProgramSlow(Variant variant, createAndCacheProgram(std::move(pb), variant); } -void FMaterial::getPostProcessProgramSlow(Variant variant, - CompilerPriorityQueue priorityQueue) const noexcept { +void FMaterial::getPostProcessProgramSlow(Variant const variant, + CompilerPriorityQueue const priorityQueue) const noexcept { Program pb{ getProgramWithVariants(variant, variant, variant) }; pb.priorityQueue(priorityQueue); createAndCacheProgram(std::move(pb), variant); @@ -581,9 +595,9 @@ Program FMaterial::getProgramWithVariants( [this, variant, vertexVariant, fragmentVariant]( io::ostream& out) -> io::ostream& { return out << mName.c_str_safe() << ", variant=(" << io::hex - << (int)variant.key << io::dec << "), vertexVariant=(" << io::hex - << (int)vertexVariant.key << io::dec << "), fragmentVariant=(" - << io::hex << (int)fragmentVariant.key << io::dec << ")"; + << +variant.key << io::dec << "), vertexVariant=(" << io::hex + << +vertexVariant.key << io::dec << "), fragmentVariant=(" + << io::hex << +fragmentVariant.key << io::dec << ")"; }); if (UTILS_UNLIKELY(mMaterialParser->getShaderLanguage() == ShaderLanguage::ESSL1)) { @@ -599,15 +613,15 @@ Program FMaterial::getProgramWithVariants( program.descriptorBindings(2, mProgramDescriptorBindings[2]); program.specializationConstants(mSpecializationConstants); - program.pushConstants(ShaderStage::VERTEX, mPushConstants[(uint8_t) ShaderStage::VERTEX]); - program.pushConstants(ShaderStage::FRAGMENT, mPushConstants[(uint8_t) ShaderStage::FRAGMENT]); + program.pushConstants(ShaderStage::VERTEX, mPushConstants[uint8_t(ShaderStage::VERTEX)]); + program.pushConstants(ShaderStage::FRAGMENT, mPushConstants[uint8_t(ShaderStage::FRAGMENT)]); - program.cacheId(utils::hash::combine(size_t(mCacheId), variant.key)); + program.cacheId(hash::combine(size_t(mCacheId), variant.key)); return program; } -void FMaterial::createAndCacheProgram(Program&& p, Variant variant) const noexcept { +void FMaterial::createAndCacheProgram(Program&& p, Variant const variant) const noexcept { FEngine const& engine = mEngine; DriverApi& driverApi = mEngine.getDriverApi(); @@ -617,7 +631,7 @@ void FMaterial::createAndCacheProgram(Program&& p, Variant variant) const noexce if (isShared) { FMaterial const* const pDefaultMaterial = engine.getDefaultMaterial(); if (pDefaultMaterial) { - auto program = pDefaultMaterial->mCachedPrograms[variant.key]; + auto const program = pDefaultMaterial->mCachedPrograms[variant.key]; if (program) { mCachedPrograms[variant.key] = program; return; @@ -625,7 +639,7 @@ void FMaterial::createAndCacheProgram(Program&& p, Variant variant) const noexce } } - auto program = driverApi.createProgram(std::move(p)); + auto const program = driverApi.createProgram(std::move(p)); driverApi.setDebugTag(program.getId(), mName); assert_invariant(program); mCachedPrograms[variant.key] = program; @@ -704,14 +718,14 @@ void FMaterial::setPendingEdits(std::unique_ptr pendingEdits) no std::swap(pendingEdits, mPendingEdits); } -bool FMaterial::hasPendingEdits() noexcept { +bool FMaterial::hasPendingEdits() const noexcept { std::lock_guard const lock(mPendingEditsLock); - return (bool)mPendingEdits; + return bool(mPendingEdits); } void FMaterial::latchPendingEdits() noexcept { std::lock_guard const lock(mPendingEditsLock); - mMaterialParser.reset(mPendingEdits.release()); + mMaterialParser = std::move(mPendingEdits); } /** @@ -721,9 +735,9 @@ void FMaterial::latchPendingEdits() noexcept { * @{ */ -void FMaterial::onEditCallback(void* userdata, const utils::CString&, const void* packageData, - size_t packageSize) { - FMaterial* material = downcast((Material*) userdata); +void FMaterial::onEditCallback(void* userdata, const CString&, const void* packageData, + size_t const packageSize) { + FMaterial* material = downcast(static_cast(userdata)); FEngine const& engine = material->mEngine; // This is called on a web server thread, so we defer clearing the program cache @@ -733,10 +747,10 @@ void FMaterial::onEditCallback(void* userdata, const utils::CString&, const void material->setPendingEdits(std::move(pending)); } -void FMaterial::onQueryCallback(void* userdata, VariantList* pVariants) { - FMaterial* material = downcast((Material*) userdata); - std::lock_guard const lock(material->mActiveProgramsLock); - *pVariants = material->mActivePrograms; +void FMaterial::onQueryCallback(void* userdata, VariantList* pActiveVariants) { + FMaterial const* material = downcast(static_cast(userdata)); + std::lock_guard const lock(material->mActiveProgramsLock); + *pActiveVariants = material->mActivePrograms; material->mActivePrograms.reset(); } @@ -754,7 +768,7 @@ void FMaterial::destroyPrograms(FEngine& engine, switch (mMaterialDomain) { case MaterialDomain::SURFACE: { if (mIsDefaultMaterial || mHasCustomDepthShader) { - // default material or we have custom depth shaders, we destroy all variants + // default material, or we have custom depth shaders, we destroy all variants for (size_t k = 0, n = VARIANT_COUNT; k < n; ++k) { if ((k & variantMask) == variantValue) { // Only destroy if the handle is valid. Not strictly needed, but we have a lot @@ -771,7 +785,7 @@ void FMaterial::destroyPrograms(FEngine& engine, // During Engine::shutdown(), auto-cleanup destroys the default material first, // so this can be null, but this is only used for debugging. UTILS_UNUSED_IN_RELEASE - auto UTILS_NULLABLE pDefaultMaterial = engine.getDefaultMaterial(); + auto const UTILS_NULLABLE pDefaultMaterial = engine.getDefaultMaterial(); for (size_t k = 0, n = VARIANT_COUNT; k < n; ++k) { if ((k & variantMask) == variantValue) { @@ -818,8 +832,8 @@ void FMaterial::destroyPrograms(FEngine& engine, } } -std::optional FMaterial::getSpecializationConstantId(std::string_view name) const noexcept { - auto pos = mSpecializationConstantsNameToIndex.find(name); +std::optional FMaterial::getSpecializationConstantId(std::string_view const name) const noexcept { + auto const pos = mSpecializationConstantsNameToIndex.find(name); if (pos != mSpecializationConstantsNameToIndex.end()) { return pos->second + CONFIG_MAX_RESERVED_SPEC_CONSTANTS; } @@ -832,8 +846,8 @@ bool FMaterial::setConstant(uint32_t id, T value) noexcept { if (UTILS_LIKELY(id < maxId)) { if (id >= CONFIG_MAX_RESERVED_SPEC_CONSTANTS) { // Constant from the material itself (as opposed to the reserved ones) - auto& constant = mMaterialConstants[id - CONFIG_MAX_RESERVED_SPEC_CONSTANTS]; - using ConstantType = backend::ConstantType; + auto const& constant = mMaterialConstants[id - CONFIG_MAX_RESERVED_SPEC_CONSTANTS]; + using ConstantType = ConstantType; switch (constant.type) { case ConstantType::INT: if (!std::is_same_v) return false; @@ -849,7 +863,7 @@ bool FMaterial::setConstant(uint32_t id, T value) noexcept { auto pos = std::find_if( mSpecializationConstants.begin(), mSpecializationConstants.end(), - [id](backend::Program::SpecializationConstant const& specializationConstant) { + [id](Program::SpecializationConstant const& specializationConstant) { return specializationConstant.id == id; }); if (pos != mSpecializationConstants.end()) { @@ -947,7 +961,7 @@ void FMaterial::processBlendingMode(MaterialParser const* const parser) { } } -void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builder const& builder, +void FMaterial::processSpecializationConstants(FEngine& engine, Builder const& builder, MaterialParser const* const parser) { // Older materials won't have a constants chunk, but that's okay. parser->getConstants(&mMaterialConstants); @@ -966,9 +980,9 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde int const maxInstanceCount = (engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0) ? 1 : CONFIG_MAX_INSTANCES; - int const maxFroxelBufferHeight = (int)std::min( + int const maxFroxelBufferHeight = int(std::min( FROXEL_BUFFER_MAX_ENTRY_COUNT / 4, - engine.getDriverApi().getMaxUniformBufferSize() / 16u); + engine.getDriverApi().getMaxUniformBufferSize() / 16u)); bool const staticTextureWorkaround = engine.getDriverApi().isWorkaroundNeeded(Workaround::METAL_STATIC_TEXTURE_TARGET_ERROR); @@ -979,13 +993,13 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde mSpecializationConstants.reserve(mMaterialConstants.size() + CONFIG_MAX_RESERVED_SPEC_CONSTANTS); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::BACKEND_FEATURE_LEVEL, - (int)engine.getSupportedFeatureLevel() }); + int(engine.getSupportedFeatureLevel()) }); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::CONFIG_MAX_INSTANCES, - (int)maxInstanceCount }); + int(maxInstanceCount) }); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::CONFIG_FROXEL_BUFFER_HEIGHT, - (int)maxFroxelBufferHeight }); + int(maxFroxelBufferHeight) }); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::CONFIG_DEBUG_DIRECTIONAL_SHADOWMAP, engine.debug.shadowmap.debug_directional_shadowmap }); @@ -1000,13 +1014,13 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde powerVrShaderWorkarounds }); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::CONFIG_STEREO_EYE_COUNT, - (int)engine.getConfig().stereoscopicEyeCount }); + int(engine.getConfig().stereoscopicEyeCount) }); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::CONFIG_SH_BANDS_COUNT, builder->mShBandsCount }); mSpecializationConstants.push_back({ +ReservedSpecializationConstants::CONFIG_SHADOW_SAMPLING_METHOD, - (int32_t)builder->mShadowSamplingQuality }); + int32_t(builder->mShadowSamplingQuality) }); if (UTILS_UNLIKELY(parser->getShaderLanguage() == ShaderLanguage::ESSL1)) { // The actual value of this spec-constant is set in the OpenGLDriver backend. mSpecializationConstants.push_back({ @@ -1020,8 +1034,8 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde FILAMENT_CHECK_PRECONDITION(pos != mSpecializationConstantsNameToIndex.end()) << "The material " << mName.c_str_safe() << " does not have a constant parameter named " << name.c_str() << "."; - const char* const types[3] = {"an int", "a float", "a bool"}; - auto& constant = mMaterialConstants[pos->second]; + constexpr char const* const types[3] = {"an int", "a float", "a bool"}; + auto const& constant = mMaterialConstants[pos->second]; switch (constant.type) { case ConstantType::INT: FILAMENT_CHECK_PRECONDITION(std::holds_alternative(value)) @@ -1047,14 +1061,14 @@ void FMaterial::processSpecializationConstants(FEngine& engine, Material::Builde } } -void FMaterial::processPushConstants(FEngine& engine, MaterialParser const* parser) { - utils::FixedCapacityVector& vertexConstants = - mPushConstants[(uint8_t) ShaderStage::VERTEX]; - utils::FixedCapacityVector& fragmentConstants = - mPushConstants[(uint8_t) ShaderStage::FRAGMENT]; +void FMaterial::processPushConstants(FEngine&, MaterialParser const* parser) { + FixedCapacityVector& vertexConstants = + mPushConstants[uint8_t(ShaderStage::VERTEX)]; + FixedCapacityVector& fragmentConstants = + mPushConstants[uint8_t(ShaderStage::FRAGMENT)]; CString structVarName; - utils::FixedCapacityVector pushConstants; + FixedCapacityVector pushConstants; parser->getPushConstants(&structVarName, &pushConstants); vertexConstants.reserve(pushConstants.size()); @@ -1070,11 +1084,11 @@ void FMaterial::processPushConstants(FEngine& engine, MaterialParser const* pars switch (constant.stage) { case ShaderStage::VERTEX: - vertexConstants.push_back({utils::CString(buf), constant.type}); + vertexConstants.push_back({CString(buf), constant.type}); vertexCount++; break; case ShaderStage::FRAGMENT: - fragmentConstants.push_back({utils::CString(buf), constant.type}); + fragmentConstants.push_back({CString(buf), constant.type}); fragmentCount++; break; case ShaderStage::COMPUTE: @@ -1083,7 +1097,7 @@ void FMaterial::processPushConstants(FEngine& engine, MaterialParser const* pars }); } -void FMaterial::precacheDepthVariants(FEngine& engine) { +void FMaterial::precacheDepthVariants(FEngine const& engine) { // pre-cache all depth variants inside the default material. Note that this should be // entirely optional; if we remove this pre-caching, these variants will be populated // later, when/if needed by createAndCacheProgram(). Doing it now potentially uses more @@ -1132,7 +1146,7 @@ void FMaterial::processDescriptorSets(FEngine& engine, MaterialParser const* con engine.getDriverApi(), std::move(descriptorSetLayout[1]) }; } -backend::descriptor_binding_t FMaterial::getSamplerBinding( +descriptor_binding_t FMaterial::getSamplerBinding( std::string_view const& name) const { return mSamplerInterfaceBlock.getSamplerInfo(name)->binding; } diff --git a/filament/src/details/Material.h b/filament/src/details/Material.h index 5dd55e733e..d0e9d1492b 100644 --- a/filament/src/details/Material.h +++ b/filament/src/details/Material.h @@ -71,11 +71,11 @@ class FEngine; class FMaterial : public Material { public: - FMaterial(FEngine& engine, const Material::Builder& builder, + FMaterial(FEngine& engine, const Builder& builder, std::unique_ptr materialParser); ~FMaterial() noexcept; - class DefaultMaterialBuilder : public Material::Builder { + class DefaultMaterialBuilder : public Builder { public: DefaultMaterialBuilder(); }; @@ -93,7 +93,7 @@ public: return mPerViewDescriptorSetLayout; } - DescriptorSetLayout const& getPerViewDescriptorSetLayout(Variant variant) const noexcept { + DescriptorSetLayout const& getPerViewDescriptorSetLayout(Variant const variant) const noexcept { if (Variant::isValidDepthVariant(variant)) { assert_invariant(mMaterialDomain == MaterialDomain::SURFACE); return mEngine.getPerViewDescriptorSetLayoutDepthVariant(); @@ -110,7 +110,7 @@ public: } void compile(CompilerPriorityQueue priority, - UserVariantFilterMask variantFilter, + UserVariantFilterMask variantSpec, backend::CallbackHandler* handler, utils::Invocable&& callback) noexcept; @@ -131,7 +131,7 @@ public: FEngine& getEngine() const noexcept { return mEngine; } - bool isCached(Variant variant) const noexcept { + bool isCached(Variant const variant) const noexcept { return bool(mCachedPrograms[variant.key]); } @@ -140,8 +140,8 @@ public: // prepareProgram creates the program for the material's given variant at the backend level. // Must be called outside of backend render pass. // Must be called before getProgram() below. - void prepareProgram(Variant variant, - backend::CompilerPriorityQueue priorityQueue = CompilerPriorityQueue::HIGH) const noexcept { + void prepareProgram(Variant const variant, + backend::CompilerPriorityQueue const priorityQueue = CompilerPriorityQueue::HIGH) const noexcept { // prepareProgram() is called for each RenderPrimitive in the scene, so it must be efficient. if (UTILS_UNLIKELY(!isCached(variant))) { prepareProgramSlow(variant, priorityQueue); @@ -150,7 +150,7 @@ public: // getProgram returns the backend program for the material's given variant. // Must be called after prepareProgram(). - [[nodiscard]] backend::Handle getProgram(Variant variant) const noexcept { + [[nodiscard]] backend::Handle getProgram(Variant const variant) const noexcept { #if FILAMENT_ENABLE_MATDBG assert_invariant((size_t)variant.key < VARIANT_COUNT); std::unique_lock lock(mActiveProgramsLock); @@ -286,18 +286,18 @@ private: void processBlendingMode(MaterialParser const* parser); - void processSpecializationConstants(FEngine& engine, Material::Builder const& builder, + void processSpecializationConstants(FEngine& engine, Builder const& builder, MaterialParser const* parser); void processPushConstants(FEngine& engine, MaterialParser const* parser); - void precacheDepthVariants(FEngine& engine); + void precacheDepthVariants(FEngine const& engine); void processDescriptorSets(FEngine& engine, MaterialParser const* parser); void createAndCacheProgram(backend::Program&& p, Variant variant) const noexcept; - inline bool isSharedVariant(Variant variant) const { + inline bool isSharedVariant(Variant const variant) const { return (mMaterialDomain == MaterialDomain::SURFACE) && !mIsDefaultMaterial && !mHasCustomDepthShader && Variant::isValidDepthVariant(variant); } @@ -374,7 +374,7 @@ private: mutable utils::Mutex mPendingEditsLock; std::unique_ptr mPendingEdits; void setPendingEdits(std::unique_ptr pendingEdits) noexcept; - bool hasPendingEdits() noexcept; + bool hasPendingEdits() const noexcept; void latchPendingEdits() noexcept; #endif diff --git a/filament/src/details/MaterialInstance.cpp b/filament/src/details/MaterialInstance.cpp index 4bbf44eddf..972b89cab7 100644 --- a/filament/src/details/MaterialInstance.cpp +++ b/filament/src/details/MaterialInstance.cpp @@ -75,7 +75,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, FMaterial const* material, if (!material->getUniformInterfaceBlock().isEmpty()) { mUniforms = UniformBuffer(material->getUniformInterfaceBlock().getSize()); mUbHandle = driver.createBufferObject(mUniforms.getSize(), - BufferObjectBinding::UNIFORM, backend::BufferUsage::STATIC); + BufferObjectBinding::UNIFORM, BufferUsage::STATIC); driver.setDebugTag(mUbHandle.getId(), material->getName()); } @@ -141,7 +141,7 @@ FMaterialInstance::FMaterialInstance(FEngine& engine, if (!material->getUniformInterfaceBlock().isEmpty()) { mUniforms.setUniforms(other->getUniformBuffer()); mUbHandle = driver.createBufferObject(mUniforms.getSize(), - BufferObjectBinding::UNIFORM, backend::BufferUsage::DYNAMIC); + BufferObjectBinding::UNIFORM, BufferUsage::DYNAMIC); driver.setDebugTag(mUbHandle.getId(), material->getName()); } @@ -214,13 +214,13 @@ void FMaterialInstance::commit(DriverApi& driver) const { // ------------------------------------------------------------------------------------------------ -void FMaterialInstance::setParameter(std::string_view name, - backend::Handle texture, backend::SamplerParams params) { +void FMaterialInstance::setParameter(std::string_view const name, + Handle texture, SamplerParams const params) { auto binding = mMaterial->getSamplerBinding(name); mDescriptorSet.setSampler(binding, texture, params); } -void FMaterialInstance::setParameterImpl(std::string_view name, +void FMaterialInstance::setParameterImpl(std::string_view const name, FTexture const* texture, TextureSampler const& sampler) { #ifndef NDEBUG @@ -258,34 +258,34 @@ void FMaterialInstance::setParameterImpl(std::string_view name, } } -void FMaterialInstance::setMaskThreshold(float threshold) noexcept { - setParameter("_maskThreshold", math::saturate(threshold)); - mMaskThreshold = math::saturate(threshold); +void FMaterialInstance::setMaskThreshold(float const threshold) noexcept { + setParameter("_maskThreshold", saturate(threshold)); + mMaskThreshold = saturate(threshold); } float FMaterialInstance::getMaskThreshold() const noexcept { return mMaskThreshold; } -void FMaterialInstance::setSpecularAntiAliasingVariance(float variance) noexcept { - setParameter("_specularAntiAliasingVariance", math::saturate(variance)); - mSpecularAntiAliasingVariance = math::saturate(variance); +void FMaterialInstance::setSpecularAntiAliasingVariance(float const variance) noexcept { + setParameter("_specularAntiAliasingVariance", saturate(variance)); + mSpecularAntiAliasingVariance = saturate(variance); } float FMaterialInstance::getSpecularAntiAliasingVariance() const noexcept { return mSpecularAntiAliasingVariance; } -void FMaterialInstance::setSpecularAntiAliasingThreshold(float threshold) noexcept { - setParameter("_specularAntiAliasingThreshold", math::saturate(threshold * threshold)); - mSpecularAntiAliasingThreshold = std::sqrt(math::saturate(threshold * threshold)); +void FMaterialInstance::setSpecularAntiAliasingThreshold(float const threshold) noexcept { + setParameter("_specularAntiAliasingThreshold", saturate(threshold * threshold)); + mSpecularAntiAliasingThreshold = std::sqrt(saturate(threshold * threshold)); } float FMaterialInstance::getSpecularAntiAliasingThreshold() const noexcept { return mSpecularAntiAliasingThreshold; } -void FMaterialInstance::setDoubleSided(bool doubleSided) noexcept { +void FMaterialInstance::setDoubleSided(bool const doubleSided) noexcept { if (UTILS_UNLIKELY(!mMaterial->hasDoubleSidedCapability())) { slog.w << "Parent material does not have double-sided capability." << io::endl; return; @@ -301,11 +301,11 @@ bool FMaterialInstance::isDoubleSided() const noexcept { return mIsDoubleSided; } -void FMaterialInstance::setTransparencyMode(TransparencyMode mode) noexcept { +void FMaterialInstance::setTransparencyMode(TransparencyMode const mode) noexcept { mTransparencyMode = mode; } -void FMaterialInstance::setDepthCulling(bool enable) noexcept { +void FMaterialInstance::setDepthCulling(bool const enable) noexcept { mDepthFunc = enable ? RasterState::DepthFunc::GE : RasterState::DepthFunc::A; } diff --git a/filament/src/details/MaterialInstance.h b/filament/src/details/MaterialInstance.h index 0a43831e12..91b0118ba7 100644 --- a/filament/src/details/MaterialInstance.h +++ b/filament/src/details/MaterialInstance.h @@ -75,7 +75,7 @@ public: UniformBuffer const& getUniformBuffer() const noexcept { return mUniforms; } - void setScissor(uint32_t left, uint32_t bottom, uint32_t width, uint32_t height) noexcept { + void setScissor(uint32_t const left, uint32_t const bottom, uint32_t const width, uint32_t const height) noexcept { constexpr uint32_t maxvalu = std::numeric_limits::max(); mScissorRect = { int32_t(left), int32_t(bottom), std::min(width, maxvalu), std::min(height, maxvalu) }; @@ -106,11 +106,11 @@ public: backend::RasterState::DepthFunc getDepthFunc() const noexcept { return mDepthFunc; } - void setDepthFunc(backend::RasterState::DepthFunc depthFunc) noexcept { + void setDepthFunc(backend::RasterState::DepthFunc const depthFunc) noexcept { mDepthFunc = depthFunc; } - void setPolygonOffset(float scale, float constant) noexcept { + void setPolygonOffset(float const scale, float const constant) noexcept { // handle reversed Z mPolygonOffset = { -scale, -constant }; } @@ -135,19 +135,19 @@ public: void setTransparencyMode(TransparencyMode mode) noexcept; - void setCullingMode(CullingMode culling) noexcept { mCulling = culling; } + void setCullingMode(CullingMode const culling) noexcept { mCulling = culling; } - void setColorWrite(bool enable) noexcept { mColorWrite = enable; } + void setColorWrite(bool const enable) noexcept { mColorWrite = enable; } - void setDepthWrite(bool enable) noexcept { mDepthWrite = enable; } + void setDepthWrite(bool const enable) noexcept { mDepthWrite = enable; } - void setStencilWrite(bool enable) noexcept { mStencilState.stencilWrite = enable; } + void setStencilWrite(bool const enable) noexcept { mStencilState.stencilWrite = enable; } void setDepthCulling(bool enable) noexcept; bool isDepthCullingEnabled() const noexcept; - void setStencilCompareFunction(StencilCompareFunc func, StencilFace face) noexcept { + void setStencilCompareFunction(StencilCompareFunc const func, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.stencilFunc = func; } @@ -156,7 +156,7 @@ public: } } - void setStencilOpStencilFail(StencilOperation op, StencilFace face) noexcept { + void setStencilOpStencilFail(StencilOperation const op, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.stencilOpStencilFail = op; } @@ -165,7 +165,7 @@ public: } } - void setStencilOpDepthFail(StencilOperation op, StencilFace face) noexcept { + void setStencilOpDepthFail(StencilOperation const op, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.stencilOpDepthFail = op; } @@ -174,7 +174,7 @@ public: } } - void setStencilOpDepthStencilPass(StencilOperation op, StencilFace face) noexcept { + void setStencilOpDepthStencilPass(StencilOperation const op, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.stencilOpDepthStencilPass = op; } @@ -183,7 +183,7 @@ public: } } - void setStencilReferenceValue(uint8_t value, StencilFace face) noexcept { + void setStencilReferenceValue(uint8_t const value, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.ref = value; } @@ -192,7 +192,7 @@ public: } } - void setStencilReadMask(uint8_t readMask, StencilFace face) noexcept { + void setStencilReadMask(uint8_t const readMask, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.readMask = readMask; } @@ -201,7 +201,7 @@ public: } } - void setStencilWriteMask(uint8_t writeMask, StencilFace face) noexcept { + void setStencilWriteMask(uint8_t const writeMask, StencilFace const face) noexcept { if (any(face & StencilFace::FRONT)) { mStencilState.front.writeMask = writeMask; } @@ -210,7 +210,7 @@ public: } } - void setDefaultInstance(bool value) noexcept { + void setDefaultInstance(bool const value) noexcept { mIsDefaultInstance = value; } @@ -260,7 +260,7 @@ private: backend::Handle mUbHandle; tsl::robin_map mTextureParameters; - mutable filament::DescriptorSet mDescriptorSet; + mutable DescriptorSet mDescriptorSet; UniformBuffer mUniforms; backend::PolygonOffset mPolygonOffset{}; diff --git a/filament/src/details/MorphTargetBuffer.cpp b/filament/src/details/MorphTargetBuffer.cpp index f7c9444e04..c496d58b06 100644 --- a/filament/src/details/MorphTargetBuffer.cpp +++ b/filament/src/details/MorphTargetBuffer.cpp @@ -40,21 +40,25 @@ struct MorphTargetBuffer::BuilderDetails { using BuilderType = MorphTargetBuffer; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -MorphTargetBuffer::Builder& MorphTargetBuffer::Builder::vertexCount(size_t vertexCount) noexcept { +MorphTargetBuffer::Builder& MorphTargetBuffer::Builder::vertexCount(size_t const vertexCount) noexcept { mImpl->mVertexCount = vertexCount; return *this; } -MorphTargetBuffer::Builder& MorphTargetBuffer::Builder::count(size_t count) noexcept { +MorphTargetBuffer::Builder& MorphTargetBuffer::Builder::count(size_t const count) noexcept { mImpl->mCount = count; return *this; } +MorphTargetBuffer::Builder& MorphTargetBuffer::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + MorphTargetBuffer* MorphTargetBuffer::Builder::build(Engine& engine) { return downcast(engine).createMorphTargetBuffer(*this); } @@ -65,11 +69,11 @@ MorphTargetBuffer* MorphTargetBuffer::Builder::build(Engine& engine) { // When you change this value, you must change MAX_MORPH_TARGET_BUFFER_WIDTH at getters.vs constexpr size_t MAX_MORPH_TARGET_BUFFER_WIDTH = 2048; -static inline size_t getWidth(size_t vertexCount) noexcept { +static inline size_t getWidth(size_t const vertexCount) noexcept { return std::min(vertexCount, MAX_MORPH_TARGET_BUFFER_WIDTH); } -static inline size_t getHeight(size_t vertexCount) noexcept { +static inline size_t getHeight(size_t const vertexCount) noexcept { return (vertexCount + MAX_MORPH_TARGET_BUFFER_WIDTH) / MAX_MORPH_TARGET_BUFFER_WIDTH; } @@ -77,7 +81,7 @@ template inline size_t getSize(size_t vertexCount) noexcept; template<> -inline size_t getSize(size_t vertexCount) noexcept { +inline size_t getSize(size_t const vertexCount) noexcept { const size_t stride = getWidth(vertexCount); const size_t height = getHeight(vertexCount); return Texture::PixelBufferDescriptor::computeDataSize( @@ -87,7 +91,7 @@ inline size_t getSize(size_t vertexCount) noexcept { } template<> -inline size_t getSize(size_t vertexCount) noexcept { +inline size_t getSize(size_t const vertexCount) noexcept { const size_t stride = getWidth(vertexCount); const size_t height = getHeight(vertexCount); return Texture::PixelBufferDescriptor::computeDataSize( @@ -142,13 +146,13 @@ void FMorphTargetBuffer::terminate(FEngine& engine) { } } -void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex, - math::float3 const* positions, size_t count, size_t offset) { +void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t const targetIndex, + float3 const* positions, size_t const count, size_t const offset) { FILAMENT_CHECK_PRECONDITION(offset + count <= mVertexCount) << "MorphTargetBuffer (size=" << (unsigned)mVertexCount << ") overflow (count=" << (unsigned)count << ", offset=" << (unsigned)offset << ")"; - auto size = getSize(count); + auto size = getSize(count); FILAMENT_CHECK_PRECONDITION(targetIndex < mCount) << targetIndex << " target index must be < " << mCount; @@ -165,20 +169,20 @@ void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex, count, offset); } -void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex, - math::float4 const* positions, size_t count, size_t offset) { +void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t const targetIndex, + float4 const* positions, size_t const count, size_t const offset) { FILAMENT_CHECK_PRECONDITION(offset + count <= mVertexCount) << "MorphTargetBuffer (size=" << (unsigned)mVertexCount << ") overflow (count=" << (unsigned)count << ", offset=" << (unsigned)offset << ")"; - auto size = getSize(count); + auto size = getSize(count); FILAMENT_CHECK_PRECONDITION(targetIndex < mCount) << targetIndex << " target index must be < " << mCount; // We could use a pool instead of malloc() directly. auto* out = (float4*) malloc(size); - memcpy(out, positions, sizeof(math::float4) * count); + memcpy(out, positions, sizeof(float4) * count); FEngine::DriverApi& driver = engine.getDriverApi(); updateDataAt(driver, mPbHandle, @@ -187,13 +191,13 @@ void FMorphTargetBuffer::setPositionsAt(FEngine& engine, size_t targetIndex, count, offset); } -void FMorphTargetBuffer::setTangentsAt(FEngine& engine, size_t targetIndex, - math::short4 const* tangents, size_t count, size_t offset) { +void FMorphTargetBuffer::setTangentsAt(FEngine& engine, size_t const targetIndex, + short4 const* tangents, size_t const count, size_t const offset) { FILAMENT_CHECK_PRECONDITION(offset + count <= mVertexCount) << "MorphTargetBuffer (size=" << (unsigned)mVertexCount << ") overflow (count=" << (unsigned)count << ", offset=" << (unsigned)offset << ")"; - const auto size = getSize(count); + const auto size = getSize(count); FILAMENT_CHECK_PRECONDITION(targetIndex < mCount) << targetIndex << " target index must be < " << mCount; @@ -210,10 +214,10 @@ void FMorphTargetBuffer::setTangentsAt(FEngine& engine, size_t targetIndex, } UTILS_NOINLINE -void FMorphTargetBuffer::updateDataAt(backend::DriverApi& driver, - Handle handle, PixelDataFormat format, PixelDataType type, - const char* out, size_t elementSize, - size_t targetIndex, size_t count, size_t offset) { +void FMorphTargetBuffer::updateDataAt(DriverApi& driver, + Handle handle, PixelDataFormat const format, PixelDataType const type, + const char* out, size_t const elementSize, + size_t const targetIndex, size_t const count, size_t const offset) { size_t yoffset = offset / MAX_MORPH_TARGET_BUFFER_WIDTH; size_t const xoffset = offset % MAX_MORPH_TARGET_BUFFER_WIDTH; @@ -225,7 +229,7 @@ void FMorphTargetBuffer::updateDataAt(backend::DriverApi& driver, // 'out' buffer is going to be used up to 3 times, so for simplicity we use a shared_buffer // to manage its lifetime. One side effect of this is that the callbacks below will allocate // a small object on the heap. - std::shared_ptr const allocation((void*)out, ::free); + std::shared_ptr const allocation((void*)out, free); // Note: because the texture width is up to 2048, we're expecting that most of the time // only a single texture update call will be necessary (i.e. that there are no more diff --git a/filament/src/details/MorphTargetBuffer.h b/filament/src/details/MorphTargetBuffer.h index 6e42dcace8..e386627770 100644 --- a/filament/src/details/MorphTargetBuffer.h +++ b/filament/src/details/MorphTargetBuffer.h @@ -37,7 +37,7 @@ class FEngine; class FMorphTargetBuffer : public MorphTargetBuffer { public: - class EmptyMorphTargetBuilder : public MorphTargetBuffer::Builder { + class EmptyMorphTargetBuilder : public Builder { public: EmptyMorphTargetBuilder(); }; diff --git a/filament/src/details/RenderTarget.cpp b/filament/src/details/RenderTarget.cpp index 53697057b7..e2ac3f9204 100644 --- a/filament/src/details/RenderTarget.cpp +++ b/filament/src/details/RenderTarget.cpp @@ -53,33 +53,33 @@ struct RenderTarget::BuilderDetails { using BuilderType = RenderTarget; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; RenderTarget::Builder& RenderTarget::Builder::texture(AttachmentPoint pt, Texture* texture) noexcept { mImpl->mAttachments[(size_t)pt].texture = downcast(texture); return *this; } -RenderTarget::Builder& RenderTarget::Builder::mipLevel(AttachmentPoint pt, uint8_t level) noexcept { +RenderTarget::Builder& RenderTarget::Builder::mipLevel(AttachmentPoint pt, uint8_t const level) noexcept { mImpl->mAttachments[(size_t)pt].mipLevel = level; return *this; } -RenderTarget::Builder& RenderTarget::Builder::face(AttachmentPoint pt, CubemapFace face) noexcept { +RenderTarget::Builder& RenderTarget::Builder::face(AttachmentPoint pt, CubemapFace const face) noexcept { mImpl->mAttachments[(size_t)pt].face = face; return *this; } -RenderTarget::Builder& RenderTarget::Builder::layer(AttachmentPoint pt, uint32_t layer) noexcept { +RenderTarget::Builder& RenderTarget::Builder::layer(AttachmentPoint pt, uint32_t const layer) noexcept { mImpl->mAttachments[(size_t)pt].layer = layer; return *this; } -RenderTarget::Builder& RenderTarget::Builder::multiview(AttachmentPoint pt, uint8_t layerCount, - uint8_t baseLayer/*= 0*/) noexcept { +RenderTarget::Builder& RenderTarget::Builder::multiview(AttachmentPoint pt, uint8_t const layerCount, + uint8_t const baseLayer/*= 0*/) noexcept { mImpl->mAttachments[(size_t)pt].layer = baseLayer; mImpl->mAttachments[(size_t)pt].layerCount = layerCount; return *this; @@ -155,13 +155,13 @@ RenderTarget* RenderTarget::Builder::build(Engine& engine) { // ------------------------------------------------------------------------------------------------ -FRenderTarget::FRenderTarget(FEngine& engine, const RenderTarget::Builder& builder) +FRenderTarget::FRenderTarget(FEngine& engine, const Builder& builder) : mSupportedColorAttachmentsCount(engine.getDriverApi().getMaxDrawBuffers()), mSupportsReadPixels(false) { std::copy(std::begin(builder.mImpl->mAttachments), std::end(builder.mImpl->mAttachments), std::begin(mAttachments)); - backend::MRT mrt{}; + MRT mrt{}; TargetBufferInfo dinfo{}; auto setAttachment = [this, &driver = engine.getDriverApi()] diff --git a/filament/src/details/RenderTarget.h b/filament/src/details/RenderTarget.h index 9fba1f60ff..8ccf725588 100644 --- a/filament/src/details/RenderTarget.h +++ b/filament/src/details/RenderTarget.h @@ -37,7 +37,7 @@ public: struct Attachment { FTexture* texture = nullptr; uint8_t mipLevel = 0; - CubemapFace face = RenderTarget::CubemapFace::POSITIVE_X; + CubemapFace face = CubemapFace::POSITIVE_X; uint32_t layer = 0; // Indicates the number of layers used for multiview, starting from the `layer` (baseIndex). // This means `layer` + `layerCount` cannot exceed the number of depth for the attachment. diff --git a/filament/src/details/Renderer.cpp b/filament/src/details/Renderer.cpp index 6bdd39daa8..768d16b28f 100644 --- a/filament/src/details/Renderer.cpp +++ b/filament/src/details/Renderer.cpp @@ -188,7 +188,7 @@ void FRenderer::resetUserTime() { mUserEpoch = std::chrono::steady_clock::now(); } -TextureFormat FRenderer::getHdrFormat(const FView& view, bool translucent) const noexcept { +TextureFormat FRenderer::getHdrFormat(const FView& view, bool const translucent) const noexcept { if (translucent) { return mHdrTranslucent; } @@ -203,7 +203,7 @@ TextureFormat FRenderer::getHdrFormat(const FView& view, bool translucent) const } } -TextureFormat FRenderer::getLdrFormat(bool translucent) const noexcept { +TextureFormat FRenderer::getLdrFormat(bool const translucent) const noexcept { return (translucent || !mIsRGB8Supported) ? TextureFormat::RGBA8 : TextureFormat::RGB8; } @@ -218,7 +218,7 @@ std::pair, TargetBufferFlags> return { outTarget, outAttachmentMask }; } -backend::TargetBufferFlags FRenderer::getClearFlags() const noexcept { +TargetBufferFlags FRenderer::getClearFlags() const noexcept { return (mClearOptions.clear ? TargetBufferFlags::COLOR : TargetBufferFlags::NONE) | TargetBufferFlags::DEPTH_AND_STENCIL; } @@ -233,12 +233,12 @@ void FRenderer::initializeClearFlags() noexcept { mClearFlags = getClearFlags(); } -void FRenderer::setPresentationTime(int64_t monotonic_clock_ns) { +void FRenderer::setPresentationTime(int64_t const monotonic_clock_ns) { FEngine::DriverApi& driver = mEngine.getDriverApi(); driver.setPresentationTime(monotonic_clock_ns); } -void FRenderer::setVsyncTime(uint64_t steadyClockTimeNano) noexcept { +void FRenderer::setVsyncTime(uint64_t const steadyClockTimeNano) noexcept { mVsyncSteadyClockTimeNano = steadyClockTimeNano; } @@ -444,7 +444,7 @@ void FRenderer::endFrame() { js.waitAndRelease(job); } -void FRenderer::readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height, +void FRenderer::readPixels(uint32_t const xoffset, uint32_t const yoffset, uint32_t const width, uint32_t const height, PixelBufferDescriptor&& buffer) { #ifndef NDEBUG const bool withinFrame = mSwapChain != nullptr; @@ -456,15 +456,15 @@ void FRenderer::readPixels(uint32_t xoffset, uint32_t yoffset, uint32_t width, u } void FRenderer::readPixels(FRenderTarget* renderTarget, - uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height, - backend::PixelBufferDescriptor&& buffer) { + uint32_t const xoffset, uint32_t const yoffset, uint32_t const width, uint32_t const height, + PixelBufferDescriptor&& buffer) { // TODO: change the following to an assert when client call sites have addressed the issue. if (!renderTarget->supportsReadPixels()) { - utils::slog.w << "readPixels() must be called with a renderTarget with COLOR0 created with " + slog.w << "readPixels() must be called with a renderTarget with COLOR0 created with " "TextureUsage::BLIT_SRC. This precondition will be asserted in a later " "release of Filament." - << utils::io::endl; + << io::endl; } RendererUtils::readPixels(mEngine.getDriverApi(), renderTarget->getHwHandle(), @@ -472,7 +472,7 @@ void FRenderer::readPixels(FRenderTarget* renderTarget, } void FRenderer::copyFrame(FSwapChain* dstSwapChain, filament::Viewport const& dstViewport, - filament::Viewport const& srcViewport, CopyFrameFlag flags) { + filament::Viewport const& srcViewport, CopyFrameFlag const flags) { SYSTRACE_CALL(); assert_invariant(mSwapChain); @@ -551,7 +551,7 @@ void FRenderer::renderStandaloneView(FView const* view) { // This is a workaround for internal bug b/361822355. // TODO: properly address the bug and remove this workaround. - if (engine.getBackend() == backend::Backend::VULKAN) { + if (engine.getBackend() == Backend::VULKAN) { engine.flushAndWait(); } } @@ -632,7 +632,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { auto ssReflectionsOptions = view.getScreenSpaceReflectionsOptions(); auto guardBandOptions = view.getGuardBandOptions(); const bool isRenderingMultiview = view.hasStereo() && - engine.getConfig().stereoscopicType == backend::StereoscopicType::MULTIVIEW; + engine.getConfig().stereoscopicType == StereoscopicType::MULTIVIEW; // FIXME: This is to override some settings that are not supported for multiview at the moment. // Remove this when all features are supported. if (isRenderingMultiview) { @@ -681,6 +681,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { hasColorGrading && !bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled; + // whether we're scaled at all + bool scaled = any(notEqual(scale, float2(1.0f))); + // asSubpass is disabled with TAA (although it's supported) because performance was degraded // on qualcomm hardware -- we might need a backend dependent toggle at some point const PostProcessManager::ColorGradingConfig colorGradingConfig{ @@ -695,18 +698,15 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { hasColorGrading && !engine.debug.renderer.disable_subpasses, .translucent = needsAlphaChannel, - .fxaa = hasFXAA, + .outputLuminance = hasFXAA || scaled, // ignored by translucent variants (false) .dithering = hasDithering, - .ldrFormat = (hasColorGrading && hasFXAA) ? + .ldrFormat = (hasColorGrading && (hasFXAA || scaled)) ? TextureFormat::RGBA8 : getLdrFormat(needsAlphaChannel) }; // by construction (msaaSampleCount) both asSubpass and customResolve can't be true assert_invariant(colorGradingConfig.asSubpass + colorGradingConfig.customResolve < 2); - // whether we're scaled at all - bool scaled = any(notEqual(scale, float2(1.0f))); - // vp is the user defined viewport within the View filament::Viewport const& vp = view.getViewport(); @@ -748,7 +748,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { // Without post-processing, we usually draw directly into // the SwapChain, and we might want to keep it this way. - auto round = [](uint32_t x) { + auto round = [](uint32_t const x) { constexpr uint32_t rounding = 16u; return (x + (rounding - 1u)) & ~(rounding - 1u); }; @@ -1162,7 +1162,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { // RenderPass::IS_INSTANCED_STEREOSCOPIC only applies to the color pass if (view.hasStereo() && - engine.getConfig().stereoscopicType == backend::StereoscopicType::INSTANCED) { + engine.getConfig().stereoscopicType == StereoscopicType::INSTANCED) { renderFlags |= RenderPass::IS_INSTANCED_STEREOSCOPIC; passBuilder.renderFlags(renderFlags); } @@ -1178,7 +1178,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { // Set the depth to the number of layers if we're rendering multiview. if (isRenderingMultiview) { colorBufferDesc.depth = engine.getConfig().stereoscopicEyeCount; - colorBufferDesc.type = backend::SamplerType::SAMPLER_2D_ARRAY; + colorBufferDesc.type = SamplerType::SAMPLER_2D_ARRAY; } // a non-drawing pass to prepare everything that need to be before the color passes execute @@ -1257,7 +1257,7 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { // we can't use colorPassOutput here because it could be tonemapped data.history = builder.sample(colorPassOutput.linearColor); // FIXME: an access must be declared for detach(), why? }, [&view, projection](FrameGraphResources const& resources, auto const& data, - backend::DriverApi&) { + DriverApi&) { auto& history = view.getFrameHistory(); auto& current = history.getCurrent(); current.ssr.projection = projection; @@ -1351,8 +1351,12 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { } if (hasFXAA) { - input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, - !hasColorGrading || needsAlphaChannel); + bool const preserveAlphaChannel = + // we're transparent -- alpha channel has user data + needsAlphaChannel || + // the color-grading pass outputted the luminance channel, and we have an upscaling pass + (hasColorGrading && colorGradingConfig.outputLuminance && scaled); + input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, preserveAlphaChannel); // the padded buffer is resolved now xvp.left = xvp.bottom = 0; svp = xvp; @@ -1360,9 +1364,11 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) { if (scaled) { mightNeedFinalBlit = false; auto viewport = DEBUG_DYNAMIC_SCALING ? xvp : vp; - input = ppm.upscale(fg, needsAlphaChannel, dsrOptions, input, xvp, { - .width = viewport.width, .height = viewport.height, - .format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR); + bool const sourceHasLuminance = !needsAlphaChannel && + (hasColorGrading && colorGradingConfig.outputLuminance); + input = ppm.upscale(fg, needsAlphaChannel, sourceHasLuminance, dsrOptions, input, xvp, { + .width = viewport.width, .height = viewport.height, + .format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR); xvp.left = xvp.bottom = 0; svp = xvp; } diff --git a/filament/src/details/Renderer.h b/filament/src/details/Renderer.h index c0c6d5aa1b..903f33c212 100644 --- a/filament/src/details/Renderer.h +++ b/filament/src/details/Renderer.h @@ -147,7 +147,7 @@ public: return mClearOptions; } - utils::FixedCapacityVector getFrameInfoHistory(size_t historySize) const noexcept { + utils::FixedCapacityVector getFrameInfoHistory(size_t const historySize) const noexcept { return mFrameInfoManager.getFrameInfoHistory(historySize); } @@ -178,7 +178,7 @@ private: std::pair, backend::TargetBufferFlags> getRenderTarget(FView const& view) const noexcept; - void recordHighWatermark(size_t watermark) noexcept { + void recordHighWatermark(size_t const watermark) noexcept { mCommandsHighWatermark = std::max(mCommandsHighWatermark, watermark); } diff --git a/filament/src/details/Scene.cpp b/filament/src/details/Scene.cpp index ece2e99f93..993540a02c 100644 --- a/filament/src/details/Scene.cpp +++ b/filament/src/details/Scene.cpp @@ -52,7 +52,7 @@ FScene::FScene(FEngine& engine) : FScene::~FScene() noexcept = default; -void FScene::prepare(utils::JobSystem& js, +void FScene::prepare(JobSystem& js, RootArenaScope& rootArenaScope, mat4 const& worldTransform, bool shadowReceiversAreCasters) noexcept { @@ -78,11 +78,11 @@ void FScene::prepare(utils::JobSystem& js, using RenderableContainerData = std::pair; using RenderableInstanceContainer = FixedCapacityVector, false>; + STLAllocator< RenderableContainerData, LinearAllocatorArena >, false>; using LightContainerData = std::pair; using LightInstanceContainer = FixedCapacityVector, false>; + STLAllocator< LightContainerData, LinearAllocatorArena >, false>; RenderableInstanceContainer renderableInstances{ RenderableInstanceContainer::with_capacity(entities.size(), localArenaScope.getArena()) }; @@ -246,11 +246,11 @@ void FScene::prepare(utils::JobSystem& js, JobSystem::Job* rootJob = js.createJob(); - auto* renderableJob = jobs::parallel_for(js, rootJob, + auto* renderableJob = parallel_for(js, rootJob, renderableInstances.data(), renderableInstances.size(), std::cref(renderableWork), jobs::CountSplitter<64>()); - auto* lightJob = jobs::parallel_for(js, rootJob, + auto* lightJob = parallel_for(js, rootJob, lightInstances.data(), lightInstances.size(), std::cref(lightWork), jobs::CountSplitter<32, 5>()); @@ -428,7 +428,7 @@ void FScene::updateUBOs( driver.resetBufferObject(renderableUbh); driver.updateBufferObjectUnsynchronized(renderableUbh, { buffer, count * sizeof(PerRenderableData), - +[](void* p, size_t s, void* user) { + +[](void* p, size_t const s, void* user) { std::weak_ptr* const weakShared = static_cast*>(user); if (s >= MAX_STREAM_ALLOCATION_COUNT * sizeof(PerRenderableData)) { @@ -448,7 +448,7 @@ void FScene::prepareDynamicLights(const CameraInfo& camera, Handle lightUbh) noexcept { FEngine::DriverApi& driver = mEngine.getDriverApi(); FLightManager const& lcm = mEngine.getLightManager(); - FScene::LightSoa& lightData = getLightData(); + LightSoa& lightData = getLightData(); /* * Here we copy our lights data into the GPU buffer. @@ -459,17 +459,17 @@ void FScene::prepareDynamicLights(const CameraInfo& camera, size_t const positionalLightCount = size - DIRECTIONAL_LIGHTS_COUNT; assert_invariant(positionalLightCount); - float4 const* const UTILS_RESTRICT spheres = lightData.data(); + float4 const* const UTILS_RESTRICT spheres = lightData.data(); // compute the light ranges (needed when building light trees) - float2* const zrange = lightData.data(); + float2* const zrange = lightData.data(); computeLightRanges(zrange, camera, spheres + DIRECTIONAL_LIGHTS_COUNT, positionalLightCount); LightsUib* const lp = driver.allocatePod(positionalLightCount); - auto const* UTILS_RESTRICT directions = lightData.data(); - auto const* UTILS_RESTRICT instances = lightData.data(); - auto const* UTILS_RESTRICT shadowInfo = lightData.data(); + auto const* UTILS_RESTRICT directions = lightData.data(); + auto const* UTILS_RESTRICT instances = lightData.data(); + auto const* UTILS_RESTRICT shadowInfo = lightData.data(); for (size_t i = DIRECTIONAL_LIGHTS_COUNT, c = size; i < c; ++i) { const size_t gpuIndex = i - DIRECTIONAL_LIGHTS_COUNT; auto li = instances[i]; @@ -525,22 +525,22 @@ inline void FScene::computeLightRanges( } UTILS_NOINLINE -void FScene::addEntity(Entity entity) { +void FScene::addEntity(Entity const entity) { mEntities.insert(entity); } UTILS_NOINLINE -void FScene::addEntities(const Entity* entities, size_t count) { +void FScene::addEntities(const Entity* entities, size_t const count) { mEntities.insert(entities, entities + count); } UTILS_NOINLINE -void FScene::remove(Entity entity) { +void FScene::remove(Entity const entity) { mEntities.erase(entity); } UTILS_NOINLINE -void FScene::removeEntities(const Entity* entities, size_t count) { +void FScene::removeEntities(const Entity* entities, size_t const count) { for (size_t i = 0; i < count; ++i, ++entities) { remove(*entities); } @@ -573,7 +573,7 @@ size_t FScene::getLightCount() const noexcept { } UTILS_NOINLINE -bool FScene::hasEntity(Entity entity) const noexcept { +bool FScene::hasEntity(Entity const entity) const noexcept { return mEntities.find(entity) != mEntities.end(); } diff --git a/filament/src/details/Scene.h b/filament/src/details/Scene.h index 03898570e2..44d0ff950c 100644 --- a/filament/src/details/Scene.h +++ b/filament/src/details/Scene.h @@ -137,13 +137,13 @@ public: RenderableSoa& getRenderableData() noexcept { return mRenderableData; } static inline uint32_t getPrimitiveCount(RenderableSoa const& soa, - uint32_t first, uint32_t last) noexcept { + uint32_t const first, uint32_t const last) noexcept { // the caller must guarantee that last is dereferenceable return soa.elementAt(last) - soa.elementAt(first); } - static inline uint32_t getPrimitiveCount(RenderableSoa const& soa, uint32_t last) noexcept { + static inline uint32_t getPrimitiveCount(RenderableSoa const& soa, uint32_t const last) noexcept { // the caller must guarantee that last is dereferenceable return soa.elementAt(last); } diff --git a/filament/src/details/SkinningBuffer.cpp b/filament/src/details/SkinningBuffer.cpp index a9f668c32a..8386aab0b6 100644 --- a/filament/src/details/SkinningBuffer.cpp +++ b/filament/src/details/SkinningBuffer.cpp @@ -44,22 +44,26 @@ struct SkinningBuffer::BuilderDetails { using BuilderType = SkinningBuffer; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -SkinningBuffer::Builder& SkinningBuffer::Builder::boneCount(uint32_t boneCount) noexcept { +SkinningBuffer::Builder& SkinningBuffer::Builder::boneCount(uint32_t const boneCount) noexcept { mImpl->mBoneCount = boneCount; return *this; } -SkinningBuffer::Builder& SkinningBuffer::Builder::initialize(bool initialize) noexcept { +SkinningBuffer::Builder& SkinningBuffer::Builder::initialize(bool const initialize) noexcept { mImpl->mInitialize = initialize; return *this; } +SkinningBuffer::Builder& SkinningBuffer::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + SkinningBuffer* SkinningBuffer::Builder::build(Engine& engine) { return downcast(engine).createSkinningBuffer(*this); } @@ -90,7 +94,7 @@ FSkinningBuffer::FSkinningBuffer(FEngine& engine, const Builder& builder) if (builder->mInitialize) { // initialize the bones to identity (before rounding up) auto* out = driver.allocatePod(mBoneCount); - std::uninitialized_fill_n(out, mBoneCount, FSkinningBuffer::makeBone({})); + std::uninitialized_fill_n(out, mBoneCount, makeBone({})); driver.updateBufferObject(mHandle, { out, mBoneCount * sizeof(PerRenderableBoneUib::BoneData) }, 0); } @@ -102,7 +106,7 @@ void FSkinningBuffer::terminate(FEngine& engine) { } void FSkinningBuffer::setBones(FEngine& engine, - RenderableManager::Bone const* transforms, size_t count, size_t offset) { + RenderableManager::Bone const* transforms, size_t const count, size_t const offset) { FILAMENT_CHECK_PRECONDITION((offset + count) <= mBoneCount) << "SkinningBuffer (size=" << (unsigned)mBoneCount << ") overflow (boneCount=" << (unsigned)count << ", offset=" << (unsigned)offset @@ -112,7 +116,7 @@ void FSkinningBuffer::setBones(FEngine& engine, } void FSkinningBuffer::setBones(FEngine& engine, - math::mat4f const* transforms, size_t count, size_t offset) { + mat4f const* transforms, size_t const count, size_t const offset) { FILAMENT_CHECK_PRECONDITION((offset + count) <= mBoneCount) << "SkinningBuffer (size=" << (unsigned)mBoneCount << ") overflow (boneCount=" << (unsigned)count << ", offset=" << (unsigned)offset @@ -128,8 +132,8 @@ static uint32_t packHalf2x16(half2 v) noexcept { return (hi << 16) | lo; } -void FSkinningBuffer::setBones(FEngine& engine, Handle handle, - RenderableManager::Bone const* transforms, size_t boneCount, size_t offset) noexcept { +void FSkinningBuffer::setBones(FEngine& engine, Handle handle, + RenderableManager::Bone const* transforms, size_t const boneCount, size_t const offset) noexcept { auto& driverApi = engine.getDriverApi(); auto* UTILS_RESTRICT out = driverApi.allocatePod(boneCount); for (size_t i = 0, c = boneCount; i < c; ++i) { @@ -157,8 +161,8 @@ PerRenderableBoneUib::BoneData FSkinningBuffer::makeBone(mat4f transform) noexce }; } -void FSkinningBuffer::setBones(FEngine& engine, Handle handle, - mat4f const* transforms, size_t boneCount, size_t offset) noexcept { +void FSkinningBuffer::setBones(FEngine& engine, Handle handle, + mat4f const* transforms, size_t const boneCount, size_t const offset) noexcept { auto& driverApi = engine.getDriverApi(); auto* UTILS_RESTRICT out = driverApi.allocatePod(boneCount); for (size_t i = 0, c = boneCount; i < c; ++i) { @@ -173,16 +177,16 @@ void FSkinningBuffer::setBones(FEngine& engine, Handle // When you change this value, you must change MAX_SKINNING_BUFFER_WIDTH at getters.vs constexpr size_t MAX_SKINNING_BUFFER_WIDTH = 2048; -static inline size_t getSkinningBufferWidth(size_t pairCount) noexcept { +static inline size_t getSkinningBufferWidth(size_t const pairCount) noexcept { return std::clamp(pairCount, size_t(1), MAX_SKINNING_BUFFER_WIDTH); } -static inline size_t getSkinningBufferHeight(size_t pairCount) noexcept { +static inline size_t getSkinningBufferHeight(size_t const pairCount) noexcept { return std::max(size_t(1), (pairCount + MAX_SKINNING_BUFFER_WIDTH - 1) / MAX_SKINNING_BUFFER_WIDTH); } -inline size_t getSkinningBufferSize(size_t pairCount) noexcept { +inline size_t getSkinningBufferSize(size_t const pairCount) noexcept { const size_t stride = getSkinningBufferWidth(pairCount); const size_t height = getSkinningBufferHeight(pairCount); return Texture::PixelBufferDescriptor::computeDataSize( @@ -192,10 +196,10 @@ inline size_t getSkinningBufferSize(size_t pairCount) noexcept { } UTILS_NOINLINE -void updateDataAt(backend::DriverApi& driver, - Handle handle, PixelDataFormat format, PixelDataType type, - const utils::FixedCapacityVector& pairs, - size_t count) { +void updateDataAt(DriverApi& driver, + Handle handle, PixelDataFormat const format, PixelDataType const type, + const utils::FixedCapacityVector& pairs, + size_t const count) { size_t const elementSize = sizeof(float2); size_t const size = getSkinningBufferSize(count); @@ -209,7 +213,7 @@ void updateDataAt(backend::DriverApi& driver, // 'out' buffer is going to be used up to 2 times, so for simplicity we use a shared_buffer // to manage its lifetime. One side effect of this is that the callbacks below will allocate // a small object on the heap. (inspired by MorphTargetBuffered) - std::shared_ptr const allocation((void*)out, ::free); + std::shared_ptr const allocation((void*)out, free); if (lineCount) { // update the full-width lines if any @@ -233,8 +237,8 @@ void updateDataAt(backend::DriverApi& driver, } } -backend::TextureHandle FSkinningBuffer::createIndicesAndWeightsHandle( - FEngine& engine, size_t count) { +TextureHandle FSkinningBuffer::createIndicesAndWeightsHandle( + FEngine& engine, size_t const count) { FEngine::DriverApi& driver = engine.getDriverApi(); // create a texture for skinning pairs data (bone index and weight) return driver.createTexture(SamplerType::SAMPLER_2D, 1, @@ -245,8 +249,8 @@ backend::TextureHandle FSkinningBuffer::createIndicesAndWeightsHandle( } void FSkinningBuffer::setIndicesAndWeightsData(FEngine& engine, - backend::Handle textureHandle, - const utils::FixedCapacityVector& pairs, size_t count) { + Handle textureHandle, + const utils::FixedCapacityVector& pairs, size_t const count) { FEngine::DriverApi& driver = engine.getDriverApi(); updateDataAt(driver, textureHandle, diff --git a/filament/src/details/SkinningBuffer.h b/filament/src/details/SkinningBuffer.h index fd831ef122..11786e9387 100644 --- a/filament/src/details/SkinningBuffer.h +++ b/filament/src/details/SkinningBuffer.h @@ -55,13 +55,13 @@ public: size_t getBoneCount() const noexcept { return mBoneCount; } // round count to the size of the UBO in the shader - static size_t getPhysicalBoneCount(size_t count) noexcept { + static size_t getPhysicalBoneCount(size_t const count) noexcept { static_assert((CONFIG_MAX_BONE_COUNT & (CONFIG_MAX_BONE_COUNT - 1)) == 0); return (count + CONFIG_MAX_BONE_COUNT - 1) & ~(CONFIG_MAX_BONE_COUNT - 1); } private: - friend class ::FilamentTest_Bones_Test; + friend class FilamentTest_Bones_Test; friend class SkinningBuffer; friend class FRenderableManager; diff --git a/filament/src/details/Skybox.cpp b/filament/src/details/Skybox.cpp index 6526c5a297..2de015dfb8 100644 --- a/filament/src/details/Skybox.cpp +++ b/filament/src/details/Skybox.cpp @@ -56,10 +56,10 @@ struct Skybox::BuilderDetails { using BuilderType = Skybox; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; Skybox::Builder& Skybox::Builder::environment(Texture* cubemap) noexcept { @@ -67,17 +67,17 @@ Skybox::Builder& Skybox::Builder::environment(Texture* cubemap) noexcept { return *this; } -Skybox::Builder& Skybox::Builder::intensity(float envIntensity) noexcept { +Skybox::Builder& Skybox::Builder::intensity(float const envIntensity) noexcept { mImpl->mIntensity = envIntensity; return *this; } -Skybox::Builder& Skybox::Builder::color(math::float4 color) noexcept { +Skybox::Builder& Skybox::Builder::color(float4 const color) noexcept { mImpl->mColor = color; return *this; } -Skybox::Builder& Skybox::Builder::showSun(bool show) noexcept { +Skybox::Builder& Skybox::Builder::showSun(bool const show) noexcept { mImpl->mShowSun = show; return *this; } @@ -153,23 +153,23 @@ FMaterial const* FSkybox::createMaterial(FEngine& engine) { void FSkybox::terminate(FEngine& engine) noexcept { // use Engine::destroy because FEngine::destroy is inlined Engine& e = engine; - e.destroy(mSkyboxMaterialInstance); e.destroy(mSkybox); + e.destroy(mSkyboxMaterialInstance); engine.getEntityManager().destroy(mSkybox); - mSkyboxMaterialInstance = nullptr; mSkybox = {}; + mSkyboxMaterialInstance = nullptr; } -void FSkybox::setLayerMask(uint8_t select, uint8_t values) noexcept { +void FSkybox::setLayerMask(uint8_t const select, uint8_t const values) noexcept { auto& rcm = mRenderableManager; rcm.setLayerMask(rcm.getInstance(mSkybox), select, values); // we keep a checked version mLayerMask = (mLayerMask & ~select) | (values & select); } -void FSkybox::setColor(math::float4 color) noexcept { +void FSkybox::setColor(float4 const color) noexcept { mSkyboxMaterialInstance->setParameter("color", color); } diff --git a/filament/src/details/Stream.cpp b/filament/src/details/Stream.cpp index c60bcf8bef..00d2ddaed7 100644 --- a/filament/src/details/Stream.cpp +++ b/filament/src/details/Stream.cpp @@ -40,10 +40,10 @@ struct Stream::BuilderDetails { using BuilderType = Stream; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; Stream::Builder& Stream::Builder::stream(void* stream) noexcept { @@ -51,16 +51,20 @@ Stream::Builder& Stream::Builder::stream(void* stream) noexcept { return *this; } -Stream::Builder& Stream::Builder::width(uint32_t width) noexcept { +Stream::Builder& Stream::Builder::width(uint32_t const width) noexcept { mImpl->mWidth = width; return *this; } -Stream::Builder& Stream::Builder::height(uint32_t height) noexcept { +Stream::Builder& Stream::Builder::height(uint32_t const height) noexcept { mImpl->mHeight = height; return *this; } +Stream::Builder& Stream::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + Stream* Stream::Builder::build(Engine& engine) { return downcast(engine).createStream(*this); } @@ -91,16 +95,16 @@ void FStream::terminate(FEngine& engine) noexcept { } void FStream::setAcquiredImage(void* image, - Callback callback, void* userdata) noexcept { + Callback const callback, void* userdata) noexcept { mEngine.getDriverApi().setAcquiredImage(mStreamHandle, image, nullptr, callback, userdata); } void FStream::setAcquiredImage(void* image, - CallbackHandler* handler, Callback callback, void* userdata) noexcept { + CallbackHandler* handler, Callback const callback, void* userdata) noexcept { mEngine.getDriverApi().setAcquiredImage(mStreamHandle, image, handler, callback, userdata); } -void FStream::setDimensions(uint32_t width, uint32_t height) noexcept { +void FStream::setDimensions(uint32_t const width, uint32_t const height) noexcept { mWidth = width; mHeight = height; diff --git a/filament/src/details/SwapChain.cpp b/filament/src/details/SwapChain.cpp index 90d0920991..a2b4499d8a 100644 --- a/filament/src/details/SwapChain.cpp +++ b/filament/src/details/SwapChain.cpp @@ -31,12 +31,12 @@ namespace filament { -FSwapChain::FSwapChain(FEngine& engine, void* nativeWindow, uint64_t flags) +FSwapChain::FSwapChain(FEngine& engine, void* nativeWindow, uint64_t const flags) : mEngine(engine), mNativeWindow(nativeWindow), mConfigFlags(initFlags(engine, flags)) { mHwSwapChain = engine.getDriverApi().createSwapChain(nativeWindow, flags); } -FSwapChain::FSwapChain(FEngine& engine, uint32_t width, uint32_t height, uint64_t flags) +FSwapChain::FSwapChain(FEngine& engine, uint32_t const width, uint32_t const height, uint64_t const flags) : mEngine(engine), mWidth(width), mHeight(height), mConfigFlags(initFlags(engine, flags)) { mHwSwapChain = engine.getDriverApi().createSwapChainHeadless(width, height, flags); } @@ -70,7 +70,7 @@ void FSwapChain::terminate(FEngine& engine) noexcept { } void FSwapChain::setFrameScheduledCallback( - backend::CallbackHandler* handler, FrameScheduledCallback&& callback, uint64_t flags) { + backend::CallbackHandler* handler, FrameScheduledCallback&& callback, uint64_t const flags) { mFrameScheduledCallbackIsSet = bool(callback); mEngine.getDriverApi().setFrameScheduledCallback( mHwSwapChain, handler, std::move(callback), flags); diff --git a/filament/src/details/Texture.cpp b/filament/src/details/Texture.cpp index cff6d7e42a..ee1c3d3432 100644 --- a/filament/src/details/Texture.cpp +++ b/filament/src/details/Texture.cpp @@ -90,48 +90,48 @@ struct Texture::BuilderDetails { using BuilderType = Texture; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -Texture::Builder& Texture::Builder::width(uint32_t width) noexcept { +Texture::Builder& Texture::Builder::width(uint32_t const width) noexcept { mImpl->mWidth = width; return *this; } -Texture::Builder& Texture::Builder::height(uint32_t height) noexcept { +Texture::Builder& Texture::Builder::height(uint32_t const height) noexcept { mImpl->mHeight = height; return *this; } -Texture::Builder& Texture::Builder::depth(uint32_t depth) noexcept { +Texture::Builder& Texture::Builder::depth(uint32_t const depth) noexcept { mImpl->mDepth = depth; return *this; } -Texture::Builder& Texture::Builder::levels(uint8_t levels) noexcept { +Texture::Builder& Texture::Builder::levels(uint8_t const levels) noexcept { mImpl->mLevels = std::max(uint8_t(1), levels); return *this; } -Texture::Builder& Texture::Builder::sampler(Texture::Sampler target) noexcept { +Texture::Builder& Texture::Builder::sampler(Sampler const target) noexcept { mImpl->mTarget = target; return *this; } -Texture::Builder& Texture::Builder::format(Texture::InternalFormat format) noexcept { +Texture::Builder& Texture::Builder::format(InternalFormat const format) noexcept { mImpl->mFormat = format; return *this; } -Texture::Builder& Texture::Builder::usage(Texture::Usage usage) noexcept { - mImpl->mUsage = Texture::Usage(usage); +Texture::Builder& Texture::Builder::usage(Usage const usage) noexcept { + mImpl->mUsage = Usage(usage); return *this; } -Texture::Builder& Texture::Builder::import(intptr_t id) noexcept { +Texture::Builder& Texture::Builder::import(intptr_t const id) noexcept { assert_invariant(id); // imported id can't be zero mImpl->mImportedId = id; return *this; @@ -142,12 +142,16 @@ Texture::Builder& Texture::Builder::external() noexcept { return *this; } -Texture::Builder& Texture::Builder::swizzle(Swizzle r, Swizzle g, Swizzle b, Swizzle a) noexcept { +Texture::Builder& Texture::Builder::swizzle(Swizzle const r, Swizzle const g, Swizzle const b, Swizzle const a) noexcept { mImpl->mTextureIsSwizzled = true; mImpl->mSwizzle = { r, g, b, a }; return *this; } +Texture::Builder& Texture::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + Texture* Texture::Builder::build(Engine& engine) { FILAMENT_CHECK_PRECONDITION(Texture::isTextureFormatSupported(engine, mImpl->mFormat)) << "Texture format " << uint16_t(mImpl->mFormat) << " not supported on this platform"; @@ -212,7 +216,7 @@ Texture* Texture::Builder::build(Engine& engine) { FILAMENT_CHECK_PRECONDITION(!swizzled) << "WebGL does not support texture swizzling."; #endif - auto validateSamplerType = [&engine = downcast(engine)](SamplerType sampler) -> bool { + auto validateSamplerType = [&engine = downcast(engine)](SamplerType const sampler) -> bool { switch (sampler) { case SamplerType::SAMPLER_2D: case SamplerType::SAMPLER_CUBEMAP: @@ -293,22 +297,22 @@ void FTexture::terminate(FEngine& engine) { setHandles({}); } -size_t FTexture::getWidth(size_t level) const noexcept { +size_t FTexture::getWidth(size_t const level) const noexcept { return valueForLevel(level, mWidth); } -size_t FTexture::getHeight(size_t level) const noexcept { +size_t FTexture::getHeight(size_t const level) const noexcept { return valueForLevel(level, mHeight); } -size_t FTexture::getDepth(size_t level) const noexcept { +size_t FTexture::getDepth(size_t const level) const noexcept { return valueForLevel(level, mDepth); } -void FTexture::setImage(FEngine& engine, size_t level, - uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, - uint32_t width, uint32_t height, uint32_t depth, - FTexture::PixelBufferDescriptor&& p) const { +void FTexture::setImage(FEngine& engine, size_t const level, + uint32_t const xoffset, uint32_t const yoffset, uint32_t const zoffset, + uint32_t const width, uint32_t const height, uint32_t const depth, + PixelBufferDescriptor&& p) const { if (UTILS_UNLIKELY(!engine.hasFeatureLevel(FeatureLevel::FEATURE_LEVEL_1))) { FILAMENT_CHECK_PRECONDITION(p.stride == 0 || p.stride == width) @@ -397,10 +401,10 @@ void FTexture::setImage(FEngine& engine, size_t level, } // deprecated -void FTexture::setImage(FEngine& engine, size_t level, - Texture::PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const { +void FTexture::setImage(FEngine& engine, size_t const level, + PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets) const { - auto validateTarget = [](SamplerType sampler) -> bool { + auto validateTarget = [](SamplerType const sampler) -> bool { switch (sampler) { case SamplerType::SAMPLER_CUBEMAP: return true; @@ -485,7 +489,7 @@ void FTexture::setExternalImage(FEngine& engine, void* image) noexcept { setHandles(texture); } -void FTexture::setExternalImage(FEngine& engine, void* image, size_t plane) noexcept { +void FTexture::setExternalImage(FEngine& engine, void* image, size_t const plane) noexcept { FILAMENT_CHECK_PRECONDITION(mExternal) << "The texture must be external."; // The call to setupExternalImage is synchronous, and allows the driver to take ownership of @@ -527,7 +531,7 @@ void FTexture::setExternalStream(FEngine& engine, FStream* stream) noexcept { api.setExternalStream(mHandle, stream->getHandle()); } else { mStream = nullptr; - api.setExternalStream(mHandle, backend::Handle()); + api.setExternalStream(mHandle, backend::Handle()); } } @@ -555,7 +559,7 @@ bool FTexture::textureHandleCanMutate() const noexcept { return (any(mUsage & Usage::SAMPLEABLE) && mLevelCount > 1) || mExternal; } -void FTexture::updateLodRange(uint8_t baseLevel, uint8_t levelCount) noexcept { +void FTexture::updateLodRange(uint8_t const baseLevel, uint8_t const levelCount) noexcept { assert_invariant(!mExternal); if (any(mUsage & Usage::SAMPLEABLE) && mLevelCount > 1) { auto& range = mLodRange; @@ -574,7 +578,7 @@ void FTexture::updateLodRange(uint8_t baseLevel, uint8_t levelCount) noexcept { } } -void FTexture::setHandles(backend::Handle handle) noexcept { +void FTexture::setHandles(Handle handle) noexcept { assert_invariant(!mHandle || mHandleForSampling); if (mHandle) { mDriver->destroyTexture(mHandle); @@ -586,8 +590,8 @@ void FTexture::setHandles(backend::Handle handle) noexcept { mHandleForSampling = handle; } -backend::Handle FTexture::setHandleForSampling( - backend::Handle handle) const noexcept { +Handle FTexture::setHandleForSampling( + Handle handle) const noexcept { assert_invariant(!mHandle || mHandleForSampling); if (mHandleForSampling && mHandleForSampling != mHandle) { mDriver->destroyTexture(mHandleForSampling); @@ -595,19 +599,19 @@ backend::Handle FTexture::setHandleForSampling( return mHandleForSampling = handle; } -backend::Handle FTexture::createPlaceholderTexture( - backend::DriverApi& driver) noexcept { +Handle FTexture::createPlaceholderTexture( + DriverApi& driver) noexcept { auto handle = driver.createTexture( Sampler::SAMPLER_2D, 1, InternalFormat::RGBA8, 1, 1, 1, 1, Usage::DEFAULT); static uint8_t pixels[4] = { 0, 0, 0, 0 }; driver.update3DImage(handle, 0, 0, 0, 0, 1, 1, 1, { (char*)&pixels[0], sizeof(pixels), - Texture::PixelBufferDescriptor::PixelDataFormat::RGBA, - Texture::PixelBufferDescriptor::PixelDataType::UBYTE }); + PixelBufferDescriptor::PixelDataFormat::RGBA, + PixelBufferDescriptor::PixelDataType::UBYTE }); return handle; } -backend::Handle FTexture::getHwHandleForSampling() const noexcept { +Handle FTexture::getHwHandleForSampling() const noexcept { if (UTILS_UNLIKELY(mExternal && !mHandleForSampling)) { return setHandleForSampling(createPlaceholderTexture(*mDriver)); } @@ -626,11 +630,11 @@ backend::Handle FTexture::getHwHandleForSampling() const noe return mHandleForSampling; } -void FTexture::updateLodRange(uint8_t level) noexcept { +void FTexture::updateLodRange(uint8_t const level) noexcept { updateLodRange(level, 1); } -bool FTexture::isTextureFormatSupported(FEngine& engine, InternalFormat format) noexcept { +bool FTexture::isTextureFormatSupported(FEngine& engine, InternalFormat const format) noexcept { return engine.getDriverApi().isTextureFormatSupported(format); } @@ -642,12 +646,12 @@ bool FTexture::isTextureSwizzleSupported(FEngine& engine) noexcept { return engine.getDriverApi().isTextureSwizzleSupported(); } -size_t FTexture::computeTextureDataSize(Texture::Format format, Texture::Type type, - size_t stride, size_t height, size_t alignment) noexcept { +size_t FTexture::computeTextureDataSize(Format const format, Type const type, + size_t const stride, size_t const height, size_t const alignment) noexcept { return PixelBufferDescriptor::computeDataSize(format, type, stride, height, alignment); } -size_t FTexture::getFormatSize(InternalFormat format) noexcept { +size_t FTexture::getFormatSize(InternalFormat const format) noexcept { return backend::getFormatSize(format); } @@ -807,9 +811,9 @@ void FTexture::generatePrefilterMipmap(FEngine& engine, CubemapIBL::roughnessFilter(js, dst, { levels.begin(), uint32_t(levels.size()) }, linearRoughness, numSamples, mirror, true); - Texture::PixelBufferDescriptor const pbd(image.getData(), image.getSize(), - Texture::PixelBufferDescriptor::PixelDataFormat::RGB, - Texture::PixelBufferDescriptor::PixelDataType::FLOAT, 1, 0, 0, image.getStride()); + PixelBufferDescriptor const pbd(image.getData(), image.getSize(), + PixelBufferDescriptor::PixelDataFormat::RGB, + PixelBufferDescriptor::PixelDataType::FLOAT, 1, 0, 0, image.getStride()); uintptr_t const base = uintptr_t(image.getData()); for (size_t j = 0; j < 6; j++) { @@ -817,8 +821,8 @@ void FTexture::generatePrefilterMipmap(FEngine& engine, auto offset = uintptr_t(faceImage.getData()) - base; driver.update3DImage(mHandle, level, 0, 0, j, dim, dim, 1, { (char*)image.getData() + offset, dim * dim * 3 * sizeof(float), - Texture::PixelBufferDescriptor::PixelDataFormat::RGB, - Texture::PixelBufferDescriptor::PixelDataType::FLOAT, 1, + PixelBufferDescriptor::PixelDataFormat::RGB, + PixelBufferDescriptor::PixelDataType::FLOAT, 1, 0, 0, uint32_t(image.getStride()) }); } @@ -831,8 +835,8 @@ void FTexture::generatePrefilterMipmap(FEngine& engine, // by the caller (without being move()d here). } -bool FTexture::validatePixelFormatAndType(TextureFormat internalFormat, - PixelDataFormat format, PixelDataType type) noexcept { +bool FTexture::validatePixelFormatAndType(TextureFormat const internalFormat, + PixelDataFormat const format, PixelDataType const type) noexcept { switch (internalFormat) { case TextureFormat::R8: diff --git a/filament/src/details/Texture.h b/filament/src/details/Texture.h index 2131988c84..f4354f2f57 100644 --- a/filament/src/details/Texture.h +++ b/filament/src/details/Texture.h @@ -72,10 +72,10 @@ public: void generateMipmaps(FEngine& engine) const noexcept; - void setSampleCount(size_t sampleCount) noexcept { mSampleCount = uint8_t(sampleCount); } + void setSampleCount(size_t const sampleCount) noexcept { mSampleCount = uint8_t(sampleCount); } size_t getSampleCount() const noexcept { return mSampleCount; } bool isMultisample() const noexcept { return mSampleCount > 1; } - bool isCompressed() const noexcept { return backend::isCompressedFormat(mFormat); } + bool isCompressed() const noexcept { return isCompressedFormat(mFormat); } bool isCubemap() const noexcept { return mTarget == Sampler::SAMPLER_CUBEMAP; } @@ -95,24 +95,24 @@ public: static bool isTextureSwizzleSupported(FEngine& engine) noexcept; // storage needed on the CPU side for texture data uploads - static size_t computeTextureDataSize(Texture::Format format, Texture::Type type, + static size_t computeTextureDataSize(Format format, Type type, size_t stride, size_t height, size_t alignment) noexcept; // Size a of a pixel in bytes for the given format static size_t getFormatSize(InternalFormat format) noexcept; // Returns the with or height for a given mipmap level from the base value. - static inline size_t valueForLevel(uint8_t level, size_t baseLevelValue) { + static inline size_t valueForLevel(uint8_t const level, size_t const baseLevelValue) { return std::max(size_t(1), baseLevelValue >> level); } // Returns the max number of levels for a texture of given max dimensions - static inline uint8_t maxLevelCount(uint32_t maxDimension) noexcept { + static inline uint8_t maxLevelCount(uint32_t const maxDimension) noexcept { return std::max(1, std::ilogbf(float(maxDimension)) + 1); } // Returns the max number of levels for a texture of given dimensions - static inline uint8_t maxLevelCount(uint32_t width, uint32_t height) noexcept { + static inline uint8_t maxLevelCount(uint32_t const width, uint32_t const height) noexcept { uint32_t const maxDimension = std::max(width, height); return maxLevelCount(maxDimension); } diff --git a/filament/src/details/VertexBuffer.cpp b/filament/src/details/VertexBuffer.cpp index 8aabcf4fc7..881ff2abce 100644 --- a/filament/src/details/VertexBuffer.cpp +++ b/filament/src/details/VertexBuffer.cpp @@ -50,8 +50,8 @@ using namespace backend; using namespace filament::math; struct VertexBuffer::BuilderDetails { - struct AttributeData : backend::Attribute { - AttributeData() : backend::Attribute{ .type = backend::ElementType::FLOAT4 } { + struct AttributeData : Attribute { + AttributeData() : Attribute{ .type = ElementType::FLOAT4 } { static_assert(sizeof(Attribute) == sizeof(AttributeData), "Attribute and Builder::Attribute must match"); } @@ -67,30 +67,30 @@ struct VertexBuffer::BuilderDetails { using BuilderType = VertexBuffer; BuilderType::Builder::Builder() noexcept = default; BuilderType::Builder::~Builder() noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder::Builder(BuilderType::Builder&& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder const& rhs) noexcept = default; -BuilderType::Builder& BuilderType::Builder::operator=(BuilderType::Builder&& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder const& rhs) noexcept = default; +BuilderType::Builder::Builder(Builder&& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder const& rhs) noexcept = default; +BuilderType::Builder& BuilderType::Builder::operator=(Builder&& rhs) noexcept = default; -VertexBuffer::Builder& VertexBuffer::Builder::vertexCount(uint32_t vertexCount) noexcept { +VertexBuffer::Builder& VertexBuffer::Builder::vertexCount(uint32_t const vertexCount) noexcept { mImpl->mVertexCount = vertexCount; return *this; } -VertexBuffer::Builder& VertexBuffer::Builder::enableBufferObjects(bool enabled) noexcept { +VertexBuffer::Builder& VertexBuffer::Builder::enableBufferObjects(bool const enabled) noexcept { mImpl->mBufferObjectsEnabled = enabled; return *this; } -VertexBuffer::Builder& VertexBuffer::Builder::bufferCount(uint8_t bufferCount) noexcept { +VertexBuffer::Builder& VertexBuffer::Builder::bufferCount(uint8_t const bufferCount) noexcept { mImpl->mBufferCount = bufferCount; return *this; } -VertexBuffer::Builder& VertexBuffer::Builder::attribute(VertexAttribute attribute, - uint8_t bufferIndex, - AttributeType attributeType, - uint32_t byteOffset, +VertexBuffer::Builder& VertexBuffer::Builder::attribute(VertexAttribute const attribute, + uint8_t const bufferIndex, + AttributeType const attributeType, + uint32_t const byteOffset, uint8_t byteStride) noexcept { size_t const attributeSize = Driver::getElementTypeSize(attributeType); @@ -117,7 +117,7 @@ VertexBuffer::Builder& VertexBuffer::Builder::attribute(VertexAttribute attribut entry.offset = byteOffset; entry.stride = byteStride; entry.type = attributeType; - if (attribute == VertexAttribute::BONE_INDICES) { + if (attribute == BONE_INDICES) { // BONE_INDICES must always be an integer type entry.flags |= Attribute::FLAG_INTEGER_TARGET; } @@ -130,8 +130,8 @@ VertexBuffer::Builder& VertexBuffer::Builder::attribute(VertexAttribute attribut return *this; } -VertexBuffer::Builder& VertexBuffer::Builder::normalized(VertexAttribute attribute, - bool normalized) noexcept { +VertexBuffer::Builder& VertexBuffer::Builder::normalized(VertexAttribute const attribute, + bool const normalized) noexcept { if (size_t(attribute) < MAX_VERTEX_ATTRIBUTE_COUNT) { auto& entry = mImpl->mAttributes[attribute]; if (normalized) { @@ -143,11 +143,15 @@ VertexBuffer::Builder& VertexBuffer::Builder::normalized(VertexAttribute attribu return *this; } -VertexBuffer::Builder& VertexBuffer::Builder::advancedSkinning(bool enabled) noexcept { +VertexBuffer::Builder& VertexBuffer::Builder::advancedSkinning(bool const enabled) noexcept { mImpl->mAdvancedSkinningEnabled = enabled; return *this; } +VertexBuffer::Builder& VertexBuffer::Builder::name(const char* name, size_t const len) noexcept { + return BuilderNameMixin::name(name, len); +} + VertexBuffer* VertexBuffer::Builder::build(Engine& engine) { FILAMENT_CHECK_PRECONDITION(mImpl->mVertexCount > 0) << "vertexCount cannot be 0"; FILAMENT_CHECK_PRECONDITION(mImpl->mBufferCount > 0) << "bufferCount cannot be 0"; @@ -160,11 +164,11 @@ VertexBuffer* VertexBuffer::Builder::build(Engine& engine) { auto const& attributes = mImpl->mAttributes; utils::bitset32 attributedBuffers; - declaredAttributes.forEachSetBit([&](size_t j){ + declaredAttributes.forEachSetBit([&](size_t const j){ // update set of used buffers attributedBuffers.set(attributes[j].buffer); - if (engine.getActiveFeatureLevel() == backend::FeatureLevel::FEATURE_LEVEL_0) { + if (engine.getActiveFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0) { FILAMENT_CHECK_PRECONDITION(!(attributes[j].flags & Attribute::FLAG_INTEGER_TARGET)) << "Attribute::FLAG_INTEGER_TARGET not supported at FEATURE_LEVEL_0"; } @@ -205,7 +209,7 @@ VertexBuffer* VertexBuffer::Builder::build(Engine& engine) { // ------------------------------------------------------------------------------------------------ -FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& builder) +FVertexBuffer::FVertexBuffer(FEngine& engine, const Builder& builder) : mVertexCount(builder->mVertexCount), mBufferCount(builder->mBufferCount), mBufferObjectsEnabled(builder->mBufferObjectsEnabled), mAdvancedSkinningEnabled(builder->mAdvancedSkinningEnabled){ @@ -213,24 +217,24 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& build mDeclaredAttributes = builder->mDeclaredAttributes; if (mAdvancedSkinningEnabled) { - mAttributes[VertexAttribute::BONE_INDICES] = { + mAttributes[BONE_INDICES] = { .offset = 0, .stride = 8, .buffer = mBufferCount, - .type = VertexBuffer::AttributeType::USHORT4, + .type = AttributeType::USHORT4, .flags = Attribute::FLAG_INTEGER_TARGET, }; - mDeclaredAttributes.set(VertexAttribute::BONE_INDICES); + mDeclaredAttributes.set(BONE_INDICES); mBufferCount++; - mAttributes[VertexAttribute::BONE_WEIGHTS] = { + mAttributes[BONE_WEIGHTS] = { .offset = 0, .stride = 16, .buffer = mBufferCount, - .type = VertexBuffer::AttributeType::FLOAT4, + .type = AttributeType::FLOAT4, .flags = 0, }; - mDeclaredAttributes.set(VertexAttribute::BONE_WEIGHTS); + mDeclaredAttributes.set(BONE_WEIGHTS); mBufferCount++; } else { // Because the Material's SKN variant supports both skinning and morphing, it expects @@ -289,7 +293,7 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& build assert_invariant(bufferSizes[i] > 0); if (!mBufferObjects[i]) { BufferObjectHandle bo = driver.createBufferObject(bufferSizes[i], - backend::BufferObjectBinding::VERTEX, backend::BufferUsage::STATIC); + BufferObjectBinding::VERTEX, BufferUsage::STATIC); if (auto name = builder.getName(); !name.empty()) { driver.setDebugTag(bo.getId(), name); } @@ -302,13 +306,13 @@ FVertexBuffer::FVertexBuffer(FEngine& engine, const VertexBuffer::Builder& build // in advanced skinning mode, we manage the BONE_INDICES and BONE_WEIGHTS arrays ourselves, // so we have to set the corresponding buffer objects. if (mAdvancedSkinningEnabled) { - for (auto index : { VertexAttribute::BONE_INDICES, VertexAttribute::BONE_WEIGHTS }) { + for (auto index : { BONE_INDICES, BONE_WEIGHTS }) { size_t const i = mAttributes[index].buffer; assert_invariant(i != Attribute::BUFFER_UNUSED); assert_invariant(bufferSizes[i] > 0); if (!mBufferObjects[i]) { BufferObjectHandle const bo = driver.createBufferObject(bufferSizes[i], - backend::BufferObjectBinding::VERTEX, backend::BufferUsage::STATIC); + BufferObjectBinding::VERTEX, BufferUsage::STATIC); if (auto name = builder.getName(); !name.empty()) { driver.setDebugTag(bo.getId(), name); } @@ -335,8 +339,8 @@ size_t FVertexBuffer::getVertexCount() const noexcept { return mVertexCount; } -void FVertexBuffer::setBufferAt(FEngine& engine, uint8_t bufferIndex, - backend::BufferDescriptor&& buffer, uint32_t byteOffset) { +void FVertexBuffer::setBufferAt(FEngine& engine, uint8_t const bufferIndex, + backend::BufferDescriptor&& buffer, uint32_t const byteOffset) { FILAMENT_CHECK_PRECONDITION(!mBufferObjectsEnabled) << "Please use setBufferObjectAt()"; if (bufferIndex < mBufferCount) { assert_invariant(mBufferObjects[bufferIndex]); @@ -348,7 +352,7 @@ void FVertexBuffer::setBufferAt(FEngine& engine, uint8_t bufferIndex, } } -void FVertexBuffer::setBufferObjectAt(FEngine& engine, uint8_t bufferIndex, +void FVertexBuffer::setBufferObjectAt(FEngine& engine, uint8_t const bufferIndex, FBufferObject const * bufferObject) { FILAMENT_CHECK_PRECONDITION(mBufferObjectsEnabled) << "Please use setBufferAt()"; FILAMENT_CHECK_PRECONDITION(bufferObject->getBindingType() == BufferObject::BindingType::VERTEX) @@ -370,14 +374,14 @@ void FVertexBuffer::updateBoneIndicesAndWeights(FEngine& engine, std::unique_ptr skinWeights) { FILAMENT_CHECK_PRECONDITION(mAdvancedSkinningEnabled) << "No advanced skinning enabled"; auto jointsData = skinJoints.release(); - uint8_t const indicesIndex = mAttributes[VertexAttribute::BONE_INDICES].buffer; + uint8_t const indicesIndex = mAttributes[BONE_INDICES].buffer; engine.getDriverApi().updateBufferObject(mBufferObjects[indicesIndex], {jointsData, mVertexCount * 8, [](void* buffer, size_t, void*) { delete[] static_cast(buffer); }}, 0); auto weightsData = skinWeights.release(); - uint8_t const weightsIndex = mAttributes[VertexAttribute::BONE_WEIGHTS].buffer; + uint8_t const weightsIndex = mAttributes[BONE_WEIGHTS].buffer; engine.getDriverApi().updateBufferObject(mBufferObjects[weightsIndex], {weightsData, mVertexCount * 16, [](void* buffer, size_t, void*) { delete[] static_cast(buffer); }}, diff --git a/filament/src/details/View.cpp b/filament/src/details/View.cpp index 24b203e48d..3022f4be59 100644 --- a/filament/src/details/View.cpp +++ b/filament/src/details/View.cpp @@ -185,7 +185,7 @@ void FView::setDynamicResolutionOptions(DynamicResolutionOptions const& options) } } -void FView::setDynamicLightingOptions(float zLightNear, float zLightFar) noexcept { +void FView::setDynamicLightingOptions(float const zLightNear, float const zLightFar) noexcept { mFroxelizer.setOptions(zLightNear, zLightFar); } @@ -311,7 +311,7 @@ float2 FView::updateScale(FEngine& engine, return mScale; } -void FView::setVisibleLayers(uint8_t select, uint8_t values) noexcept { +void FView::setVisibleLayers(uint8_t const select, uint8_t const values) noexcept { mVisibleLayers = (mVisibleLayers & ~select) | (values & select); } @@ -481,8 +481,8 @@ CameraInfo FView::computeCameraInfo(FEngine& engine) const noexcept { } void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootArenaScope, - filament::Viewport viewport, CameraInfo cameraInfo, - float4 const& userTime, bool needsAlphaChannel) noexcept { + filament::Viewport const viewport, CameraInfo cameraInfo, + float4 const& userTime, bool const needsAlphaChannel) noexcept { SYSTRACE_CALL(); SYSTRACE_CONTEXT(); @@ -542,7 +542,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren [&engine, distances, positionalLightCount, &viewMatrix = cameraInfo.view, &cullingFrustum, &lightData = scene->getLightData()] (JobSystem&, JobSystem::Job*) { - FView::prepareVisibleLights(engine.getLightManager(), + prepareVisibleLights(engine.getLightManager(), { distances, distances + positionalLightCount }, viewMatrix, cullingFrustum, lightData); })); @@ -786,7 +786,7 @@ void FView::prepare(FEngine& engine, DriverApi& driver, RootArenaScope& rootAren } void FView::computeVisibilityMasks( - uint8_t visibleLayers, + uint8_t const visibleLayers, uint8_t const* UTILS_RESTRICT layers, FRenderableManager::Visibility const* UTILS_RESTRICT visibility, Culler::result_type* UTILS_RESTRICT visibleMask, size_t count) { @@ -818,8 +818,8 @@ void FView::computeVisibilityMasks( UTILS_NOINLINE /* static */ FScene::RenderableSoa::iterator FView::partition( - FScene::RenderableSoa::iterator begin, - FScene::RenderableSoa::iterator end, + FScene::RenderableSoa::iterator const begin, + FScene::RenderableSoa::iterator const end, Culler::result_type mask, Culler::result_type value) noexcept { return std::partition(begin, end, [mask, value](auto it) { // Mask VISIBLE_MASK to ignore higher bits related to spot shadows. We only partition based @@ -828,7 +828,7 @@ UTILS_NOINLINE }); } -void FView::prepareUpscaler(float2 scale, +void FView::prepareUpscaler(float2 const scale, TemporalAntiAliasingOptions const& taaOptions, DynamicResolutionOptions const& dsrOptions) const noexcept { SYSTRACE_CALL(); @@ -865,8 +865,8 @@ void FView::prepareSSAO(Handle ssao) const noexcept { } void FView::prepareSSR(Handle ssr, - bool disableSSR, - float refractionLodOffset, + bool const disableSSR, + float const refractionLodOffset, ScreenSpaceReflectionsOptions const& ssrOptions) const noexcept { mColorPassDescriptorSet.prepareSSR(ssr, disableSSR, refractionLodOffset, ssrOptions); } @@ -884,25 +884,25 @@ void FView::prepareShadow(Handle texture) const noexcept { uniforms = mShadowMapManager->getShadowMappingUniforms(); } switch (mShadowType) { - case filament::ShadowType::PCF: + case ShadowType::PCF: mColorPassDescriptorSet.prepareShadowPCF(texture, uniforms); break; - case filament::ShadowType::VSM: + case ShadowType::VSM: mColorPassDescriptorSet.prepareShadowVSM(texture, uniforms, mVsmShadowOptions); break; - case filament::ShadowType::DPCF: + case ShadowType::DPCF: mColorPassDescriptorSet.prepareShadowDPCF(texture, uniforms, mSoftShadowOptions); break; - case filament::ShadowType::PCSS: + case ShadowType::PCSS: mColorPassDescriptorSet.prepareShadowPCSS(texture, uniforms, mSoftShadowOptions); break; - case filament::ShadowType::PCFd: + case ShadowType::PCFd: mColorPassDescriptorSet.prepareShadowPCFDebug(texture, uniforms); break; } } -void FView::prepareShadowMapping(bool highPrecision) const noexcept { +void FView::prepareShadowMapping(bool const highPrecision) const noexcept { if (mHasShadowing) { assert_invariant(mShadowMapManager); mColorPassDescriptorSet.prepareShadowMapping( @@ -929,7 +929,7 @@ void FView::prepareVisibleRenderables(JobSystem& js, Frustum const& frustum, FScene::RenderableSoa& renderableData) const noexcept { SYSTRACE_CALL(); if (UTILS_LIKELY(isFrustumCullingEnabled())) { - FView::cullRenderables(js, renderableData, frustum, VISIBLE_RENDERABLE_BIT); + cullRenderables(js, renderableData, frustum, VISIBLE_RENDERABLE_BIT); } else { std::uninitialized_fill(renderableData.begin(), renderableData.end(), VISIBLE_RENDERABLE); @@ -946,7 +946,7 @@ void FView::cullRenderables(JobSystem&, // culling job (this runs on multiple threads) auto functor = [&frustum, worldAABBCenter, worldAABBExtent, visibleArray, bit] - (uint32_t index, uint32_t c) { + (uint32_t const index, uint32_t const c) { Culler::intersects( visibleArray + index, frustum, @@ -963,7 +963,7 @@ void FView::cullRenderables(JobSystem&, } void FView::prepareVisibleLights(FLightManager const& lcm, - utils::Slice scratch, + Slice scratch, mat4f const& viewMatrix, Frustum const& frustum, FScene::LightSoa& lightData) noexcept { SYSTRACE_CALL(); @@ -1112,8 +1112,8 @@ void FView::clearFrameHistory(FEngine& engine) noexcept { } } -void FView::executePickingQueries(backend::DriverApi& driver, - backend::RenderTargetHandle handle, float2 scale) noexcept { +void FView::executePickingQueries(DriverApi& driver, + RenderTargetHandle handle, float2 const scale) noexcept { while (mActivePickingQueriesList) { FPickingQuery* const pQuery = mActivePickingQueriesList; @@ -1126,7 +1126,7 @@ void FView::executePickingQueries(backend::DriverApi& driver, if (UTILS_UNLIKELY(driver.getFeatureLevel() == FeatureLevel::FEATURE_LEVEL_0)) { driver.readPixels(handle, x, y, 1, 1, { &pQuery->result.reserved1, 4u, // 4 - backend::PixelDataFormat::RGBA, backend::PixelDataType::UBYTE, + PixelDataFormat::RGBA, PixelDataType::UBYTE, pQuery->handler, [](void*, size_t, void* user) { FPickingQuery* pQuery = static_cast(user); uint8_t const* const p = @@ -1148,7 +1148,7 @@ void FView::executePickingQueries(backend::DriverApi& driver, } else { driver.readPixels(handle, x, y, 1, 1, { &pQuery->result.renderable, 4u * 4u, // 4*float - backend::PixelDataFormat::RG, backend::PixelDataType::FLOAT, + PixelDataFormat::RG, PixelDataType::FLOAT, pQuery->handler, [](void*, size_t, void* user) { FPickingQuery* const pQuery = static_cast(user); // pQuery->result.renderable already contains the right value! @@ -1163,7 +1163,7 @@ void FView::executePickingQueries(backend::DriverApi& driver, } void FView::setTemporalAntiAliasingOptions(TemporalAntiAliasingOptions options) noexcept { - options.feedback = math::clamp(options.feedback, 0.0f, 1.0f); + options.feedback = clamp(options.feedback, 0.0f, 1.0f); options.filterWidth = std::max(0.2f, options.filterWidth); // below 0.2 causes issues mTemporalAntiAliasingOptions = options; } @@ -1182,29 +1182,29 @@ void FView::setScreenSpaceReflectionsOptions(ScreenSpaceReflectionsOptions optio mScreenSpaceReflectionsOptions = options; } -void FView::setGuardBandOptions(GuardBandOptions options) noexcept { +void FView::setGuardBandOptions(GuardBandOptions const options) noexcept { mGuardBandOptions = options; } void FView::setAmbientOcclusionOptions(AmbientOcclusionOptions options) noexcept { - options.radius = math::max(0.0f, options.radius); + options.radius = max(0.0f, options.radius); options.power = std::max(0.0f, options.power); - options.bias = math::clamp(options.bias, 0.0f, 0.1f); + options.bias = clamp(options.bias, 0.0f, 0.1f); // snap to the closer of 0.5 or 1.0 options.resolution = std::floor( - math::clamp(options.resolution * 2.0f, 1.0f, 2.0f) + 0.5f) * 0.5f; + clamp(options.resolution * 2.0f, 1.0f, 2.0f) + 0.5f) * 0.5f; options.intensity = std::max(0.0f, options.intensity); options.bilateralThreshold = std::max(0.0f, options.bilateralThreshold); - options.minHorizonAngleRad = math::clamp(options.minHorizonAngleRad, 0.0f, math::f::PI_2); - options.ssct.lightConeRad = math::clamp(options.ssct.lightConeRad, 0.0f, math::f::PI_2); + options.minHorizonAngleRad = clamp(options.minHorizonAngleRad, 0.0f, f::PI_2); + options.ssct.lightConeRad = clamp(options.ssct.lightConeRad, 0.0f, f::PI_2); options.ssct.shadowDistance = std::max(0.0f, options.ssct.shadowDistance); options.ssct.contactDistanceMax = std::max(0.0f, options.ssct.contactDistanceMax); options.ssct.intensity = std::max(0.0f, options.ssct.intensity); options.ssct.lightDirection = normalize(options.ssct.lightDirection); options.ssct.depthBias = std::max(0.0f, options.ssct.depthBias); options.ssct.depthSlopeBias = std::max(0.0f, options.ssct.depthSlopeBias); - options.ssct.sampleCount = math::clamp((unsigned)options.ssct.sampleCount, 1u, 255u); - options.ssct.rayCount = math::clamp((unsigned)options.ssct.rayCount, 1u, 255u); + options.ssct.sampleCount = clamp((unsigned)options.ssct.sampleCount, 1u, 255u); + options.ssct.rayCount = clamp((unsigned)options.ssct.rayCount, 1u, 255u); mAmbientOcclusionOptions = options; } void FView::setVsmShadowOptions(VsmShadowOptions options) noexcept { @@ -1219,9 +1219,9 @@ void FView::setSoftShadowOptions(SoftShadowOptions options) noexcept { } void FView::setBloomOptions(BloomOptions options) noexcept { - options.dirtStrength = math::saturate(options.dirtStrength); - options.resolution = math::clamp(options.resolution, 2u, 2048u); - options.levels = math::clamp(options.levels, uint8_t(1), + options.dirtStrength = saturate(options.dirtStrength); + options.resolution = clamp(options.resolution, 2u, 2048u); + options.levels = clamp(options.levels, uint8_t(1), FTexture::maxLevelCount(options.resolution)); options.highlight = std::max(10.0f, options.highlight); mBloomOptions = options; @@ -1229,7 +1229,7 @@ void FView::setBloomOptions(BloomOptions options) noexcept { void FView::setFogOptions(FogOptions options) noexcept { options.distance = std::max(0.0f, options.distance); - options.maximumOpacity = math::clamp(options.maximumOpacity, 0.0f, 1.0f); + options.maximumOpacity = clamp(options.maximumOpacity, 0.0f, 1.0f); options.density = std::max(0.0f, options.density); options.heightFalloff = std::max(0.0f, options.heightFalloff); options.inScatteringSize = options.inScatteringSize; @@ -1244,14 +1244,14 @@ void FView::setDepthOfFieldOptions(DepthOfFieldOptions options) noexcept { } void FView::setVignetteOptions(VignetteOptions options) noexcept { - options.roundness = math::saturate(options.roundness); - options.midPoint = math::saturate(options.midPoint); - options.feather = math::clamp(options.feather, 0.05f, 1.0f); + options.roundness = saturate(options.roundness); + options.midPoint = saturate(options.midPoint); + options.feather = clamp(options.feather, 0.05f, 1.0f); mVignetteOptions = options; } -View::PickingQuery& FView::pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler, - View::PickingQueryResultCallback callback) noexcept { +View::PickingQuery& FView::pick(uint32_t const x, uint32_t const y, CallbackHandler* handler, + PickingQueryResultCallback const callback) noexcept { FPickingQuery* pQuery = FPickingQuery::get(x, y, handler, callback); pQuery->next = mActivePickingQueriesList; mActivePickingQueriesList = pQuery; @@ -1262,13 +1262,13 @@ void FView::setStereoscopicOptions(const StereoscopicOptions& options) noexcept mStereoscopicOptions = options; } -void FView::setMaterialGlobal(uint32_t index, float4 const& value) { +void FView::setMaterialGlobal(uint32_t const index, float4 const& value) { FILAMENT_CHECK_PRECONDITION(index < 4) << "material global variable index (" << +index << ") out of range"; mMaterialGlobals[index] = value; } -math::float4 FView::getMaterialGlobal(uint32_t index) const { +float4 FView::getMaterialGlobal(uint32_t const index) const { FILAMENT_CHECK_PRECONDITION(index < 4) << "material global variable index (" << +index << ") out of range"; return mMaterialGlobals[index]; diff --git a/filament/src/details/View.h b/filament/src/details/View.h index 715ebfd1a5..34c49e40d5 100644 --- a/filament/src/details/View.h +++ b/filament/src/details/View.h @@ -106,7 +106,7 @@ public: // note: viewport/cameraInfo are passed by value to make it clear that prepare cannot // keep references on them that would outlive the scope of prepare() (e.g. with JobSystem). void prepare(FEngine& engine, backend::DriverApi& driver, RootArenaScope& rootArenaScope, - filament::Viewport viewport, CameraInfo cameraInfo, + Viewport viewport, CameraInfo cameraInfo, math::float4 const& userTime, bool needsAlphaChannel) noexcept; void setScene(FScene* scene) { mScene = scene; } @@ -127,13 +127,13 @@ public: } bool isSkyboxVisible() const noexcept; - void setFrustumCullingEnabled(bool culling) noexcept { mCulling = culling; } + void setFrustumCullingEnabled(bool const culling) noexcept { mCulling = culling; } bool isFrustumCullingEnabled() const noexcept { return mCulling; } - void setFrontFaceWindingInverted(bool inverted) noexcept { mFrontFaceWindingInverted = inverted; } + void setFrontFaceWindingInverted(bool const inverted) noexcept { mFrontFaceWindingInverted = inverted; } bool isFrontFaceWindingInverted() const noexcept { return mFrontFaceWindingInverted; } - void setTransparentPickingEnabled(bool enabled) noexcept { mIsTransparentPickingEnabled = enabled; } + void setTransparentPickingEnabled(bool const enabled) noexcept { mIsTransparentPickingEnabled = enabled; } bool isTransparentPickingEnabled() const noexcept { return mIsTransparentPickingEnabled; } @@ -158,7 +158,7 @@ public: void prepareViewport( const Viewport& physicalViewport, - const filament::Viewport& logicalViewport) const noexcept; + const Viewport& logicalViewport) const noexcept; void prepareShadowing(FEngine& engine, FScene::RenderableSoa& renderableData, FScene::LightSoa const& lightData, CameraInfo const& cameraInfo) noexcept; @@ -208,17 +208,17 @@ public: FEngine const& engine, CameraInfo const& camera, Range visible) noexcept; - void setShadowingEnabled(bool enabled) noexcept { mShadowingEnabled = enabled; } + void setShadowingEnabled(bool const enabled) noexcept { mShadowingEnabled = enabled; } bool isShadowingEnabled() const noexcept { return mShadowingEnabled; } - void setScreenSpaceRefractionEnabled(bool enabled) noexcept { mScreenSpaceRefractionEnabled = enabled; } + void setScreenSpaceRefractionEnabled(bool const enabled) noexcept { mScreenSpaceRefractionEnabled = enabled; } bool isScreenSpaceRefractionEnabled() const noexcept { return mScreenSpaceRefractionEnabled; } bool isScreenSpaceReflectionEnabled() const noexcept { return mScreenSpaceReflectionsOptions.enabled; } - void setStencilBufferEnabled(bool enabled) noexcept { mStencilBufferEnabled = enabled; } + void setStencilBufferEnabled(bool const enabled) noexcept { mStencilBufferEnabled = enabled; } bool isStencilBufferEnabled() const noexcept { return mStencilBufferEnabled; } @@ -249,7 +249,7 @@ public: return mMultiSampleAntiAliasingOptions.sampleCount; } - void setAntiAliasing(AntiAliasing type) noexcept { + void setAntiAliasing(AntiAliasing const type) noexcept { mAntiAliasing = type; } @@ -289,7 +289,7 @@ public: return mColorGrading; } - void setDithering(Dithering dithering) noexcept { + void setDithering(Dithering const dithering) noexcept { mDithering = dithering; } @@ -310,7 +310,7 @@ public: Renderer::FrameRateOptions const& frameRateOptions, Renderer::DisplayInfo const& displayInfo) noexcept; - void setDynamicResolutionOptions(View::DynamicResolutionOptions const& options) noexcept; + void setDynamicResolutionOptions(DynamicResolutionOptions const& options) noexcept; DynamicResolutionOptions getDynamicResolutionOptions() const noexcept { return mDynamicResolution; @@ -326,11 +326,11 @@ public: void setDynamicLightingOptions(float zLightNear, float zLightFar) noexcept; - void setPostProcessingEnabled(bool enabled) noexcept { + void setPostProcessingEnabled(bool const enabled) noexcept { mHasPostProcessPass = enabled; } - void setAmbientOcclusion(AmbientOcclusion ambientOcclusion) noexcept { + void setAmbientOcclusion(AmbientOcclusion const ambientOcclusion) noexcept { mAmbientOcclusionOptions.enabled = ambientOcclusion == AmbientOcclusion::SSAO; } @@ -344,7 +344,7 @@ public: return mShadowType; } - void setShadowType(ShadowType shadow) noexcept { + void setShadowType(ShadowType const shadow) noexcept { mShadowType = shadow; } @@ -388,7 +388,7 @@ public: return mVignetteOptions; } - void setBlendMode(BlendMode blendMode) noexcept { + void setBlendMode(BlendMode const blendMode) noexcept { mBlendMode = blendMode; } @@ -449,8 +449,8 @@ public: void clearFrameHistory(FEngine& engine) noexcept; // create the picking query - View::PickingQuery& pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler, - View::PickingQueryResultCallback callback) noexcept; + PickingQuery& pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler, + PickingQueryResultCallback callback) noexcept; void executePickingQueries(backend::DriverApi& driver, backend::RenderTargetHandle handle, math::float2 scale) noexcept; @@ -470,15 +470,15 @@ public: private: struct FPickingQuery : public PickingQuery { private: - FPickingQuery(uint32_t x, uint32_t y, + FPickingQuery(uint32_t const x, uint32_t const y, backend::CallbackHandler* handler, - View::PickingQueryResultCallback callback) noexcept + PickingQueryResultCallback const callback) noexcept : PickingQuery{}, x(x), y(y), handler(handler), callback(callback) {} ~FPickingQuery() noexcept = default; public: // TODO: use a small pool - static FPickingQuery* get(uint32_t x, uint32_t y, backend::CallbackHandler* handler, - View::PickingQueryResultCallback callback) noexcept { + static FPickingQuery* get(uint32_t const x, uint32_t const y, backend::CallbackHandler* handler, + PickingQueryResultCallback const callback) noexcept { return new(std::nothrow) FPickingQuery(x, y, handler, callback); } static void put(FPickingQuery* pQuery) noexcept { @@ -489,7 +489,7 @@ private: uint32_t const x; uint32_t const y; backend::CallbackHandler* const handler; - View::PickingQueryResultCallback const callback; + PickingQueryResultCallback const callback; // picking query result PickingQueryResult result; }; @@ -521,7 +521,7 @@ private: // these are accessed in the render loop, keep together backend::Handle mLightUbh; backend::Handle mRenderableUbh; - filament::DescriptorSet mCommonRenderableDescriptorSet; + DescriptorSet mCommonRenderableDescriptorSet; FScene* mScene = nullptr; // The camera set by the user, used for culling and viewing diff --git a/filament/src/ds/ColorPassDescriptorSet.cpp b/filament/src/ds/ColorPassDescriptorSet.cpp index 03f8924bb9..e5234dd157 100644 --- a/filament/src/ds/ColorPassDescriptorSet.cpp +++ b/filament/src/ds/ColorPassDescriptorSet.cpp @@ -65,7 +65,7 @@ using namespace backend; using namespace math; uint8_t ColorPassDescriptorSet::getIndex( - bool lit, bool ssr, bool fog) noexcept { + bool const lit, bool const ssr, bool const fog) noexcept { uint8_t index = 0; @@ -99,7 +99,7 @@ ColorPassDescriptorSet::ColorPassDescriptorSet(FEngine& engine, for (bool const lit: { false, true }) { for (bool const ssr: { false, true }) { for (bool const fog: { false, true }) { - auto index = ColorPassDescriptorSet::getIndex(lit, ssr, fog); + auto index = getIndex(lit, ssr, fog); mDescriptorSetLayout[index] = { engine.getDescriptorSetLayoutFactory(), engine.getDriverApi(), @@ -183,13 +183,13 @@ void ColorPassDescriptorSet::prepareCamera(FEngine& engine, const CameraInfo& ca s.clipControl = engine.getDriverApi().getClipSpaceParams(); } -void ColorPassDescriptorSet::prepareLodBias(float bias, float2 derivativesScale) noexcept { +void ColorPassDescriptorSet::prepareLodBias(float const bias, float2 const derivativesScale) noexcept { auto& s = mUniforms.edit(); s.lodBias = bias; s.derivativesScale = derivativesScale; } -void ColorPassDescriptorSet::prepareExposure(float ev100) noexcept { +void ColorPassDescriptorSet::prepareExposure(float const ev100) noexcept { const float exposure = Exposure::exposure(ev100); auto& s = mUniforms.edit(); s.exposure = exposure; @@ -209,7 +209,7 @@ void ColorPassDescriptorSet::prepareViewport( s.logicalViewportOffset = -logical.xy / logical.zw; } -void ColorPassDescriptorSet::prepareTime(FEngine& engine, math::float4 const& userTime) noexcept { +void ColorPassDescriptorSet::prepareTime(FEngine& engine, float4 const& userTime) noexcept { auto& s = mUniforms.edit(); const uint64_t oneSecondRemainder = engine.getEngineTime().count() % 1000000000; const float fraction = float(double(oneSecondRemainder) / 1000000000.0); @@ -228,7 +228,7 @@ void ColorPassDescriptorSet::prepareTemporalNoise(FEngine& engine, void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& cameraInfo, mat4 const& userWorldFromFog, FogOptions const& options, FIndirectLight const* ibl) noexcept { - auto packHalf2x16 = [](math::half2 v) -> uint32_t { + auto packHalf2x16 = [](half2 v) -> uint32_t { short2 s; memcpy(&s[0], &v[0], sizeof(s)); return s.y << 16 | s.x; @@ -262,7 +262,7 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer Handle fogColorTextureHandle; if (options.skyColor) { fogColorTextureHandle = downcast(options.skyColor)->getHwHandleForSampling(); - math::half2 const minMaxMip{ 0.0f, float(options.skyColor->getLevels()) - 1.0f }; + half2 const minMaxMip{ 0.0f, float(options.skyColor->getLevels()) - 1.0f }; s.fogMinMaxMip = packHalf2x16(minMaxMip); s.fogOneOverFarMinusNear = 1.0f / (cameraInfo.zf - cameraInfo.zn); s.fogNearOverFarMinusNear = cameraInfo.zn / (cameraInfo.zf - cameraInfo.zn); @@ -276,7 +276,7 @@ void ColorPassDescriptorSet::prepareFog(FEngine& engine, const CameraInfo& camer // improves the effect overall. fogColorTextureHandle = ibl->getReflectionHwHandle(); float const levelCount = float(ibl->getLevelCount()); - math::half2 const minMaxMip{ levelCount - 2.0f, levelCount - 1.0f }; + half2 const minMaxMip{ levelCount - 2.0f, levelCount - 1.0f }; s.fogMinMaxMip = packHalf2x16(minMaxMip); s.fogOneOverFarMinusNear = 1.0f / (cameraInfo.zf - cameraInfo.zn); s.fogNearOverFarMinusNear = cameraInfo.zn / (cameraInfo.zf - cameraInfo.zn); @@ -322,12 +322,12 @@ void ColorPassDescriptorSet::prepareSSAO(Handle ssao, s.aoBentNormals = options.enabled && options.bentNormals ? 1.0f : 0.0f; } -void ColorPassDescriptorSet::prepareBlending(bool needsAlphaChannel) noexcept { +void ColorPassDescriptorSet::prepareBlending(bool const needsAlphaChannel) noexcept { mUniforms.edit().needsAlphaChannel = needsAlphaChannel ? 1.0f : 0.0f; } void ColorPassDescriptorSet::prepareMaterialGlobals( - std::array const& materialGlobals) noexcept { + std::array const& materialGlobals) noexcept { mUniforms.edit().custom[0] = materialGlobals[0]; mUniforms.edit().custom[1] = materialGlobals[1]; mUniforms.edit().custom[2] = materialGlobals[2]; @@ -335,8 +335,8 @@ void ColorPassDescriptorSet::prepareMaterialGlobals( } void ColorPassDescriptorSet::prepareSSR(Handle ssr, - bool disableSSR, - float refractionLodOffset, + bool const disableSSR, + float const refractionLodOffset, ScreenSpaceReflectionsOptions const& ssrOptions) noexcept { setSampler(+PerViewBindingPoints::SSR, ssr, { @@ -350,8 +350,8 @@ void ColorPassDescriptorSet::prepareSSR(Handle ssr, } void ColorPassDescriptorSet::prepareHistorySSR(Handle ssr, - math::mat4f const& historyProjection, - math::mat4f const& uvFromViewMatrix, + mat4f const& historyProjection, + mat4f const& uvFromViewMatrix, ScreenSpaceReflectionsOptions const& ssrOptions) noexcept { setSampler(+PerViewBindingPoints::SSR, ssr, { @@ -376,7 +376,7 @@ void ColorPassDescriptorSet::prepareStructure(Handle structure) noexc void ColorPassDescriptorSet::prepareDirectionalLight(FEngine& engine, float exposure, float3 const& sceneSpaceDirection, - ColorPassDescriptorSet::LightManagerInstance directionalLight) noexcept { + LightManagerInstance directionalLight) noexcept { FLightManager const& lcm = engine.getLightManager(); auto& s = mUniforms.edit(); @@ -416,14 +416,14 @@ void ColorPassDescriptorSet::prepareDirectionalLight(FEngine& engine, } void ColorPassDescriptorSet::prepareAmbientLight(FEngine& engine, FIndirectLight const& ibl, - float intensity, float exposure) noexcept { + float const intensity, float const exposure) noexcept { auto& s = mUniforms.edit(); // Set up uniforms and sampler for the IBL, guaranteed to be non-null at this point. float const iblRoughnessOneLevel = float(ibl.getLevelCount() - 1); s.iblRoughnessOneLevel = iblRoughnessOneLevel; s.iblLuminance = intensity * exposure; - std::transform(ibl.getSH(), ibl.getSH() + 9, s.iblSH, [](float3 v) { + std::transform(ibl.getSH(), ibl.getSH() + 9, s.iblSH, [](float3 const v) { return float4(v, 0.0f); }); @@ -447,7 +447,7 @@ void ColorPassDescriptorSet::prepareDynamicLights(Froxelizer& froxelizer) noexce s.lightFarAttenuationParams = 0.5f * float2{ 10.0f, 10.0f / (f * f) }; } -void ColorPassDescriptorSet::prepareShadowMapping(backend::BufferObjectHandle shadowUniforms, bool highPrecision) noexcept { +void ColorPassDescriptorSet::prepareShadowMapping(BufferObjectHandle shadowUniforms, bool const highPrecision) noexcept { auto& s = mUniforms.edit(); constexpr float low = 5.54f; // ~ std::log(std::numeric_limits::max()) * 0.5f; constexpr float high = 42.0f; // ~ std::log(std::numeric_limits::max()) * 0.5f; @@ -483,7 +483,7 @@ void ColorPassDescriptorSet::prepareShadowVSM(Handle texture, s.vsmExponent = options.highPrecision ? high : low; s.vsmDepthScale = options.minVarianceScale * 0.01f * s.vsmExponent; s.vsmLightBleedReduction = options.lightBleedReduction; - ColorPassDescriptorSet::prepareShadowSampling(s, shadowMappingUniforms); + prepareShadowSampling(s, shadowMappingUniforms); } void ColorPassDescriptorSet::prepareShadowPCF(Handle texture, @@ -497,7 +497,7 @@ void ColorPassDescriptorSet::prepareShadowPCF(Handle texture, }); auto& s = mUniforms.edit(); s.shadowSamplingType = SHADOW_SAMPLING_RUNTIME_PCF; - ColorPassDescriptorSet::prepareShadowSampling(s, shadowMappingUniforms); + prepareShadowSampling(s, shadowMappingUniforms); } void ColorPassDescriptorSet::prepareShadowDPCF(Handle texture, @@ -507,7 +507,7 @@ void ColorPassDescriptorSet::prepareShadowDPCF(Handle texture, auto& s = mUniforms.edit(); s.shadowSamplingType = SHADOW_SAMPLING_RUNTIME_DPCF; s.shadowPenumbraRatioScale = options.penumbraRatioScale; - ColorPassDescriptorSet::prepareShadowSampling(s, shadowMappingUniforms); + prepareShadowSampling(s, shadowMappingUniforms); } void ColorPassDescriptorSet::prepareShadowPCSS(Handle texture, @@ -517,7 +517,7 @@ void ColorPassDescriptorSet::prepareShadowPCSS(Handle texture, auto& s = mUniforms.edit(); s.shadowSamplingType = SHADOW_SAMPLING_RUNTIME_PCSS; s.shadowPenumbraRatioScale = options.penumbraRatioScale; - ColorPassDescriptorSet::prepareShadowSampling(s, shadowMappingUniforms); + prepareShadowSampling(s, shadowMappingUniforms); } void ColorPassDescriptorSet::prepareShadowPCFDebug(Handle texture, @@ -528,10 +528,10 @@ void ColorPassDescriptorSet::prepareShadowPCFDebug(Handle texture, }); auto& s = mUniforms.edit(); s.shadowSamplingType = SHADOW_SAMPLING_RUNTIME_PCF; - ColorPassDescriptorSet::prepareShadowSampling(s, shadowMappingUniforms); + prepareShadowSampling(s, shadowMappingUniforms); } -void ColorPassDescriptorSet::commit(backend::DriverApi& driver) noexcept { +void ColorPassDescriptorSet::commit(DriverApi& driver) noexcept { if (mUniforms.isDirty()) { driver.updateBufferObject(mUniforms.getUboHandle(), mUniforms.toBufferDescriptor(driver), 0); @@ -552,8 +552,8 @@ void ColorPassDescriptorSet::unbindSamplers(DriverApi&) noexcept { setSampler(+PerViewBindingPoints::SSR, {}, {}); } -void ColorPassDescriptorSet::setSampler(backend::descriptor_binding_t binding, - TextureHandle th, SamplerParams params) noexcept { +void ColorPassDescriptorSet::setSampler(descriptor_binding_t const binding, + TextureHandle th, SamplerParams const params) noexcept { for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) { auto samplers = mDescriptorSetLayout[i].getSamplerDescriptors(); if (samplers[binding]) { @@ -562,8 +562,8 @@ void ColorPassDescriptorSet::setSampler(backend::descriptor_binding_t binding, } } -void ColorPassDescriptorSet::setBuffer(backend::descriptor_binding_t binding, - BufferObjectHandle boh, uint32_t offset, uint32_t size) noexcept { +void ColorPassDescriptorSet::setBuffer(descriptor_binding_t const binding, + BufferObjectHandle boh, uint32_t const offset, uint32_t const size) noexcept { for (size_t i = 0; i < DESCRIPTOR_LAYOUT_COUNT; i++) { auto ubos = mDescriptorSetLayout[i].getUniformBufferDescriptors(); if (ubos[binding]) { diff --git a/filament/src/ds/ColorPassDescriptorSet.h b/filament/src/ds/ColorPassDescriptorSet.h index 81b4fc28ea..db0bfa2217 100644 --- a/filament/src/ds/ColorPassDescriptorSet.h +++ b/filament/src/ds/ColorPassDescriptorSet.h @@ -96,8 +96,8 @@ public: * Non-zero when we have guard bands. */ void prepareViewport( - const filament::Viewport& physicalViewport, - const filament::Viewport& logicalViewport) noexcept; + const Viewport& physicalViewport, + const Viewport& logicalViewport) noexcept; void prepareTime(FEngine& engine, math::float4 const& userTime) noexcept; void prepareTemporalNoise(FEngine& engine, TemporalAntiAliasingOptions const& options) noexcept; @@ -155,7 +155,7 @@ public: void unbindSamplers(backend::DriverApi& driver) noexcept; // bind this UBO - void bind(backend::DriverApi& driver, uint8_t index) const noexcept { + void bind(backend::DriverApi& driver, uint8_t const index) const noexcept { mDescriptorSet[index].bind(driver, DescriptorSetBindingPoints::PER_VIEW); } diff --git a/filament/src/ds/DescriptorSet.cpp b/filament/src/ds/DescriptorSet.cpp index caa433ad46..01348dc1d5 100644 --- a/filament/src/ds/DescriptorSet.cpp +++ b/filament/src/ds/DescriptorSet.cpp @@ -99,11 +99,11 @@ void DescriptorSet::commitSlow(DescriptorSetLayout const& layout, }); } -void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints set) const noexcept { +void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints const set) const noexcept { bind(driver, set, {}); } -void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints set, +void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints const set, backend::DescriptorSetOffsetArray dynamicOffsets) const noexcept { // TODO: on debug check that dynamicOffsets is large enough @@ -114,7 +114,7 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints // build. // assert_invariant(mDirty.none()); if (mDirty.any() && !mSetAfterCommitWarning) { - mDirty.forEachSetBit([&](uint8_t binding) { + mDirty.forEachSetBit([&](uint8_t const binding) { utils::slog.w << "Descriptor set (handle=" << mDescriptorSetHandle.getId() << ") binding=" << (int) binding << " was set between begin/endRenderPass" << utils::io::endl; @@ -125,8 +125,8 @@ void DescriptorSet::bind(FEngine::DriverApi& driver, DescriptorSetBindingPoints } void DescriptorSet::setBuffer( - backend::descriptor_binding_t binding, - backend::Handle boh, uint32_t offset, uint32_t size) noexcept { + backend::descriptor_binding_t const binding, + backend::Handle boh, uint32_t const offset, uint32_t const size) noexcept { // TODO: validate it's the right kind of descriptor if (mDescriptors[binding].buffer.boh != boh || mDescriptors[binding].buffer.size != size) { // we don't set the dirty bit if only offset changes @@ -137,8 +137,8 @@ void DescriptorSet::setBuffer( } void DescriptorSet::setSampler( - backend::descriptor_binding_t binding, - backend::Handle th, backend::SamplerParams params) noexcept { + backend::descriptor_binding_t const binding, + backend::Handle th, backend::SamplerParams const params) noexcept { // TODO: validate it's the right kind of descriptor if (mDescriptors[binding].texture.th != th || mDescriptors[binding].texture.params != params) { mDirty.set(binding); diff --git a/filament/src/ds/DescriptorSetLayout.h b/filament/src/ds/DescriptorSetLayout.h index c995860219..44b5d47850 100644 --- a/filament/src/ds/DescriptorSetLayout.h +++ b/filament/src/ds/DescriptorSetLayout.h @@ -56,7 +56,7 @@ public: return mMaxDescriptorBinding; } - bool isSampler(backend::descriptor_binding_t binding) const noexcept { + bool isSampler(backend::descriptor_binding_t const binding) const noexcept { return mSamplers[binding]; } diff --git a/filament/src/ds/PostProcessDescriptorSet.cpp b/filament/src/ds/PostProcessDescriptorSet.cpp index 0980de21f6..8ed72e79a4 100644 --- a/filament/src/ds/PostProcessDescriptorSet.cpp +++ b/filament/src/ds/PostProcessDescriptorSet.cpp @@ -59,7 +59,7 @@ void PostProcessDescriptorSet::setFrameUniforms(DriverApi& driver, mDescriptorSet.commit(mDescriptorSetLayout, driver); } -void PostProcessDescriptorSet::bind(backend::DriverApi& driver) noexcept { +void PostProcessDescriptorSet::bind(DriverApi& driver) noexcept { mDescriptorSet.bind(driver, DescriptorSetBindingPoints::PER_VIEW); } diff --git a/filament/src/ds/ShadowMapDescriptorSet.cpp b/filament/src/ds/ShadowMapDescriptorSet.cpp index da7f1c777c..e2cceecce9 100644 --- a/filament/src/ds/ShadowMapDescriptorSet.cpp +++ b/filament/src/ds/ShadowMapDescriptorSet.cpp @@ -61,7 +61,7 @@ PerViewUib& ShadowMapDescriptorSet::edit(Transaction const& transaction) noexcep } void ShadowMapDescriptorSet::prepareCamera(Transaction const& transaction, - backend::DriverApi& driver, const CameraInfo& camera) noexcept { + DriverApi& driver, const CameraInfo& camera) noexcept { mat4f const& viewFromWorld = camera.view; mat4f const& worldFromView = camera.model; mat4f const& clipFromView = camera.projection; @@ -88,7 +88,7 @@ void ShadowMapDescriptorSet::prepareCamera(Transaction const& transaction, s.clipControl = driver.getClipSpaceParams(); } -void ShadowMapDescriptorSet::prepareLodBias(Transaction const& transaction, float bias) noexcept { +void ShadowMapDescriptorSet::prepareLodBias(Transaction const& transaction, float const bias) noexcept { auto& s = edit(transaction); s.lodBias = bias; } @@ -103,7 +103,7 @@ void ShadowMapDescriptorSet::prepareViewport(Transaction const& transaction, } void ShadowMapDescriptorSet::prepareTime(Transaction const& transaction, - FEngine const& engine, math::float4 const& userTime) noexcept { + FEngine const& engine, float4 const& userTime) noexcept { auto& s = edit(transaction); const uint64_t oneSecondRemainder = engine.getEngineTime().count() % 1'000'000'000; const float fraction = float(double(oneSecondRemainder) / 1'000'000'000.0); @@ -112,14 +112,14 @@ void ShadowMapDescriptorSet::prepareTime(Transaction const& transaction, } void ShadowMapDescriptorSet::prepareShadowMapping(Transaction const& transaction, - bool highPrecision) noexcept { + bool const highPrecision) noexcept { auto& s = edit(transaction); constexpr float low = 5.54f; // ~ std::log(std::numeric_limits::max()) * 0.5f; constexpr float high = 42.0f; // ~ std::log(std::numeric_limits::max()) * 0.5f; s.vsmExponent = highPrecision ? high : low; } -ShadowMapDescriptorSet::Transaction ShadowMapDescriptorSet::open(backend::DriverApi& driver) noexcept { +ShadowMapDescriptorSet::Transaction ShadowMapDescriptorSet::open(DriverApi& driver) noexcept { Transaction transaction; // TODO: use out-of-line buffer if too large transaction.uniforms = (PerViewUib *)driver.allocate(sizeof(PerViewUib), 16); @@ -128,14 +128,14 @@ ShadowMapDescriptorSet::Transaction ShadowMapDescriptorSet::open(backend::Driver } void ShadowMapDescriptorSet::commit(Transaction& transaction, - FEngine& engine, backend::DriverApi& driver) noexcept { + FEngine& engine, DriverApi& driver) noexcept { driver.updateBufferObject(mUniformBufferHandle, { transaction.uniforms, sizeof(PerViewUib) }, 0); mDescriptorSet.commit(engine.getPerViewDescriptorSetLayoutDepthVariant(), driver); transaction.uniforms = nullptr; } -void ShadowMapDescriptorSet::bind(backend::DriverApi& driver) noexcept { +void ShadowMapDescriptorSet::bind(DriverApi& driver) noexcept { mDescriptorSet.bind(driver, DescriptorSetBindingPoints::PER_VIEW); } diff --git a/filament/src/ds/SsrPassDescriptorSet.cpp b/filament/src/ds/SsrPassDescriptorSet.cpp index 86e83436d9..e20a6bbfab 100644 --- a/filament/src/ds/SsrPassDescriptorSet.cpp +++ b/filament/src/ds/SsrPassDescriptorSet.cpp @@ -67,8 +67,8 @@ void SsrPassDescriptorSet::setFrameUniforms(TypedUniformBuffer& unif } void SsrPassDescriptorSet::prepareHistorySSR(Handle ssr, - math::mat4f const& historyProjection, - math::mat4f const& uvFromViewMatrix, + mat4f const& historyProjection, + mat4f const& uvFromViewMatrix, ScreenSpaceReflectionsOptions const& ssrOptions) noexcept { mDescriptorSet.setSampler(+PerViewBindingPoints::SSR, ssr, { @@ -101,7 +101,7 @@ void SsrPassDescriptorSet::commit(FEngine& engine) noexcept { mDescriptorSet.commit(engine.getPerViewDescriptorSetLayoutSsrVariant(), driver); } -void SsrPassDescriptorSet::bind(backend::DriverApi& driver) noexcept { +void SsrPassDescriptorSet::bind(DriverApi& driver) noexcept { mDescriptorSet.bind(driver, DescriptorSetBindingPoints::PER_VIEW); } diff --git a/filament/src/ds/TypedBuffer.h b/filament/src/ds/TypedBuffer.h index ea55b7c43d..22f245931a 100644 --- a/filament/src/ds/TypedBuffer.h +++ b/filament/src/ds/TypedBuffer.h @@ -56,7 +56,7 @@ public: // copy the UBO data and cleans the dirty bits backend::BufferDescriptor toBufferDescriptor( - backend::DriverApi& driver, size_t offset, size_t size) const noexcept { + backend::DriverApi& driver, size_t const offset, size_t const size) const noexcept { backend::BufferDescriptor p; p.size = size; p.buffer = driver.allocate(p.size); // TODO: use out-of-line buffer if too large diff --git a/filament/src/fg/Blackboard.cpp b/filament/src/fg/Blackboard.cpp index e2044a8079..62853cb174 100644 --- a/filament/src/fg/Blackboard.cpp +++ b/filament/src/fg/Blackboard.cpp @@ -24,7 +24,7 @@ Blackboard::Blackboard() noexcept = default; Blackboard::~Blackboard() noexcept = default; -FrameGraphHandle Blackboard::getHandle(std::string_view name) const noexcept { +FrameGraphHandle Blackboard::getHandle(std::string_view const name) const noexcept { auto it = mMap.find(name); if (it != mMap.end()) { return it->second; @@ -32,17 +32,17 @@ FrameGraphHandle Blackboard::getHandle(std::string_view name) const noexcept { return {}; } -FrameGraphHandle& Blackboard::operator [](std::string_view name) noexcept { +FrameGraphHandle& Blackboard::operator [](std::string_view const name) noexcept { auto[pos, _] = mMap.insert_or_assign(name, FrameGraphHandle{}); return pos->second; } -void Blackboard::put(std::string_view name, FrameGraphHandle handle) noexcept { +void Blackboard::put(std::string_view const name, FrameGraphHandle const handle) noexcept { operator[](name) = handle; } -void Blackboard::remove(std::string_view name) noexcept { +void Blackboard::remove(std::string_view const name) noexcept { mMap.erase(name); } diff --git a/filament/src/fg/DependencyGraph.cpp b/filament/src/fg/DependencyGraph.cpp index c018bcf982..fbcbf97886 100644 --- a/filament/src/fg/DependencyGraph.cpp +++ b/filament/src/fg/DependencyGraph.cpp @@ -34,7 +34,7 @@ uint32_t DependencyGraph::generateNodeId() noexcept { return mNodes.size(); } -void DependencyGraph::registerNode(Node* node, NodeID id) noexcept { +void DependencyGraph::registerNode(Node* node, NodeID const id) noexcept { // Node* is not fully constructed here assert_invariant(id == mNodes.size()); @@ -46,14 +46,14 @@ void DependencyGraph::registerNode(Node* node, NodeID id) noexcept { nodes.push_back(node); } -bool DependencyGraph::isEdgeValid(DependencyGraph::Edge const* edge) const noexcept { +bool DependencyGraph::isEdgeValid(Edge const* edge) const noexcept { auto& nodes = mNodes; Node const* from = nodes[edge->from]; Node const* to = nodes[edge->to]; return !from->isCulled() && !to->isCulled(); } -void DependencyGraph::link(DependencyGraph::Edge* edge) noexcept { +void DependencyGraph::link(Edge* edge) noexcept { // here we manually grow the fixed-size vector EdgeContainer& edges = mEdges; if (UTILS_UNLIKELY(edges.capacity() == edges.size())) { @@ -72,7 +72,7 @@ DependencyGraph::NodeContainer const& DependencyGraph::getNodes() const noexcept } DependencyGraph::EdgeContainer DependencyGraph::getIncomingEdges( - DependencyGraph::Node const* node) const noexcept { + Node const* node) const noexcept { // TODO: we might need something more efficient auto result = EdgeContainer::with_capacity(mEdges.size()); NodeID const nodeId = node->getId(); @@ -83,7 +83,7 @@ DependencyGraph::EdgeContainer DependencyGraph::getIncomingEdges( } DependencyGraph::EdgeContainer DependencyGraph::getOutgoingEdges( - DependencyGraph::Node const* node) const noexcept { + Node const* node) const noexcept { // TODO: we might need something more efficient auto result = EdgeContainer::with_capacity(mEdges.size()); NodeID const nodeId = node->getId(); @@ -93,11 +93,11 @@ DependencyGraph::EdgeContainer DependencyGraph::getOutgoingEdges( return result; } -DependencyGraph::Node const* DependencyGraph::getNode(DependencyGraph::NodeID id) const noexcept { +DependencyGraph::Node const* DependencyGraph::getNode(NodeID const id) const noexcept { return mNodes[id]; } -DependencyGraph::Node* DependencyGraph::getNode(DependencyGraph::NodeID id) noexcept { +DependencyGraph::Node* DependencyGraph::getNode(NodeID const id) noexcept { return mNodes[id]; } @@ -197,7 +197,7 @@ bool DependencyGraph::isAcyclic() const noexcept { DependencyGraph graph; graph.mEdges = mEdges; graph.mNodes = mNodes; - return DependencyGraph::isAcyclicInternal(graph); + return isAcyclicInternal(graph); #else return true; #endif diff --git a/filament/src/fg/FrameGraph.cpp b/filament/src/fg/FrameGraph.cpp index d7c2a6f07e..6ccd895766 100644 --- a/filament/src/fg/FrameGraph.cpp +++ b/filament/src/fg/FrameGraph.cpp @@ -52,7 +52,7 @@ void FrameGraph::Builder::sideEffect() noexcept { mPassNode->makeTarget(); } -const char* FrameGraph::Builder::getName(FrameGraphHandle handle) const noexcept { +const char* FrameGraph::Builder::getName(FrameGraphHandle const handle) const noexcept { return mFrameGraph.getResource(handle)->name; } @@ -74,7 +74,7 @@ FrameGraphId FrameGraph::Builder::declareRenderPass( // ------------------------------------------------------------------------------------------------ -FrameGraph::FrameGraph(ResourceAllocatorInterface& resourceAllocator, Mode mode) +FrameGraph::FrameGraph(ResourceAllocatorInterface& resourceAllocator, Mode const mode) : mResourceAllocator(resourceAllocator), mArena("FrameGraph Arena", 262144), mMode(mode), @@ -232,7 +232,7 @@ void FrameGraph::execute(backend::DriverApi& driver) noexcept { driver.popGroupMarker(); } -void FrameGraph::addPresentPass(const std::function& setup) noexcept { +void FrameGraph::addPresentPass(const std::function& setup) noexcept { PresentPassNode* node = mArena.make(*this); mPassNodes.push_back(node); Builder builder(*this, node); @@ -290,7 +290,7 @@ FrameGraphHandle FrameGraph::addSubResourceInternal(FrameGraphHandle parent, return handle; } -FrameGraphHandle FrameGraph::readInternal(FrameGraphHandle handle, PassNode* passNode, +FrameGraphHandle FrameGraph::readInternal(FrameGraphHandle const handle, PassNode* passNode, const std::function& connect) { assertValid(handle); @@ -397,8 +397,8 @@ FrameGraphHandle FrameGraph::writeInternal(FrameGraphHandle handle, PassNode* pa return {}; } -FrameGraphHandle FrameGraph::forwardResourceInternal(FrameGraphHandle resourceHandle, - FrameGraphHandle replaceResourceHandle) { +FrameGraphHandle FrameGraph::forwardResourceInternal(FrameGraphHandle const resourceHandle, + FrameGraphHandle const replaceResourceHandle) { assertValid(resourceHandle); @@ -449,7 +449,7 @@ FrameGraphId FrameGraph::import(char const* name, return FrameGraphId(addResourceInternal(vresource)); } -bool FrameGraph::isValid(FrameGraphHandle handle) const { +bool FrameGraph::isValid(FrameGraphHandle const handle) const { // Code below is written this way so that we can set breakpoints easily. if (!handle.isInitialized()) { return false; @@ -461,7 +461,7 @@ bool FrameGraph::isValid(FrameGraphHandle handle) const { return true; } -void FrameGraph::assertValid(FrameGraphHandle handle) const { +void FrameGraph::assertValid(FrameGraphHandle const handle) const { FILAMENT_CHECK_PRECONDITION(isValid(handle)) << "Resource handle is invalid or uninitialized {id=" << (int)handle.index << ", version=" << (int)handle.version << "}"; diff --git a/filament/src/fg/FrameGraph.h b/filament/src/fg/FrameGraph.h index 0e01379a01..2311e68967 100644 --- a/filament/src/fg/FrameGraph.h +++ b/filament/src/fg/FrameGraph.h @@ -204,7 +204,7 @@ public: * @return A new handle to the FrameGraphTexture. * The input handle is no-longer valid. */ - FrameGraphId sample(FrameGraphId input) { + FrameGraphId sample(FrameGraphId const input) { return read(input, FrameGraphTexture::Usage::SAMPLEABLE); } @@ -484,36 +484,36 @@ private: FrameGraphId write(PassNode* passNode, FrameGraphId input, typename RESOURCE::Usage usage); - ResourceSlot& getResourceSlot(FrameGraphHandle handle) noexcept { + ResourceSlot& getResourceSlot(FrameGraphHandle const handle) noexcept { assert_invariant((size_t)handle.index < mResourceSlots.size()); assert_invariant((size_t)mResourceSlots[handle.index].rid < mResources.size()); assert_invariant((size_t)mResourceSlots[handle.index].nid < mResourceNodes.size()); return mResourceSlots[handle.index]; } - ResourceSlot const& getResourceSlot(FrameGraphHandle handle) const noexcept { + ResourceSlot const& getResourceSlot(FrameGraphHandle const handle) const noexcept { return const_cast(this)->getResourceSlot(handle); } - VirtualResource* getResource(FrameGraphHandle handle) noexcept { + VirtualResource* getResource(FrameGraphHandle const handle) noexcept { assert_invariant(handle.isInitialized()); ResourceSlot const& slot = getResourceSlot(handle); assert_invariant((size_t)slot.rid < mResources.size()); return mResources[slot.rid]; } - ResourceNode* getActiveResourceNode(FrameGraphHandle handle) noexcept { + ResourceNode* getActiveResourceNode(FrameGraphHandle const handle) noexcept { assert_invariant(handle); ResourceSlot const& slot = getResourceSlot(handle); assert_invariant((size_t)slot.nid < mResourceNodes.size()); return mResourceNodes[slot.nid]; } - VirtualResource const* getResource(FrameGraphHandle handle) const noexcept { + VirtualResource const* getResource(FrameGraphHandle const handle) const noexcept { return const_cast(this)->getResource(handle); } - ResourceNode const* getResourceNode(FrameGraphHandle handle) const noexcept { + ResourceNode const* getResourceNode(FrameGraphHandle const handle) const noexcept { return const_cast(this)->getActiveResourceNode(handle); } @@ -560,7 +560,7 @@ FrameGraphPass& FrameGraph::addPass(char const* name, Setup setup) { template void FrameGraph::addTrivialSideEffectPass(char const* name, Execute&& execute) { - addPass(name, [](FrameGraph::Builder& builder, auto&) { builder.sideEffect(); }, + addPass(name, [](Builder& builder, auto&) { builder.sideEffect(); }, [execute](FrameGraphResources const&, auto const&, backend::DriverApi& driver) { execute(driver); }); diff --git a/filament/src/fg/FrameGraphId.h b/filament/src/fg/FrameGraphId.h index e5b8fc8d65..eb89174ad8 100644 --- a/filament/src/fg/FrameGraphId.h +++ b/filament/src/fg/FrameGraphId.h @@ -50,7 +50,7 @@ private: // private ctor -- this cannot be constructed by users FrameGraphHandle() noexcept = default; - explicit FrameGraphHandle(Index index) noexcept : index(index) {} + explicit FrameGraphHandle(Index const index) noexcept : index(index) {} // index to the resource handle static constexpr uint16_t UNINITIALIZED = std::numeric_limits::max(); @@ -87,7 +87,7 @@ class FrameGraphId : public FrameGraphHandle { public: using FrameGraphHandle::FrameGraphHandle; FrameGraphId() noexcept = default; - explicit FrameGraphId(FrameGraphHandle r) : FrameGraphHandle(r) { } + explicit FrameGraphId(FrameGraphHandle const r) : FrameGraphHandle(r) { } }; } // namespace filament diff --git a/filament/src/fg/FrameGraphResources.cpp b/filament/src/fg/FrameGraphResources.cpp index a3b04c3f74..23444393f0 100644 --- a/filament/src/fg/FrameGraphResources.cpp +++ b/filament/src/fg/FrameGraphResources.cpp @@ -33,7 +33,7 @@ const char* FrameGraphResources::getPassName() const noexcept { // fails, it has to assert (or throw), it can't return for e.g. a nullptr, because the public // API doesn't return pointers. // We still use FILAMENT_CHECK_PRECONDITION() because these failures are due to post conditions not met. -VirtualResource& FrameGraphResources::getResource(FrameGraphHandle handle) const { +VirtualResource& FrameGraphResources::getResource(FrameGraphHandle const handle) const { FILAMENT_CHECK_PRECONDITION(handle) << "Uninitialized handle when using FrameGraphResources."; VirtualResource* const resource = mFrameGraph.getResource(handle); @@ -50,7 +50,7 @@ VirtualResource& FrameGraphResources::getResource(FrameGraphHandle handle) const return *resource; } -FrameGraphResources::RenderPassInfo FrameGraphResources::getRenderPassInfo(uint32_t id) const { +FrameGraphResources::RenderPassInfo FrameGraphResources::getRenderPassInfo(uint32_t const id) const { // this cast is safe because this can only be called from a RenderPassNode RenderPassNode const& renderPassNode = static_cast(mPassNode); RenderPassNode::RenderPassData const* pRenderPassData = renderPassNode.getRenderPassData(id); diff --git a/filament/src/fg/FrameGraphResources.h b/filament/src/fg/FrameGraphResources.h index 9bc428f1cc..bef469c50b 100644 --- a/filament/src/fg/FrameGraphResources.h +++ b/filament/src/fg/FrameGraphResources.h @@ -115,7 +115,7 @@ public: * @param handle to a FrameGraphTexture * @return backend concrete Texture handle */ - backend::Handle getTexture(FrameGraphId handle) const { + backend::Handle getTexture(FrameGraphId const handle) const { return get(handle).handle; } diff --git a/filament/src/fg/FrameGraphTexture.cpp b/filament/src/fg/FrameGraphTexture.cpp index 4785867a43..03f29ad1f2 100644 --- a/filament/src/fg/FrameGraphTexture.cpp +++ b/filament/src/fg/FrameGraphTexture.cpp @@ -23,11 +23,11 @@ namespace filament { void FrameGraphTexture::create(ResourceAllocatorInterface& resourceAllocator, const char* name, - FrameGraphTexture::Descriptor const& descriptor, FrameGraphTexture::Usage usage, - bool useProtectedMemory) noexcept { + Descriptor const& descriptor, Usage usage, + bool const useProtectedMemory) noexcept { if (useProtectedMemory) { // FIXME: I think we should restrict this to attachments and blit destinations only - usage |= FrameGraphTexture::Usage::PROTECTED; + usage |= Usage::PROTECTED; } std::array swizzle = { descriptor.swizzle.r, diff --git a/filament/src/fg/PassNode.cpp b/filament/src/fg/PassNode.cpp index 51eb06645d..caed82aff9 100644 --- a/filament/src/fg/PassNode.cpp +++ b/filament/src/fg/PassNode.cpp @@ -30,7 +30,7 @@ using namespace filament::backend; namespace filament { PassNode::PassNode(FrameGraph& fg) noexcept - : DependencyGraph::Node(fg.getGraph()), + : Node(fg.getGraph()), mFrameGraph(fg), devirtualize(fg.getArena()), destroy(fg.getArena()) { @@ -44,7 +44,7 @@ utils::CString PassNode::graphvizifyEdgeColor() const noexcept { return utils::CString{"red"}; } -void PassNode::registerResource(FrameGraphHandle resourceHandle) noexcept { +void PassNode::registerResource(FrameGraphHandle const resourceHandle) noexcept { VirtualResource* resource = mFrameGraph.getResource(resourceHandle); resource->neededByPass(this); mDeclaredHandles.insert(resourceHandle.index); @@ -288,7 +288,7 @@ void RenderPassNode::RenderPassData::destroy( } } -RenderPassNode::RenderPassData const* RenderPassNode::getRenderPassData(uint32_t id) const noexcept { +RenderPassNode::RenderPassData const* RenderPassNode::getRenderPassData(uint32_t const id) const noexcept { return id < mRenderTargetData.size() ? &mRenderTargetData[id] : nullptr; } diff --git a/filament/src/fg/Resource.cpp b/filament/src/fg/Resource.cpp index df34011424..be974a0def 100644 --- a/filament/src/fg/Resource.cpp +++ b/filament/src/fg/Resource.cpp @@ -95,7 +95,7 @@ ImportedRenderTarget::ImportedRenderTarget(char const* resourceName, } UTILS_NOINLINE -void ImportedRenderTarget::assertConnect(FrameGraphTexture::Usage u) { +void ImportedRenderTarget::assertConnect(FrameGraphTexture::Usage const u) { constexpr auto ANY_ATTACHMENT = FrameGraphTexture::Usage::COLOR_ATTACHMENT | FrameGraphTexture::Usage::DEPTH_ATTACHMENT | FrameGraphTexture::Usage::STENCIL_ATTACHMENT; @@ -106,21 +106,21 @@ void ImportedRenderTarget::assertConnect(FrameGraphTexture::Usage u) { } bool ImportedRenderTarget::connect(DependencyGraph& graph, PassNode* passNode, - ResourceNode* resourceNode, TextureUsage u) { + ResourceNode* resourceNode, TextureUsage const u) { // pass Node to resource Node edge (a write to) assertConnect(u); return Resource::connect(graph, passNode, resourceNode, u); } bool ImportedRenderTarget::connect(DependencyGraph& graph, ResourceNode* resourceNode, - PassNode* passNode, TextureUsage u) { + PassNode* passNode, TextureUsage const u) { // resource Node to pass Node edge (a read from) assertConnect(u); return Resource::connect(graph, resourceNode, passNode, u); } FrameGraphTexture::Usage ImportedRenderTarget::usageFromAttachmentsFlags( - TargetBufferFlags attachments) noexcept { + TargetBufferFlags const attachments) noexcept { if (any(attachments & TargetBufferFlags::COLOR_ALL)) return FrameGraphTexture::Usage::COLOR_ATTACHMENT; diff --git a/filament/src/fg/ResourceNode.cpp b/filament/src/fg/ResourceNode.cpp index 31b956f642..2b4cf2af66 100644 --- a/filament/src/fg/ResourceNode.cpp +++ b/filament/src/fg/ResourceNode.cpp @@ -20,8 +20,8 @@ namespace filament { -ResourceNode::ResourceNode(FrameGraph& fg, FrameGraphHandle h, FrameGraphHandle parent) noexcept - : DependencyGraph::Node(fg.getGraph()), +ResourceNode::ResourceNode(FrameGraph& fg, FrameGraphHandle const h, FrameGraphHandle const parent) noexcept + : Node(fg.getGraph()), resourceHandle(h), mFrameGraph(fg), mReaderPasses(fg.getArena()), mParentHandle(parent) { } diff --git a/filament/src/fg/details/DependencyGraph.h b/filament/src/fg/details/DependencyGraph.h index 8acd58018c..d75fa3a5f1 100644 --- a/filament/src/fg/details/DependencyGraph.h +++ b/filament/src/fg/details/DependencyGraph.h @@ -186,7 +186,7 @@ private: }; inline DependencyGraph::Edge::Edge(DependencyGraph& graph, - DependencyGraph::Node* from, DependencyGraph::Node* to) + Node* from, Node* to) : from(from->getId()), to(to->getId()) { assert_invariant(graph.mNodes[this->from] == from); assert_invariant(graph.mNodes[this->to] == to); diff --git a/filament/src/fg/details/Resource.h b/filament/src/fg/details/Resource.h index d2207dd96d..7acd0e1595 100644 --- a/filament/src/fg/details/Resource.h +++ b/filament/src/fg/details/Resource.h @@ -39,7 +39,7 @@ class ImportedRenderTarget; */ class ResourceEdgeBase : public DependencyGraph::Edge { public: - using DependencyGraph::Edge::Edge; + using Edge::Edge; }; /* @@ -199,7 +199,7 @@ protected: */ void resolveUsage(DependencyGraph& graph, - ResourceEdgeBase const* const* edges, size_t count, + ResourceEdgeBase const* const* edges, size_t const count, ResourceEdgeBase const* writer) noexcept override { for (size_t i = 0; i < count; i++) { if (graph.isEdgeValid(edges[i])) { diff --git a/filament/src/fsr.h b/filament/src/fsr.h index 98c70558aa..350ee3c7e3 100644 --- a/filament/src/fsr.h +++ b/filament/src/fsr.h @@ -26,8 +26,8 @@ namespace filament { struct FSRScalingConfig { - filament::backend::Backend backend; - filament::Viewport input; // region of source to be scaled + backend::Backend backend; + Viewport input; // region of source to be scaled uint32_t inputWidth; // width of source uint32_t inputHeight; // height of source uint32_t outputWidth; // width of destination diff --git a/filament/src/materials/colorGrading/colorGrading.mat b/filament/src/materials/colorGrading/colorGrading.mat index 7667b42d9b..83712beafe 100644 --- a/filament/src/materials/colorGrading/colorGrading.mat +++ b/filament/src/materials/colorGrading/colorGrading.mat @@ -41,7 +41,7 @@ material { }, { type : int, - name : fxaa + name : outputLuminance }, { type : float, @@ -166,10 +166,10 @@ void postProcess(inout PostProcessInputs postProcess) { color = dither(color, materialParams.temporalNoise); } - // kill alpha computations when opaque / fxaa luminance + // kill alpha computations when opaque / luminance #if POST_PROCESS_OPAQUE color.a = 1.0; - if (materialParams.fxaa > 0) { + if (materialParams.outputLuminance > 0) { color.a = luminance(color.rgb); } #endif diff --git a/filament/src/materials/colorGrading/colorGradingAsSubpass.mat b/filament/src/materials/colorGrading/colorGradingAsSubpass.mat index 236ab4d407..58459dc2c9 100644 --- a/filament/src/materials/colorGrading/colorGradingAsSubpass.mat +++ b/filament/src/materials/colorGrading/colorGradingAsSubpass.mat @@ -16,7 +16,7 @@ material { }, { type : int, - name : fxaa + name : outputLuminance }, { type : float, @@ -110,10 +110,10 @@ void postProcess(inout PostProcessInputs postProcess) { color = dither(color, materialParams.temporalNoise); } - // kill alpha computations when opaque / fxaa luminance + // kill alpha computations when opaque / luminance #if POST_PROCESS_OPAQUE color.a = 1.0; - if (materialParams.fxaa > 0) { + if (materialParams.outputLuminance > 0) { color.a = luminance(color.rgb); } #endif diff --git a/filament/src/materials/sgsr/LICENSE.txt b/filament/src/materials/sgsr/LICENSE.txt new file mode 100644 index 0000000000..d9d513c758 --- /dev/null +++ b/filament/src/materials/sgsr/LICENSE.txt @@ -0,0 +1,29 @@ +Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are met: + +1. Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + +2. Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + +3. Neither the name of the copyright holder nor the names of its contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" +AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF +SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS +INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN +CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) +ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE +POSSIBILITY OF SUCH DAMAGE. + +SPDX-License-Identifier: BSD-3-Clause \ No newline at end of file diff --git a/filament/src/materials/sgsr/sgsr1.mat b/filament/src/materials/sgsr/sgsr1.mat new file mode 100644 index 0000000000..38fe23fc02 --- /dev/null +++ b/filament/src/materials/sgsr/sgsr1.mat @@ -0,0 +1,80 @@ +material { + name : sgsr1, + parameters : [ + { + type : sampler2d, + name : color, + precision: medium + }, + { + type : float4, + name : viewport, + precision: high + } + ], + variables : [ + vertex + ], + depthWrite : false, + depthCulling : false, + domain: postprocess +} + +vertex { + void postProcessVertex(inout PostProcessVertexInputs postProcess) { + postProcess.normalizedUV = uvToRenderTargetUV(postProcess.normalizedUV); + postProcess.vertex.xy = postProcess.normalizedUV; + } +} + +fragment { + + void dummy(){} + + precision mediump float; + precision highp int; + +#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER) + #define gather textureGather +#else + vec4 gather(const mediump sampler2D color, highp vec2 p, const int comp) { + highp ivec2 i = ivec2(p * materialParams.viewport.zw - 0.5); + vec4 d; + d[0] = texelFetchOffset(color, i, 0, ivec2(0, 1))[comp]; + d[1] = texelFetchOffset(color, i, 0, ivec2(1, 1))[comp]; + d[2] = texelFetchOffset(color, i, 0, ivec2(1, 0))[comp]; + d[3] = texelFetchOffset(color, i, 0, ivec2(0, 0))[comp]; + return d; + } +#endif + +/* +* Operation modes: +* RGBA -> 1 +* RGBY -> 3 +* LERP -> 4 +*/ + +// SGSR cannot support translucency; +// So we hijack the POST_PROCESS variant to select whether a luminance channel is present +#if POST_PROCESS_OPAQUE +# define OperationMode 1 +#else +# define OperationMode 3 +#endif + +/* +* If set, will use edge direction to improve visual quality +* Expect a minimal cost increase +*/ +#define UseEdgeDirection +#define EdgeThreshold 8.0 / 255.0 +#define EdgeSharpness 2.0 + +#include "sgsr1_shader_mobile.fs" + + void postProcess(inout PostProcessInputs postProcess) { + highp vec4 vp[1] = vec4[1]( materialParams.viewport ); + postProcess.color = sgsr(materialParams_color, variable_vertex.xy, vp); + } +} diff --git a/filament/src/materials/sgsr/sgsr1_shader_mobile.fs b/filament/src/materials/sgsr/sgsr1_shader_mobile.fs new file mode 100644 index 0000000000..edc937f4ad --- /dev/null +++ b/filament/src/materials/sgsr/sgsr1_shader_mobile.fs @@ -0,0 +1,132 @@ +//============================================================================================================ +// +// +// Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved. +// SPDX-License-Identifier: BSD-3-Clause +// +//============================================================================================================ + +//////////////////////// +// USER CONFIGURATION // +//////////////////////// + +float fastLanczos2(float x) +{ + float wA = x-4.0; + float wB = x*wA-wA; + wA *= wA; + return wB*wA; +} + +#if defined(UseEdgeDirection) +vec2 weightY(float dx, float dy, float c, vec3 data) +#else +vec2 weightY(float dx, float dy, float c, float data) +#endif +{ +#if defined(UseEdgeDirection) + float std = data.x; + vec2 dir = data.yz; + + float edgeDis = ((dx*dir.y)+(dy*dir.x)); + float x = (((dx*dx)+(dy*dy))+((edgeDis*edgeDis)*((clamp(((c*c)*std),0.0,1.0)*0.7)+-1.0))); +#else + float std = data; + float x = ((dx*dx)+(dy*dy))* 0.55 + clamp(abs(c)*std, 0.0, 1.0); +#endif + + float w = fastLanczos2(x); + return vec2(w, w * c); +} + +vec2 edgeDirection(vec4 left, vec4 right) +{ + vec2 dir; + float RxLz = (right.x + (-left.z)); + float RwLy = (right.w + (-left.y)); + vec2 delta; + delta.x = (RxLz + RwLy); + delta.y = (RxLz + (-RwLy)); + float lengthInv = inversesqrt((delta.x * delta.x+ 3.075740e-05) + (delta.y * delta.y)); + dir.x = (delta.x * lengthInv); + dir.y = (delta.y * lengthInv); + return dir; +} + +vec4 sgsr(mediump sampler2D ps0, highp vec2 in_TEXCOORD0, highp vec4 ViewportInfo[1]) +{ + vec4 color; + if(OperationMode == 1) + color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz; + else + color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw; + +#if OperationMode != 4 + if (OperationMode!=4) + { + highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5)); + highp vec2 imgCoordPixel = floor(imgCoord); + highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy); + vec2 pl = (imgCoord+(-imgCoordPixel)); + vec4 left = gather(ps0,coord, OperationMode); + + float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ; + if(edgeVote > EdgeThreshold) + { + coord.x += ViewportInfo[0].x; + + vec4 right = gather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode); + vec4 upDown; + upDown.xy = gather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz; + upDown.zw = gather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx; + + float mean = (left.y+left.z+right.x+right.w)*0.25; + left = left - vec4(mean); + right = right - vec4(mean); + upDown = upDown - vec4(mean); + color.w = color[OperationMode] - mean; + + float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w)) + + (((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w))) + + (((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w))); + +#if defined(UseEdgeDirection) + float sumMean = 1.014185e+01 / sum; + float std = (sumMean * sumMean); + vec3 data = vec3(std, edgeDirection(left, right)); +#else + // taken from sgsr sample + float data = 2.181818 / sum; +#endif + + vec2 aWY = weightY(pl.x, pl.y+1.0, upDown.x,data); + aWY += weightY(pl.x-1.0, pl.y+1.0, upDown.y,data); + aWY += weightY(pl.x-1.0, pl.y-2.0, upDown.z,data); + aWY += weightY(pl.x, pl.y-2.0, upDown.w,data); + aWY += weightY(pl.x+1.0, pl.y-1.0, left.x,data); + aWY += weightY(pl.x, pl.y-1.0, left.y,data); + aWY += weightY(pl.x, pl.y, left.z,data); + aWY += weightY(pl.x+1.0, pl.y, left.w,data); + aWY += weightY(pl.x-1.0, pl.y-1.0, right.x,data); + aWY += weightY(pl.x-2.0, pl.y-1.0, right.y,data); + aWY += weightY(pl.x-2.0, pl.y, right.z,data); + aWY += weightY(pl.x-1.0, pl.y, right.w,data); + + float finalY = aWY.y/aWY.x; + float maxY = max(max(left.y,left.z),max(right.x,right.w)); + float minY = min(min(left.y,left.z),min(right.x,right.w)); + float deltaY = clamp(EdgeSharpness*finalY, minY, maxY) -color.w; + + //smooth high contrast input + deltaY = clamp(deltaY, -23.0 / 255.0, 23.0 / 255.0); + + color.x = clamp(color.x+deltaY, 0.0, 1.0); + color.y = clamp(color.y+deltaY, 0.0, 1.0); + color.z = clamp(color.z+deltaY, 0.0, 1.0); + } + } +#endif + + color.w = 1.0; //assume alpha channel is not used + return color; +} \ No newline at end of file diff --git a/ios/CocoaPods/Filament.podspec b/ios/CocoaPods/Filament.podspec index e5e319aab0..9d28231177 100644 --- a/ios/CocoaPods/Filament.podspec +++ b/ios/CocoaPods/Filament.podspec @@ -1,12 +1,12 @@ Pod::Spec.new do |spec| spec.name = "Filament" - spec.version = "1.56.7" + spec.version = "1.56.8" spec.license = { :type => "Apache 2.0", :file => "LICENSE" } spec.homepage = "https://google.github.io/filament" spec.authors = "Google LLC." spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL." spec.platform = :ios, "11.0" - spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.7/filament-v1.56.7-ios.tgz" } + spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.8/filament-v1.56.8-ios.tgz" } # Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon. spec.pod_target_xcconfig = { diff --git a/libs/fgviewer/CMakeLists.txt b/libs/fgviewer/CMakeLists.txt index cf6bdb526d..892232f433 100644 --- a/libs/fgviewer/CMakeLists.txt +++ b/libs/fgviewer/CMakeLists.txt @@ -15,12 +15,14 @@ endif() set(PUBLIC_HDRS include/fgviewer/DebugServer.h include/fgviewer/JsonWriter.h + include/fgviewer/FrameGraphInfo.h ) set(SRCS src/ApiHandler.cpp src/ApiHandler.h src/DebugServer.cpp + src/FrameGraphInfo.cpp ) # ================================================================================================== diff --git a/libs/fgviewer/include/fgviewer/DebugServer.h b/libs/fgviewer/include/fgviewer/DebugServer.h index ef05448333..d56addf909 100644 --- a/libs/fgviewer/include/fgviewer/DebugServer.h +++ b/libs/fgviewer/include/fgviewer/DebugServer.h @@ -17,6 +17,8 @@ #ifndef FGVIEWER_DEBUGSERVER_H #define FGVIEWER_DEBUGSERVER_H +#include + #include #include @@ -27,17 +29,9 @@ class CivetServer; namespace filament::fgviewer { -using FrameGraphInfoKey = uint32_t; +using ViewHandle = uint32_t; -struct FrameGraphPassInfo { - utils::CString pass_name; - // TODO: Add struct detail properties -}; -struct FrameGraphInfo { - utils::CString view_name; - std::vector passes; -}; /** * Server-side frame graph debugger. @@ -50,30 +44,31 @@ public: static std::string_view const kSuccessHeader; static std::string_view const kErrorHeader; - DebugServer(int port); + explicit DebugServer(int port); ~DebugServer(); /** * Notifies the debugger that a new view has been added. */ - void addView(const utils::CString& name, FrameGraphInfo info); + ViewHandle createView(utils::CString name); /** * Notifies the debugger that the given view has been deleted. */ - void removeView(const utils::CString& name); + void destroyView(ViewHandle h); /** * Updates the information for a given view. */ - void updateView(const utils::CString& name, FrameGraphInfo info); + void update(ViewHandle h, FrameGraphInfo info); bool isReady() const { return mServer; } private: CivetServer* mServer; - std::unordered_map mViews; + std::unordered_map mViews; + uint32_t mViewCounter = 0; mutable utils::Mutex mViewsMutex; class FileRequestHandler* mFileHandler = nullptr; diff --git a/libs/fgviewer/include/fgviewer/FrameGraphInfo.h b/libs/fgviewer/include/fgviewer/FrameGraphInfo.h new file mode 100644 index 0000000000..7de8dd02de --- /dev/null +++ b/libs/fgviewer/include/fgviewer/FrameGraphInfo.h @@ -0,0 +1,82 @@ +/* +* Copyright (C) 2024 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 FGVIEWER_FRAMEGRAPHINFO_H +#define FGVIEWER_FRAMEGRAPHINFO_H + +#include + +#include +#include +#include + +namespace filament::fgviewer { +using ResourceId = uint32_t; + +class FrameGraphInfo { +public: + explicit FrameGraphInfo(utils::CString viewName); + + ~FrameGraphInfo(); + + FrameGraphInfo(FrameGraphInfo &&rhs) noexcept; + + FrameGraphInfo(FrameGraphInfo const &) = delete; + + struct Pass { + Pass(utils::CString name, std::vector reads, + std::vector writes); + + utils::CString name; + std::vector reads; + std::vector writes; + }; + + struct Resource { + struct Property { + utils::CString name; + utils::CString value; + }; + + Resource(ResourceId id, utils::CString name, + std::vector properties); + + ResourceId id; + utils::CString name; + // We use a vector of Property here to store the resource properties, + // so different kinds of resources could choose different types of + // properties to record. + // ex. + // Texture2D --> { {"name","XXX"}, {"sizeX", "1024"}, {"sizeY", "768"} } + // Buffer1D --> { {"name", "XXX"}, {"size", "512"} } + std::vector properties; + }; + + void setResources(std::unordered_map resources); + + // The incoming passes should be sorted by the execution order. + void setPasses(std::vector sortedPasses); + +private: + utils::CString viewName; + // The order of the passes in the vector indicates the execution + // order of the passes. + std::vector passes; + std::unordered_map resources; +}; +} // namespace filament::fgviewer + +#endif //FGVIEWER_FRAMEGRAPHINFO_H diff --git a/libs/fgviewer/src/DebugServer.cpp b/libs/fgviewer/src/DebugServer.cpp index ce1ccaa36b..70d2af0894 100644 --- a/libs/fgviewer/src/DebugServer.cpp +++ b/libs/fgviewer/src/DebugServer.cpp @@ -15,6 +15,7 @@ */ #include +#include #include "ApiHandler.h" @@ -31,12 +32,6 @@ namespace filament::fgviewer { namespace { std::string const BASE_URL = "libs/fgviewer/web"; - -FrameGraphInfoKey getKeybyString(const utils::CString &input, - uint32_t seed) { - return utils::hash::murmurSlow(reinterpret_cast( - input.c_str()), input.size(), 0); -} } // anonymous using namespace utils; @@ -49,6 +44,7 @@ std::string_view const DebugServer::kErrorHeader = "HTTP/1.1 404 Not Found\r\nContent-Type: %s\r\n" "Connection: close\r\n\r\n"; + class FileRequestHandler : public CivetHandler { public: FileRequestHandler(DebugServer* server) : mServer(server) {} @@ -110,22 +106,23 @@ DebugServer::~DebugServer() { delete mServer; } -void DebugServer::addView(const utils::CString &name, FrameGraphInfo info) { +ViewHandle DebugServer::createView(utils::CString name) { std::unique_lock lock(mViewsMutex); - const FrameGraphInfoKey key = getKeybyString(name, 0); - mViews.insert({key, info}); + ViewHandle handle = mViewCounter++; + mViews.emplace(handle, FrameGraphInfo(std::move(name))); + + return handle; } -void DebugServer::removeView(const utils::CString& name) { +void DebugServer::destroyView(ViewHandle h) { std::unique_lock lock(mViewsMutex); - const FrameGraphInfoKey key = getKeybyString(name, 0); - mViews.erase(key); + mViews.erase(h); } -void DebugServer::updateView(const utils::CString& name, FrameGraphInfo info) { +void DebugServer::update(ViewHandle h, FrameGraphInfo info) { std::unique_lock lock(mViewsMutex); - const FrameGraphInfoKey key = getKeybyString(name, 0); - mViews[key] = info; + mViews.erase(h); + mViews.emplace(h, std::move(info)); } } // namespace filament::fgviewer diff --git a/libs/fgviewer/src/FrameGraphInfo.cpp b/libs/fgviewer/src/FrameGraphInfo.cpp new file mode 100644 index 0000000000..59fcaea489 --- /dev/null +++ b/libs/fgviewer/src/FrameGraphInfo.cpp @@ -0,0 +1,46 @@ +/* +* Copyright (C) 2024 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. + */ + +#include + +namespace filament::fgviewer { + +FrameGraphInfo::FrameGraphInfo(utils::CString viewName): + viewName(std::move(viewName)), passes({}), resources({}) {} + +FrameGraphInfo::~FrameGraphInfo() = default; + +FrameGraphInfo::FrameGraphInfo(FrameGraphInfo&& rhs) noexcept = default; + +FrameGraphInfo::Pass::Pass(utils::CString name, std::vector reads, + std::vector writes): name(std::move(name)), + reads(std::move(reads)), + writes(std::move(writes)) {} + +FrameGraphInfo::Resource::Resource(ResourceId id, utils::CString name, + std::vector properties): id(id), + name(std::move(name)), properties(std::move(properties)) {} + +void FrameGraphInfo::setResources( + std::unordered_map resources) { + this->resources = std::move(resources); +} + +void FrameGraphInfo::setPasses(std::vector sortedPasses) { + passes = std::move(sortedPasses); +} + +} // namespace filament::fgviewer diff --git a/libs/filamat/include/filamat/MaterialBuilder.h b/libs/filamat/include/filamat/MaterialBuilder.h index 767bdecc6f..f21abe129e 100644 --- a/libs/filamat/include/filamat/MaterialBuilder.h +++ b/libs/filamat/include/filamat/MaterialBuilder.h @@ -585,8 +585,7 @@ public: */ MaterialBuilder& optimization(Optimization optimization) noexcept; - // TODO: this is present here for matc's "--print" flag, but ideally does not belong inside - // MaterialBuilder. + // TODO: this is present here for matc's "--print" flag, but ideally does not belong inside MaterialBuilder. //! If true, will output the generated GLSL shader code to stdout. MaterialBuilder& printShaders(bool printShaders) noexcept; diff --git a/libs/filamat/src/GLSLPostProcessor.cpp b/libs/filamat/src/GLSLPostProcessor.cpp index 92675b8dff..8d38ed7cc2 100644 --- a/libs/filamat/src/GLSLPostProcessor.cpp +++ b/libs/filamat/src/GLSLPostProcessor.cpp @@ -297,6 +297,19 @@ GLSLPostProcessor::GLSLPostProcessor(MaterialBuilder::Optimization optimization, spv::spirvbin_t::registerErrorHandler([](const std::string& str) { slog.e << str << io::endl; }); + + // Similar to above, we need to do a no-op remap to init a static table in the remapper before + // the jobs start using remap(). + spv::spirvbin_t remapper(0); + // We need to provide at least a valid header to not crash. + SpirvBlob spirv { + 0x07230203,// MAGIC + 0, // VERSION + 0, // GENERATOR + 0, // BOUND + 0 // SCHEMA, must be 0 + }; + remapper.remap(spirv, 0); } GLSLPostProcessor::~GLSLPostProcessor() = default; diff --git a/libs/filamat/src/MaterialBuilder.cpp b/libs/filamat/src/MaterialBuilder.cpp index 96563bfa6e..3a8061e4de 100644 --- a/libs/filamat/src/MaterialBuilder.cpp +++ b/libs/filamat/src/MaterialBuilder.cpp @@ -1368,7 +1368,6 @@ bool MaterialBuilder::checkMaterialLevelFeatures(MaterialInfo const& info) const textureUsedByFilamentCount -= 1; // fog texture } - // TODO: we need constants somewhere for these values if (userSamplerCount > maxTextureCount - textureUsedByFilamentCount) { slog.e << "Error: material \"" << mMaterialName.c_str() << "\" has feature level " << +info.featureLevel diff --git a/libs/filamat/src/shaders/ShaderGenerator.cpp b/libs/filamat/src/shaders/ShaderGenerator.cpp index 63273b952b..6457992709 100644 --- a/libs/filamat/src/shaders/ShaderGenerator.cpp +++ b/libs/filamat/src/shaders/ShaderGenerator.cpp @@ -489,7 +489,6 @@ std::string ShaderGenerator::createVertexProgram(ShaderModel shaderModel, CodeGenerator::generateSeparator(vs); - // TODO: should we generate per-view SIB in the vertex shader? cg.generateSamplers(vs, DescriptorSetBindingPoints::PER_MATERIAL, material.sib); // shader code diff --git a/libs/filamentapp/src/Cube.cpp b/libs/filamentapp/src/Cube.cpp index a8027b6953..4283aa88b0 100644 --- a/libs/filamentapp/src/Cube.cpp +++ b/libs/filamentapp/src/Cube.cpp @@ -140,12 +140,15 @@ void Cube::mapAabb(filament::Engine& engine, filament::Box const& box) { Cube::~Cube() { mEngine.destroy(mVertexBuffer); mEngine.destroy(mIndexBuffer); - mEngine.destroy(mMaterialInstanceSolid); - mEngine.destroy(mMaterialInstanceWireFrame); + // We don't own the material, only instances mEngine.destroy(mSolidRenderable); mEngine.destroy(mWireFrameRenderable); + // material instances must be destroyed after the renderables + mEngine.destroy(mMaterialInstanceSolid); + mEngine.destroy(mMaterialInstanceWireFrame); + utils::EntityManager& em = utils::EntityManager::get(); em.destroy(mSolidRenderable); em.destroy(mWireFrameRenderable); diff --git a/libs/gltfio/src/FilamentAsset.cpp b/libs/gltfio/src/FilamentAsset.cpp index 161ae03195..4940766e1d 100644 --- a/libs/gltfio/src/FilamentAsset.cpp +++ b/libs/gltfio/src/FilamentAsset.cpp @@ -37,12 +37,8 @@ FFilamentAsset::~FFilamentAsset() { // Free transient load-time data if they haven't been freed yet. releaseSourceData(); - // Destroy all instance objects. Instance entities / components are - // destroyed later in this method because they are owned by the asset - // (except for the root of the instance). for (FFilamentInstance* instance : mInstances) { mEntityManager->destroy(instance->mRoot); - delete instance; } delete mWireframe; @@ -76,6 +72,12 @@ FFilamentAsset::~FFilamentAsset() { } } + // FilamentInstances need to be destroyed after the renderables have been destroyed + // so that there are no dangling MaterialInstance around + for (FFilamentInstance* instance : mInstances) { + delete instance; + } + for (auto vb : mVertexBuffers) { mEngine->destroy(vb); } diff --git a/libs/iblprefilter/src/IBLPrefilterContext.cpp b/libs/iblprefilter/src/IBLPrefilterContext.cpp index 9e889f36a7..0ac10e5071 100644 --- a/libs/iblprefilter/src/IBLPrefilterContext.cpp +++ b/libs/iblprefilter/src/IBLPrefilterContext.cpp @@ -254,8 +254,8 @@ Texture* IBLPrefilterContext::EquirectangularToCubemap::operator()( const uint32_t dim = outCube->getWidth(); RenderableManager& rcm = engine.getRenderableManager(); - rcm.setMaterialInstanceAt( - rcm.getInstance(mContext.mFullScreenQuadEntity), 0, mi); + auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); + rcm.setMaterialInstanceAt(ci, 0, mi); TextureSampler environmentSampler; environmentSampler.setMagFilter(SamplerMagFilter::LINEAR); @@ -289,6 +289,7 @@ Texture* IBLPrefilterContext::EquirectangularToCubemap::operator()( engine.destroy(rt); } + rcm.clearMaterialInstanceAt(ci, 0); engine.destroy(mi); return outCube; @@ -328,8 +329,8 @@ IBLPrefilterContext::IrradianceFilter::IrradianceFilter(IBLPrefilterContext& con mi->setParameter("sampleCount", float(mSampleCount)); RenderableManager& rcm = engine.getRenderableManager(); - rcm.setMaterialInstanceAt( - rcm.getInstance(mContext.mFullScreenQuadEntity), 0, mi); + auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); + rcm.setMaterialInstanceAt(ci, 0, mi); RenderTarget* const rt = RenderTarget::Builder() .texture(RenderTarget::AttachmentPoint::COLOR0, mKernelTexture) @@ -340,6 +341,8 @@ IBLPrefilterContext::IrradianceFilter::IrradianceFilter(IBLPrefilterContext& con renderer->renderStandaloneView(view); + rcm.clearMaterialInstanceAt(ci, 0); + engine.destroy(rt); engine.destroy(mi); } @@ -410,8 +413,8 @@ filament::Texture* IBLPrefilterContext::IrradianceFilter::operator()( MaterialInstance* const mi = mContext.mIrradianceIntegrationMaterial->createInstance(); RenderableManager& rcm = engine.getRenderableManager(); - rcm.setMaterialInstanceAt( - rcm.getInstance(mContext.mFullScreenQuadEntity), 0, mi); + auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); + rcm.setMaterialInstanceAt(ci, 0, mi); const uint32_t sampleCount = mSampleCount; const float linear = options.hdrLinear; @@ -455,6 +458,8 @@ filament::Texture* IBLPrefilterContext::IrradianceFilter::operator()( engine.destroy(rt); } + rcm.clearMaterialInstanceAt(ci, 0); + engine.destroy(mi); return outIrradianceTexture; @@ -533,8 +538,8 @@ IBLPrefilterContext::SpecularFilter::SpecularFilter(IBLPrefilterContext& context mi->setParameter("roughness", roughnessArray, 16); RenderableManager& rcm = engine.getRenderableManager(); - rcm.setMaterialInstanceAt( - rcm.getInstance(mContext.mFullScreenQuadEntity), 0, mi); + auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); + rcm.setMaterialInstanceAt(ci, 0, mi); RenderTarget* const rt = RenderTarget::Builder() .texture(RenderTarget::AttachmentPoint::COLOR0, mKernelTexture) @@ -545,6 +550,8 @@ IBLPrefilterContext::SpecularFilter::SpecularFilter(IBLPrefilterContext& context renderer->renderStandaloneView(view); + rcm.clearMaterialInstanceAt(ci, 0); + engine.destroy(rt); engine.destroy(mi); } @@ -643,8 +650,8 @@ Texture* IBLPrefilterContext::SpecularFilter::operator()( MaterialInstance* const mi = mContext.mIntegrationMaterial->createInstance(); RenderableManager& rcm = engine.getRenderableManager(); - rcm.setMaterialInstanceAt( - rcm.getInstance(mContext.mFullScreenQuadEntity), 0, mi); + auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); + rcm.setMaterialInstanceAt(ci, 0, mi); const uint32_t sampleCount = mSampleCount; const float linear = options.hdrLinear; @@ -707,6 +714,8 @@ Texture* IBLPrefilterContext::SpecularFilter::operator()( dim >>= 1; } + rcm.clearMaterialInstanceAt(ci, 0); + engine.destroy(mi); return outReflectionsTexture; diff --git a/libs/imageio/include/imageio/ImageDecoder.h b/libs/imageio/include/imageio/ImageDecoder.h index cd341c49d8..4573e0b2c8 100644 --- a/libs/imageio/include/imageio/ImageDecoder.h +++ b/libs/imageio/include/imageio/ImageDecoder.h @@ -33,7 +33,7 @@ public: SRGB }; - // Returns linear floating-point data, or a non-valid image if an error occured. + // Returns linear floating-point data, or a non-valid image if an error occurred. static LinearImage decode(std::istream& stream, const std::string& sourceName, ColorSpace sourceSpace = ColorSpace::SRGB); diff --git a/libs/matdbg/src/SourceFormatter.cpp b/libs/matdbg/src/SourceFormatter.cpp index c068a34f4b..fe7c3f88ed 100644 --- a/libs/matdbg/src/SourceFormatter.cpp +++ b/libs/matdbg/src/SourceFormatter.cpp @@ -25,14 +25,32 @@ namespace filament::matdbg { #if defined(__linux__) || defined(__APPLE__) std::string SourceFormatter::format(char const* source) { - std::string const TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp"; + char output[1024]; - std::string original(source); - FILE* fp; - fp = fopen(TMP_FILENAME.c_str(), "w"); - if (!fp) { - return original; + // First check if clang-format is available. + FILE* fp = popen("clang-format -version", "r"); + + // Need to drain the output + while (fgets(output, 1024, fp) != NULL) {} + + int status = pclose(fp); + if (!fp || !WEXITSTATUS(status)) { + std::call_once(mClangWarningFlag, []() { + utils::slog.w << "[matdbg] unable to run clang-format to format shader file. " + << "Please make sure it's installed." << utils::io::endl; + }); + return source; } + + // Write the source to a temp file for formatting + char const* TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp"; + fp = fopen(TMP_FILENAME, "w"); + if (!fp) { + return source; + } + + // Unknown if the input is 0-terminated so we put it in a string first. + std::string original(source); fputs(original.c_str(), fp); fflush(fp); pclose(fp); @@ -45,22 +63,16 @@ std::string SourceFormatter::format(char const* source) { "}'"; fp = popen(("clang-format " + CLANG_FORMAT_OPTIONS + "< " + TMP_FILENAME).c_str(), "r"); - if (!fp) { - std::call_once(mClangWarningFlag, []() { - utils::slog.w << "[matdbg] unable to run clang-format to format shader file. " - << "Please make sure it's installed."; - }); return original; } - char output[1024]; std::stringstream outStream; while (fgets(output, 1024, fp) != NULL) { outStream << output; } - int status = pclose(fp); + status = pclose(fp); if (WEXITSTATUS(status)) { utils::slog.w << "[matdbg] clang-format failed with code=" << WEXITSTATUS(status) << utils::io::endl; @@ -69,11 +81,11 @@ std::string SourceFormatter::format(char const* source) { } #else std::string SourceFormatter::format(char const* source) { - std::call_once(mClangWarningFlag, []() { + std::call_once(mClangWarningFlag, []() { utils::slog.w <<"[matdbg]: source formatting is not available on this platform" << utils::io::endl; }); - return ""; + return source; } #endif diff --git a/libs/math/include/math/TQuatHelpers.h b/libs/math/include/math/TQuatHelpers.h index 0439b9712b..b4787481bd 100644 --- a/libs/math/include/math/TQuatHelpers.h +++ b/libs/math/include/math/TQuatHelpers.h @@ -259,7 +259,7 @@ public: return normalize(lerp(d < 0 ? -p : p, q, t)); } const T npq = std::sqrt(dot(p, p) * dot(q, q)); // ||p|| * ||q|| - const T a = std::acos(filament::math::clamp(absd / npq, T(-1), T(1))); + const T a = std::acos(math::clamp(absd / npq, T(-1), T(1))); const T a0 = a * (1 - t); const T a1 = a * t; const T sina = sin(a); diff --git a/libs/math/include/math/fast.h b/libs/math/include/math/fast.h index 85b990d287..9988cfd2a3 100644 --- a/libs/math/include/math/fast.h +++ b/libs/math/include/math/fast.h @@ -50,7 +50,7 @@ constexpr T MATH_PURE cos(T x) noexcept { // x between -pi and pi template::value>> constexpr T MATH_PURE sin(T x) noexcept { - return filament::math::fast::cos(x - T(F_PI_2)); + return fast::cos(x - T(F_PI_2)); } constexpr inline float MATH_PURE ilog2(float x) noexcept { diff --git a/libs/math/include/math/half.h b/libs/math/include/math/half.h index d792e1bf9b..c46d4ee4b6 100644 --- a/libs/math/include/math/half.h +++ b/libs/math/include/math/half.h @@ -164,7 +164,7 @@ inline constexpr half operator""_h(long double v) { return half( static_cast(v) ); } -template<> struct is_arithmetic : public std::true_type {}; +template<> struct is_arithmetic : public std::true_type {}; } // namespace math } // namespace filament diff --git a/libs/math/include/math/mat2.h b/libs/math/include/math/mat2.h index dba9ca4723..d12aa532de 100644 --- a/libs/math/include/math/mat2.h +++ b/libs/math/include/math/mat2.h @@ -225,7 +225,7 @@ public: * Rotate by radians in the 2D plane */ static TMat22 rotate(T radian) noexcept { - TMat22 r(TMat22::NO_INIT); + TMat22 r(NO_INIT); T c = std::cos(radian); T s = std::sin(radian); r[0][0] = c; diff --git a/libs/math/include/math/mat3.h b/libs/math/include/math/mat3.h index 035865fe2b..ae78e58889 100644 --- a/libs/math/include/math/mat3.h +++ b/libs/math/include/math/mat3.h @@ -256,7 +256,7 @@ public: */ friend inline constexpr TMat33 orthogonalize(const TMat33& m) noexcept { - TMat33 ret(TMat33::NO_INIT); + TMat33 ret(NO_INIT); ret[0] = normalize(m[0]); ret[2] = normalize(cross(ret[0], m[1])); ret[1] = normalize(cross(ret[2], ret[0])); diff --git a/libs/math/include/math/mat4.h b/libs/math/include/math/mat4.h index 570585397c..7eb50e3576 100644 --- a/libs/math/include/math/mat4.h +++ b/libs/math/include/math/mat4.h @@ -498,10 +498,10 @@ constexpr TMat44 TMat44::frustum(T left, T right, T bottom, T top, T near, } template -TMat44 TMat44::perspective(T fov, T aspect, T near, T far, TMat44::Fov direction) noexcept { +TMat44 TMat44::perspective(T fov, T aspect, T near, T far, Fov direction) noexcept { T h, w; - if (direction == TMat44::Fov::VERTICAL) { + if (direction == Fov::VERTICAL) { h = std::tan(fov * F_PI / 360.0f) * near; w = h * aspect; } else { diff --git a/libs/utils/include/utils/Allocator.h b/libs/utils/include/utils/Allocator.h index 2543460488..300034af48 100644 --- a/libs/utils/include/utils/Allocator.h +++ b/libs/utils/include/utils/Allocator.h @@ -194,7 +194,7 @@ public: } ~LinearAllocatorWithFallback() noexcept { - LinearAllocatorWithFallback::reset(); + reset(); } void* alloc(size_t size, size_t alignment = alignof(std::max_align_t)); @@ -204,7 +204,7 @@ public: } void rewind(void* p) noexcept { - if (p >= LinearAllocator::base() && p < LinearAllocator::end()) { + if (p >= base() && p < end()) { LinearAllocator::rewind(p); } } @@ -214,7 +214,7 @@ public: void free(void*, size_t) noexcept { } bool isHeapAllocation(void* p) const noexcept { - return p < LinearAllocator::base() || p >= LinearAllocator::end(); + return p < base() || p >= end(); } }; @@ -240,7 +240,6 @@ public: void push(void* p) noexcept { assert_invariant(p); assert_invariant(p >= mBegin && p < mEnd); - // TODO: assert this is one of our pointer (i.e.: it's address match one of ours) Node* const head = static_cast(p); head->next = mHead; mHead = head; @@ -718,13 +717,13 @@ public: // trivially destructible, since free() won't call the destructor and this is allocating // an array. template ::value>::type> + typename = std::enable_if_t>> T* alloc(size_t count, size_t alignment, size_t extra) noexcept { return (T*)alloc(count * sizeof(T), alignment, extra); } template ::value>::type> + typename = std::enable_if_t>> T* alloc(size_t count, size_t alignment = alignof(T)) noexcept { return (T*)alloc(count * sizeof(T), alignment); } @@ -880,7 +879,7 @@ public: template T* make(ARGS&& ... args) noexcept { T* o = nullptr; - if (std::is_trivially_destructible::value) { + if (std::is_trivially_destructible_v) { o = mArena.template make(std::forward(args)...); } else { void* const p = (Finalizer*)mArena.alloc(sizeof(T), ALIGN, sizeof(Finalizer)); diff --git a/libs/utils/include/utils/BinaryTreeArray.h b/libs/utils/include/utils/BinaryTreeArray.h index b4e2b1913d..c2f70deaf4 100644 --- a/libs/utils/include/utils/BinaryTreeArray.h +++ b/libs/utils/include/utils/BinaryTreeArray.h @@ -31,7 +31,7 @@ class BinaryTreeArray { // Simple fixed capacity stack template::value>::type> + typename = std::enable_if_t>> class stack { TYPE mElements[CAPACITY]; size_t mSize = 0; diff --git a/libs/utils/include/utils/BitmaskEnum.h b/libs/utils/include/utils/BitmaskEnum.h index 17f94d215b..ae4122046c 100644 --- a/libs/utils/include/utils/BitmaskEnum.h +++ b/libs/utils/include/utils/BitmaskEnum.h @@ -41,32 +41,32 @@ size_t count(); // ------------------------------------------------------------------------------------------------ template::value && utils::EnableIntegerOperators::value, int> = 0> + std::is_enum_v && utils::EnableIntegerOperators::value, int> = 0> inline constexpr int operator+(Enum value) noexcept { return int(value); } template::value && utils::EnableIntegerOperators::value, int> = 0> + std::is_enum_v && utils::EnableIntegerOperators::value, int> = 0> inline constexpr bool operator==(Enum lhs, size_t rhs) noexcept { using underlying_t = std::underlying_type_t; return underlying_t(lhs) == rhs; } template::value && utils::EnableIntegerOperators::value, int> = 0> + std::is_enum_v && utils::EnableIntegerOperators::value, int> = 0> inline constexpr bool operator==(size_t lhs, Enum rhs) noexcept { return rhs == lhs; } template::value && utils::EnableIntegerOperators::value, int> = 0> + std::is_enum_v && utils::EnableIntegerOperators::value, int> = 0> inline constexpr bool operator!=(Enum lhs, size_t rhs) noexcept { return !(rhs == lhs); } template::value && utils::EnableIntegerOperators::value, int> = 0> + std::is_enum_v && utils::EnableIntegerOperators::value, int> = 0> inline constexpr bool operator!=(size_t lhs, Enum rhs) noexcept { return rhs != lhs; } @@ -74,66 +74,66 @@ inline constexpr bool operator!=(size_t lhs, Enum rhs) noexcept { // ------------------------------------------------------------------------------------------------ template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr bool operator!(Enum rhs) noexcept { using underlying = std::underlying_type_t; return underlying(rhs) == 0; } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator~(Enum rhs) noexcept { using underlying = std::underlying_type_t; return Enum(~underlying(rhs)); } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator|(Enum lhs, Enum rhs) noexcept { using underlying = std::underlying_type_t; return Enum(underlying(lhs) | underlying(rhs)); } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator&(Enum lhs, Enum rhs) noexcept { using underlying = std::underlying_type_t; return Enum(underlying(lhs) & underlying(rhs)); } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator^(Enum lhs, Enum rhs) noexcept { using underlying = std::underlying_type_t; return Enum(underlying(lhs) ^ underlying(rhs)); } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator|=(Enum& lhs, Enum rhs) noexcept { return lhs = lhs | rhs; } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator&=(Enum& lhs, Enum rhs) noexcept { return lhs = lhs & rhs; } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr Enum operator^=(Enum& lhs, Enum rhs) noexcept { return lhs = lhs ^ rhs; } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr bool none(Enum lhs) noexcept { return !lhs; } template::value && utils::EnableBitMaskOperators::value, int> = 0> + std::is_enum_v && utils::EnableBitMaskOperators::value, int> = 0> inline constexpr bool any(Enum lhs) noexcept { return !none(lhs); } diff --git a/libs/utils/include/utils/CallStack.h b/libs/utils/include/utils/CallStack.h index 33ac0b504f..fa7ff72777 100644 --- a/libs/utils/include/utils/CallStack.h +++ b/libs/utils/include/utils/CallStack.h @@ -68,10 +68,10 @@ public: intptr_t operator [](size_t index) const; /** Demangles a C++ type name */ - static utils::CString demangleTypeName(const char* mangled); + static CString demangleTypeName(const char* mangled); template - static utils::CString typeName() { + static CString typeName() { #if UTILS_HAS_RTTI return demangleTypeName(typeid(T).name()); #else @@ -84,7 +84,7 @@ public: * This will print, when possible, the demangled names of functions corresponding to the * program-counter recorded. */ - friend utils::io::ostream& operator <<(utils::io::ostream& stream, const CallStack& callstack); + friend io::ostream& operator <<(io::ostream& stream, const CallStack& callstack); bool operator <(const CallStack& rhs) const; @@ -111,7 +111,7 @@ public: private: void update_gcc(size_t ignore) noexcept; - static utils::CString demangle(const char* mangled); + static CString demangle(const char* mangled); static constexpr size_t NUM_FRAMES = 20; diff --git a/libs/utils/include/utils/JobSystem.h b/libs/utils/include/utils/JobSystem.h index 704755aa49..1e424e4c5b 100644 --- a/libs/utils/include/utils/JobSystem.h +++ b/libs/utils/include/utils/JobSystem.h @@ -344,7 +344,7 @@ public: } // for debugging - friend utils::io::ostream& operator << (utils::io::ostream& out, JobSystem const& js); + friend io::ostream& operator << (io::ostream& out, JobSystem const& js); // utility functions... @@ -419,7 +419,7 @@ private: void decRef(Job const* job) noexcept; Job* allocateJob() noexcept; - JobSystem::ThreadState* getStateToStealFrom(JobSystem::ThreadState& state) noexcept; + ThreadState* getStateToStealFrom(ThreadState& state) noexcept; static bool hasJobCompleted(Job const* job) noexcept; void requestExit() noexcept; @@ -427,8 +427,8 @@ private: bool hasActiveJobs() const noexcept; void loop(ThreadState* state) noexcept; - bool execute(JobSystem::ThreadState& state) noexcept; - Job* steal(JobSystem::ThreadState& state) noexcept; + bool execute(ThreadState& state) noexcept; + Job* steal(ThreadState& state) noexcept; void finish(Job* job) noexcept; void put(WorkQueue& workQueue, Job* job) noexcept; @@ -446,10 +446,10 @@ private: Condition mWaiterCondition; std::atomic mActiveJobs = { 0 }; - utils::Arena, LockingPolicy::Mutex> mJobPool; + Arena, LockingPolicy::Mutex> mJobPool; template - using aligned_vector = std::vector>; + using aligned_vector = std::vector>; // These are essentially const, make sure they're on a different cache-lines than the // read-write atomics. @@ -494,9 +494,9 @@ JobSystem::Job* createJob(JobSystem& js, JobSystem::Job* parent, } template::type>::value - >::type + typename = std::enable_if_t< + std::is_member_function_pointer_v> + > > JobSystem::Job* createJob(JobSystem& js, JobSystem::Job* parent, CALLABLE&& func, T&& o, ARGS&&... args) noexcept { @@ -596,7 +596,7 @@ JobSystem::Job* parallel_for(JobSystem& js, JobSystem::Job* parent, // parallel jobs on a Slice<> template JobSystem::Job* parallel_for(JobSystem& js, JobSystem::Job* parent, - utils::Slice slice, F functor, const S& splitter) noexcept { + Slice slice, F functor, const S& splitter) noexcept { return parallel_for(js, parent, slice.data(), slice.size(), functor, splitter); } diff --git a/libs/utils/include/utils/NameComponentManager.h b/libs/utils/include/utils/NameComponentManager.h index 4ac7435a2b..403cc011a8 100644 --- a/libs/utils/include/utils/NameComponentManager.h +++ b/libs/utils/include/utils/NameComponentManager.h @@ -47,7 +47,7 @@ class EntityManager; * printf("%s\n", names->getName(names->getInstance(myEntity)); * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ */ -class UTILS_PUBLIC NameComponentManager : private SingleInstanceComponentManager { +class UTILS_PUBLIC NameComponentManager : private SingleInstanceComponentManager { public: using Instance = EntityInstance; @@ -97,7 +97,7 @@ public: const char* getName(Instance instance) const noexcept; void gc(EntityManager& em) noexcept { - SingleInstanceComponentManager::gc(em, [this](Entity e) { + SingleInstanceComponentManager::gc(em, [this](Entity e) { removeComponent(e); }); } diff --git a/libs/utils/include/utils/Profiler.h b/libs/utils/include/utils/Profiler.h index 3de9a9b058..0a0aa5d348 100644 --- a/libs/utils/include/utils/Profiler.h +++ b/libs/utils/include/utils/Profiler.h @@ -91,7 +91,7 @@ public: struct { uint64_t value; uint64_t id; - } counters[Profiler::EVENT_COUNT]; + } counters[EVENT_COUNT]; friend Counters operator-(Counters lhs, const Counters& rhs) noexcept { lhs.nr -= rhs.nr; diff --git a/libs/utils/include/utils/QuadTree.h b/libs/utils/include/utils/QuadTree.h index c0200fd5af..3e7c6dba08 100644 --- a/libs/utils/include/utils/QuadTree.h +++ b/libs/utils/include/utils/QuadTree.h @@ -50,7 +50,7 @@ static inline constexpr uint16_t morton(uint8_t x, uint8_t y) noexcept { * @return the number of elements in the tree */ static inline constexpr size_t size(size_t height) noexcept { - return QuadTreeUtils::morton(uint8_t((1u << height) - 1u), 0u); + return morton(uint8_t((1u << height) - 1u), 0u); } /** @@ -97,7 +97,7 @@ class QuadTreeArray : public std::array { // Simple fixed capacity stack template::value>::type> + typename = std::enable_if_t>> class stack { TYPE mElements[CAPACITY]; size_t mSize = 0; @@ -147,8 +147,8 @@ public: * @param process closure to process each visited node */ template>::type> + typename = std::enable_if_t< + std::is_invocable_r_v>> static void traverse(int8_t l, code_t code, size_t maxHeight, Process&& process) noexcept { assert_invariant(maxHeight < height()); const int8_t h = int8_t(maxHeight); @@ -173,8 +173,8 @@ public: } template>::type> + typename = std::enable_if_t< + std::is_invocable_r_v>> static void traverse(int8_t l, code_t code, Node&& process) noexcept { traverse(l, code, height() - 1, std::forward(process)); } diff --git a/libs/utils/include/utils/RangeMap.h b/libs/utils/include/utils/RangeMap.h index e7f9581b24..c28b453bfe 100644 --- a/libs/utils/include/utils/RangeMap.h +++ b/libs/utils/include/utils/RangeMap.h @@ -268,7 +268,7 @@ private: Iterator shrink(Iterator iter, KeyType first, KeyType last) { assert_invariant(first < last); assert_invariant(getRange(iter).first == first || getRange(iter).last == last); - std::pair, ValueType> value = {{first, last}, iter->second.second}; + std::pair, ValueType> value = {{first, last}, iter->second.second}; mMap.erase(iter); return mMap.insert({first, value}).first; } diff --git a/libs/utils/include/utils/SingleInstanceComponentManager.h b/libs/utils/include/utils/SingleInstanceComponentManager.h index ddd538f5e9..95f6bcb774 100644 --- a/libs/utils/include/utils/SingleInstanceComponentManager.h +++ b/libs/utils/include/utils/SingleInstanceComponentManager.h @@ -108,7 +108,7 @@ public: return getComponentCount() == 0; } - utils::Entity const* getEntities() const noexcept { + Entity const* getEntities() const noexcept { return data() + 1; } diff --git a/libs/utils/include/utils/StructureOfArrays.h b/libs/utils/include/utils/StructureOfArrays.h index c0b2315ecc..b5d56c79bf 100644 --- a/libs/utils/include/utils/StructureOfArrays.h +++ b/libs/utils/include/utils/StructureOfArrays.h @@ -130,7 +130,7 @@ public: friend class IteratorValueRef; friend iterator; friend const_iterator; - using Type = std::tuple::type...>; + using Type = std::tuple...>; Type elements; template @@ -535,22 +535,22 @@ public: private: template - inline typename std::enable_if::type + inline std::enable_if_t for_each(std::tuple&, FuncT) {} template - inline typename std::enable_if::type + inline std::enable_if_t for_each(std::tuple& t, FuncT f) { f(I, std::get(t)); for_each(t, f); } template - inline typename std::enable_if::type + inline std::enable_if_t for_each_index(std::tuple&, FuncT) {} template - inline typename std::enable_if::type + inline std::enable_if_t for_each_index(std::tuple& t, FuncT f) { f.template operator()(std::get(t)); for_each_index(t, f); @@ -597,7 +597,7 @@ private: void construct_each(size_t from, size_t to) noexcept { forEach([from, to](auto p) { - using T = typename std::decay::type; + using T = std::decay_t; // note: scalar types like int/float get initialized to zero if constexpr (!std::is_trivially_default_constructible_v) { for (size_t i = from; i < to; i++) { @@ -609,7 +609,7 @@ private: void destroy_each(size_t from, size_t to) noexcept { forEach([from, to](auto p) { - using T = typename std::decay::type; + using T = std::decay_t; if constexpr (!std::is_trivially_destructible_v) { for (size_t i = from; i < to; i++) { p[i].~T(); @@ -624,7 +624,7 @@ private: if (mSize) { auto size = mSize; // placate a compiler warning forEach([buffer, &index, &offsets, size](auto p) { - using T = typename std::decay::type; + using T = std::decay_t; T* UTILS_RESTRICT b = static_cast(buffer); // go through each element and move them from the old array to the new @@ -671,7 +671,7 @@ template inline typename StructureOfArraysBase::IteratorValueRef& StructureOfArraysBase::IteratorValueRef::operator=( - StructureOfArraysBase::IteratorValueRef const& rhs) { + IteratorValueRef const& rhs) { return operator=(IteratorValue(rhs)); } @@ -679,7 +679,7 @@ template inline typename StructureOfArraysBase::IteratorValueRef& StructureOfArraysBase::IteratorValueRef::operator=( - StructureOfArraysBase::IteratorValueRef&& rhs) noexcept { + IteratorValueRef&& rhs) noexcept { return operator=(IteratorValue(rhs)); } @@ -688,7 +688,7 @@ template inline typename StructureOfArraysBase::IteratorValueRef& StructureOfArraysBase::IteratorValueRef::assign( - StructureOfArraysBase::IteratorValue const& rhs, std::index_sequence) { + IteratorValue const& rhs, std::index_sequence) { // implements IteratorValueRef& IteratorValueRef::operator=(IteratorValue const& rhs) auto UTILS_UNUSED l = { (soa->elementAt(index) = std::get(rhs.elements), 0)... }; return *this; @@ -699,7 +699,7 @@ template inline typename StructureOfArraysBase::IteratorValueRef& StructureOfArraysBase::IteratorValueRef::assign( - StructureOfArraysBase::IteratorValue&& rhs, std::index_sequence) noexcept { + IteratorValue&& rhs, std::index_sequence) noexcept { // implements IteratorValueRef& IteratorValueRef::operator=(IteratorValue&& rhs) noexcept auto UTILS_UNUSED l = { (soa->elementAt(index) = std::move(std::get(rhs.elements)), 0)... }; diff --git a/libs/utils/include/utils/algorithm.h b/libs/utils/include/utils/algorithm.h index 7a747b84ce..c4f400f4b7 100644 --- a/libs/utils/include/utils/algorithm.h +++ b/libs/utils/include/utils/algorithm.h @@ -39,7 +39,7 @@ constexpr inline T popcount(T v) noexcept { return (T) (v * (ONES / 255)) >> (sizeof(T) - 1) * CHAR_BIT; } -template::value>> +template>> constexpr inline T clz(T x) noexcept { static_assert(sizeof(T) * CHAR_BIT <= 128, "details::clz() only support up to 128 bits"); x |= (x >> 1u); @@ -62,7 +62,7 @@ constexpr inline T clz(T x) noexcept { return T(sizeof(T) * CHAR_BIT) - details::popcount(x); } -template::value>> +template>> constexpr inline T ctz(T x) noexcept { static_assert(sizeof(T) * CHAR_BIT <= 64, "details::ctz() only support up to 64 bits"); T c = sizeof(T) * CHAR_BIT; @@ -227,7 +227,7 @@ unsigned long long UTILS_ALWAYS_INLINE popcount(unsigned long long x) noexcept { } template::value && std::is_unsigned::value>> + typename = std::enable_if_t && std::is_unsigned_v>> constexpr inline UTILS_PUBLIC UTILS_PURE T log2i(T x) noexcept { return (sizeof(x) * 8 - 1u) - clz(x); diff --git a/libs/utils/include/utils/android/PerformanceHintManager.h b/libs/utils/include/utils/android/PerformanceHintManager.h index 4010177315..b5910abca1 100644 --- a/libs/utils/include/utils/android/PerformanceHintManager.h +++ b/libs/utils/include/utils/android/PerformanceHintManager.h @@ -37,7 +37,7 @@ class UTILS_PUBLIC PerformanceHintManager : public: class UTILS_PUBLIC Session : PrivateImplementation { friend class PerformanceHintManager; - friend struct PerformanceHintManager::SessionDetails; + friend struct SessionDetails; public: Session() noexcept; Session(PerformanceHintManager& manager, diff --git a/libs/utils/include/utils/bitset.h b/libs/utils/include/utils/bitset.h index 8844fdb80a..4afba3955c 100644 --- a/libs/utils/include/utils/bitset.h +++ b/libs/utils/include/utils/bitset.h @@ -45,8 +45,8 @@ namespace utils { */ template::value && - std::is_unsigned::value>::type> + typename = std::enable_if_t && + std::is_unsigned_v>> class UTILS_PUBLIC bitset { T storage[N]; diff --git a/libs/utils/include/utils/ostream.h b/libs/utils/include/utils/ostream.h index f554985176..f440e62531 100644 --- a/libs/utils/include/utils/ostream.h +++ b/libs/utils/include/utils/ostream.h @@ -29,7 +29,7 @@ namespace utils::io { struct ostream_; -class UTILS_PUBLIC ostream : protected utils::PrivateImplementation { +class UTILS_PUBLIC ostream : protected PrivateImplementation { friend struct ostream_; public: @@ -123,7 +123,7 @@ private: }; // handles utils::bitset -inline ostream& operator << (ostream& o, utils::bitset32 const& s) noexcept { +inline ostream& operator << (ostream& o, bitset32 const& s) noexcept { return o << (void*)uintptr_t(s.getValue()); } diff --git a/libs/utils/src/CallStack.cpp b/libs/utils/src/CallStack.cpp index 38549d59d0..3c95701bd2 100644 --- a/libs/utils/src/CallStack.cpp +++ b/libs/utils/src/CallStack.cpp @@ -27,7 +27,6 @@ #include #include -// FIXME: Some platforms do not have execinfo.h #if !defined(__ANDROID__) && !defined(WIN32) && !defined(__EMSCRIPTEN__) #include #define HAS_EXECINFO 1 @@ -120,7 +119,7 @@ bool CallStack::operator<(const CallStack& rhs) const { // ------------------------------------------------------------------------------------------------ -utils::CString CallStack::demangle(const char* mangled) { +CString CallStack::demangle(const char* mangled) { #if !defined(NDEBUG) && !defined(WIN32) size_t len; int status; @@ -135,7 +134,7 @@ utils::CString CallStack::demangle(const char* mangled) { } -utils::CString CallStack::demangleTypeName(const char* mangled) { +CString CallStack::demangleTypeName(const char* mangled) { return demangle(mangled); } diff --git a/libs/utils/src/EntityManager.cpp b/libs/utils/src/EntityManager.cpp index bdb12db325..fda7cfeea9 100644 --- a/libs/utils/src/EntityManager.cpp +++ b/libs/utils/src/EntityManager.cpp @@ -49,11 +49,11 @@ void EntityManager::destroy(size_t n, Entity* entities) noexcept { static_cast(this)->destroy(n, entities); } -void EntityManager::registerListener(EntityManager::Listener* l) noexcept { +void EntityManager::registerListener(Listener* l) noexcept { static_cast(this)->registerListener(l); } -void EntityManager::unregisterListener(EntityManager::Listener* l) noexcept { +void EntityManager::unregisterListener(Listener* l) noexcept { static_cast(this)->unregisterListener(l); } diff --git a/libs/utils/src/EntityManagerImpl.h b/libs/utils/src/EntityManagerImpl.h index 0465dc1cb1..f385a8a7c4 100644 --- a/libs/utils/src/EntityManagerImpl.h +++ b/libs/utils/src/EntityManagerImpl.h @@ -132,12 +132,12 @@ public: } } - void registerListener(EntityManager::Listener* l) noexcept { + void registerListener(Listener* l) noexcept { std::lock_guard const lock(mListenerLock); mListeners.insert(l); } - void unregisterListener(EntityManager::Listener* l) noexcept { + void unregisterListener(Listener* l) noexcept { std::lock_guard const lock(mListenerLock); mListeners.erase(l); } @@ -162,10 +162,10 @@ public: #endif private: - utils::FixedCapacityVector getListeners() const noexcept { + FixedCapacityVector getListeners() const noexcept { std::lock_guard const lock(mListenerLock); tsl::robin_set const& listeners = mListeners; - utils::FixedCapacityVector result(listeners.size()); + FixedCapacityVector result(listeners.size()); result.resize(result.capacity()); // unfortunately this memset() std::copy(listeners.begin(), listeners.end(), result.begin()); return result; // the c++ standard guarantees a move diff --git a/libs/utils/src/JobSystem.cpp b/libs/utils/src/JobSystem.cpp index 1051a6f45c..ae8bba5443 100644 --- a/libs/utils/src/JobSystem.cpp +++ b/libs/utils/src/JobSystem.cpp @@ -269,7 +269,7 @@ inline bool JobSystem::hasActiveJobs() const noexcept { return mActiveJobs.load(std::memory_order_relaxed) > 0; } -inline bool JobSystem::hasJobCompleted(JobSystem::Job const* job) noexcept { +inline bool JobSystem::hasJobCompleted(Job const* job) noexcept { return (job->runningJobCount.load(std::memory_order_acquire) & JOB_COUNT_MASK) == 0; } @@ -374,14 +374,14 @@ JobSystem::Job* JobSystem::steal(WorkQueue& workQueue) noexcept { return job; } -inline JobSystem::ThreadState* JobSystem::getStateToStealFrom(JobSystem::ThreadState& state) noexcept { +inline JobSystem::ThreadState* JobSystem::getStateToStealFrom(ThreadState& state) noexcept { auto& threadStates = mThreadStates; // memory_order_relaxed is okay because we don't take any action that has data dependency // on this value (in particular mThreadStates, is always initialized properly). uint16_t const adopted = mAdoptedThreads.load(std::memory_order_relaxed); uint16_t const threadCount = mThreadCount + adopted; - JobSystem::ThreadState* stateToStealFrom = nullptr; + ThreadState* stateToStealFrom = nullptr; // don't try to steal from someone else if we're the only thread (infinite loop) if (threadCount >= 2) { @@ -396,7 +396,7 @@ inline JobSystem::ThreadState* JobSystem::getStateToStealFrom(JobSystem::ThreadS return stateToStealFrom; } -JobSystem::Job* JobSystem::steal(JobSystem::ThreadState& state) noexcept { +JobSystem::Job* JobSystem::steal(ThreadState& state) noexcept { HEAVY_SYSTRACE_CALL(); Job* job = nullptr; do { @@ -410,7 +410,7 @@ JobSystem::Job* JobSystem::steal(JobSystem::ThreadState& state) noexcept { return job; } -bool JobSystem::execute(JobSystem::ThreadState& state) noexcept { +bool JobSystem::execute(ThreadState& state) noexcept { HEAVY_SYSTRACE_CALL(); Job* job = pop(state.workQueue); @@ -500,7 +500,7 @@ void JobSystem::finish(Job* job) noexcept { // public API... -JobSystem::Job* JobSystem::create(JobSystem::Job* parent, JobFunc func) noexcept { +JobSystem::Job* JobSystem::create(Job* parent, JobFunc func) noexcept { parent = (parent == nullptr) ? mRootJob : parent; Job* const job = allocateJob(); if (UTILS_LIKELY(job)) { @@ -529,13 +529,13 @@ void JobSystem::cancel(Job*& job) noexcept { job = nullptr; } -JobSystem::Job* JobSystem::retain(JobSystem::Job* job) noexcept { - JobSystem::Job* retained = job; +JobSystem::Job* JobSystem::retain(Job* job) noexcept { + Job* retained = job; incRef(retained); return retained; } -void JobSystem::release(JobSystem::Job*& job) noexcept { +void JobSystem::release(Job*& job) noexcept { decRef(job); job = nullptr; } @@ -564,7 +564,7 @@ void JobSystem::run(Job*& job, uint8_t id) noexcept { } JobSystem::Job* JobSystem::runAndRetain(Job* job) noexcept { - JobSystem::Job* retained = retain(job); + Job* retained = retain(job); run(job); return retained; } @@ -618,7 +618,7 @@ void JobSystem::waitAndRelease(Job*& job) noexcept { release(job); } -void JobSystem::runAndWait(JobSystem::Job*& job) noexcept { +void JobSystem::runAndWait(Job*& job) noexcept { SYSTRACE_CALL(); runAndRetain(job); waitAndRelease(job); @@ -648,7 +648,7 @@ void JobSystem::adopt() { << "Too many calls to adopt(). No more adoptable threads!"; // all threads adopted by the JobSystem need to run at the same priority - JobSystem::setThreadPriority(Priority::DISPLAY); + setThreadPriority(Priority::DISPLAY); // This thread's queue will be selectable immediately (i.e.: before we set its TLS) // however, it's not a problem since mThreadState is pre-initialized and valid diff --git a/libs/utils/src/Panic.cpp b/libs/utils/src/Panic.cpp index 1b8921ac06..e0aec064fa 100644 --- a/libs/utils/src/Panic.cpp +++ b/libs/utils/src/Panic.cpp @@ -43,7 +43,7 @@ class UserPanicHandler { struct CallBack { Panic::PanicHandlerCallback handler = nullptr; void* user = nullptr; - void call(Panic const& panic) const noexcept { + void call(Panic const& panic) const { if (UTILS_UNLIKELY(handler)) { handler(user, panic); } @@ -64,7 +64,7 @@ public: return data; } - void call(Panic const& panic) const noexcept { + void call(Panic const& panic) const { getCallback().call(panic); } diff --git a/libs/utils/src/Profiler.cpp b/libs/utils/src/Profiler.cpp index 61513b8dae..f509d72248 100644 --- a/libs/utils/src/Profiler.cpp +++ b/libs/utils/src/Profiler.cpp @@ -59,7 +59,7 @@ Profiler::Profiler() noexcept { } Profiler::Profiler(uint32_t eventMask) noexcept : Profiler() { - Profiler::resetEvents(eventMask); + resetEvents(eventMask); } Profiler::~Profiler() noexcept { diff --git a/libs/utils/src/android/ThermalManager.cpp b/libs/utils/src/android/ThermalManager.cpp index 20c27b9e9b..5ef088aa8d 100644 --- a/libs/utils/src/android/ThermalManager.cpp +++ b/libs/utils/src/android/ThermalManager.cpp @@ -46,7 +46,7 @@ ThermalManager& ThermalManager::operator=(ThermalManager&& rhs) noexcept { ThermalManager::ThermalStatus ThermalManager::getCurrentThermalStatus() const noexcept { if (__builtin_available(android 30, *)) { - return (ThermalManager::ThermalStatus)AThermal_getCurrentThermalStatus(mThermalManager); + return (ThermalStatus)AThermal_getCurrentThermalStatus(mThermalManager); } else { return ThermalStatus::NONE; } diff --git a/libs/utils/src/ostream.cpp b/libs/utils/src/ostream.cpp index c50d0c293b..ebc3a319d2 100644 --- a/libs/utils/src/ostream.cpp +++ b/libs/utils/src/ostream.cpp @@ -75,21 +75,21 @@ ostream::Buffer const& ostream::getBuffer() const noexcept { return mImpl->mData; } -const char* ostream::getFormat(ostream::type t) const noexcept { +const char* ostream::getFormat(type t) const noexcept { switch (t) { - case type::SHORT: return mImpl->mShowHex ? "0x%hx" : "%hd"; - case type::USHORT: return mImpl->mShowHex ? "0x%hx" : "%hu"; - case type::CHAR: return "%c"; - case type::UCHAR: return "%c"; - case type::INT: return mImpl->mShowHex ? "0x%x" : "%d"; - case type::UINT: return mImpl->mShowHex ? "0x%x" : "%u"; - case type::LONG: return mImpl->mShowHex ? "0x%lx" : "%ld"; - case type::ULONG: return mImpl->mShowHex ? "0x%lx" : "%lu"; - case type::LONG_LONG: return mImpl->mShowHex ? "0x%llx" : "%lld"; - case type::ULONG_LONG: return mImpl->mShowHex ? "0x%llx" : "%llu"; - case type::FLOAT: return "%.9g"; - case type::DOUBLE: return "%.17g"; - case type::LONG_DOUBLE: return "%Lf"; + case SHORT: return mImpl->mShowHex ? "0x%hx" : "%hd"; + case USHORT: return mImpl->mShowHex ? "0x%hx" : "%hu"; + case CHAR: return "%c"; + case UCHAR: return "%c"; + case INT: return mImpl->mShowHex ? "0x%x" : "%d"; + case UINT: return mImpl->mShowHex ? "0x%x" : "%u"; + case LONG: return mImpl->mShowHex ? "0x%lx" : "%ld"; + case ULONG: return mImpl->mShowHex ? "0x%lx" : "%lu"; + case LONG_LONG: return mImpl->mShowHex ? "0x%llx" : "%lld"; + case ULONG_LONG: return mImpl->mShowHex ? "0x%llx" : "%llu"; + case FLOAT: return "%.9g"; + case DOUBLE: return "%.17g"; + case LONG_DOUBLE: return "%Lf"; } } @@ -126,67 +126,67 @@ ostream& ostream::print(const char* format, ...) noexcept { } ostream& ostream::operator<<(short value) noexcept { - const char* format = getFormat(type::SHORT); + const char* format = getFormat(SHORT); return print(format, value); } ostream& ostream::operator<<(unsigned short value) noexcept { - const char* format = getFormat(type::USHORT); + const char* format = getFormat(USHORT); return print(format, value); } ostream& ostream::operator<<(char value) noexcept { - const char* format = getFormat(type::CHAR); + const char* format = getFormat(CHAR); return print(format, value); } ostream& ostream::operator<<(unsigned char value) noexcept { - const char* format = getFormat(type::UCHAR); + const char* format = getFormat(UCHAR); return print(format, value); } ostream& ostream::operator<<(int value) noexcept { - const char* format = getFormat(type::INT); + const char* format = getFormat(INT); return print(format, value); } ostream& ostream::operator<<(unsigned int value) noexcept { - const char* format = getFormat(type::UINT); + const char* format = getFormat(UINT); return print(format, value); } ostream& ostream::operator<<(long value) noexcept { - const char* format = getFormat(type::LONG); + const char* format = getFormat(LONG); return print(format, value); } ostream& ostream::operator<<(unsigned long value) noexcept { - const char* format = getFormat(type::ULONG); + const char* format = getFormat(ULONG); return print(format, value); } ostream& ostream::operator<<(long long value) noexcept { - const char* format = getFormat(type::LONG_LONG); + const char* format = getFormat(LONG_LONG); return print(format, value); } ostream& ostream::operator<<(unsigned long long value) noexcept { - const char* format = getFormat(type::ULONG_LONG); + const char* format = getFormat(ULONG_LONG); return print(format, value); } ostream& ostream::operator<<(float value) noexcept { - const char* format = getFormat(type::FLOAT); + const char* format = getFormat(FLOAT); return print(format, value); } ostream& ostream::operator<<(double value) noexcept { - const char* format = getFormat(type::DOUBLE); + const char* format = getFormat(DOUBLE); return print(format, value); } ostream& ostream::operator<<(long double value) noexcept { - const char* format = getFormat(type::LONG_DOUBLE); + const char* format = getFormat(LONG_DOUBLE); return print(format, value); } diff --git a/libs/utils/src/sstream.cpp b/libs/utils/src/sstream.cpp index cab96cebbb..c7bd0a5b5e 100644 --- a/libs/utils/src/sstream.cpp +++ b/libs/utils/src/sstream.cpp @@ -21,7 +21,7 @@ namespace utils::io { -utils::io::ostream& sstream::flush() noexcept { +ostream& sstream::flush() noexcept { // no-op. return *this; } diff --git a/libs/viewer/src/Settings.cpp b/libs/viewer/src/Settings.cpp index 639d07a2c9..a1de4ee105 100644 --- a/libs/viewer/src/Settings.cpp +++ b/libs/viewer/src/Settings.cpp @@ -412,21 +412,30 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk, out->cascadeSplitPositions[0] = splitsVector[0]; out->cascadeSplitPositions[1] = splitsVector[1]; out->cascadeSplitPositions[2] = splitsVector[2]; - // TODO: constantBias - // TODO: normalBias - // TODO: shadowFar - // TODO: shadowNearHint - // TODO: shadowFarHint + } else if (compare(tok, jsonChunk, "constantBias") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->constantBias); + } else if (compare(tok, jsonChunk, "normalBias") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->normalBias); + } else if (compare(tok, jsonChunk, "shadowFar") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->shadowFar); + } else if (compare(tok, jsonChunk, "shadowNearHint") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->shadowNearHint); + } else if (compare(tok, jsonChunk, "shadowFarHint") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->shadowFarHint); } else if (compare(tok, jsonChunk, "stable") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->stable); } else if (compare(tok, jsonChunk, "lispsm") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->lispsm); - // TODO: polygonOffsetConstant - // TODO: polygonOffsetSlope + } else if (compare(tok, jsonChunk, "polygonOffsetConstant") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->polygonOffsetConstant); + } else if (compare(tok, jsonChunk, "polygonOffsetSlope") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->polygonOffsetSlope); } else if (compare(tok, jsonChunk, "screenSpaceContactShadows") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->screenSpaceContactShadows); - // TODO: stepCount - // TODO: maxShadowDistance + } else if (compare(tok, jsonChunk, "stepCount") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->stepCount); + } else if (compare(tok, jsonChunk, "maxShadowDistance") == 0) { + i = parse(tokens, i + 1, jsonChunk, &out->maxShadowDistance); } else if (compare(tok, jsonChunk, "vsm") == 0) { i = parse(tokens, i + 1, jsonChunk, &out->vsm); } else if (compare(tok, jsonChunk, "shadowBulbRadius") == 0) { @@ -810,10 +819,19 @@ static std::ostream& operator<<(std::ostream& out, const LightManager::ShadowOpt << "},\n" << "\"mapSize\": " << in.mapSize << ",\n" << "\"shadowCascades\": " << int(in.shadowCascades) << ",\n" - << "\"cascadeSplitPositions\": " << (splitsVector) << "\n" + << "\"cascadeSplitPositions\": " << splitsVector << "\n" + << "\"constantBias\": " << in.constantBias << ",\n" + << "\"normalBias\": " << in.normalBias << ",\n" + << "\"shadowFar\": " << in.shadowFar << ",\n" + << "\"shadowNearHint\": " << in.shadowNearHint << ",\n" + << "\"shadowFarHint\": " << in.shadowFarHint << ",\n" << "\"stable\": " << to_string(in.stable) << ",\n" << "\"lispsm\": " << to_string(in.lispsm) << ",\n" + << "\"polygonOffsetConstant\": " << in.polygonOffsetConstant << ",\n" + << "\"polygonOffsetSlope\": " << in.polygonOffsetSlope << ",\n" << "\"screenSpaceContactShadows\": " << to_string(in.screenSpaceContactShadows) << ",\n" + << "\"stepCount\": " << +in.stepCount << ",\n" + << "\"maxShadowDistance\": " << in.maxShadowDistance << ",\n" << "\"shadowBulbRadius\": " << in.shadowBulbRadius << ",\n" << "\"transform\": " << in.transform.xyzw << ",\n" << "}"; diff --git a/test/utils/get_mesa.sh b/test/utils/get_mesa.sh index 0a86aef243..79fa87f348 100755 --- a/test/utils/get_mesa.sh +++ b/test/utils/get_mesa.sh @@ -16,20 +16,36 @@ set -xe -CLANG_VERSION=`clang --version | head -n 1 | awk '{ print $4 }' | python3 -c "import sys; print(sys.stdin.read().split('.')[0])"` +# GITHUB_CLANG_VERSION is set in build/linux/ci-common.sh -sudo apt-get -y build-dep mesa +if [[ "$GITHUB_WORKFLOW" ]]; then + # We only want to do this if it is a CI machine. + sudo apt-get -y remove llvm-* -# Uninstall llvm-18 (and above) as they conflict with the mesa version we are compiling. -set +e -sudo apt -y remove llvm-18 llvm-18-* -set -e + # We do a manual install of dependencies instead of `apt-get -y build-dep mesa` + # because this allows us to compile an older mesa, and also because build-deps + # is constantly being updated and sometimes not compatible with the current + # linux platform. + # Note that we assume this platform is compatible with ubuntu-22.04 x86_64 + sudo apt-get -y install \ + autoconf automake autopoint autotools-dev bindgen bison build-essential bzip2 cpp cpp-11 debhelper debugedit dh-autoreconf dh-strip-nondeterminism diffstat directx-headers-dev dpkg-dev dwz flex g++ g++-11 gcc gcc-11 gcc-11-base:amd64 gettext glslang-tools icu-devtools intltool-debian lib32gcc-s1 lib32stdc++6 libarchive-zip-perl libasan6:amd64 libatomic1:amd64 libc-dev-bin libc6-dbg:amd64 libc6-dev:amd64 libc6-i386 libcc1-0:amd64 libclang-${GITHUB_CLANG_VERSION}-dev libclang-common-${GITHUB_CLANG_VERSION}-dev libclang-cpp${GITHUB_CLANG_VERSION} libclang-cpp${GITHUB_CLANG_VERSION}-dev libclang1-14 libclang1-${GITHUB_CLANG_VERSION} libclc-${GITHUB_CLANG_VERSION} libclc-${GITHUB_CLANG_VERSION}-dev libcrypt-dev:amd64 libdebhelper-perl libdpkg-perl libdrm-amdgpu1:amd64 libdrm-dev:amd64 libdrm-intel1:amd64 libdrm-nouveau2:amd64 libdrm-radeon1:amd64 libelf-dev:amd64 libexpat1-dev:amd64 libffi-dev:amd64 libfile-stripnondeterminism-perl libgc1:amd64 libgcc-11-dev:amd64 libgl1:amd64 libgl1-mesa-dri:amd64 libglapi-mesa:amd64 libglvnd-core-dev:amd64 libglvnd0:amd64 libglx-mesa0:amd64 libglx0:amd64 libgomp1:amd64 libicu-dev:amd64 libisl23:amd64 libitm1:amd64 libllvm14:amd64 libllvm${GITHUB_CLANG_VERSION}:amd64 libllvmspirvlib-${GITHUB_CLANG_VERSION}-dev:amd64 libllvmspirvlib${GITHUB_CLANG_VERSION}:amd64 liblsan0:amd64 libmpc3:amd64 libncurses-dev:amd64 libnsl-dev:amd64 libobjc-11-dev:amd64 libobjc4:amd64 libpciaccess-dev:amd64 libpciaccess0:amd64 libpfm4:amd64 libpthread-stubs0-dev:amd64 libquadmath0:amd64 libsensors-config libsensors-dev:amd64 libsensors5:amd64 libset-scalar-perl libstd-rust-1.75:amd64 libstd-rust-dev:amd64 libstdc++-11-dev:amd64 libsub-override-perl libtinfo-dev:amd64 libtirpc-dev:amd64 libtool libtsan0:amd64 libubsan1:amd64 libva-dev:amd64 libva-drm2:amd64 libva-glx2:amd64 libva-wayland2:amd64 libva-x11-2:amd64 libva2:amd64 libvdpau-dev:amd64 libvdpau1:amd64 libvulkan-dev:amd64 libvulkan1:amd64 libwayland-bin libwayland-client0:amd64 libwayland-cursor0:amd64 libwayland-dev:amd64 libwayland-egl-backend-dev:amd64 libwayland-egl1:amd64 libwayland-server0:amd64 libx11-dev:amd64 libx11-xcb-dev:amd64 libx11-xcb1:amd64 libxau-dev:amd64 libxcb-dri2-0:amd64 libxcb-dri2-0-dev:amd64 libxcb-dri3-0:amd64 libxcb-dri3-dev:amd64 libxcb-glx0:amd64 libxcb-glx0-dev:amd64 libxcb-present-dev:amd64 libxcb-present0:amd64 libxcb-randr0:amd64 libxcb-randr0-dev:amd64 libxcb-render0:amd64 libxcb-render0-dev:amd64 libxcb-shape0:amd64 libxcb-shape0-dev:amd64 libxcb-shm0:amd64 libxcb-shm0-dev:amd64 libxcb-sync-dev:amd64 libxcb-sync1:amd64 libxcb-xfixes0:amd64 libxcb-xfixes0-dev:amd64 libxcb1-dev:amd64 libxdmcp-dev:amd64 libxext-dev:amd64 libxfixes-dev:amd64 libxfixes3:amd64 libxml2-dev:amd64 libxrandr-dev:amd64 libxrandr2:amd64 libxrender-dev:amd64 libxrender1:amd64 libxshmfence-dev:amd64 libxshmfence1:amd64 libxxf86vm-dev:amd64 libxxf86vm1:amd64 libz3-4:amd64 libz3-dev:amd64 libzstd-dev:amd64 linux-libc-dev:amd64 llvm-${GITHUB_CLANG_VERSION} llvm-${GITHUB_CLANG_VERSION}-dev llvm-${GITHUB_CLANG_VERSION}-linker-tools llvm-${GITHUB_CLANG_VERSION}-runtime llvm-${GITHUB_CLANG_VERSION}-tools llvm-spirv-${GITHUB_CLANG_VERSION} lto-disabled-list m4 make meson ninja-build pkg-config po-debconf python3-mako python3-ply python3-pygments quilt rpcsvc-proto rustc spirv-tools valgrind wayland-protocols x11proto-dev xorg-sgml-doctools xtrans-dev zlib1g-dev:amd64 \ + clang-$GITHUB_CLANG_VERSION libc++-$GITHUB_CLANG_VERSION-dev libc++abi-$GITHUB_CLANG_VERSION-dev + + sudo update-alternatives --install /usr/bin/cc cc /usr/bin/clang-${GITHUB_CLANG_VERSION} 100 + sudo update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++-${GITHUB_CLANG_VERSION} 100 +else + set +e + apt-get -y build-dep mesa + sudo apt -y remove llvm-18 llvm-18-* + set -e + + sudo apt-get -y install clang-${GITHUB_CLANG_VERSION} \ + libc++-${GITHUB_CLANG_VERSION}-dev \ + libc++abi-${GITHUB_CLANG_VERSION}-dev \ + llvm-${GITHUB_CLANG_VERSION} \ + llvm-${GITHUB_CLANG_VERSION}-{dev,tools,runtime} +fi -sudo apt -y install clang-${CLANG_VERSION} \ - libc++-${CLANG_VERSION}-dev \ - libc++abi-${CLANG_VERSION}-dev \ - llvm-${CLANG_VERSION} \ - llvm-${CLANG_VERSION}-{dev,tools,runtime} export CXX=`which clang++` && export CC=`which clang` diff --git a/third_party/abseil/.github/ISSUE_TEMPLATE/00-bug_report.yml b/third_party/abseil/.github/ISSUE_TEMPLATE/00-bug_report.yml new file mode 100644 index 0000000000..32cebe15a8 --- /dev/null +++ b/third_party/abseil/.github/ISSUE_TEMPLATE/00-bug_report.yml @@ -0,0 +1,53 @@ +name: Bug Report +description: Let us know that something does not work as expected. +title: "[Bug]: Please title this bug report" +body: + - type: textarea + id: what-happened + attributes: + label: Describe the issue + description: What happened, and what did you expect to happen? + validations: + required: true + - type: textarea + id: steps + attributes: + label: Steps to reproduce the problem + description: It is important that we are able to reproduce the problem that you are experiencing. Please provide all code and relevant steps to reproduce the problem, including your `BUILD`/`CMakeLists.txt` file and build commands. Links to a GitHub branch or [godbolt.org](https://godbolt.org/) that demonstrate the problem are also helpful. + validations: + required: true + - type: textarea + id: version + attributes: + label: What version of Abseil are you using? + description: Please include the output of `git rev-parse HEAD` or the name of the LTS release that you are using. + validations: + required: true + - type: textarea + id: os + attributes: + label: What operating system and version are you using? + description: If you are using a Linux distribution please include the name and version of the distribution as well. + validations: + required: true + - type: textarea + id: compiler + attributes: + label: What compiler and version are you using? + description: Please include the output of `gcc -v` or `clang -v`, or the equivalent for your compiler. + validations: + required: true + - type: textarea + id: buildsystem + attributes: + label: What build system are you using? + description: Please include the output of `bazel --version` or `cmake --version`, or the equivalent for your build system. + validations: + required: true + - type: textarea + id: additional + attributes: + label: Additional context + description: Add any other context about the problem here. + validations: + required: false diff --git a/third_party/abseil/.github/ISSUE_TEMPLATE/config.yml b/third_party/abseil/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 0000000000..c690fd9a51 --- /dev/null +++ b/third_party/abseil/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1,5 @@ +blank_issues_enabled: false +contact_links: + - name: Question + url: https://github.com/abseil/abseil-cpp/discussions + about: Have a question? Ask us anything! :-) diff --git a/third_party/abseil/.github/PULL_REQUEST_TEMPLATE.md b/third_party/abseil/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 0000000000..ff55e35294 --- /dev/null +++ b/third_party/abseil/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,8 @@ +Thank you for your contribution to Abseil! + +Before submitting this PR, please be sure to read our [contributing +guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md). + +If you are a Googler, please also note that it is required that you send us a +Piper CL instead of using the GitHub pull-request process. The code propagation +process will deliver the change to GitHub. diff --git a/third_party/abseil/.gitignore b/third_party/abseil/.gitignore new file mode 100644 index 0000000000..3a729f416b --- /dev/null +++ b/third_party/abseil/.gitignore @@ -0,0 +1,17 @@ +# Bzlmod lockfile +MODULE.bazel.lock +# Ignore all bazel-* symlinks. +/bazel-* +# Ignore Bazel verbose explanations +--verbose_explanations +# Ignore CMake usual build directory +build +# Ignore Vim files +*.swp +# Ignore QtCreator Project file +CMakeLists.txt.user +# Ignore VS Code files +.vscode/* +# Ignore generated python artifacts +*.pyc +copts/__pycache__/ diff --git a/third_party/abseil/ABSEIL_ISSUE_TEMPLATE.md b/third_party/abseil/ABSEIL_ISSUE_TEMPLATE.md new file mode 100644 index 0000000000..ed5461f166 --- /dev/null +++ b/third_party/abseil/ABSEIL_ISSUE_TEMPLATE.md @@ -0,0 +1,22 @@ +Please submit a new Abseil Issue using the template below: + +## [Short title of proposed API change(s)] + +-------------------------------------------------------------------------------- +-------------------------------------------------------------------------------- + +## Background + +[Provide the background information that is required in order to evaluate the +proposed API changes. No controversial claims should be made here. If there are +design constraints that need to be considered, they should be presented here +**along with justification for those constraints**. Linking to other docs is +good, but please keep the **pertinent information as self contained** as +possible in this section.] + +## Proposed API Change (s) + +[Please clearly describe the API change(s) being proposed. If multiple changes, +please keep them clearly distinguished. When possible, **use example code +snippets to illustrate before-after API usages**. List pros-n-cons. Highlight +the main questions that you want to be answered. Given the Abseil project compatibility requirements, describe why the API change is safe.] diff --git a/third_party/abseil/AUTHORS b/third_party/abseil/AUTHORS new file mode 100644 index 0000000000..976d31defc --- /dev/null +++ b/third_party/abseil/AUTHORS @@ -0,0 +1,6 @@ +# This is the list of Abseil authors for copyright purposes. +# +# This does not necessarily list everyone who has contributed code, since in +# some cases, their employer may be the copyright holder. To see the full list +# of contributors, see the revision history in source control. +Google Inc. diff --git a/third_party/abseil/BUILD.bazel b/third_party/abseil/BUILD.bazel new file mode 100644 index 0000000000..03122a958e --- /dev/null +++ b/third_party/abseil/BUILD.bazel @@ -0,0 +1,35 @@ +# Copyright 2020 The Abseil Authors. +# +# 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 +# +# https://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. +# + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) # Apache 2.0 + +# Expose license for external usage through bazel. +exports_files([ + "AUTHORS", + "LICENSE", +]) + +# For building with clang-cl. +# https://bazel.build/configure/windows#clang +platform( + name = "x64_windows-clang-cl", + constraint_values = [ + "@platforms//cpu:x86_64", + "@platforms//os:windows", + "@bazel_tools//tools/cpp:clang-cl", + ], +) diff --git a/third_party/abseil/CMake/AbseilDll.cmake b/third_party/abseil/CMake/AbseilDll.cmake new file mode 100644 index 0000000000..039d41397d --- /dev/null +++ b/third_party/abseil/CMake/AbseilDll.cmake @@ -0,0 +1,914 @@ +include(CMakeParseArguments) +include(GNUInstallDirs) + +set(ABSL_INTERNAL_DLL_FILES + "algorithm/algorithm.h" + "algorithm/container.h" + "base/attributes.h" + "base/call_once.h" + "base/casts.h" + "base/config.h" + "base/const_init.h" + "base/dynamic_annotations.h" + "base/internal/atomic_hook.h" + "base/internal/cycleclock.cc" + "base/internal/cycleclock.h" + "base/internal/cycleclock_config.h" + "base/internal/direct_mmap.h" + "base/internal/dynamic_annotations.h" + "base/internal/endian.h" + "base/internal/errno_saver.h" + "base/internal/fast_type_id.h" + "base/internal/hide_ptr.h" + "base/internal/identity.h" + "base/internal/invoke.h" + "base/internal/inline_variable.h" + "base/internal/low_level_alloc.cc" + "base/internal/low_level_alloc.h" + "base/internal/low_level_scheduling.h" + "base/internal/nullability_impl.h" + "base/internal/per_thread_tls.h" + "base/internal/poison.cc" + "base/internal/poison.h" + "base/prefetch.h" + "base/internal/pretty_function.h" + "base/internal/raw_logging.cc" + "base/internal/raw_logging.h" + "base/internal/scheduling_mode.h" + "base/internal/scoped_set_env.cc" + "base/internal/scoped_set_env.h" + "base/internal/strerror.h" + "base/internal/strerror.cc" + "base/internal/spinlock.cc" + "base/internal/spinlock.h" + "base/internal/spinlock_wait.cc" + "base/internal/spinlock_wait.h" + "base/internal/sysinfo.cc" + "base/internal/sysinfo.h" + "base/internal/thread_identity.cc" + "base/internal/thread_identity.h" + "base/internal/throw_delegate.cc" + "base/internal/throw_delegate.h" + "base/internal/tracing.cc" + "base/internal/tracing.h" + "base/internal/tsan_mutex_interface.h" + "base/internal/unaligned_access.h" + "base/internal/unscaledcycleclock.cc" + "base/internal/unscaledcycleclock.h" + "base/internal/unscaledcycleclock_config.h" + "base/log_severity.cc" + "base/log_severity.h" + "base/macros.h" + "base/no_destructor.h" + "base/nullability.h" + "base/optimization.h" + "base/options.h" + "base/policy_checks.h" + "base/port.h" + "base/thread_annotations.h" + "cleanup/cleanup.h" + "cleanup/internal/cleanup.h" + "container/btree_map.h" + "container/btree_set.h" + "container/hash_container_defaults.h" + "container/fixed_array.h" + "container/flat_hash_map.h" + "container/flat_hash_set.h" + "container/inlined_vector.h" + "container/internal/btree.h" + "container/internal/btree_container.h" + "container/internal/common.h" + "container/internal/common_policy_traits.h" + "container/internal/compressed_tuple.h" + "container/internal/container_memory.h" + "container/internal/hash_function_defaults.h" + "container/internal/hash_policy_traits.h" + "container/internal/hashtable_debug.h" + "container/internal/hashtable_debug_hooks.h" + "container/internal/hashtablez_sampler.cc" + "container/internal/hashtablez_sampler.h" + "container/internal/hashtablez_sampler_force_weak_definition.cc" + "container/internal/inlined_vector.h" + "container/internal/layout.h" + "container/internal/node_slot_policy.h" + "container/internal/raw_hash_map.h" + "container/internal/raw_hash_set.cc" + "container/internal/raw_hash_set.h" + "container/internal/tracked.h" + "container/node_hash_map.h" + "container/node_hash_set.h" + "crc/crc32c.cc" + "crc/crc32c.h" + "crc/internal/cpu_detect.cc" + "crc/internal/cpu_detect.h" + "crc/internal/crc32c.h" + "crc/internal/crc32c_inline.h" + "crc/internal/crc32_x86_arm_combined_simd.h" + "crc/internal/crc.cc" + "crc/internal/crc.h" + "crc/internal/crc_cord_state.cc" + "crc/internal/crc_cord_state.h" + "crc/internal/crc_internal.h" + "crc/internal/crc_x86_arm_combined.cc" + "crc/internal/crc_memcpy_fallback.cc" + "crc/internal/crc_memcpy.h" + "crc/internal/crc_memcpy_x86_arm_combined.cc" + "crc/internal/crc_non_temporal_memcpy.cc" + "crc/internal/crc_x86_arm_combined.cc" + "crc/internal/non_temporal_arm_intrinsics.h" + "crc/internal/non_temporal_memcpy.h" + "debugging/failure_signal_handler.cc" + "debugging/failure_signal_handler.h" + "debugging/leak_check.h" + "debugging/stacktrace.cc" + "debugging/stacktrace.h" + "debugging/symbolize.cc" + "debugging/symbolize.h" + "debugging/internal/address_is_readable.cc" + "debugging/internal/address_is_readable.h" + "debugging/internal/bounded_utf8_length_sequence.h" + "debugging/internal/decode_rust_punycode.cc" + "debugging/internal/decode_rust_punycode.h" + "debugging/internal/demangle.cc" + "debugging/internal/demangle.h" + "debugging/internal/demangle_rust.cc" + "debugging/internal/demangle_rust.h" + "debugging/internal/elf_mem_image.cc" + "debugging/internal/elf_mem_image.h" + "debugging/internal/examine_stack.cc" + "debugging/internal/examine_stack.h" + "debugging/internal/stack_consumption.cc" + "debugging/internal/stack_consumption.h" + "debugging/internal/stacktrace_config.h" + "debugging/internal/symbolize.h" + "debugging/internal/utf8_for_code_point.cc" + "debugging/internal/utf8_for_code_point.h" + "debugging/internal/vdso_support.cc" + "debugging/internal/vdso_support.h" + "functional/any_invocable.h" + "functional/internal/front_binder.h" + "functional/bind_front.h" + "functional/function_ref.h" + "functional/internal/any_invocable.h" + "functional/internal/function_ref.h" + "functional/overload.h" + "hash/hash.h" + "hash/internal/city.h" + "hash/internal/city.cc" + "hash/internal/hash.h" + "hash/internal/hash.cc" + "hash/internal/spy_hash_state.h" + "hash/internal/low_level_hash.h" + "hash/internal/low_level_hash.cc" + "log/absl_check.h" + "log/absl_log.h" + "log/absl_vlog_is_on.h" + "log/check.h" + "log/die_if_null.cc" + "log/die_if_null.h" + "log/globals.cc" + "log/globals.h" + "log/internal/append_truncated.h" + "log/internal/check_impl.h" + "log/internal/check_op.cc" + "log/internal/check_op.h" + "log/internal/conditions.cc" + "log/internal/conditions.h" + "log/internal/config.h" + "log/internal/fnmatch.h" + "log/internal/fnmatch.cc" + "log/internal/globals.cc" + "log/internal/globals.h" + "log/internal/log_format.cc" + "log/internal/log_format.h" + "log/internal/log_impl.h" + "log/internal/log_message.cc" + "log/internal/log_message.h" + "log/internal/log_sink_set.cc" + "log/internal/log_sink_set.h" + "log/internal/nullguard.cc" + "log/internal/nullguard.h" + "log/internal/nullstream.h" + "log/internal/proto.h" + "log/internal/proto.cc" + "log/internal/strip.h" + "log/internal/structured.h" + "log/internal/structured_proto.cc" + "log/internal/structured_proto.h" + "log/internal/vlog_config.cc" + "log/internal/vlog_config.h" + "log/internal/voidify.h" + "log/initialize.cc" + "log/initialize.h" + "log/log.h" + "log/log_entry.cc" + "log/log_entry.h" + "log/log_sink.cc" + "log/log_sink.h" + "log/log_sink_registry.h" + "log/log_streamer.h" + "log/structured.h" + "log/vlog_is_on.h" + "memory/memory.h" + "meta/type_traits.h" + "numeric/bits.h" + "numeric/int128.cc" + "numeric/int128.h" + "numeric/internal/bits.h" + "numeric/internal/representation.h" + "profiling/internal/exponential_biased.cc" + "profiling/internal/exponential_biased.h" + "profiling/internal/periodic_sampler.cc" + "profiling/internal/periodic_sampler.h" + "profiling/internal/sample_recorder.h" + "random/bernoulli_distribution.h" + "random/beta_distribution.h" + "random/bit_gen_ref.h" + "random/discrete_distribution.cc" + "random/discrete_distribution.h" + "random/distributions.h" + "random/exponential_distribution.h" + "random/gaussian_distribution.cc" + "random/gaussian_distribution.h" + "random/internal/distribution_caller.h" + "random/internal/fastmath.h" + "random/internal/fast_uniform_bits.h" + "random/internal/generate_real.h" + "random/internal/iostream_state_saver.h" + "random/internal/nonsecure_base.h" + "random/internal/pcg_engine.h" + "random/internal/platform.h" + "random/internal/pool_urbg.cc" + "random/internal/pool_urbg.h" + "random/internal/randen.cc" + "random/internal/randen.h" + "random/internal/randen_detect.cc" + "random/internal/randen_detect.h" + "random/internal/randen_engine.h" + "random/internal/randen_hwaes.cc" + "random/internal/randen_hwaes.h" + "random/internal/randen_round_keys.cc" + "random/internal/randen_slow.cc" + "random/internal/randen_slow.h" + "random/internal/randen_traits.h" + "random/internal/salted_seed_seq.h" + "random/internal/seed_material.cc" + "random/internal/seed_material.h" + "random/internal/sequence_urbg.h" + "random/internal/traits.h" + "random/internal/uniform_helper.h" + "random/internal/wide_multiply.h" + "random/log_uniform_int_distribution.h" + "random/poisson_distribution.h" + "random/random.h" + "random/seed_gen_exception.cc" + "random/seed_gen_exception.h" + "random/seed_sequences.cc" + "random/seed_sequences.h" + "random/uniform_int_distribution.h" + "random/uniform_real_distribution.h" + "random/zipf_distribution.h" + "status/internal/status_internal.h" + "status/internal/status_internal.cc" + "status/internal/statusor_internal.h" + "status/status.h" + "status/status.cc" + "status/statusor.h" + "status/statusor.cc" + "status/status_payload_printer.h" + "status/status_payload_printer.cc" + "strings/ascii.cc" + "strings/ascii.h" + "strings/charconv.cc" + "strings/charconv.h" + "strings/charset.h" + "strings/cord.cc" + "strings/cord.h" + "strings/cord_analysis.cc" + "strings/cord_analysis.h" + "strings/cord_buffer.cc" + "strings/cord_buffer.h" + "strings/escaping.cc" + "strings/escaping.h" + "strings/internal/charconv_bigint.cc" + "strings/internal/charconv_bigint.h" + "strings/internal/charconv_parse.cc" + "strings/internal/charconv_parse.h" + "strings/internal/cord_data_edge.h" + "strings/internal/cord_internal.cc" + "strings/internal/cord_internal.h" + "strings/internal/cord_rep_btree.cc" + "strings/internal/cord_rep_btree.h" + "strings/internal/cord_rep_btree_navigator.cc" + "strings/internal/cord_rep_btree_navigator.h" + "strings/internal/cord_rep_btree_reader.cc" + "strings/internal/cord_rep_btree_reader.h" + "strings/internal/cord_rep_crc.cc" + "strings/internal/cord_rep_crc.h" + "strings/internal/cord_rep_consume.h" + "strings/internal/cord_rep_consume.cc" + "strings/internal/cord_rep_flat.h" + "strings/internal/cordz_functions.cc" + "strings/internal/cordz_functions.h" + "strings/internal/cordz_handle.cc" + "strings/internal/cordz_handle.h" + "strings/internal/cordz_info.cc" + "strings/internal/cordz_info.h" + "strings/internal/cordz_sample_token.cc" + "strings/internal/cordz_sample_token.h" + "strings/internal/cordz_statistics.h" + "strings/internal/cordz_update_scope.h" + "strings/internal/cordz_update_tracker.h" + "strings/internal/damerau_levenshtein_distance.h" + "strings/internal/damerau_levenshtein_distance.cc" + "strings/internal/stl_type_traits.h" + "strings/internal/string_constant.h" + "strings/internal/stringify_sink.h" + "strings/internal/stringify_sink.cc" + "strings/has_absl_stringify.h" + "strings/has_ostream_operator.h" + "strings/match.cc" + "strings/match.h" + "strings/numbers.cc" + "strings/numbers.h" + "strings/str_format.h" + "strings/str_cat.cc" + "strings/str_cat.h" + "strings/str_join.h" + "strings/str_replace.cc" + "strings/str_replace.h" + "strings/str_split.cc" + "strings/str_split.h" + "strings/string_view.cc" + "strings/string_view.h" + "strings/strip.h" + "strings/substitute.cc" + "strings/substitute.h" + "strings/internal/escaping.h" + "strings/internal/escaping.cc" + "strings/internal/memutil.cc" + "strings/internal/memutil.h" + "strings/internal/ostringstream.cc" + "strings/internal/ostringstream.h" + "strings/internal/pow10_helper.cc" + "strings/internal/pow10_helper.h" + "strings/internal/resize_uninitialized.h" + "strings/internal/str_format/arg.cc" + "strings/internal/str_format/arg.h" + "strings/internal/str_format/bind.cc" + "strings/internal/str_format/bind.h" + "strings/internal/str_format/checker.h" + "strings/internal/str_format/constexpr_parser.h" + "strings/internal/str_format/extension.cc" + "strings/internal/str_format/extension.h" + "strings/internal/str_format/float_conversion.cc" + "strings/internal/str_format/float_conversion.h" + "strings/internal/str_format/output.cc" + "strings/internal/str_format/output.h" + "strings/internal/str_format/parser.cc" + "strings/internal/str_format/parser.h" + "strings/internal/str_join_internal.h" + "strings/internal/str_split_internal.h" + "strings/internal/utf8.cc" + "strings/internal/utf8.h" + "synchronization/barrier.cc" + "synchronization/barrier.h" + "synchronization/blocking_counter.cc" + "synchronization/blocking_counter.h" + "synchronization/mutex.cc" + "synchronization/mutex.h" + "synchronization/notification.cc" + "synchronization/notification.h" + "synchronization/internal/create_thread_identity.cc" + "synchronization/internal/create_thread_identity.h" + "synchronization/internal/futex.h" + "synchronization/internal/futex_waiter.h" + "synchronization/internal/futex_waiter.cc" + "synchronization/internal/graphcycles.cc" + "synchronization/internal/graphcycles.h" + "synchronization/internal/kernel_timeout.h" + "synchronization/internal/kernel_timeout.cc" + "synchronization/internal/per_thread_sem.cc" + "synchronization/internal/per_thread_sem.h" + "synchronization/internal/pthread_waiter.h" + "synchronization/internal/pthread_waiter.cc" + "synchronization/internal/sem_waiter.h" + "synchronization/internal/sem_waiter.cc" + "synchronization/internal/stdcpp_waiter.h" + "synchronization/internal/stdcpp_waiter.cc" + "synchronization/internal/thread_pool.h" + "synchronization/internal/waiter.h" + "synchronization/internal/waiter_base.h" + "synchronization/internal/waiter_base.cc" + "synchronization/internal/win32_waiter.h" + "synchronization/internal/win32_waiter.cc" + "time/civil_time.cc" + "time/civil_time.h" + "time/clock.cc" + "time/clock.h" + "time/duration.cc" + "time/format.cc" + "time/time.cc" + "time/time.h" + "time/internal/cctz/include/cctz/civil_time.h" + "time/internal/cctz/include/cctz/civil_time_detail.h" + "time/internal/cctz/include/cctz/time_zone.h" + "time/internal/cctz/include/cctz/zone_info_source.h" + "time/internal/cctz/src/civil_time_detail.cc" + "time/internal/cctz/src/time_zone_fixed.cc" + "time/internal/cctz/src/time_zone_fixed.h" + "time/internal/cctz/src/time_zone_format.cc" + "time/internal/cctz/src/time_zone_if.cc" + "time/internal/cctz/src/time_zone_if.h" + "time/internal/cctz/src/time_zone_impl.cc" + "time/internal/cctz/src/time_zone_impl.h" + "time/internal/cctz/src/time_zone_info.cc" + "time/internal/cctz/src/time_zone_info.h" + "time/internal/cctz/src/time_zone_libc.cc" + "time/internal/cctz/src/time_zone_libc.h" + "time/internal/cctz/src/time_zone_lookup.cc" + "time/internal/cctz/src/time_zone_posix.cc" + "time/internal/cctz/src/time_zone_posix.h" + "time/internal/cctz/src/tzfile.h" + "time/internal/cctz/src/zone_info_source.cc" + "types/any.h" + "types/bad_any_cast.cc" + "types/bad_any_cast.h" + "types/bad_optional_access.cc" + "types/bad_optional_access.h" + "types/bad_variant_access.cc" + "types/bad_variant_access.h" + "types/compare.h" + "types/internal/variant.h" + "types/optional.h" + "types/internal/optional.h" + "types/span.h" + "types/internal/span.h" + "types/variant.h" + "utility/internal/if_constexpr.h" + "utility/utility.h" + "debugging/leak_check.cc" +) + +if(NOT MSVC) + list(APPEND ABSL_INTERNAL_DLL_FILES + "flags/commandlineflag.cc" + "flags/commandlineflag.h" + "flags/config.h" + "flags/declare.h" + "flags/flag.h" + "flags/internal/commandlineflag.cc" + "flags/internal/commandlineflag.h" + "flags/internal/flag.cc" + "flags/internal/flag.h" + "flags/internal/parse.h" + "flags/internal/path_util.h" + "flags/internal/private_handle_accessor.cc" + "flags/internal/private_handle_accessor.h" + "flags/internal/program_name.cc" + "flags/internal/program_name.h" + "flags/internal/registry.h" + "flags/internal/sequence_lock.h" + "flags/internal/usage.cc" + "flags/internal/usage.h" + "flags/marshalling.cc" + "flags/marshalling.h" + "flags/parse.cc" + "flags/parse.h" + "flags/reflection.cc" + "flags/reflection.h" + "flags/usage.cc" + "flags/usage.h" + "flags/usage_config.cc" + "flags/usage_config.h" + "log/flags.cc" + "log/flags.h" + "log/internal/flags.h" + ) +endif() + +set(ABSL_INTERNAL_DLL_TARGETS + "absl_check" + "absl_log" + "absl_vlog_is_on" + "algorithm" + "algorithm_container" + "any" + "any_invocable" + "atomic_hook" + "bad_any_cast" + "bad_any_cast_impl" + "bad_optional_access" + "bad_variant_access" + "base" + "base_internal" + "bind_front" + "bits" + "btree" + "check" + "city" + "civil_time" + "compare" + "compressed_tuple" + "config" + "container" + "container_common" + "container_memory" + "cord" + "cord_internal" + "cordz_functions" + "cordz_handle" + "cordz_info" + "cordz_sample_token" + "core_headers" + "counting_allocator" + "crc_cord_state" + "crc_cpu_detect" + "crc_internal" + "crc32c" + "debugging" + "debugging_internal" + "demangle_internal" + "die_if_null" + "dynamic_annotations" + "endian" + "examine_stack" + "exponential_biased" + "failure_signal_handler" + "fixed_array" + "flat_hash_map" + "flat_hash_set" + "function_ref" + "graphcycles_internal" + "hash" + "hash_function_defaults" + "hash_policy_traits" + "hashtable_debug" + "hashtable_debug_hooks" + "hashtablez_sampler" + "inlined_vector" + "inlined_vector_internal" + "int128" + "kernel_timeout_internal" + "layout" + "leak_check" + "log_internal_check_impl" + "log_internal_check_op" + "log_internal_conditions" + "log_internal_config" + "log_internal_fnmatch" + "log_internal_format" + "log_internal_globals" + "log_internal_log_impl" + "log_internal_proto" + "log_internal_message" + "log_internal_log_sink_set" + "log_internal_nullguard" + "log_internal_nullstream" + "log_internal_strip" + "log_internal_voidify" + "log_internal_append_truncated" + "log_globals" + "log_initialize" + "log" + "log_entry" + "log_sink" + "log_sink_registry" + "log_streamer" + "log_internal_structured" + "log_severity" + "log_structured" + "low_level_hash" + "malloc_internal" + "memory" + "meta" + "node_hash_map" + "node_hash_set" + "node_slot_policy" + "non_temporal_arm_intrinsics" + "non_temporal_memcpy" + "numeric" + "optional" + "periodic_sampler" + "pow10_helper" + "pretty_function" + "random_bit_gen_ref" + "random_distributions" + "random_internal_distribution_caller" + "random_internal_distributions" + "random_internal_explicit_seed_seq" + "random_internal_fastmath" + "random_internal_fast_uniform_bits" + "random_internal_generate_real" + "random_internal_iostream_state_saver" + "random_internal_nonsecure_base" + "random_internal_pcg_engine" + "random_internal_platform" + "random_internal_pool_urbg" + "random_internal_randen" + "random_internal_randen_engine" + "random_internal_randen_hwaes" + "random_internal_randen_hwaes_impl" + "random_internal_randen_slow" + "random_internal_salted_seed_seq" + "random_internal_seed_material" + "random_internal_sequence_urbg" + "random_internal_traits" + "random_internal_uniform_helper" + "random_internal_wide_multiply" + "random_random" + "random_seed_gen_exception" + "random_seed_sequences" + "raw_hash_map" + "raw_hash_set" + "raw_logging_internal" + "sample_recorder" + "scoped_set_env" + "span" + "spinlock_wait" + "spy_hash_state" + "stack_consumption" + "stacktrace" + "status" + "statusor" + "str_format" + "str_format_internal" + "strerror" + "strings" + "strings_internal" + "string_view" + "symbolize" + "synchronization" + "thread_pool" + "throw_delegate" + "time" + "time_zone" + "tracked" + "type_traits" + "utility" + "variant" + "vlog_config_internal" + "vlog_is_on" +) + +if(NOT MSVC) + list(APPEND ABSL_INTERNAL_DLL_TARGETS + "flags" + "flags_commandlineflag" + "flags_commandlineflag_internal" + "flags_config" + "flags_internal" + "flags_marshalling" + "flags_parse" + "flags_path_util" + "flags_private_handle_accessor" + "flags_program_name" + "flags_reflection" + "flags_usage" + "flags_usage_internal" + "log_internal_flags" + "log_flags" + ) +endif() + +set(ABSL_INTERNAL_TEST_DLL_FILES + "hash/hash_testing.h" + "log/scoped_mock_log.cc" + "log/scoped_mock_log.h" + "random/internal/chi_square.cc" + "random/internal/chi_square.h" + "random/internal/distribution_test_util.cc" + "random/internal/distribution_test_util.h" + "random/internal/mock_helpers.h" + "random/internal/mock_overload_set.h" + "random/mocking_bit_gen.h" + "random/mock_distributions.h" + "status/status_matchers.h" + "status/internal/status_matchers.cc" + "status/internal/status_matchers.h" + "strings/cordz_test_helpers.h" + "strings/cord_test_helpers.h" +) + +set(ABSL_INTERNAL_TEST_DLL_TARGETS + "cord_test_helpers" + "cordz_test_helpers" + "hash_testing" + "random_mocking_bit_gen" + "random_internal_distribution_test_util" + "random_internal_mock_overload_set" + "scoped_mock_log" + "status_matchers" +) + +include(CheckCXXSourceCompiles) + +check_cxx_source_compiles( + [==[ +#ifdef _MSC_VER +# if _MSVC_LANG < 201703L +# error "The compiler defaults or is configured for C++ < 17" +# endif +#elif __cplusplus < 201703L +# error "The compiler defaults or is configured for C++ < 17" +#endif +int main() { return 0; } +]==] + ABSL_INTERNAL_AT_LEAST_CXX17) + +check_cxx_source_compiles( + [==[ +#ifdef _MSC_VER +# if _MSVC_LANG < 202002L +# error "The compiler defaults or is configured for C++ < 20" +# endif +#elif __cplusplus < 202002L +# error "The compiler defaults or is configured for C++ < 20" +#endif +int main() { return 0; } +]==] + ABSL_INTERNAL_AT_LEAST_CXX20) + +if(ABSL_INTERNAL_AT_LEAST_CXX20) + set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_20) +elseif(ABSL_INTERNAL_AT_LEAST_CXX17) + set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_17) +else() + set(ABSL_INTERNAL_CXX_STD_FEATURE cxx_std_14) +endif() + +function(absl_internal_dll_contains) + cmake_parse_arguments(ABSL_INTERNAL_DLL + "" + "OUTPUT;TARGET" + "" + ${ARGN} + ) + + STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_DLL_TARGET}) + + if (_target IN_LIST ABSL_INTERNAL_DLL_TARGETS) + set(${ABSL_INTERNAL_DLL_OUTPUT} 1 PARENT_SCOPE) + else() + set(${ABSL_INTERNAL_DLL_OUTPUT} 0 PARENT_SCOPE) + endif() +endfunction() + +function(absl_internal_test_dll_contains) + cmake_parse_arguments(ABSL_INTERNAL_TEST_DLL + "" + "OUTPUT;TARGET" + "" + ${ARGN} + ) + + STRING(REGEX REPLACE "^absl::" "" _target ${ABSL_INTERNAL_TEST_DLL_TARGET}) + + if (_target IN_LIST ABSL_INTERNAL_TEST_DLL_TARGETS) + set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 1 PARENT_SCOPE) + else() + set(${ABSL_INTERNAL_TEST_DLL_OUTPUT} 0 PARENT_SCOPE) + endif() +endfunction() + +function(absl_internal_dll_targets) + cmake_parse_arguments(ABSL_INTERNAL_DLL + "" + "OUTPUT" + "DEPS" + ${ARGN} + ) + + set(_deps "") + foreach(dep IN LISTS ABSL_INTERNAL_DLL_DEPS) + absl_internal_dll_contains(TARGET ${dep} OUTPUT _dll_contains) + absl_internal_test_dll_contains(TARGET ${dep} OUTPUT _test_dll_contains) + if (_dll_contains) + list(APPEND _deps abseil_dll) + elseif (_test_dll_contains) + list(APPEND _deps abseil_test_dll) + else() + list(APPEND _deps ${dep}) + endif() + endforeach() + + # Because we may have added the DLL multiple times + list(REMOVE_DUPLICATES _deps) + set(${ABSL_INTERNAL_DLL_OUTPUT} "${_deps}" PARENT_SCOPE) +endfunction() + +function(absl_make_dll) + cmake_parse_arguments(ABSL_INTERNAL_MAKE_DLL + "" + "TEST" + "" + ${ARGN} + ) + + if (ABSL_INTERNAL_MAKE_DLL_TEST) + set(_dll "abseil_test_dll") + set(_dll_files ${ABSL_INTERNAL_TEST_DLL_FILES}) + set(_dll_libs "abseil_dll" "GTest::gtest" "GTest::gmock") + set(_dll_compile_definitions "GTEST_LINKED_AS_SHARED_LIBRARY=1") + set(_dll_includes ${absl_gtest_src_dir}/googletest/include ${absl_gtest_src_dir}/googlemock/include) + set(_dll_consume "ABSL_CONSUME_TEST_DLL") + set(_dll_build "ABSL_BUILD_TEST_DLL") + else() + set(_dll "abseil_dll") + set(_dll_files ${ABSL_INTERNAL_DLL_FILES}) + set(_dll_libs + Threads::Threads + # TODO(#1495): Use $ once our + # minimum CMake version >= 3.24 + $<$:-Wl,-framework,CoreFoundation> + ) + set(_dll_compile_definitions "") + set(_dll_includes "") + set(_dll_consume "ABSL_CONSUME_DLL") + set(_dll_build "ABSL_BUILD_DLL") + endif() + + add_library( + ${_dll} + SHARED + ${_dll_files} + ) + target_link_libraries( + ${_dll} + PRIVATE + ${_dll_libs} + ${ABSL_DEFAULT_LINKOPTS} + ) + set_target_properties(${_dll} PROPERTIES + LINKER_LANGUAGE "CXX" + SOVERSION ${ABSL_SOVERSION} + ) + target_include_directories( + ${_dll} + PUBLIC + "$" + $ + PRIVATE + ${_dll_includes} + ) + + target_compile_options( + ${_dll} + PRIVATE + ${ABSL_DEFAULT_COPTS} + ) + + foreach(cflag ${ABSL_CC_LIB_COPTS}) + if(${cflag} MATCHES "^(-Wno|/wd)") + # These flags are needed to suppress warnings that might fire in our headers. + set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") + elseif(${cflag} MATCHES "^(-W|/w[1234eo])") + # Don't impose our warnings on others. + else() + set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") + endif() + endforeach() + string(REPLACE ";" " " PC_LINKOPTS "${ABSL_CC_LIB_LINKOPTS}") + + FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc" CONTENT "\ +prefix=${CMAKE_INSTALL_PREFIX}\n\ +exec_prefix=\${prefix}\n\ +libdir=${CMAKE_INSTALL_FULL_LIBDIR}\n\ +includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\n\ +\n\ +Name: ${_dll}\n\ +Description: Abseil DLL library\n\ +URL: https://abseil.io/\n\ +Version: ${absl_VERSION}\n\ +Libs: -L\${libdir} $<$>:-l${_dll}> ${PC_LINKOPTS}\n\ +Cflags: -I\${includedir}${PC_CFLAGS}\n") + INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/${_dll}.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + + target_compile_definitions( + ${_dll} + PUBLIC + ${_dll_compile_definitions} + PRIVATE + ${_dll_build} + NOMINMAX + INTERFACE + ${ABSL_CC_LIB_DEFINES} + ${_dll_consume} + ) + + if(ABSL_PROPAGATE_CXX_STD) + # Abseil libraries require C++14 as the current minimum standard. When + # compiled with a higher minimum (either because it is the compiler's + # default or explicitly requested), then Abseil requires that standard. + target_compile_features(${_dll} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) + endif() + + install(TARGETS ${_dll} EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + + add_library(absl::${_dll} ALIAS ${_dll}) +endfunction() diff --git a/third_party/abseil/CMake/AbseilHelpers.cmake b/third_party/abseil/CMake/AbseilHelpers.cmake new file mode 100644 index 0000000000..d8fb9fe5de --- /dev/null +++ b/third_party/abseil/CMake/AbseilHelpers.cmake @@ -0,0 +1,460 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +include(CMakeParseArguments) +include(AbseilConfigureCopts) +include(AbseilDll) + +# The IDE folder for Abseil that will be used if Abseil is included in a CMake +# project that sets +# set_property(GLOBAL PROPERTY USE_FOLDERS ON) +# For example, Visual Studio supports folders. +if(NOT DEFINED ABSL_IDE_FOLDER) + set(ABSL_IDE_FOLDER Abseil) +endif() + +if(ABSL_USE_SYSTEM_INCLUDES) + set(ABSL_INTERNAL_INCLUDE_WARNING_GUARD SYSTEM) +else() + set(ABSL_INTERNAL_INCLUDE_WARNING_GUARD "") +endif() + +# absl_cc_library() +# +# CMake function to imitate Bazel's cc_library rule. +# +# Parameters: +# NAME: name of target (see Note) +# HDRS: List of public header files for the library +# SRCS: List of source files for the library +# DEPS: List of other libraries to be linked in to the binary targets +# COPTS: List of private compile options +# DEFINES: List of public defines +# LINKOPTS: List of link options +# PUBLIC: Add this so that this library will be exported under absl:: +# Also in IDE, target will appear in Abseil folder while non PUBLIC will be in Abseil/internal. +# TESTONLY: When added, this target will only be built if both +# BUILD_TESTING=ON and ABSL_BUILD_TESTING=ON. +# +# Note: +# By default, absl_cc_library will always create a library named absl_${NAME}, +# and alias target absl::${NAME}. The absl:: form should always be used. +# This is to reduce namespace pollution. +# +# absl_cc_library( +# NAME +# awesome +# HDRS +# "a.h" +# SRCS +# "a.cc" +# ) +# absl_cc_library( +# NAME +# fantastic_lib +# SRCS +# "b.cc" +# DEPS +# absl::awesome # not "awesome" ! +# PUBLIC +# ) +# +# absl_cc_library( +# NAME +# main_lib +# ... +# DEPS +# absl::fantastic_lib +# ) +# +# TODO(b/320467376): Implement "ALWAYSLINK". +function(absl_cc_library) + cmake_parse_arguments(ABSL_CC_LIB + "DISABLE_INSTALL;PUBLIC;TESTONLY" + "NAME" + "HDRS;SRCS;COPTS;DEFINES;LINKOPTS;DEPS" + ${ARGN} + ) + + if(ABSL_CC_LIB_TESTONLY AND + NOT ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR + (ABSL_BUILD_TEST_HELPERS AND ABSL_CC_LIB_PUBLIC))) + return() + endif() + + if(ABSL_ENABLE_INSTALL) + set(_NAME "${ABSL_CC_LIB_NAME}") + else() + set(_NAME "absl_${ABSL_CC_LIB_NAME}") + endif() + + # Check if this is a header-only library + # Note that as of February 2019, many popular OS's (for example, Ubuntu + # 16.04 LTS) only come with cmake 3.5 by default. For this reason, we can't + # use list(FILTER...) + set(ABSL_CC_SRCS "${ABSL_CC_LIB_SRCS}") + foreach(src_file IN LISTS ABSL_CC_SRCS) + if(${src_file} MATCHES ".*\\.(h|inc)") + list(REMOVE_ITEM ABSL_CC_SRCS "${src_file}") + endif() + endforeach() + + if(ABSL_CC_SRCS STREQUAL "") + set(ABSL_CC_LIB_IS_INTERFACE 1) + else() + set(ABSL_CC_LIB_IS_INTERFACE 0) + endif() + + # Determine this build target's relationship to the DLL. It's one of four things: + # 1. "dll" -- This target is part of the DLL + # 2. "dll_dep" -- This target is not part of the DLL, but depends on the DLL. + # Note that we assume any target not in the DLL depends on the + # DLL. This is not a technical necessity but a convenience + # which happens to be true, because nearly every target is + # part of the DLL. + # 3. "shared" -- This is a shared library, perhaps on a non-windows platform + # where DLL doesn't make sense. + # 4. "static" -- This target does not depend on the DLL and should be built + # statically. + if (${ABSL_BUILD_DLL}) + if(ABSL_ENABLE_INSTALL) + absl_internal_dll_contains(TARGET ${_NAME} OUTPUT _in_dll) + absl_internal_test_dll_contains(TARGET ${_NAME} OUTPUT _in_test_dll) + else() + absl_internal_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_dll) + absl_internal_test_dll_contains(TARGET ${ABSL_CC_LIB_NAME} OUTPUT _in_test_dll) + endif() + if (${_in_dll} OR ${_in_test_dll}) + # This target should be replaced by the DLL + set(_build_type "dll") + set(ABSL_CC_LIB_IS_INTERFACE 1) + else() + # Building a DLL, but this target is not part of the DLL + set(_build_type "dll_dep") + endif() + elseif(BUILD_SHARED_LIBS) + set(_build_type "shared") + else() + set(_build_type "static") + endif() + + # Generate a pkg-config file for every library: + if(ABSL_ENABLE_INSTALL) + if(absl_VERSION) + set(PC_VERSION "${absl_VERSION}") + else() + set(PC_VERSION "head") + endif() + if(NOT _build_type STREQUAL "dll") + set(LNK_LIB "${LNK_LIB} -labsl_${_NAME}") + endif() + foreach(dep ${ABSL_CC_LIB_DEPS}) + if(${dep} MATCHES "^absl::(.*)") + # for DLL builds many libs are not created, but add + # the pkgconfigs nevertheless, pointing to the dll. + if(_build_type STREQUAL "dll") + # hide this MATCHES in an if-clause so it doesn't overwrite + # the CMAKE_MATCH_1 from (${dep} MATCHES "^absl::(.*)") + if(NOT PC_DEPS MATCHES "abseil_dll") + # Join deps with commas. + if(PC_DEPS) + set(PC_DEPS "${PC_DEPS},") + endif() + # don't duplicate dll-dep if it exists already + set(PC_DEPS "${PC_DEPS} abseil_dll = ${PC_VERSION}") + set(LNK_LIB "${LNK_LIB} -labseil_dll") + endif() + else() + # Join deps with commas. + if(PC_DEPS) + set(PC_DEPS "${PC_DEPS},") + endif() + set(PC_DEPS "${PC_DEPS} absl_${CMAKE_MATCH_1} = ${PC_VERSION}") + endif() + endif() + endforeach() + foreach(cflag ${ABSL_CC_LIB_COPTS}) + # Strip out the CMake-specific `SHELL:` prefix, which is used to construct + # a group of space-separated options. + # https://cmake.org/cmake/help/v3.30/command/target_compile_options.html#option-de-duplication + string(REGEX REPLACE "^SHELL:" "" cflag "${cflag}") + if(${cflag} MATCHES "^-Xarch_") + # An -Xarch_ flag implies that its successor only applies to the + # specified platform. Such option groups are each specified in a single + # `SHELL:`-prefixed string in the COPTS list, which we simply ignore. + elseif(${cflag} MATCHES "^(-Wno-|/wd)") + # These flags are needed to suppress warnings that might fire in our headers. + set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") + elseif(${cflag} MATCHES "^(-W|/w[1234eo])") + # Don't impose our warnings on others. + elseif(${cflag} MATCHES "^-m") + # Don't impose CPU instruction requirements on others, as + # the code performs feature detection on runtime. + else() + set(PC_CFLAGS "${PC_CFLAGS} ${cflag}") + endif() + endforeach() + string(REPLACE ";" " " PC_LINKOPTS "${ABSL_CC_LIB_LINKOPTS}") + FILE(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" CONTENT "\ +prefix=${CMAKE_INSTALL_PREFIX}\n\ +exec_prefix=\${prefix}\n\ +libdir=${CMAKE_INSTALL_FULL_LIBDIR}\n\ +includedir=${CMAKE_INSTALL_FULL_INCLUDEDIR}\n\ +\n\ +Name: absl_${_NAME}\n\ +Description: Abseil ${_NAME} library\n\ +URL: https://abseil.io/\n\ +Version: ${PC_VERSION}\n\ +Requires:${PC_DEPS}\n\ +Libs: -L\${libdir} $<$>:${LNK_LIB}> ${PC_LINKOPTS}\n\ +Cflags: -I\${includedir}${PC_CFLAGS}\n") + INSTALL(FILES "${CMAKE_BINARY_DIR}/lib/pkgconfig/absl_${_NAME}.pc" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig") + endif() + + if(NOT ABSL_CC_LIB_IS_INTERFACE) + if(_build_type STREQUAL "dll_dep") + # This target depends on the DLL. When adding dependencies to this target, + # any depended-on-target which is contained inside the DLL is replaced + # with a dependency on the DLL. + add_library(${_NAME} STATIC "") + target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) + absl_internal_dll_targets( + DEPS ${ABSL_CC_LIB_DEPS} + OUTPUT _dll_deps + ) + target_link_libraries(${_NAME} + PUBLIC ${_dll_deps} + PRIVATE + ${ABSL_CC_LIB_LINKOPTS} + ${ABSL_DEFAULT_LINKOPTS} + ) + + if (ABSL_CC_LIB_TESTONLY) + set(_gtest_link_define "GTEST_LINKED_AS_SHARED_LIBRARY=1") + else() + set(_gtest_link_define) + endif() + + target_compile_definitions(${_NAME} + PUBLIC + ABSL_CONSUME_DLL + "${_gtest_link_define}" + ) + + elseif(_build_type STREQUAL "static" OR _build_type STREQUAL "shared") + add_library(${_NAME} "") + target_sources(${_NAME} PRIVATE ${ABSL_CC_LIB_SRCS} ${ABSL_CC_LIB_HDRS}) + if(APPLE) + set_target_properties(${_NAME} PROPERTIES + INSTALL_RPATH "@loader_path") + elseif(UNIX) + set_target_properties(${_NAME} PROPERTIES + INSTALL_RPATH "$ORIGIN") + endif() + target_link_libraries(${_NAME} + PUBLIC ${ABSL_CC_LIB_DEPS} + PRIVATE + ${ABSL_CC_LIB_LINKOPTS} + ${ABSL_DEFAULT_LINKOPTS} + ) + else() + message(FATAL_ERROR "Invalid build type: ${_build_type}") + endif() + + # Linker language can be inferred from sources, but in the case of DLLs we + # don't have any .cc files so it would be ambiguous. We could set it + # explicitly only in the case of DLLs but, because "CXX" is always the + # correct linker language for static or for shared libraries, we set it + # unconditionally. + set_property(TARGET ${_NAME} PROPERTY LINKER_LANGUAGE "CXX") + + target_include_directories(${_NAME} ${ABSL_INTERNAL_INCLUDE_WARNING_GUARD} + PUBLIC + "$" + $ + ) + target_compile_options(${_NAME} + PRIVATE ${ABSL_CC_LIB_COPTS}) + target_compile_definitions(${_NAME} PUBLIC ${ABSL_CC_LIB_DEFINES}) + + # Add all Abseil targets to a a folder in the IDE for organization. + if(ABSL_CC_LIB_PUBLIC) + set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}) + elseif(ABSL_CC_LIB_TESTONLY) + set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) + else() + set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/internal) + endif() + + if(ABSL_PROPAGATE_CXX_STD) + # Abseil libraries require C++14 as the current minimum standard. When + # compiled with a higher standard (either because it is the compiler's + # default or explicitly requested), then Abseil requires that standard. + target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) + endif() + + # When being installed, we lose the absl_ prefix. We want to put it back + # to have properly named lib files. This is a no-op when we are not being + # installed. + if(ABSL_ENABLE_INSTALL) + set_target_properties(${_NAME} PROPERTIES + OUTPUT_NAME "absl_${_NAME}" + SOVERSION "${ABSL_SOVERSION}" + ) + endif() + else() + # Generating header-only library + add_library(${_NAME} INTERFACE) + target_include_directories(${_NAME} ${ABSL_INTERNAL_INCLUDE_WARNING_GUARD} + INTERFACE + "$" + $ + ) + + if (_build_type STREQUAL "dll") + set(ABSL_CC_LIB_DEPS abseil_dll) + endif() + + target_link_libraries(${_NAME} + INTERFACE + ${ABSL_CC_LIB_DEPS} + ${ABSL_CC_LIB_LINKOPTS} + ${ABSL_DEFAULT_LINKOPTS} + ) + target_compile_definitions(${_NAME} INTERFACE ${ABSL_CC_LIB_DEFINES}) + + if(ABSL_PROPAGATE_CXX_STD) + # Abseil libraries require C++14 as the current minimum standard. + # Top-level application CMake projects should ensure a consistent C++ + # standard for all compiled sources by setting CMAKE_CXX_STANDARD. + target_compile_features(${_NAME} INTERFACE ${ABSL_INTERNAL_CXX_STD_FEATURE}) + endif() + endif() + + if(ABSL_ENABLE_INSTALL) + install(TARGETS ${_NAME} EXPORT ${PROJECT_NAME}Targets + RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} + LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} + ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} + ) + endif() + + add_library(absl::${ABSL_CC_LIB_NAME} ALIAS ${_NAME}) +endfunction() + +# absl_cc_test() +# +# CMake function to imitate Bazel's cc_test rule. +# +# Parameters: +# NAME: name of target (see Usage below) +# SRCS: List of source files for the binary +# DEPS: List of other libraries to be linked in to the binary targets +# COPTS: List of private compile options +# DEFINES: List of public defines +# LINKOPTS: List of link options +# +# Note: +# By default, absl_cc_test will always create a binary named absl_${NAME}. +# This will also add it to ctest list as absl_${NAME}. +# +# Usage: +# absl_cc_library( +# NAME +# awesome +# HDRS +# "a.h" +# SRCS +# "a.cc" +# PUBLIC +# ) +# +# absl_cc_test( +# NAME +# awesome_test +# SRCS +# "awesome_test.cc" +# DEPS +# absl::awesome +# GTest::gmock +# GTest::gtest_main +# ) +function(absl_cc_test) + if(NOT (BUILD_TESTING AND ABSL_BUILD_TESTING)) + return() + endif() + + cmake_parse_arguments(ABSL_CC_TEST + "" + "NAME" + "SRCS;COPTS;DEFINES;LINKOPTS;DEPS" + ${ARGN} + ) + + set(_NAME "absl_${ABSL_CC_TEST_NAME}") + + add_executable(${_NAME} "") + target_sources(${_NAME} PRIVATE ${ABSL_CC_TEST_SRCS}) + target_include_directories(${_NAME} + PUBLIC ${ABSL_COMMON_INCLUDE_DIRS} + PRIVATE ${absl_gtest_src_dir}/googletest/include ${absl_gtest_src_dir}/googlemock/include + ) + + if (${ABSL_BUILD_DLL}) + target_compile_definitions(${_NAME} + PUBLIC + ${ABSL_CC_TEST_DEFINES} + ABSL_CONSUME_DLL + ABSL_CONSUME_TEST_DLL + GTEST_LINKED_AS_SHARED_LIBRARY=1 + ) + + # Replace dependencies on targets inside the DLL with abseil_dll itself. + absl_internal_dll_targets( + DEPS ${ABSL_CC_TEST_DEPS} + OUTPUT ABSL_CC_TEST_DEPS + ) + absl_internal_dll_targets( + DEPS ${ABSL_CC_TEST_LINKOPTS} + OUTPUT ABSL_CC_TEST_LINKOPTS + ) + else() + target_compile_definitions(${_NAME} + PUBLIC + ${ABSL_CC_TEST_DEFINES} + ) + endif() + target_compile_options(${_NAME} + PRIVATE ${ABSL_CC_TEST_COPTS} + ) + + target_link_libraries(${_NAME} + PUBLIC ${ABSL_CC_TEST_DEPS} + PRIVATE ${ABSL_CC_TEST_LINKOPTS} + ) + # Add all Abseil targets to a folder in the IDE for organization. + set_property(TARGET ${_NAME} PROPERTY FOLDER ${ABSL_IDE_FOLDER}/test) + + if(ABSL_PROPAGATE_CXX_STD) + # Abseil libraries require C++14 as the current minimum standard. + # Top-level application CMake projects should ensure a consistent C++ + # standard for all compiled sources by setting CMAKE_CXX_STANDARD. + target_compile_features(${_NAME} PUBLIC ${ABSL_INTERNAL_CXX_STD_FEATURE}) + endif() + + add_test(NAME ${_NAME} COMMAND ${_NAME}) +endfunction() diff --git a/third_party/abseil/CMake/Googletest/CMakeLists.txt.in b/third_party/abseil/CMake/Googletest/CMakeLists.txt.in new file mode 100644 index 0000000000..3db48341a2 --- /dev/null +++ b/third_party/abseil/CMake/Googletest/CMakeLists.txt.in @@ -0,0 +1,14 @@ +cmake_minimum_required(VERSION 3.16) + +project(googletest-external NONE) + +include(ExternalProject) +ExternalProject_Add(googletest + URL "${absl_gtest_download_url}" # May be empty + SOURCE_DIR "${absl_gtest_src_dir}" + BINARY_DIR "${absl_gtest_build_dir}" + CONFIGURE_COMMAND "" + BUILD_COMMAND "" + INSTALL_COMMAND "" + TEST_COMMAND "" +) diff --git a/third_party/abseil/CMake/Googletest/DownloadGTest.cmake b/third_party/abseil/CMake/Googletest/DownloadGTest.cmake new file mode 100644 index 0000000000..9d071c9170 --- /dev/null +++ b/third_party/abseil/CMake/Googletest/DownloadGTest.cmake @@ -0,0 +1,41 @@ +# Integrates googletest at configure time. Based on the instructions at +# https://github.com/google/googletest/tree/master/googletest#incorporating-into-an-existing-cmake-project + +# Set up the external googletest project, downloading the latest from Github +# master if requested. +configure_file( + ${CMAKE_CURRENT_LIST_DIR}/CMakeLists.txt.in + ${CMAKE_BINARY_DIR}/googletest-external/CMakeLists.txt +) + +set(ABSL_SAVE_CMAKE_CXX_FLAGS ${CMAKE_CXX_FLAGS}) +set(ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}) +if (BUILD_SHARED_LIBS) + set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DGTEST_CREATE_SHARED_LIBRARY=1") +endif() + +# Configure and build the googletest source. +execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external ) +if(result) + message(FATAL_ERROR "CMake step for googletest failed: ${result}") +endif() + +execute_process(COMMAND ${CMAKE_COMMAND} --build . + RESULT_VARIABLE result + WORKING_DIRECTORY ${CMAKE_BINARY_DIR}/googletest-external) +if(result) + message(FATAL_ERROR "Build step for googletest failed: ${result}") +endif() + +set(CMAKE_CXX_FLAGS ${ABSL_SAVE_CMAKE_CXX_FLAGS}) +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${ABSL_SAVE_CMAKE_RUNTIME_OUTPUT_DIRECTORY}) + +# Prevent overriding the parent project's compiler/linker settings on Windows +set(gtest_force_shared_crt ON CACHE BOOL "" FORCE) + +# Add googletest directly to our build. This defines the gtest and gtest_main +# targets. +add_subdirectory(${absl_gtest_src_dir} ${absl_gtest_build_dir} EXCLUDE_FROM_ALL) diff --git a/third_party/abseil/CMake/README.md b/third_party/abseil/CMake/README.md new file mode 100644 index 0000000000..808edfe855 --- /dev/null +++ b/third_party/abseil/CMake/README.md @@ -0,0 +1,188 @@ +# Abseil CMake Build Instructions + +Abseil comes with a CMake build script ([CMakeLists.txt](../CMakeLists.txt)) +that can be used on a wide range of platforms ("C" stands for cross-platform.). +If you don't have CMake installed already, you can download it for free from +. + +CMake works by generating native makefiles or build projects that can +be used in the compiler environment of your choice. + +For API/ABI compatibility reasons, we strongly recommend building Abseil in a +subdirectory of your project or as an embedded dependency. + +## Incorporating Abseil Into a CMake Project + +The recommendations below are similar to those for using CMake within the +googletest framework +() + +### Step-by-Step Instructions + +1. If you want to build the Abseil tests, integrate the Abseil dependency +[Google Test](https://github.com/google/googletest) into your CMake +project. To disable Abseil tests, you have to pass either +`-DBUILD_TESTING=OFF` or `-DABSL_BUILD_TESTING=OFF` when configuring your +project with CMake. + +2. Download Abseil and copy it into a subdirectory in your CMake project or add +Abseil as a [git submodule](https://git-scm.com/docs/git-submodule) in your +CMake project. + +3. You can then use the CMake command +[`add_subdirectory()`](https://cmake.org/cmake/help/latest/command/add_subdirectory.html) +to include Abseil directly in your CMake project. + +4. Add the **absl::** target you wish to use to the +[`target_link_libraries()`](https://cmake.org/cmake/help/latest/command/target_link_libraries.html) +section of your executable or of your library.
+Here is a short CMakeLists.txt example of an application project using Abseil. + +```cmake +cmake_minimum_required(VERSION 3.16) +project(my_app_project) + +# Pick the C++ standard to compile with. +# Abseil currently supports C++14, C++17, and C++20. +set(CMAKE_CXX_STANDARD 14) +set(CMAKE_CXX_STANDARD_REQUIRED ON) + +add_subdirectory(abseil-cpp) + +add_executable(my_exe source.cpp) +target_link_libraries(my_exe absl::base absl::synchronization absl::strings) +``` + +Note that if you are developing a library designed for use by other clients, you +should instead leave `CMAKE_CXX_STANDARD` unset (or only set if being built as +the current top-level CMake project) and configure the minimum required C++ +standard at the target level. If you require a later minimum C++ standard than +Abseil does, it's a good idea to also enforce that `CMAKE_CXX_STANDARD` (which +will control Abseil library targets) is set to at least that minimum. For +example: + +```cmake +cmake_minimum_required(VERSION 3.16) +project(my_lib_project) + +# Leave C++ standard up to the root application, so set it only if this is the +# current top-level CMake project. +if(CMAKE_SOURCE_DIR STREQUAL my_lib_project_SOURCE_DIR) + set(CMAKE_CXX_STANDARD 17) + set(CMAKE_CXX_STANDARD_REQUIRED ON) +endif() + +add_subdirectory(abseil-cpp) + +add_library(my_lib source.cpp) +target_link_libraries(my_lib absl::base absl::synchronization absl::strings) + +# Enforce that my_lib requires C++17. Important to document for clients that they +# must set CMAKE_CXX_STANDARD to 17 or higher for proper Abseil ABI compatibility +# (since otherwise, Abseil library targets could be compiled with a lower C++ +# standard than my_lib). +target_compile_features(my_lib PUBLIC cxx_std_17) +if(CMAKE_CXX_STANDARD LESS 17) + message(FATAL_ERROR + "my_lib_project requires CMAKE_CXX_STANDARD >= 17 (got: ${CMAKE_CXX_STANDARD})") +endif() +``` + +Then the top-level application project that uses your library is responsible for +setting a consistent `CMAKE_CXX_STANDARD` that is sufficiently high. + +### Running Abseil Tests with CMake + +Use the `-DABSL_BUILD_TESTING=ON` flag to run Abseil tests. Note that +BUILD_TESTING must also be on (the default). + +You will need to provide Abseil with a Googletest dependency. There are two +options for how to do this: + +* Use `-DABSL_USE_GOOGLETEST_HEAD`. This will automatically download the latest +Googletest source into the build directory at configure time. Googletest will +then be compiled directly alongside Abseil's tests. +* Manually integrate Googletest with your build. See +https://github.com/google/googletest/blob/master/googletest/README.md#using-cmake +for more information on using Googletest in a CMake project. + +For example, to run just the Abseil tests, you could use this script: + +``` +cd path/to/abseil-cpp +mkdir build +cd build +cmake -DABSL_BUILD_TESTING=ON -DABSL_USE_GOOGLETEST_HEAD=ON .. +make -j +ctest +``` + +Currently, we only run our tests with CMake in a Linux environment, but we are +working on the rest of our supported platforms. See +https://github.com/abseil/abseil-cpp/projects/1 and +https://github.com/abseil/abseil-cpp/issues/109 for more information. + +### Available Abseil CMake Public Targets + +Here's a non-exhaustive list of Abseil CMake public targets: + +```cmake +absl::algorithm +absl::base +absl::debugging +absl::flat_hash_map +absl::flags +absl::memory +absl::meta +absl::numeric +absl::random_random +absl::strings +absl::synchronization +absl::time +absl::utility +``` + +## Traditional CMake Set-Up + +For larger projects, it may make sense to use the traditional CMake set-up where you build and install projects separately. + +First, you'd need to build and install Google Test: +``` +cmake -S /source/googletest -B /build/googletest -DCMAKE_BUILD_TYPE=Release -DCMAKE_INSTALL_PREFIX=/installation/dir -DBUILD_GMOCK=ON +cmake --build /build/googletest --target install +``` + +Then you need to configure and build Abseil. Make sure you enable `ABSL_USE_EXTERNAL_GOOGLETEST` and `ABSL_FIND_GOOGLETEST`. You also need to enable `ABSL_ENABLE_INSTALL` so that you can install Abseil itself. +``` +cmake -S /source/abseil-cpp -B /build/abseil-cpp -DCMAKE_PREFIX_PATH=/installation/dir -DCMAKE_INSTALL_PREFIX=/installation/dir -DABSL_ENABLE_INSTALL=ON -DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON +cmake --build /temporary/build/abseil-cpp +``` + +(`CMAKE_PREFIX_PATH` is where you already have Google Test installed; `CMAKE_INSTALL_PREFIX` is where you want to have Abseil installed; they can be different.) + +Run the tests: +``` +ctest --test-dir /temporary/build/abseil-cpp +``` + +And finally install: +``` +cmake --build /temporary/build/abseil-cpp --target install +``` + +# CMake Option Synopsis + +## Enable Standard CMake Installation + +`-DABSL_ENABLE_INSTALL=ON` + +## Google Test Options + +`-DABSL_BUILD_TESTING=ON` must be set to enable testing + +- Have Abseil download and build Google Test for you: `-DABSL_USE_EXTERNAL_GOOGLETEST=OFF` (default) + - Download and build latest Google Test: `-DABSL_USE_GOOGLETEST_HEAD=ON` + - Download specific Google Test version (ZIP archive): `-DABSL_GOOGLETEST_DOWNLOAD_URL=https://.../version.zip` + - Use Google Test from specific local directory: `-DABSL_LOCAL_GOOGLETEST_DIR=/path/to/googletest` +- Use Google Test included elsewhere in your project: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON` +- Use standard CMake `find_package(CTest)` to find installed Google Test: `-DABSL_USE_EXTERNAL_GOOGLETEST=ON -DABSL_FIND_GOOGLETEST=ON` diff --git a/third_party/abseil/CMake/abslConfig.cmake.in b/third_party/abseil/CMake/abslConfig.cmake.in new file mode 100644 index 0000000000..62d246d01e --- /dev/null +++ b/third_party/abseil/CMake/abslConfig.cmake.in @@ -0,0 +1,8 @@ +# absl CMake configuration file. + +include(CMakeFindDependencyMacro) +find_dependency(Threads) + +@PACKAGE_INIT@ + +include ("${CMAKE_CURRENT_LIST_DIR}/@PROJECT_NAME@Targets.cmake") diff --git a/third_party/abseil/CMake/install_test_project/CMakeLists.txt b/third_party/abseil/CMake/install_test_project/CMakeLists.txt new file mode 100644 index 0000000000..3229887c8d --- /dev/null +++ b/third_party/abseil/CMake/install_test_project/CMakeLists.txt @@ -0,0 +1,25 @@ +# +# Copyright 2019 The Abseil Authors. +# +# 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 +# +# https://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. + +# A simple CMakeLists.txt for testing cmake installation + +cmake_minimum_required(VERSION 3.16) +project(absl_cmake_testing CXX) + +add_executable(simple simple.cc) + +find_package(absl REQUIRED) + +target_link_libraries(simple absl::strings absl::config) diff --git a/third_party/abseil/CMake/install_test_project/simple.cc b/third_party/abseil/CMake/install_test_project/simple.cc new file mode 100644 index 0000000000..7daa7f0901 --- /dev/null +++ b/third_party/abseil/CMake/install_test_project/simple.cc @@ -0,0 +1,32 @@ +// +// Copyright 2019 The Abseil Authors. +// +// 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 +// +// https://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. + +#include +#include "absl/base/config.h" +#include "absl/strings/substitute.h" + +#if !defined(ABSL_LTS_RELEASE_VERSION) || ABSL_LTS_RELEASE_VERSION != 99998877 +#error ABSL_LTS_RELEASE_VERSION is not set correctly. +#endif + +#if !defined(ABSL_LTS_RELEASE_PATCH_LEVEL) || ABSL_LTS_RELEASE_PATCH_LEVEL != 0 +#error ABSL_LTS_RELEASE_PATCH_LEVEL is not set correctly. +#endif + +int main(int argc, char** argv) { + for (int i = 0; i < argc; ++i) { + std::cout << absl::Substitute("Arg $0: $1\n", i, argv[i]); + } +} diff --git a/third_party/abseil/CMake/install_test_project/test.sh b/third_party/abseil/CMake/install_test_project/test.sh new file mode 100755 index 0000000000..962bc8d2d8 --- /dev/null +++ b/third_party/abseil/CMake/install_test_project/test.sh @@ -0,0 +1,113 @@ +#!/bin/bash +# +# Copyright 2019 The Abseil Authors. +# +# 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 +# +# https://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. +# +# Unit and integration tests for Abseil LTS CMake installation + +# Fail on any error. Treat unset variables an error. Print commands as executed. +set -euox pipefail + +absl_dir=/abseil-cpp +absl_build_dir=/buildfs +googletest_builddir=/googletest_builddir +googletest_archive="googletest-${ABSL_GOOGLETEST_VERSION}.tar.gz" +project_dir="${absl_dir}/CMake/install_test_project" +project_build_dir=/buildfs/project-build + +build_shared_libs="OFF" +if [ "${LINK_TYPE:-}" = "DYNAMIC" ]; then + build_shared_libs="ON" +fi + +# Build and install GoogleTest +mkdir "${googletest_builddir}" +pushd "${googletest_builddir}" +curl -L "${ABSL_GOOGLETEST_DOWNLOAD_URL}" --output "${googletest_archive}" +tar -xz -f "${googletest_archive}" +pushd "googletest-${ABSL_GOOGLETEST_VERSION}" +mkdir build +pushd build +cmake -DCMAKE_BUILD_TYPE=Release -DBUILD_SHARED_LIBS="${build_shared_libs}" .. +make -j $(nproc) +make install +ldconfig +popd +popd +popd + +# Run the LTS transformations +./create_lts.py 99998877 + +# Build and install Abseil +pushd "${absl_build_dir}" +cmake "${absl_dir}" \ + -DABSL_USE_EXTERNAL_GOOGLETEST=ON \ + -DABSL_FIND_GOOGLETEST=ON \ + -DCMAKE_BUILD_TYPE=Release \ + -DABSL_BUILD_TESTING=ON \ + -DBUILD_SHARED_LIBS="${build_shared_libs}" +make -j $(nproc) +ctest -j $(nproc) --output-on-failure +make install +ldconfig +popd + +# Test the project against the installed Abseil +mkdir -p "${project_build_dir}" +pushd "${project_build_dir}" +cmake "${project_dir}" +cmake --build . --target simple + +output="$(${project_build_dir}/simple "printme" 2>&1)" +if [[ "${output}" != *"Arg 1: printme"* ]]; then + echo "Faulty output on simple project:" + echo "${output}" + exit 1 +fi + +popd + +if ! grep absl::strings "/usr/local/lib/cmake/absl/abslTargets.cmake"; then + cat "/usr/local/lib/cmake/absl/abslTargets.cmake" + echo "CMake targets named incorrectly" + exit 1 +fi + +pushd "${HOME}" +cat > hello-abseil.cc << EOF +#include + +#include "absl/strings/str_format.h" + +int main(int argc, char **argv) { + absl::PrintF("Hello Abseil!\n"); + return EXIT_SUCCESS; +} +EOF + +if [ "${LINK_TYPE:-}" != "DYNAMIC" ]; then + pc_args=($(pkg-config --cflags --libs --static absl_str_format)) + g++ -static -o hello-abseil hello-abseil.cc "${pc_args[@]}" +else + pc_args=($(pkg-config --cflags --libs absl_str_format)) + g++ -o hello-abseil hello-abseil.cc "${pc_args[@]}" +fi +hello="$(./hello-abseil)" +[[ "${hello}" == "Hello Abseil!" ]] + +popd + +echo "Install test complete!" +exit 0 diff --git a/third_party/abseil/CMakeLists.txt b/third_party/abseil/CMakeLists.txt new file mode 100644 index 0000000000..27411b456b --- /dev/null +++ b/third_party/abseil/CMakeLists.txt @@ -0,0 +1,280 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +# https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md +# As of 2024-07-01, CMake 3.16 is the minimum supported version. +cmake_minimum_required(VERSION 3.16) + +# Allow the user to specify the CMAKE_MSVC_DEBUG_INFORMATION_FORMAT +if (POLICY CMP0141) + cmake_policy(SET CMP0141 NEW) +endif (POLICY CMP0141) + +project(absl LANGUAGES CXX) +set(ABSL_SOVERSION 0) +include(CTest) + +# Output directory is correct by default for most build setups. However, when +# building Abseil as a DLL, it is important to have the DLL in the same +# directory as the executable using it. Thus, we put all executables in a single +# /bin directory. +set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) + +# when absl is included as subproject (i.e. using add_subdirectory(abseil-cpp)) +# in the source tree of a project that uses it, install rules are disabled. +if(NOT CMAKE_SOURCE_DIR STREQUAL PROJECT_SOURCE_DIR) + option(ABSL_ENABLE_INSTALL "Enable install rule" OFF) +else() + option(ABSL_ENABLE_INSTALL "Enable install rule" ON) +endif() + +set(CMAKE_INSTALL_RPATH "$ORIGIN") +set(CMAKE_INSTALL_RPATH_USE_LINK_PATH ON) +set(CMAKE_BUILD_RPATH_USE_ORIGIN ON) + +option(ABSL_PROPAGATE_CXX_STD + "Use CMake C++ standard meta features (e.g. cxx_std_14) that propagate to targets that link to Abseil" + ON) + +option(ABSL_USE_SYSTEM_INCLUDES + "Silence warnings in Abseil headers by marking them as SYSTEM includes" + OFF) + +list(APPEND CMAKE_MODULE_PATH + ${CMAKE_CURRENT_LIST_DIR}/CMake + ${CMAKE_CURRENT_LIST_DIR}/absl/copts +) + +option(ABSL_MSVC_STATIC_RUNTIME + "Link static runtime libraries" + OFF) +if(ABSL_MSVC_STATIC_RUNTIME) + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>") +else() + set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$:Debug>DLL") +endif() + +include(CMakePackageConfigHelpers) +include(GNUInstallDirs) +include(AbseilDll) +include(AbseilHelpers) + + +## +## Using absl targets +## +## all public absl targets are +## exported with the absl:: prefix +## +## e.g absl::base absl::synchronization absl::strings .... +## +## DO NOT rely on the internal targets outside of the prefix + + +# include current path +list(APPEND ABSL_COMMON_INCLUDE_DIRS ${CMAKE_CURRENT_SOURCE_DIR}) + +if("${CMAKE_CXX_COMPILER_ID}" MATCHES "Clang") + set(ABSL_USING_CLANG ON) +else() + set(ABSL_USING_CLANG OFF) +endif() + +# find dependencies +## pthread +find_package(Threads REQUIRED) + +include(CMakeDependentOption) + +option(ABSL_BUILD_TESTING + "If ON, Abseil will build all of Abseil's own tests." OFF) + +option(ABSL_BUILD_TEST_HELPERS + "If ON, Abseil will build libraries that you can use to write tests against Abseil code. This option requires that Abseil is configured to use GoogleTest." + OFF) + +option(ABSL_USE_EXTERNAL_GOOGLETEST + "If ON, Abseil will assume that the targets for GoogleTest are already provided by the including project. This makes sense when Abseil is used with add_subdirectory." OFF) + +cmake_dependent_option(ABSL_FIND_GOOGLETEST + "If ON, Abseil will use find_package(GTest) rather than assuming that GoogleTest is already provided by the including project." + ON + "ABSL_USE_EXTERNAL_GOOGLETEST" + OFF) + + +option(ABSL_USE_GOOGLETEST_HEAD + "If ON, abseil will download HEAD from GoogleTest at config time." OFF) + +set(ABSL_GOOGLETEST_DOWNLOAD_URL "" CACHE STRING "If set, download GoogleTest from this URL") + +set(ABSL_LOCAL_GOOGLETEST_DIR "/usr/src/googletest" CACHE PATH + "If ABSL_USE_GOOGLETEST_HEAD is OFF and ABSL_GOOGLETEST_URL is not set, specifies the directory of a local GoogleTest checkout." + ) + +option(ABSL_BUILD_MONOLITHIC_SHARED_LIBS + "Build Abseil as a single shared library (always enabled for Windows)" + OFF +) +if(NOT BUILD_SHARED_LIBS AND ABSL_BUILD_MONOLITHIC_SHARED_LIBS) + message(WARNING "Not building a shared library because BUILD_SHARED_LIBS is not set. Ignoring ABSL_BUILD_MONOLITHIC_SHARED_LIBS.") +endif() + +if((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS) + if (ABSL_USE_EXTERNAL_GOOGLETEST) + if (ABSL_FIND_GOOGLETEST) + find_package(GTest REQUIRED) + elseif(NOT TARGET GTest::gtest) + if(TARGET gtest) + # When Google Test is included directly rather than through find_package, the aliases are missing. + add_library(GTest::gtest ALIAS gtest) + add_library(GTest::gtest_main ALIAS gtest_main) + add_library(GTest::gmock ALIAS gmock) + add_library(GTest::gmock_main ALIAS gmock_main) + else() + message(FATAL_ERROR "ABSL_USE_EXTERNAL_GOOGLETEST is ON and ABSL_FIND_GOOGLETEST is OFF, which means that the top-level project must build the Google Test project. However, the target gtest was not found.") + endif() + endif() + else() + set(absl_gtest_build_dir ${CMAKE_BINARY_DIR}/googletest-build) + if(ABSL_USE_GOOGLETEST_HEAD AND ABSL_GOOGLETEST_DOWNLOAD_URL) + message(FATAL_ERROR "Do not set both ABSL_USE_GOOGLETEST_HEAD and ABSL_GOOGLETEST_DOWNLOAD_URL") + endif() + if(ABSL_USE_GOOGLETEST_HEAD) + set(absl_gtest_download_url "https://github.com/google/googletest/archive/main.zip") + elseif(ABSL_GOOGLETEST_DOWNLOAD_URL) + set(absl_gtest_download_url ${ABSL_GOOGLETEST_DOWNLOAD_URL}) + endif() + if(absl_gtest_download_url) + set(absl_gtest_src_dir ${CMAKE_BINARY_DIR}/googletest-src) + else() + set(absl_gtest_src_dir ${ABSL_LOCAL_GOOGLETEST_DIR}) + endif() + include(CMake/Googletest/DownloadGTest.cmake) + endif() +endif() + +add_subdirectory(absl) + +if(ABSL_ENABLE_INSTALL) + # absl:lts-remove-begin(system installation is supported for LTS releases) + # We don't support system-wide installation + list(APPEND SYSTEM_INSTALL_DIRS "/usr/local" "/usr" "/opt/" "/opt/local" "c:/Program Files/${PROJECT_NAME}") + if(NOT DEFINED CMAKE_INSTALL_PREFIX OR CMAKE_INSTALL_PREFIX IN_LIST SYSTEM_INSTALL_DIRS) + message(WARNING "\ + The default and system-level install directories are unsupported except in LTS \ + releases of Abseil. Please set CMAKE_INSTALL_PREFIX to install Abseil in your \ + source or build tree directly.\ + ") + endif() + # absl:lts-remove-end + + # install as a subdirectory only + install(EXPORT ${PROJECT_NAME}Targets + NAMESPACE absl:: + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" + ) + + configure_package_config_file( + CMake/abslConfig.cmake.in + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + INSTALL_DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" + ) + install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}Config.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" + ) + + # Abseil only has a version in LTS releases. This mechanism is accomplished + # Abseil's internal Copybara (https://github.com/google/copybara) workflows and + # isn't visible in the CMake buildsystem itself. + if(absl_VERSION) + write_basic_package_version_file( + "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + COMPATIBILITY ExactVersion + ) + + install(FILES "${PROJECT_BINARY_DIR}/${PROJECT_NAME}ConfigVersion.cmake" + DESTINATION "${CMAKE_INSTALL_LIBDIR}/cmake/${PROJECT_NAME}" + ) + endif() # absl_VERSION + + # Install the headers except for "options.h" which is installed separately. + install(DIRECTORY absl + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR} + FILES_MATCHING + PATTERN "*.inc" + PATTERN "*.h" + PATTERN "options.h" EXCLUDE + PATTERN "copts" EXCLUDE + PATTERN "testdata" EXCLUDE + ) + + # Rewrite options.h to use the compiled ABI. + file(READ "absl/base/options.h" ABSL_INTERNAL_OPTIONS_H_CONTENTS) + + # Handle features that require at least C++20. + if (ABSL_INTERNAL_AT_LEAST_CXX20) + foreach(FEATURE "ORDERING") + string(REPLACE + "#define ABSL_OPTION_USE_STD_${FEATURE} 2" + "#define ABSL_OPTION_USE_STD_${FEATURE} 1" + ABSL_INTERNAL_OPTIONS_H_PINNED + "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") + set(ABSL_INTERNAL_OPTIONS_H_CONTENTS "${ABSL_INTERNAL_OPTIONS_H_PINNED}") + endforeach() + endif() + + # Handle features that require at least C++17. + if (ABSL_INTERNAL_AT_LEAST_CXX17) + foreach(FEATURE "ANY" "OPTIONAL" "STRING_VIEW" "VARIANT") + string(REPLACE + "#define ABSL_OPTION_USE_STD_${FEATURE} 2" + "#define ABSL_OPTION_USE_STD_${FEATURE} 1" + ABSL_INTERNAL_OPTIONS_H_PINNED + "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") + set(ABSL_INTERNAL_OPTIONS_H_CONTENTS "${ABSL_INTERNAL_OPTIONS_H_PINNED}") + endforeach() + endif() + + # Any feature that still has the value of 2 (because it was not handled above) + # should be set to 0. + string(REGEX REPLACE + "#define ABSL_OPTION_USE_STD_([^ ]*) 2" + "#define ABSL_OPTION_USE_STD_\\1 0" + ABSL_INTERNAL_OPTIONS_H_PINNED + "${ABSL_INTERNAL_OPTIONS_H_CONTENTS}") + + # If the file already exists, check if it matches the new contents. + # This avoids writing the file if it is already up-to-date when the CMake + # generation is triggered and triggering unnecessary rebuilds. + set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE TRUE) + if (EXISTS "${CMAKE_BINARY_DIR}/options-pinned.h") + file(READ "${CMAKE_BINARY_DIR}/options-pinned.h" ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS) + if ("${ABSL_INTERNAL_OPTIONS_H_PINNED}" STREQUAL "${ABSL_INTERNAL_OPTIONS_PINNED_H_CONTENTS}") + set(ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE FALSE) + endif() + endif() + + # If the file needs an update, generate it. + if (ABSL_INTERNAL_OPTIONS_H_PINNED_NEEDS_UPDATE) + file(GENERATE OUTPUT "${CMAKE_BINARY_DIR}/options-pinned.h" CONTENT "${ABSL_INTERNAL_OPTIONS_H_PINNED}") + endif() + + install(FILES "${CMAKE_BINARY_DIR}/options-pinned.h" + DESTINATION ${CMAKE_INSTALL_INCLUDEDIR}/absl/base + RENAME "options.h") + +endif() # ABSL_ENABLE_INSTALL diff --git a/third_party/abseil/CONTRIBUTING.md b/third_party/abseil/CONTRIBUTING.md new file mode 100644 index 0000000000..a87254c503 --- /dev/null +++ b/third_party/abseil/CONTRIBUTING.md @@ -0,0 +1,141 @@ +# How to Contribute to Abseil + +We'd love to accept your patches and contributions to this project. There are +just a few small guidelines you need to follow. + +NOTE: If you are new to GitHub, please start by reading [Pull Request +howto](https://help.github.com/articles/about-pull-requests/) + +## Contributor License Agreement + +Contributions to this project must be accompanied by a Contributor License +Agreement. You (or your employer) retain the copyright to your contribution, +this simply gives us permission to use and redistribute your contributions as +part of the project. Head over to to see +your current agreements on file or to sign a new one. + +You generally only need to submit a CLA once, so if you've already submitted one +(even if it was for a different project), you probably don't need to do it +again. + +## Contribution Guidelines + +Potential contributors sometimes ask us if the Abseil project is the appropriate +home for their utility library code or for specific functions implementing +missing portions of the standard. Often, the answer to this question is "no". +We’d like to articulate our thinking on this issue so that our choices can be +understood by everyone and so that contributors can have a better intuition +about whether Abseil might be interested in adopting a new library. + +### Priorities + +Although our mission is to augment the C++ standard library, our goal is not to +provide a full forward-compatible implementation of the latest standard. For us +to consider a library for inclusion in Abseil, it is not enough that a library +is useful. We generally choose to release a library when it meets at least one +of the following criteria: + +* **Widespread usage** - Using our internal codebase to help gauge usage, most + of the libraries we've released have tens of thousands of users. +* **Anticipated widespread usage** - Pre-adoption of some standard-compliant + APIs may not have broad adoption initially but can be expected to pick up + usage when it replaces legacy APIs. `absl::from_chars`, for example, + replaces existing code that converts strings to numbers and will therefore + likely see usage growth. +* **High impact** - APIs that provide a key solution to a specific problem, + such as `absl::FixedArray`, have higher impact than usage numbers may signal + and are released because of their importance. +* **Direct support for a library that falls under one of the above** - When we + want access to a smaller library as an implementation detail for a + higher-priority library we plan to release, we may release it, as we did + with portions of `absl/meta/type_traits.h`. One consequence of this is that + the presence of a library in Abseil does not necessarily mean that other + similar libraries would be a high priority. + +### API Freeze Consequences + +Via the +[Abseil Compatibility Guidelines](https://abseil.io/about/compatibility), we +have promised a large degree of API stability. In particular, we will not make +backward-incompatible changes to released APIs without also shipping a tool or +process that can upgrade our users' code. We are not yet at the point of easily +releasing such tools. Therefore, at this time, shipping a library establishes an +API contract which is borderline unchangeable. (We can add new functionality, +but we cannot easily change existing behavior.) This constraint forces us to +very carefully review all APIs that we ship. + + +## Coding Style + +To keep the source consistent, readable, diffable and easy to merge, we use a +fairly rigid coding style, as defined by the +[google-styleguide](https://github.com/google/styleguide) project. All patches +will be expected to conform to the style outlined +[here](https://google.github.io/styleguide/cppguide.html). + +## Guidelines for Pull Requests + +* If you are a Googler, it is required that you send us a Piper CL instead of + using the GitHub pull-request process. The code propagation process will + deliver the change to GitHub. + +* Create **small PRs** that are narrowly focused on **addressing a single + concern**. We often receive PRs that are trying to fix several things at a + time, but if only one fix is considered acceptable, nothing gets merged and + both author's & review's time is wasted. Create more PRs to address + different concerns and everyone will be happy. + +* For speculative changes, consider opening an [Abseil + issue](https://github.com/abseil/abseil-cpp/issues) and discussing it first. + If you are suggesting a behavioral or API change, consider starting with an + [Abseil proposal template](ABSEIL_ISSUE_TEMPLATE.md). + +* Provide a good **PR description** as a record of **what** change is being + made and **why** it was made. Link to a GitHub issue if it exists. + +* Don't fix code style and formatting unless you are already changing that + line to address an issue. Formatting of modified lines may be done using + `git clang-format`. PRs with irrelevant changes won't be merged. If + you do want to fix formatting or style, do that in a separate PR. + +* Unless your PR is trivial, you should expect there will be reviewer comments + that you'll need to address before merging. We expect you to be reasonably + responsive to those comments, otherwise the PR will be closed after 2-3 + weeks of inactivity. + +* Maintain **clean commit history** and use **meaningful commit messages**. + PRs with messy commit history are difficult to review and won't be merged. + Use `rebase -i upstream/master` to curate your commit history and/or to + bring in latest changes from master (but avoid rebasing in the middle of a + code review). + +* Keep your PR up to date with upstream/master (if there are merge conflicts, + we can't really merge your change). + +* **All tests need to be passing** before your change can be merged. We + recommend you **run tests locally** (see below) + +* Exceptions to the rules can be made if there's a compelling reason for doing + so. That is - the rules are here to serve us, not the other way around, and + the rules need to be serving their intended purpose to be valuable. + +* All submissions, including submissions by project members, require review. + +## Running Tests + +If you have [Bazel](https://bazel.build/) installed, use `bazel test +--test_tag_filters="-benchmark" ...` to run the unit tests. + +If you are running the Linux operating system and have +[Docker](https://www.docker.com/) installed, you can also run the `linux_*.sh` +scripts under the `ci/`(https://github.com/abseil/abseil-cpp/tree/master/ci) +directory to test Abseil under a variety of conditions. + +## Abseil Committers + +The current members of the Abseil engineering team are the only committers at +present. + +## Release Process + +Abseil lives at head, where latest-and-greatest code can be found. diff --git a/third_party/abseil/FAQ.md b/third_party/abseil/FAQ.md new file mode 100644 index 0000000000..fbd92ce975 --- /dev/null +++ b/third_party/abseil/FAQ.md @@ -0,0 +1,167 @@ +# Abseil FAQ + +## Is Abseil the right home for my utility library? + +Most often the answer to the question is "no." As both the [About +Abseil](https://abseil.io/about/) page and our [contributing +guidelines](https://github.com/abseil/abseil-cpp/blob/master/CONTRIBUTING.md#contribution-guidelines) +explain, Abseil contains a variety of core C++ library code that is widely used +at [Google](https://www.google.com/). As such, Abseil's primary purpose is to be +used as a dependency by Google's open source C++ projects. While we do hope that +Abseil is also useful to the C++ community at large, this added constraint also +means that we are unlikely to accept a contribution of utility code that isn't +already widely used by Google. + +## How to I set the C++ dialect used to build Abseil? + +The short answer is that whatever mechanism you choose, you need to make sure +that you set this option consistently at the global level for your entire +project. If, for example, you want to set the C++ dialect to C++17, with +[Bazel](https://bazel/build/) as the build system and `gcc` or `clang` as the +compiler, there several ways to do this: +* Pass `--cxxopt=-std=c++17` on the command line (for example, `bazel build + --cxxopt=-std=c++17 ...`) +* Set the environment variable `BAZEL_CXXOPTS` (for example, + `BAZEL_CXXOPTS=-std=c++17`) +* Add `build --cxxopt=-std=c++17` to your [`.bazelrc` + file](https://docs.bazel.build/versions/master/guide.html#bazelrc) + +If you are using CMake as the build system, you'll need to add a line like +`set(CMAKE_CXX_STANDARD 17)` to your top level `CMakeLists.txt` file. If you +are developing a library designed to be used by other clients, you should +instead leave `CMAKE_CXX_STANDARD` unset and configure the minimum C++ standard +required by each of your library targets via `target_compile_features`. See the +[CMake build +instructions](https://github.com/abseil/abseil-cpp/blob/master/CMake/README.md) +for more information. + +For a longer answer to this question and to understand why some other approaches +don't work, see the answer to ["What is ABI and why don't you recommend using a +pre-compiled version of +Abseil?"](#what-is-abi-and-why-dont-you-recommend-using-a-pre-compiled-version-of-abseil) + +## What is ABI and why don't you recommend using a pre-compiled version of Abseil? + +For the purposes of this discussion, you can think of +[ABI](https://en.wikipedia.org/wiki/Application_binary_interface) as the +compiled representation of the interfaces in code. This is in contrast to +[API](https://en.wikipedia.org/wiki/Application_programming_interface), which +you can think of as the interfaces as defined by the code itself. [Abseil has a +strong promise of API compatibility, but does not make any promise of ABI +compatibility](https://abseil.io/about/compatibility). Let's take a look at what +this means in practice. + +You might be tempted to do something like this in a +[Bazel](https://bazel.build/) `BUILD` file: + +``` +# DON'T DO THIS!!! +cc_library( + name = "my_library", + srcs = ["my_library.cc"], + copts = ["-std=c++17"], # May create a mixed-mode compile! + deps = ["@com_google_absl//absl/strings"], +) +``` + +Applying `-std=c++17` to an individual target in your `BUILD` file is going to +compile that specific target in C++17 mode, but it isn't going to ensure the +Abseil library is built in C++17 mode, since the Abseil library itself is a +different build target. If your code includes an Abseil header, then your +program may contain conflicting definitions of the same +class/function/variable/enum, etc. As a rule, all compile options that affect +the ABI of a program need to be applied to the entire build on a global basis. + +C++ has something called the [One Definition +Rule](https://en.wikipedia.org/wiki/One_Definition_Rule) (ODR). C++ doesn't +allow multiple definitions of the same class/function/variable/enum, etc. ODR +violations sometimes result in linker errors, but linkers do not always catch +violations. Uncaught ODR violations can result in strange runtime behaviors or +crashes that can be hard to debug. + +If you build the Abseil library and your code using different compile options +that affect ABI, there is a good chance you will run afoul of the One Definition +Rule. Examples of GCC compile options that affect ABI include (but aren't +limited to) language dialect (e.g. `-std=`), optimization level (e.g. `-O2`), +code generation flags (e.g. `-fexceptions`), and preprocessor defines +(e.g. `-DNDEBUG`). + +If you use a pre-compiled version of Abseil, (for example, from your Linux +distribution package manager or from something like +[vcpkg](https://github.com/microsoft/vcpkg)) you have to be very careful to +ensure ABI compatibility across the components of your program. The only way you +can be sure your program is going to be correct regarding ABI is to ensure +you've used the exact same compile options as were used to build the +pre-compiled library. This does not mean that Abseil cannot work as part of a +Linux distribution since a knowledgeable binary packager will have ensured that +all packages have been built with consistent compile options. This is one of the +reasons we warn against - though do not outright reject - using Abseil as a +pre-compiled library. + +Another possible way that you might afoul of ABI issues is if you accidentally +include two versions of Abseil in your program. Multiple versions of Abseil can +end up within the same binary if your program uses the Abseil library and +another library also transitively depends on Abseil (resulting in what is +sometimes called the diamond dependency problem). In cases such as this you must +structure your build so that all libraries use the same version of Abseil. +[Abseil's strong promise of API compatibility between +releases](https://abseil.io/about/compatibility) means the latest "HEAD" release +of Abseil is almost certainly the right choice if you are doing as we recommend +and building all of your code from source. + +For these reasons we recommend you avoid pre-compiled code and build the Abseil +library yourself in a consistent manner with the rest of your code. + +## What is "live at head" and how do I do it? + +From Abseil's point-of-view, "live at head" means that every Abseil source +release (which happens on an almost daily basis) is either API compatible with +the previous release, or comes with an automated tool that you can run over code +to make it compatible. In practice, the need to use an automated tool is +extremely rare. This means that upgrading from one source release to another +should be a routine practice that can and should be performed often. + +We recommend you update to the [latest commit in the `master` branch of +Abseil](https://github.com/abseil/abseil-cpp/commits/master) as often as +possible. Not only will you pick up bug fixes more quickly, but if you have good +automated testing, you will catch and be able to fix any [Hyrum's +Law](https://www.hyrumslaw.com/) dependency problems on an incremental basis +instead of being overwhelmed by them and having difficulty isolating them if you +wait longer between updates. + +If you are using the [Bazel](https://bazel.build/) build system and its +[external dependencies](https://docs.bazel.build/versions/master/external.html) +feature, updating the +[`http_archive`](https://docs.bazel.build/versions/master/repo/http.html#http_archive) +rule in your +[`WORKSPACE`](https://docs.bazel.build/versions/master/be/workspace.html) for +`com_google_abseil` to point to the [latest commit in the `master` branch of +Abseil](https://github.com/abseil/abseil-cpp/commits/master) is all you need to +do. For example, on February 11, 2020, the latest commit to the master branch +was `98eb410c93ad059f9bba1bf43f5bb916fc92a5ea`. To update to this commit, you +would add the following snippet to your `WORKSPACE` file: + +``` +http_archive( + name = "com_google_absl", + urls = ["https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip"], # 2020-02-11T18:50:53Z + strip_prefix = "abseil-cpp-98eb410c93ad059f9bba1bf43f5bb916fc92a5ea", + sha256 = "aabf6c57e3834f8dc3873a927f37eaf69975d4b28117fc7427dfb1c661542a87", +) +``` + +To get the `sha256` of this URL, run `curl -sL --output - +https://github.com/abseil/abseil-cpp/archive/98eb410c93ad059f9bba1bf43f5bb916fc92a5ea.zip +| sha256sum -`. + +You can commit the updated `WORKSPACE` file to your source control every time +you update, and if you have good automated testing, you might even consider +automating this. + +One thing we don't recommend is using GitHub's `master.zip` files (for example +[https://github.com/abseil/abseil-cpp/archive/master.zip](https://github.com/abseil/abseil-cpp/archive/master.zip)), +which are always the latest commit in the `master` branch, to implement live at +head. Since these `master.zip` URLs are not versioned, you will lose build +reproducibility. In addition, some build systems, including Bazel, will simply +cache this file, which means you won't actually be updating to the latest +release until your cache is cleared or invalidated. diff --git a/third_party/abseil/LICENSE b/third_party/abseil/LICENSE new file mode 100644 index 0000000000..ccd61dcfe3 --- /dev/null +++ b/third_party/abseil/LICENSE @@ -0,0 +1,203 @@ + + Apache License + Version 2.0, January 2004 + https://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + 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 + + https://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. + diff --git a/third_party/abseil/MODULE.bazel b/third_party/abseil/MODULE.bazel new file mode 100644 index 0000000000..9805065391 --- /dev/null +++ b/third_party/abseil/MODULE.bazel @@ -0,0 +1,46 @@ +# Copyright 2024 The Abseil Authors. +# +# 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 +# +# https://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. + +# https://bazel.build/external/overview#bzlmod + +module( + name = "abseil-cpp", + version = "head", + compatibility_level = 1, +) + +cc_configure = use_extension("@rules_cc//cc:extensions.bzl", + "cc_configure_extension", + dev_dependency = True) +use_repo(cc_configure, "local_config_cc") + +# Only direct dependencies need to be listed below. +# Please keep the versions in sync with the versions in the WORKSPACE file. + +bazel_dep(name = "rules_cc", version = "0.1.0") +bazel_dep(name = "bazel_skylib", version = "1.7.1") +bazel_dep(name = "platforms", version = "0.0.10") + +bazel_dep( + name = "google_benchmark", + version = "1.8.5", + dev_dependency = True, +) + +# Note: Googletest is NOT a dev_dependency. Some Abseil test utilities +# intended to be used by Abseil users depend on GoogleTest. +bazel_dep( + name = "googletest", + version = "1.15.2", +) diff --git a/third_party/abseil/PrivacyInfo.xcprivacy b/third_party/abseil/PrivacyInfo.xcprivacy new file mode 100644 index 0000000000..3ff4a9d98b --- /dev/null +++ b/third_party/abseil/PrivacyInfo.xcprivacy @@ -0,0 +1,14 @@ + + + + + NSPrivacyTracking + + NSPrivacyCollectedDataTypes + + NSPrivacyTrackingDomains + + NSPrivacyAccessedAPITypes + + + diff --git a/third_party/abseil/README.md b/third_party/abseil/README.md new file mode 100644 index 0000000000..f834fcdec0 --- /dev/null +++ b/third_party/abseil/README.md @@ -0,0 +1,160 @@ +# Abseil - C++ Common Libraries + +The repository contains the Abseil C++ library code. Abseil is an open-source +collection of C++ code (compliant to C++14) designed to augment the C++ +standard library. + +## Table of Contents + +- [About Abseil](#about) +- [Quickstart](#quickstart) +- [Building Abseil](#build) +- [Support](#support) +- [Codemap](#codemap) +- [Releases](#releases) +- [License](#license) +- [Links](#links) + + +## About Abseil + +Abseil is an open-source collection of C++ library code designed to augment +the C++ standard library. The Abseil library code is collected from Google's +own C++ code base, has been extensively tested and used in production, and +is the same code we depend on in our daily coding lives. + +In some cases, Abseil provides pieces missing from the C++ standard; in +others, Abseil provides alternatives to the standard for special needs +we've found through usage in the Google code base. We denote those cases +clearly within the library code we provide you. + +Abseil is not meant to be a competitor to the standard library; we've +just found that many of these utilities serve a purpose within our code +base, and we now want to provide those resources to the C++ community as +a whole. + + +## Quickstart + +If you want to just get started, make sure you at least run through the +[Abseil Quickstart](https://abseil.io/docs/cpp/quickstart). The Quickstart +contains information about setting up your development environment, downloading +the Abseil code, running tests, and getting a simple binary working. + + +## Building Abseil + +[Bazel](https://bazel.build) and [CMake](https://cmake.org/) are the official +build systems for Abseil. +See the [quickstart](https://abseil.io/docs/cpp/quickstart) for more information +on building Abseil using the Bazel build system. +If you require CMake support, please check the [CMake build +instructions](CMake/README.md) and [CMake +Quickstart](https://abseil.io/docs/cpp/quickstart-cmake). + + +## Support + +Abseil follows Google's [Foundational C++ Support +Policy](https://opensource.google/documentation/policies/cplusplus-support). See +[this +table](https://github.com/google/oss-policies-info/blob/main/foundational-cxx-support-matrix.md) +for a list of currently supported versions compilers, platforms, and build +tools. + + +## Codemap + +Abseil contains the following C++ library components: + +* [`base`](absl/base/) +
The `base` library contains initialization code and other code which + all other Abseil code depends on. Code within `base` may not depend on any + other code (other than the C++ standard library). +* [`algorithm`](absl/algorithm/) +
The `algorithm` library contains additions to the C++ `` + library and container-based versions of such algorithms. +* [`cleanup`](absl/cleanup/) +
The `cleanup` library contains the control-flow-construct-like type + `absl::Cleanup` which is used for executing a callback on scope exit. +* [`container`](absl/container/) +
The `container` library contains additional STL-style containers, + including Abseil's unordered "Swiss table" containers. +* [`crc`](absl/crc/) The `crc` library contains code for + computing error-detecting cyclic redundancy checks on data. +* [`debugging`](absl/debugging/) +
The `debugging` library contains code useful for enabling leak + checks, and stacktrace and symbolization utilities. +* [`flags`](absl/flags/) +
The `flags` library contains code for handling command line flags for + libraries and binaries built with Abseil. +* [`hash`](absl/hash/) +
The `hash` library contains the hashing framework and default hash + functor implementations for hashable types in Abseil. +* [`log`](absl/log/) +
The `log` library contains `LOG` and `CHECK` macros and facilities + for writing logged messages out to disk, `stderr`, or user-extensible + destinations. +* [`memory`](absl/memory/) +
The `memory` library contains memory management facilities that augment + C++'s `` library. +* [`meta`](absl/meta/) +
The `meta` library contains compatible versions of type checks + available within C++14 and C++17 versions of the C++ `` library. +* [`numeric`](absl/numeric/) +
The `numeric` library contains 128-bit integer types as well as + implementations of C++20's bitwise math functions. +* [`profiling`](absl/profiling/) +
The `profiling` library contains utility code for profiling C++ + entities. It is currently a private dependency of other Abseil libraries. +* [`random`](absl/random/) +
The `random` library contains functions for generating psuedorandom + values. +* [`status`](absl/status/) +
The `status` library contains abstractions for error handling, + specifically `absl::Status` and `absl::StatusOr`. +* [`strings`](absl/strings/) +
The `strings` library contains a variety of strings routines and + utilities, including a C++14-compatible version of the C++17 + `std::string_view` type. +* [`synchronization`](absl/synchronization/) +
The `synchronization` library contains concurrency primitives (Abseil's + `absl::Mutex` class, an alternative to `std::mutex`) and a variety of + synchronization abstractions. +* [`time`](absl/time/) +
The `time` library contains abstractions for computing with absolute + points in time, durations of time, and formatting and parsing time within + time zones. +* [`types`](absl/types/) +
The `types` library contains non-container utility types, like a + C++14-compatible version of the C++17 `std::optional` type. +* [`utility`](absl/utility/) +
The `utility` library contains utility and helper code. + + +## Releases + +Abseil recommends users "live-at-head" (update to the latest commit from the +master branch as often as possible). However, we realize this philosophy doesn't +work for every project, so we also provide [Long Term Support +Releases](https://github.com/abseil/abseil-cpp/releases) to which we backport +fixes for severe bugs. See our [release +management](https://abseil.io/about/releases) document for more details. + + +## License + +The Abseil C++ library is licensed under the terms of the Apache +license. See [LICENSE](LICENSE) for more information. + + +## Links + +For more information about Abseil: + +* Consult our [Abseil Introduction](https://abseil.io/about/intro) +* Read [Why Adopt Abseil](https://abseil.io/about/philosophy) to understand our + design philosophy. +* Peruse our + [Abseil Compatibility Guarantees](https://abseil.io/about/compatibility) to + understand both what we promise to you, and what we expect of you in return. diff --git a/third_party/abseil/UPGRADES.md b/third_party/abseil/UPGRADES.md new file mode 100644 index 0000000000..3cac141d0f --- /dev/null +++ b/third_party/abseil/UPGRADES.md @@ -0,0 +1,17 @@ +# C++ Upgrade Tools + +Abseil may occasionally release API-breaking changes. As noted in our +[Compatibility Guidelines][compatibility-guide], we will aim to provide a tool +to do the work of effecting such API-breaking changes, when absolutely +necessary. + +These tools will be listed on the [C++ Upgrade Tools][upgrade-tools] guide on +https://abseil.io. + +For more information, the [C++ Automated Upgrade Guide][api-upgrades-guide] +outlines this process. + +[compatibility-guide]: https://abseil.io/about/compatibility +[api-upgrades-guide]: https://abseil.io/docs/cpp/tools/api-upgrades +[upgrade-tools]: https://abseil.io/docs/cpp/tools/upgrades/ + diff --git a/third_party/abseil/WORKSPACE b/third_party/abseil/WORKSPACE new file mode 100644 index 0000000000..3f0aa76769 --- /dev/null +++ b/third_party/abseil/WORKSPACE @@ -0,0 +1,68 @@ +# +# Copyright 2019 The Abseil Authors. +# +# 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 +# +# https://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. +# + +workspace(name = "abseil-cpp") + +load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive") + +# GoogleTest/GoogleMock framework. Used by most unit-tests. +http_archive( + name = "googletest", + sha256 = "7b42b4d6ed48810c5362c265a17faebe90dc2373c885e5216439d37927f02926", + strip_prefix = "googletest-1.15.2", + # Keep this URL in sync with the version in ci/cmake_common.sh and + # ci/windows_msvc_cmake.bat. + urls = ["https://github.com/google/googletest/releases/download/v1.15.2/googletest-1.15.2.tar.gz"], + # Now that Abseil is using the canonical names from the Bazel Central Registry, map + # GoogleTest's old names to the new canonical names. + repo_mapping = { + "@com_google_absl": "@", + "@com_googlesource_code_re2": "@re2", + }, +) + +# RE2 (the regular expression library used by GoogleTest) +http_archive( + name = "re2", + sha256 = "eb2df807c781601c14a260a507a5bb4509be1ee626024cb45acbd57cb9d4032b", + strip_prefix = "re2-2024-07-02", + urls = ["https://github.com/google/re2/releases/download/2024-07-02/re2-2024-07-02.tar.gz"], +) + +# Google benchmark. +http_archive( + name = "google_benchmark", + sha256 = "d26789a2b46d8808a48a4556ee58ccc7c497fcd4c0af9b90197674a81e04798a", + strip_prefix = "benchmark-1.8.5", + urls = ["https://github.com/google/benchmark/archive/refs/tags/v1.8.5.tar.gz"], +) + +# Bazel Skylib. +http_archive( + name = "bazel_skylib", + sha256 = "bc283cdfcd526a52c3201279cda4bc298652efa898b10b4db0837dc51652756f", + urls = ["https://github.com/bazelbuild/bazel-skylib/releases/download/1.7.1/bazel-skylib-1.7.1.tar.gz"], +) + +# Bazel platform rules. +http_archive( + name = "platforms", + urls = [ + "https://mirror.bazel.build/github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz", + "https://github.com/bazelbuild/platforms/releases/download/0.0.10/platforms-0.0.10.tar.gz", + ], + sha256 = "218efe8ee736d26a3572663b374a253c012b716d8af0c07e842e82f238a0a7ee", +) diff --git a/third_party/abseil/WORKSPACE.bzlmod b/third_party/abseil/WORKSPACE.bzlmod new file mode 100644 index 0000000000..83e67baa73 --- /dev/null +++ b/third_party/abseil/WORKSPACE.bzlmod @@ -0,0 +1,19 @@ +# Copyright 2024 The Abseil Authors. +# +# 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 +# +# https://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. + +# https://bazel.build/external/migration#workspace.bzlmod +# +# This file is intentionally empty. When bzlmod is enabled and this +# file exists, the contents of WORKSPACE is ignored. This prevents +# bzlmod builds from unintentionally depending on the WORKSPACE file. diff --git a/third_party/abseil/absl/BUILD.bazel b/third_party/abseil/absl/BUILD.bazel new file mode 100644 index 0000000000..ba1691fc75 --- /dev/null +++ b/third_party/abseil/absl/BUILD.bazel @@ -0,0 +1,133 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +load("@bazel_skylib//lib:selects.bzl", "selects") + +package(default_visibility = ["//visibility:public"]) + +licenses(["notice"]) + +config_setting( + name = "clang_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "clang", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "gcc_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "gcc", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "mingw_unspecified_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "mingw", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "mingw-gcc_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "mingw-gcc", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "msvc_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "msvc-cl", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "clang-cl_compiler", + flag_values = { + "@bazel_tools//tools/cpp:compiler": "clang-cl", + }, + visibility = [":__subpackages__"], +) + +config_setting( + name = "osx", + constraint_values = [ + "@platforms//os:osx", + ], +) + +config_setting( + name = "ios", + constraint_values = [ + "@platforms//os:ios", + ], +) + +config_setting( + name = "ppc", + constraint_values = [ + "@platforms//cpu:ppc", + ], + visibility = [":__subpackages__"], +) + +config_setting( + name = "platforms_wasm32", + constraint_values = [ + "@platforms//cpu:wasm32", + ], + visibility = [":__subpackages__"], +) + +config_setting( + name = "platforms_wasm64", + constraint_values = [ + "@platforms//cpu:wasm64", + ], + visibility = [":__subpackages__"], +) + +selects.config_setting_group( + name = "wasm", + match_any = [ + ":platforms_wasm32", + ":platforms_wasm64", + ], + visibility = [":__subpackages__"], +) + +config_setting( + name = "fuchsia", + constraint_values = [ + "@platforms//os:fuchsia", + ], + visibility = [":__subpackages__"], +) + +selects.config_setting_group( + name = "mingw_compiler", + match_any = [ + ":mingw_unspecified_compiler", + ":mingw-gcc_compiler", + ], + visibility = [":__subpackages__"], +) diff --git a/third_party/abseil/absl/CMakeLists.txt b/third_party/abseil/absl/CMakeLists.txt new file mode 100644 index 0000000000..810d7f31b9 --- /dev/null +++ b/third_party/abseil/absl/CMakeLists.txt @@ -0,0 +1,44 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +add_subdirectory(base) +add_subdirectory(algorithm) +add_subdirectory(cleanup) +add_subdirectory(container) +add_subdirectory(crc) +add_subdirectory(debugging) +add_subdirectory(flags) +add_subdirectory(functional) +add_subdirectory(hash) +add_subdirectory(log) +add_subdirectory(memory) +add_subdirectory(meta) +add_subdirectory(numeric) +add_subdirectory(profiling) +add_subdirectory(random) +add_subdirectory(status) +add_subdirectory(strings) +add_subdirectory(synchronization) +add_subdirectory(time) +add_subdirectory(types) +add_subdirectory(utility) + +if (ABSL_BUILD_DLL) + absl_make_dll() + if ((BUILD_TESTING AND ABSL_BUILD_TESTING) OR ABSL_BUILD_TEST_HELPERS) + absl_make_dll(TEST ON) + endif() +endif() diff --git a/third_party/abseil/absl/abseil.podspec.gen.py b/third_party/abseil/absl/abseil.podspec.gen.py new file mode 100755 index 0000000000..cbf7cb423b --- /dev/null +++ b/third_party/abseil/absl/abseil.podspec.gen.py @@ -0,0 +1,243 @@ +#!/usr/bin/env python3 +# -*- coding: utf-8 -*- +"""This script generates abseil.podspec from all BUILD.bazel files. + +This is expected to run on abseil git repository with Bazel 1.0 on Linux. +It recursively analyzes BUILD.bazel files using query command of Bazel to +dump its build rules in XML format. From these rules, it constructs podspec +structure. +""" + +import argparse +import collections +import os +import re +import subprocess +import xml.etree.ElementTree + +# Template of root podspec. +SPEC_TEMPLATE = """ +# This file has been automatically generated from a script. +# Please make modifications to `abseil.podspec.gen.py` instead. +Pod::Spec.new do |s| + s.name = 'abseil' + s.version = '${version}' + s.summary = 'Abseil Common Libraries (C++) from Google' + s.homepage = 'https://abseil.io' + s.license = 'Apache License, Version 2.0' + s.authors = { 'Abseil Team' => 'abseil-io@googlegroups.com' } + s.source = { + :git => 'https://github.com/abseil/abseil-cpp.git', + :tag => '${tag}', + } + s.resource_bundles = { + s.module_name => 'PrivacyInfo.xcprivacy', + } + s.module_name = 'absl' + s.header_mappings_dir = 'absl' + s.header_dir = 'absl' + s.libraries = 'c++' + s.compiler_flags = '-Wno-everything' + s.pod_target_xcconfig = { + 'USER_HEADER_SEARCH_PATHS' => '$(inherited) "$(PODS_TARGET_SRCROOT)"', + 'USE_HEADERMAP' => 'NO', + 'ALWAYS_SEARCH_USER_PATHS' => 'NO', + } + s.ios.deployment_target = '9.0' + s.osx.deployment_target = '10.11' + s.tvos.deployment_target = '9.0' + s.watchos.deployment_target = '2.0' + s.subspec 'xcprivacy' do |ss| + ss.resource_bundles = { + ss.module_name => 'PrivacyInfo.xcprivacy', + } + end +""" + +# Rule object representing the rule of Bazel BUILD. +Rule = collections.namedtuple( + "Rule", "type name package srcs hdrs textual_hdrs deps visibility testonly") + + +def get_elem_value(elem, name): + """Returns the value of XML element with the given name.""" + for child in elem: + if child.attrib.get("name") != name: + continue + if child.tag == "string": + return child.attrib.get("value") + if child.tag == "boolean": + return child.attrib.get("value") == "true" + if child.tag == "list": + return [nested_child.attrib.get("value") for nested_child in child] + raise "Cannot recognize tag: " + child.tag + return None + + +def normalize_paths(paths): + """Returns the list of normalized path.""" + # e.g. ["//absl/strings:dir/header.h"] -> ["absl/strings/dir/header.h"] + return [path.lstrip("/").replace(":", "/") for path in paths] + + +def parse_rule(elem, package): + """Returns a rule from bazel XML rule.""" + return Rule( + type=elem.attrib["class"], + name=get_elem_value(elem, "name"), + package=package, + srcs=normalize_paths(get_elem_value(elem, "srcs") or []), + hdrs=normalize_paths(get_elem_value(elem, "hdrs") or []), + textual_hdrs=normalize_paths(get_elem_value(elem, "textual_hdrs") or []), + deps=get_elem_value(elem, "deps") or [], + visibility=get_elem_value(elem, "visibility") or [], + testonly=get_elem_value(elem, "testonly") or False) + + +def read_build(package): + """Runs bazel query on given package file and returns all cc rules.""" + result = subprocess.check_output( + ["bazel", "query", package + ":all", "--output", "xml"]) + root = xml.etree.ElementTree.fromstring(result) + return [ + parse_rule(elem, package) + for elem in root + if elem.tag == "rule" and elem.attrib["class"].startswith("cc_") + ] + + +def collect_rules(root_path): + """Collects and returns all rules from root path recursively.""" + rules = [] + for cur, _, _ in os.walk(root_path): + build_path = os.path.join(cur, "BUILD.bazel") + if os.path.exists(build_path): + rules.extend(read_build("//" + cur)) + return rules + + +def relevant_rule(rule): + """Returns true if a given rule is relevant when generating a podspec.""" + return ( + # cc_library only (ignore cc_test, cc_binary) + rule.type == "cc_library" and + # ignore empty rule + (rule.hdrs + rule.textual_hdrs + rule.srcs) and + # ignore test-only rule + not rule.testonly) + + +def get_spec_var(depth): + """Returns the name of variable for spec with given depth.""" + return "s" if depth == 0 else "s{}".format(depth) + + +def get_spec_name(label): + """Converts the label of bazel rule to the name of podspec.""" + assert label.startswith("//absl/"), "{} doesn't start with //absl/".format( + label) + # e.g. //absl/apple/banana -> abseil/apple/banana + return "abseil/" + label[7:] + + +def write_podspec(f, rules, args): + """Writes a podspec from given rules and args.""" + rule_dir = build_rule_directory(rules)["abseil"] + # Write root part with given arguments + spec = re.sub(r"\$\{(\w+)\}", lambda x: args[x.group(1)], + SPEC_TEMPLATE).lstrip() + f.write(spec) + # Write all target rules + write_podspec_map(f, rule_dir, 0) + f.write("end\n") + + +def build_rule_directory(rules): + """Builds a tree-style rule directory from given rules.""" + rule_dir = {} + for rule in rules: + cur = rule_dir + for frag in get_spec_name(rule.package).split("/"): + cur = cur.setdefault(frag, {}) + cur[rule.name] = rule + return rule_dir + + +def write_podspec_map(f, cur_map, depth): + """Writes podspec from rule map recursively.""" + for key, value in sorted(cur_map.items()): + indent = " " * (depth + 1) + f.write("{indent}{var0}.subspec '{key}' do |{var1}|\n".format( + indent=indent, + key=key, + var0=get_spec_var(depth), + var1=get_spec_var(depth + 1))) + if isinstance(value, dict): + write_podspec_map(f, value, depth + 1) + else: + write_podspec_rule(f, value, depth + 1) + f.write("{indent}end\n".format(indent=indent)) + + +def write_podspec_rule(f, rule, depth): + """Writes podspec from given rule.""" + indent = " " * (depth + 1) + spec_var = get_spec_var(depth) + # Puts all files in hdrs, textual_hdrs, and srcs into source_files. + # Since CocoaPods treats header_files a bit differently from bazel, + # this won't generate a header_files field so that all source_files + # are considered as header files. + srcs = sorted(set(rule.hdrs + rule.textual_hdrs + rule.srcs)) + write_indented_list( + f, "{indent}{var}.source_files = ".format(indent=indent, var=spec_var), + srcs) + # Writes dependencies of this rule. + for dep in sorted(rule.deps): + name = get_spec_name(dep.replace(":", "/")) + f.write("{indent}{var}.dependency '{dep}'\n".format( + indent=indent, var=spec_var, dep=name)) + # Writes dependency to xcprivacy + f.write( + "{indent}{var}.dependency '{dep}'\n".format( + indent=indent, var=spec_var, dep="abseil/xcprivacy" + ) + ) + + +def write_indented_list(f, leading, values): + """Writes leading values in an indented style.""" + f.write(leading) + f.write((",\n" + " " * len(leading)).join("'{}'".format(v) for v in values)) + f.write("\n") + + +def generate(args): + """Generates a podspec file from all BUILD files under absl directory.""" + rules = filter(relevant_rule, collect_rules("absl")) + with open(args.output, "wt") as f: + write_podspec(f, rules, vars(args)) + + +def main(): + parser = argparse.ArgumentParser( + description="Generates abseil.podspec from BUILD.bazel") + parser.add_argument( + "-v", "--version", help="The version of podspec", required=True) + parser.add_argument( + "-t", + "--tag", + default=None, + help="The name of git tag (default: version)") + parser.add_argument( + "-o", + "--output", + default="abseil.podspec", + help="The name of output file (default: abseil.podspec)") + args = parser.parse_args() + if args.tag is None: + args.tag = args.version + generate(args) + + +if __name__ == "__main__": + main() diff --git a/third_party/abseil/absl/algorithm/BUILD.bazel b/third_party/abseil/absl/algorithm/BUILD.bazel new file mode 100644 index 0000000000..9a723e5b99 --- /dev/null +++ b/third_party/abseil/absl/algorithm/BUILD.bazel @@ -0,0 +1,90 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +load( + "//absl:copts/configure_copts.bzl", + "ABSL_DEFAULT_COPTS", + "ABSL_DEFAULT_LINKOPTS", + "ABSL_TEST_COPTS", +) + +package( + default_visibility = ["//visibility:public"], + features = [ + "header_modules", + "layering_check", + "parse_headers", + ], +) + +licenses(["notice"]) + +cc_library( + name = "algorithm", + hdrs = ["algorithm.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + "//absl/base:config", + ], +) + +cc_test( + name = "algorithm_test", + size = "small", + srcs = ["algorithm_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":algorithm", + "//absl/base:config", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "container", + hdrs = [ + "container.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":algorithm", + "//absl/base:config", + "//absl/base:core_headers", + "//absl/base:nullability", + "//absl/meta:type_traits", + ], +) + +cc_test( + name = "container_test", + srcs = ["container_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":container", + "//absl/base", + "//absl/base:config", + "//absl/base:core_headers", + "//absl/memory", + "//absl/types:span", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) diff --git a/third_party/abseil/absl/algorithm/CMakeLists.txt b/third_party/abseil/absl/algorithm/CMakeLists.txt new file mode 100644 index 0000000000..252b6b2035 --- /dev/null +++ b/third_party/abseil/absl/algorithm/CMakeLists.txt @@ -0,0 +1,73 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +absl_cc_library( + NAME + algorithm + HDRS + "algorithm.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + PUBLIC +) + +absl_cc_test( + NAME + algorithm_test + SRCS + "algorithm_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::algorithm + absl::config + GTest::gmock_main +) + +absl_cc_library( + NAME + algorithm_container + HDRS + "container.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::algorithm + absl::config + absl::core_headers + absl::meta + absl::nullability + PUBLIC +) + +absl_cc_test( + NAME + container_test + SRCS + "container_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::algorithm_container + absl::base + absl::config + absl::core_headers + absl::memory + absl::span + GTest::gmock_main +) diff --git a/third_party/abseil/absl/algorithm/algorithm.h b/third_party/abseil/absl/algorithm/algorithm.h new file mode 100644 index 0000000000..48f59504d2 --- /dev/null +++ b/third_party/abseil/absl/algorithm/algorithm.h @@ -0,0 +1,64 @@ +// Copyright 2017 The Abseil Authors. +// +// 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 +// +// https://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. +// +// ----------------------------------------------------------------------------- +// File: algorithm.h +// ----------------------------------------------------------------------------- +// +// This header file contains Google extensions to the standard C++ +// header. + +#ifndef ABSL_ALGORITHM_ALGORITHM_H_ +#define ABSL_ALGORITHM_ALGORITHM_H_ + +#include +#include +#include + +#include "absl/base/config.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN + +// equal() +// rotate() +// +// Historical note: Abseil once provided implementations of these algorithms +// prior to their adoption in C++14. New code should prefer to use the std +// variants. +// +// See the documentation for the STL header for more information: +// https://en.cppreference.com/w/cpp/header/algorithm +using std::equal; +using std::rotate; + +// linear_search() +// +// Performs a linear search for `value` using the iterator `first` up to +// but not including `last`, returning true if [`first`, `last`) contains an +// element equal to `value`. +// +// A linear search is of O(n) complexity which is guaranteed to make at most +// n = (`last` - `first`) comparisons. A linear search over short containers +// may be faster than a binary search, even when the container is sorted. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool linear_search( + InputIterator first, InputIterator last, const EqualityComparable& value) { + return std::find(first, last, value) != last; +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_ALGORITHM_ALGORITHM_H_ diff --git a/third_party/abseil/absl/algorithm/algorithm_test.cc b/third_party/abseil/absl/algorithm/algorithm_test.cc new file mode 100644 index 0000000000..1c1a3079f8 --- /dev/null +++ b/third_party/abseil/absl/algorithm/algorithm_test.cc @@ -0,0 +1,60 @@ +// Copyright 2017 The Abseil Authors. +// +// 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 +// +// https://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. + +#include "absl/algorithm/algorithm.h" + +#include +#include + +#include "gtest/gtest.h" +#include "absl/base/config.h" + +namespace { + +class LinearSearchTest : public testing::Test { + protected: + LinearSearchTest() : container_{1, 2, 3} {} + + static bool Is3(int n) { return n == 3; } + static bool Is4(int n) { return n == 4; } + + std::vector container_; +}; + +TEST_F(LinearSearchTest, linear_search) { + EXPECT_TRUE(absl::linear_search(container_.begin(), container_.end(), 3)); + EXPECT_FALSE(absl::linear_search(container_.begin(), container_.end(), 4)); +} + +TEST_F(LinearSearchTest, linear_searchConst) { + const std::vector *const const_container = &container_; + EXPECT_TRUE( + absl::linear_search(const_container->begin(), const_container->end(), 3)); + EXPECT_FALSE( + absl::linear_search(const_container->begin(), const_container->end(), 4)); +} + +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + +TEST_F(LinearSearchTest, Constexpr) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::linear_search(kArray.begin(), kArray.end(), 3)); + static_assert(!absl::linear_search(kArray.begin(), kArray.end(), 4)); +} + +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + +} // namespace diff --git a/third_party/abseil/absl/algorithm/container.h b/third_party/abseil/absl/algorithm/container.h new file mode 100644 index 0000000000..3193656f88 --- /dev/null +++ b/third_party/abseil/absl/algorithm/container.h @@ -0,0 +1,1830 @@ +// Copyright 2017 The Abseil Authors. +// +// 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 +// +// https://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. +// +// ----------------------------------------------------------------------------- +// File: container.h +// ----------------------------------------------------------------------------- +// +// This header file provides Container-based versions of algorithmic functions +// within the C++ standard library. The following standard library sets of +// functions are covered within this file: +// +// * Algorithmic functions +// * Algorithmic functions +// * functions +// +// The standard library functions operate on iterator ranges; the functions +// within this API operate on containers, though many return iterator ranges. +// +// All functions within this API are named with a `c_` prefix. Calls such as +// `absl::c_xx(container, ...) are equivalent to std:: functions such as +// `std::xx(std::begin(cont), std::end(cont), ...)`. Functions that act on +// iterators but not conceptually on iterator ranges (e.g. `std::iter_swap`) +// have no equivalent here. +// +// For template parameter and variable naming, `C` indicates the container type +// to which the function is applied, `Pred` indicates the predicate object type +// to be used by the function and `T` indicates the applicable element type. + +#ifndef ABSL_ALGORITHM_CONTAINER_H_ +#define ABSL_ALGORITHM_CONTAINER_H_ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "absl/algorithm/algorithm.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/base/nullability.h" +#include "absl/meta/type_traits.h" + +namespace absl { +ABSL_NAMESPACE_BEGIN +namespace container_algorithm_internal { + +// NOTE: it is important to defer to ADL lookup for building with C++ modules, +// especially for headers like which are not visible from this file +// but specialize std::begin and std::end. +using std::begin; +using std::end; + +// The type of the iterator given by begin(c) (possibly std::begin(c)). +// ContainerIter> gives vector::const_iterator, +// while ContainerIter> gives vector::iterator. +template +using ContainerIter = decltype(begin(std::declval())); + +// An MSVC bug involving template parameter substitution requires us to use +// decltype() here instead of just std::pair. +template +using ContainerIterPairType = + decltype(std::make_pair(ContainerIter(), ContainerIter())); + +template +using ContainerDifferenceType = decltype(std::distance( + std::declval>(), std::declval>())); + +template +using ContainerPointerType = + typename std::iterator_traits>::pointer; + +// container_algorithm_internal::c_begin and +// container_algorithm_internal::c_end are abbreviations for proper ADL +// lookup of std::begin and std::end, i.e. +// using std::begin; +// using std::end; +// std::foo(begin(c), end(c)); +// becomes +// std::foo(container_algorithm_internal::c_begin(c), +// container_algorithm_internal::c_end(c)); +// These are meant for internal use only. + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_begin(C& c) { + return begin(c); +} + +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 ContainerIter c_end(C& c) { + return end(c); +} + +template +struct IsUnorderedContainer : std::false_type {}; + +template +struct IsUnorderedContainer< + std::unordered_map> : std::true_type {}; + +template +struct IsUnorderedContainer> + : std::true_type {}; + +} // namespace container_algorithm_internal + +// PUBLIC API + +//------------------------------------------------------------------------------ +// Abseil algorithm.h functions +//------------------------------------------------------------------------------ + +// c_linear_search() +// +// Container-based version of absl::linear_search() for performing a linear +// search within a container. +// +// For a generalization that uses a predicate, see absl::c_any_of(). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_linear_search( + const C& c, EqualityComparable&& value) { + return absl::linear_search(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +//------------------------------------------------------------------------------ +// algorithms +//------------------------------------------------------------------------------ + +// c_distance() +// +// Container-based version of the `std::distance()` function to +// return the number of elements within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerDifferenceType + c_distance(const C& c) { + return std::distance(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +//------------------------------------------------------------------------------ +// Non-modifying sequence operations +//------------------------------------------------------------------------------ + +// c_all_of() +// +// Container-based version of the `std::all_of()` function to +// test if all elements within a container satisfy a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_all_of(const C& c, Pred&& pred) { + return std::all_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_any_of() +// +// Container-based version of the `std::any_of()` function to +// test if any element in a container fulfills a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_any_of(const C& c, Pred&& pred) { + return std::any_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_none_of() +// +// Container-based version of the `std::none_of()` function to +// test if no elements in a container fulfill a condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_none_of(const C& c, Pred&& pred) { + return std::none_of(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_for_each() +// +// Container-based version of the `std::for_each()` function to +// apply a function to a container's elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 decay_t c_for_each(C&& c, + Function&& f) { + return std::for_each(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(f)); +} + +// c_find() +// +// Container-based version of the `std::find()` function to find +// the first element containing the passed value within a container value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find(C& c, T&& value) { + return std::find(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +// c_contains() +// +// Container-based version of the `std::ranges::contains()` C++23 +// function to search a container for a value. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains(const Sequence& sequence, + T&& value) { + return absl::c_find(sequence, std::forward(value)) != + container_algorithm_internal::c_end(sequence); +} + +// c_find_if() +// +// Container-based version of the `std::find_if()` function to find +// the first element in a container matching the given condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if(C& c, Pred&& pred) { + return std::find_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_find_if_not() +// +// Container-based version of the `std::find_if_not()` function to +// find the first element in a container not matching the given condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_if_not(C& c, Pred&& pred) { + return std::find_if_not(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_find_end() +// +// Container-based version of the `std::find_end()` function to +// find the last subsequence within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence) { + return std::find_end(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence)); +} + +// Overload of c_find_end() for using a predicate evaluation other than `==` as +// the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_end(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return std::find_end(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence), + std::forward(pred)); +} + +// c_find_first_of() +// +// Container-based version of the `std::find_first_of()` function to +// find the first element within the container that is also within the options +// container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, const C2& options) { + return std::find_first_of(container_algorithm_internal::c_begin(container), + container_algorithm_internal::c_end(container), + container_algorithm_internal::c_begin(options), + container_algorithm_internal::c_end(options)); +} + +// Overload of c_find_first_of() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_find_first_of(C1& container, const C2& options, BinaryPredicate&& pred) { + return std::find_first_of(container_algorithm_internal::c_begin(container), + container_algorithm_internal::c_end(container), + container_algorithm_internal::c_begin(options), + container_algorithm_internal::c_end(options), + std::forward(pred)); +} + +// c_adjacent_find() +// +// Container-based version of the `std::adjacent_find()` function to +// find equal adjacent elements within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence) { + return std::adjacent_find(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_adjacent_find() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_adjacent_find(Sequence& sequence, BinaryPredicate&& pred) { + return std::adjacent_find(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(pred)); +} + +// c_count() +// +// Container-based version of the `std::count()` function to count +// values that match within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count(const C& c, T&& value) { + return std::count(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(value)); +} + +// c_count_if() +// +// Container-based version of the `std::count_if()` function to +// count values matching a condition within a container. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerDifferenceType + c_count_if(const C& c, Pred&& pred) { + return std::count_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_mismatch() +// +// Container-based version of the `std::mismatch()` function to +// return the first element where two ordered containers differ. Applies `==` to +// the first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2) { + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_mismatch() for using a predicate evaluation other than `==` as +// the function's test condition. Applies `pred`to the first N elements of `c1` +// and `c2`, where N = min(size(c1), size(c2)). +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIterPairType + c_mismatch(C1& c1, C2& c2, BinaryPredicate pred) { + return std::mismatch(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), pred); +} + +// c_equal() +// +// Container-based version of the `std::equal()` function to +// test whether two containers are equal. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2) { + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_equal() for using a predicate evaluation other than `==` as +// the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_equal(const C1& c1, const C2& c2, + BinaryPredicate&& pred) { + return std::equal(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(pred)); +} + +// c_is_permutation() +// +// Container-based version of the `std::is_permutation()` function +// to test whether a container is a permutation of another. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation(const C1& c1, + const C2& c2) { + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_is_permutation() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_is_permutation( + const C1& c1, const C2& c2, BinaryPredicate&& pred) { + return std::is_permutation(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(pred)); +} + +// c_search() +// +// Container-based version of the `std::search()` function to search +// a container for a subsequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence) { + return std::search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence)); +} + +// Overload of c_search() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search(Sequence1& sequence, Sequence2& subsequence, + BinaryPredicate&& pred) { + return std::search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(subsequence), + container_algorithm_internal::c_end(subsequence), + std::forward(pred)); +} + +// c_contains_subrange() +// +// Container-based version of the `std::ranges::contains_subrange()` +// C++23 function to search a container for a subsequence. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence) { + return absl::c_search(sequence, subsequence) != + container_algorithm_internal::c_end(sequence); +} + +// Overload of c_contains_subrange() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 bool c_contains_subrange( + Sequence1& sequence, Sequence2& subsequence, BinaryPredicate&& pred) { + return absl::c_search(sequence, subsequence, + std::forward(pred)) != + container_algorithm_internal::c_end(sequence); +} + +// c_search_n() +// +// Container-based version of the `std::search_n()` function to +// search a container for the first sequence of N elements. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value) { + return std::search_n(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), count, + std::forward(value)); +} + +// Overload of c_search_n() for using a predicate evaluation other than +// `==` as the function's test condition. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX20 + container_algorithm_internal::ContainerIter + c_search_n(Sequence& sequence, Size count, T&& value, + BinaryPredicate&& pred) { + return std::search_n(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), count, + std::forward(value), + std::forward(pred)); +} + +//------------------------------------------------------------------------------ +// Modifying sequence operations +//------------------------------------------------------------------------------ + +// c_copy() +// +// Container-based version of the `std::copy()` function to copy a +// container's elements into an iterator. +template +OutputIterator c_copy(const InputSequence& input, OutputIterator output) { + return std::copy(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output); +} + +// c_copy_n() +// +// Container-based version of the `std::copy_n()` function to copy a +// container's first N elements into an iterator. +template +OutputIterator c_copy_n(const C& input, Size n, OutputIterator output) { + return std::copy_n(container_algorithm_internal::c_begin(input), n, output); +} + +// c_copy_if() +// +// Container-based version of the `std::copy_if()` function to copy +// a container's elements satisfying some condition into an iterator. +template +OutputIterator c_copy_if(const InputSequence& input, OutputIterator output, + Pred&& pred) { + return std::copy_if(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output, + std::forward(pred)); +} + +// c_copy_backward() +// +// Container-based version of the `std::copy_backward()` function to +// copy a container's elements in reverse order into an iterator. +template +BidirectionalIterator c_copy_backward(const C& src, + BidirectionalIterator dest) { + return std::copy_backward(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_move() +// +// Container-based version of the `std::move()` function to move +// a container's elements into an iterator. +template +OutputIterator c_move(C&& src, OutputIterator dest) { + return std::move(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_move_backward() +// +// Container-based version of the `std::move_backward()` function to +// move a container's elements into an iterator in reverse order. +template +BidirectionalIterator c_move_backward(C&& src, BidirectionalIterator dest) { + return std::move_backward(container_algorithm_internal::c_begin(src), + container_algorithm_internal::c_end(src), dest); +} + +// c_swap_ranges() +// +// Container-based version of the `std::swap_ranges()` function to +// swap a container's elements with another container's elements. Swaps the +// first N elements of `c1` and `c2`, where N = min(size(c1), size(c2)). +template +container_algorithm_internal::ContainerIter c_swap_ranges(C1& c1, C2& c2) { + auto first1 = container_algorithm_internal::c_begin(c1); + auto last1 = container_algorithm_internal::c_end(c1); + auto first2 = container_algorithm_internal::c_begin(c2); + auto last2 = container_algorithm_internal::c_end(c2); + + using std::swap; + for (; first1 != last1 && first2 != last2; ++first1, (void)++first2) { + swap(*first1, *first2); + } + return first2; +} + +// c_transform() +// +// Container-based version of the `std::transform()` function to +// transform a container's elements using the unary operation, storing the +// result in an iterator pointing to the last transformed element in the output +// range. +template +OutputIterator c_transform(const InputSequence& input, OutputIterator output, + UnaryOp&& unary_op) { + return std::transform(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), output, + std::forward(unary_op)); +} + +// Overload of c_transform() for performing a transformation using a binary +// predicate. Applies `binary_op` to the first N elements of `c1` and `c2`, +// where N = min(size(c1), size(c2)). +template +OutputIterator c_transform(const InputSequence1& input1, + const InputSequence2& input2, OutputIterator output, + BinaryOp&& binary_op) { + auto first1 = container_algorithm_internal::c_begin(input1); + auto last1 = container_algorithm_internal::c_end(input1); + auto first2 = container_algorithm_internal::c_begin(input2); + auto last2 = container_algorithm_internal::c_end(input2); + for (; first1 != last1 && first2 != last2; + ++first1, (void)++first2, ++output) { + *output = binary_op(*first1, *first2); + } + + return output; +} + +// c_replace() +// +// Container-based version of the `std::replace()` function to +// replace a container's elements of some value with a new value. The container +// is modified in place. +template +void c_replace(Sequence& sequence, const T& old_value, const T& new_value) { + std::replace(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), old_value, + new_value); +} + +// c_replace_if() +// +// Container-based version of the `std::replace_if()` function to +// replace a container's elements of some value with a new value based on some +// condition. The container is modified in place. +template +void c_replace_if(C& c, Pred&& pred, T&& new_value) { + std::replace_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred), std::forward(new_value)); +} + +// c_replace_copy() +// +// Container-based version of the `std::replace_copy()` function to +// replace a container's elements of some value with a new value and return the +// results within an iterator. +template +OutputIterator c_replace_copy(const C& c, OutputIterator result, T&& old_value, + T&& new_value) { + return std::replace_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(old_value), + std::forward(new_value)); +} + +// c_replace_copy_if() +// +// Container-based version of the `std::replace_copy_if()` function +// to replace a container's elements of some value with a new value based on +// some condition, and return the results within an iterator. +template +OutputIterator c_replace_copy_if(const C& c, OutputIterator result, Pred&& pred, + const T& new_value) { + return std::replace_copy_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred), new_value); +} + +// c_fill() +// +// Container-based version of the `std::fill()` function to fill a +// container with some value. +template +void c_fill(C& c, const T& value) { + std::fill(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), value); +} + +// c_fill_n() +// +// Container-based version of the `std::fill_n()` function to fill +// the first N elements in a container with some value. +template +void c_fill_n(C& c, Size n, const T& value) { + std::fill_n(container_algorithm_internal::c_begin(c), n, value); +} + +// c_generate() +// +// Container-based version of the `std::generate()` function to +// assign a container's elements to the values provided by the given generator. +template +void c_generate(C& c, Generator&& gen) { + std::generate(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(gen)); +} + +// c_generate_n() +// +// Container-based version of the `std::generate_n()` function to +// assign a container's first N elements to the values provided by the given +// generator. +template +container_algorithm_internal::ContainerIter c_generate_n(C& c, Size n, + Generator&& gen) { + return std::generate_n(container_algorithm_internal::c_begin(c), n, + std::forward(gen)); +} + +// Note: `c_xx()` container versions for `remove()`, `remove_if()`, +// and `unique()` are omitted, because it's not clear whether or not such +// functions should call erase on their supplied sequences afterwards. Either +// behavior would be surprising for a different set of users. + +// c_remove_copy() +// +// Container-based version of the `std::remove_copy()` function to +// copy a container's elements while removing any elements matching the given +// `value`. +template +OutputIterator c_remove_copy(const C& c, OutputIterator result, + const T& value) { + return std::remove_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + value); +} + +// c_remove_copy_if() +// +// Container-based version of the `std::remove_copy_if()` function +// to copy a container's elements while removing any elements matching the given +// condition. +template +OutputIterator c_remove_copy_if(const C& c, OutputIterator result, + Pred&& pred) { + return std::remove_copy_if(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred)); +} + +// c_unique_copy() +// +// Container-based version of the `std::unique_copy()` function to +// copy a container's elements while removing any elements containing duplicate +// values. +template +OutputIterator c_unique_copy(const C& c, OutputIterator result) { + return std::unique_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result); +} + +// Overload of c_unique_copy() for using a predicate evaluation other than +// `==` for comparing uniqueness of the element values. +template +OutputIterator c_unique_copy(const C& c, OutputIterator result, + BinaryPredicate&& pred) { + return std::unique_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, + std::forward(pred)); +} + +// c_reverse() +// +// Container-based version of the `std::reverse()` function to +// reverse a container's elements. +template +void c_reverse(Sequence& sequence) { + std::reverse(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// c_reverse_copy() +// +// Container-based version of the `std::reverse()` function to +// reverse a container's elements and write them to an iterator range. +template +OutputIterator c_reverse_copy(const C& sequence, OutputIterator result) { + return std::reverse_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + result); +} + +// c_rotate() +// +// Container-based version of the `std::rotate()` function to +// shift a container's elements leftward such that the `middle` element becomes +// the first element in the container. +template > +Iterator c_rotate(C& sequence, Iterator middle) { + return absl::rotate(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence)); +} + +// c_rotate_copy() +// +// Container-based version of the `std::rotate_copy()` function to +// shift a container's elements leftward such that the `middle` element becomes +// the first element in a new iterator range. +template +OutputIterator c_rotate_copy( + const C& sequence, + container_algorithm_internal::ContainerIter middle, + OutputIterator result) { + return std::rotate_copy(container_algorithm_internal::c_begin(sequence), + middle, container_algorithm_internal::c_end(sequence), + result); +} + +// c_shuffle() +// +// Container-based version of the `std::shuffle()` function to +// randomly shuffle elements within the container using a `gen()` uniform random +// number generator. +template +void c_shuffle(RandomAccessContainer& c, UniformRandomBitGenerator&& gen) { + std::shuffle(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(gen)); +} + +// c_sample() +// +// Container-based version of the `std::sample()` function to +// randomly sample elements from the container without replacement using a +// `gen()` uniform random number generator and write them to an iterator range. +template +OutputIterator c_sample(const C& c, OutputIterator result, Distance n, + UniformRandomBitGenerator&& gen) { +#if defined(__cpp_lib_sample) && __cpp_lib_sample >= 201603L + return std::sample(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), result, n, + std::forward(gen)); +#else + // Fall back to a stable selection-sampling implementation. + auto first = container_algorithm_internal::c_begin(c); + Distance unsampled_elements = c_distance(c); + n = (std::min)(n, unsampled_elements); + for (; n != 0; ++first) { + Distance r = + std::uniform_int_distribution(0, --unsampled_elements)(gen); + if (r < n) { + *result++ = *first; + --n; + } + } + return result; +#endif +} + +//------------------------------------------------------------------------------ +// Partition functions +//------------------------------------------------------------------------------ + +// c_is_partitioned() +// +// Container-based version of the `std::is_partitioned()` function +// to test whether all elements in the container for which `pred` returns `true` +// precede those for which `pred` is `false`. +template +bool c_is_partitioned(const C& c, Pred&& pred) { + return std::is_partitioned(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_partition() +// +// Container-based version of the `std::partition()` function +// to rearrange all elements in a container in such a way that all elements for +// which `pred` returns `true` precede all those for which it returns `false`, +// returning an iterator to the first element of the second group. +template +container_algorithm_internal::ContainerIter c_partition(C& c, Pred&& pred) { + return std::partition(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_stable_partition() +// +// Container-based version of the `std::stable_partition()` function +// to rearrange all elements in a container in such a way that all elements for +// which `pred` returns `true` precede all those for which it returns `false`, +// preserving the relative ordering between the two groups. The function returns +// an iterator to the first element of the second group. +template +container_algorithm_internal::ContainerIter c_stable_partition(C& c, + Pred&& pred) { + return std::stable_partition(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +// c_partition_copy() +// +// Container-based version of the `std::partition_copy()` function +// to partition a container's elements and return them into two iterators: one +// for which `pred` returns `true`, and one for which `pred` returns `false.` + +template +std::pair c_partition_copy( + const C& c, OutputIterator1 out_true, OutputIterator2 out_false, + Pred&& pred) { + return std::partition_copy(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), out_true, + out_false, std::forward(pred)); +} + +// c_partition_point() +// +// Container-based version of the `std::partition_point()` function +// to return the first element of an already partitioned container for which +// the given `pred` is not `true`. +template +container_algorithm_internal::ContainerIter c_partition_point(C& c, + Pred&& pred) { + return std::partition_point(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(pred)); +} + +//------------------------------------------------------------------------------ +// Sorting functions +//------------------------------------------------------------------------------ + +// c_sort() +// +// Container-based version of the `std::sort()` function +// to sort elements in ascending order of their values. +template +void c_sort(C& c) { + std::sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_sort() for performing a `comp` comparison other than the +// default `operator<`. +template +void c_sort(C& c, LessThan&& comp) { + std::sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_stable_sort() +// +// Container-based version of the `std::stable_sort()` function +// to sort elements in ascending order of their values, preserving the order +// of equivalents. +template +void c_stable_sort(C& c) { + std::stable_sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_stable_sort() for performing a `comp` comparison other than the +// default `operator<`. +template +void c_stable_sort(C& c, LessThan&& comp) { + std::stable_sort(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_is_sorted() +// +// Container-based version of the `std::is_sorted()` function +// to evaluate whether the given container is sorted in ascending order. +template +bool c_is_sorted(const C& c) { + return std::is_sorted(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// c_is_sorted() overload for performing a `comp` comparison other than the +// default `operator<`. +template +bool c_is_sorted(const C& c, LessThan&& comp) { + return std::is_sorted(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_partial_sort() +// +// Container-based version of the `std::partial_sort()` function +// to rearrange elements within a container such that elements before `middle` +// are sorted in ascending order. +template +void c_partial_sort( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter middle) { + std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_partial_sort() for performing a `comp` comparison other than +// the default `operator<`. +template +void c_partial_sort( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter middle, + LessThan&& comp) { + std::partial_sort(container_algorithm_internal::c_begin(sequence), middle, + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_partial_sort_copy() +// +// Container-based version of the `std::partial_sort_copy()` +// function to sort the elements in the given range `result` within the larger +// `sequence` in ascending order (and using `result` as the output parameter). +// At most min(result.last - result.first, sequence.last - sequence.first) +// elements from the sequence will be stored in the result. +template +container_algorithm_internal::ContainerIter +c_partial_sort_copy(const C& sequence, RandomAccessContainer& result) { + return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(result), + container_algorithm_internal::c_end(result)); +} + +// Overload of c_partial_sort_copy() for performing a `comp` comparison other +// than the default `operator<`. +template +container_algorithm_internal::ContainerIter +c_partial_sort_copy(const C& sequence, RandomAccessContainer& result, + LessThan&& comp) { + return std::partial_sort_copy(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + container_algorithm_internal::c_begin(result), + container_algorithm_internal::c_end(result), + std::forward(comp)); +} + +// c_is_sorted_until() +// +// Container-based version of the `std::is_sorted_until()` function +// to return the first element within a container that is not sorted in +// ascending order as an iterator. +template +container_algorithm_internal::ContainerIter c_is_sorted_until(C& c) { + return std::is_sorted_until(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_is_sorted_until() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIter c_is_sorted_until( + C& c, LessThan&& comp) { + return std::is_sorted_until(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_nth_element() +// +// Container-based version of the `std::nth_element()` function +// to rearrange the elements within a container such that the `nth` element +// would be in that position in an ordered sequence; other elements may be in +// any order, except that all preceding `nth` will be less than that element, +// and all following `nth` will be greater than that element. +template +void c_nth_element( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter nth) { + std::nth_element(container_algorithm_internal::c_begin(sequence), nth, + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_nth_element() for performing a `comp` comparison other than +// the default `operator<`. +template +void c_nth_element( + RandomAccessContainer& sequence, + container_algorithm_internal::ContainerIter nth, + LessThan&& comp) { + std::nth_element(container_algorithm_internal::c_begin(sequence), nth, + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Binary Search +//------------------------------------------------------------------------------ + +// c_lower_bound() +// +// Container-based version of the `std::lower_bound()` function +// to return an iterator pointing to the first element in a sorted container +// which does not compare less than `value`. +template +container_algorithm_internal::ContainerIter c_lower_bound( + Sequence& sequence, const T& value) { + return std::lower_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_lower_bound() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIter c_lower_bound( + Sequence& sequence, const T& value, LessThan&& comp) { + return std::lower_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_upper_bound() +// +// Container-based version of the `std::upper_bound()` function +// to return an iterator pointing to the first element in a sorted container +// which is greater than `value`. +template +container_algorithm_internal::ContainerIter c_upper_bound( + Sequence& sequence, const T& value) { + return std::upper_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_upper_bound() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIter c_upper_bound( + Sequence& sequence, const T& value, LessThan&& comp) { + return std::upper_bound(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_equal_range() +// +// Container-based version of the `std::equal_range()` function +// to return an iterator pair pointing to the first and last elements in a +// sorted container which compare equal to `value`. +template +container_algorithm_internal::ContainerIterPairType +c_equal_range(Sequence& sequence, const T& value) { + return std::equal_range(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// Overload of c_equal_range() for performing a `comp` comparison other than +// the default `operator<`. +template +container_algorithm_internal::ContainerIterPairType +c_equal_range(Sequence& sequence, const T& value, LessThan&& comp) { + return std::equal_range(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value, + std::forward(comp)); +} + +// c_binary_search() +// +// Container-based version of the `std::binary_search()` function +// to test if any element in the sorted container contains a value equivalent to +// 'value'. +template +bool c_binary_search(const Sequence& sequence, const T& value) { + return std::binary_search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + value); +} + +// Overload of c_binary_search() for performing a `comp` comparison other than +// the default `operator<`. +template +bool c_binary_search(const Sequence& sequence, const T& value, + LessThan&& comp) { + return std::binary_search(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + value, std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Merge functions +//------------------------------------------------------------------------------ + +// c_merge() +// +// Container-based version of the `std::merge()` function +// to merge two sorted containers into a single sorted iterator. +template +OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result) { + return std::merge(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), result); +} + +// Overload of c_merge() for performing a `comp` comparison other than +// the default `operator<`. +template +OutputIterator c_merge(const C1& c1, const C2& c2, OutputIterator result, + LessThan&& comp) { + return std::merge(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), result, + std::forward(comp)); +} + +// c_inplace_merge() +// +// Container-based version of the `std::inplace_merge()` function +// to merge a supplied iterator `middle` into a container. +template +void c_inplace_merge(C& c, + container_algorithm_internal::ContainerIter middle) { + std::inplace_merge(container_algorithm_internal::c_begin(c), middle, + container_algorithm_internal::c_end(c)); +} + +// Overload of c_inplace_merge() for performing a merge using a `comp` other +// than `operator<`. +template +void c_inplace_merge(C& c, + container_algorithm_internal::ContainerIter middle, + LessThan&& comp) { + std::inplace_merge(container_algorithm_internal::c_begin(c), middle, + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_includes() +// +// Container-based version of the `std::includes()` function +// to test whether a sorted container `c1` entirely contains another sorted +// container `c2`. +template +bool c_includes(const C1& c1, const C2& c2) { + return std::includes(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2)); +} + +// Overload of c_includes() for performing a merge using a `comp` other than +// `operator<`. +template +bool c_includes(const C1& c1, const C2& c2, LessThan&& comp) { + return std::includes(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), + std::forward(comp)); +} + +// c_set_union() +// +// Container-based version of the `std::set_union()` function +// to return an iterator containing the union of two containers; duplicate +// values are not copied into the output. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output) { + return std::set_union(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_union() for performing a merge using a `comp` other than +// `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_union(const C1& c1, const C2& c2, OutputIterator output, + LessThan&& comp) { + return std::set_union(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_intersection() +// +// Container-based version of the `std::set_intersection()` function +// to return an iterator containing the intersection of two sorted containers. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_intersection(const C1& c1, const C2& c2, + OutputIterator output) { + // In debug builds, ensure that both containers are sorted with respect to the + // default comparator. std::set_intersection requires the containers be sorted + // using operator<. + assert(absl::c_is_sorted(c1)); + assert(absl::c_is_sorted(c2)); + return std::set_intersection(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_intersection() for performing a merge using a `comp` other +// than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_intersection(const C1& c1, const C2& c2, + OutputIterator output, LessThan&& comp) { + // In debug builds, ensure that both containers are sorted with respect to the + // default comparator. std::set_intersection requires the containers be sorted + // using the same comparator. + assert(absl::c_is_sorted(c1, comp)); + assert(absl::c_is_sorted(c2, comp)); + return std::set_intersection(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_difference() +// +// Container-based version of the `std::set_difference()` function +// to return an iterator containing elements present in the first container but +// not in the second. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_difference(const C1& c1, const C2& c2, + OutputIterator output) { + return std::set_difference(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_difference() for performing a merge using a `comp` other +// than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_difference(const C1& c1, const C2& c2, + OutputIterator output, LessThan&& comp) { + return std::set_difference(container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +// c_set_symmetric_difference() +// +// Container-based version of the `std::set_symmetric_difference()` +// function to return an iterator containing elements present in either one +// container or the other, but not both. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, + OutputIterator output) { + return std::set_symmetric_difference( + container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output); +} + +// Overload of c_set_symmetric_difference() for performing a merge using a +// `comp` other than `operator<`. +template ::value, + void>::type, + typename = typename std::enable_if< + !container_algorithm_internal::IsUnorderedContainer::value, + void>::type> +OutputIterator c_set_symmetric_difference(const C1& c1, const C2& c2, + OutputIterator output, + LessThan&& comp) { + return std::set_symmetric_difference( + container_algorithm_internal::c_begin(c1), + container_algorithm_internal::c_end(c1), + container_algorithm_internal::c_begin(c2), + container_algorithm_internal::c_end(c2), output, + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Heap functions +//------------------------------------------------------------------------------ + +// c_push_heap() +// +// Container-based version of the `std::push_heap()` function +// to push a value onto a container heap. +template +void c_push_heap(RandomAccessContainer& sequence) { + std::push_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_push_heap() for performing a push operation on a heap using a +// `comp` other than `operator<`. +template +void c_push_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::push_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_pop_heap() +// +// Container-based version of the `std::pop_heap()` function +// to pop a value from a heap container. +template +void c_pop_heap(RandomAccessContainer& sequence) { + std::pop_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_pop_heap() for performing a pop operation on a heap using a +// `comp` other than `operator<`. +template +void c_pop_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::pop_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_make_heap() +// +// Container-based version of the `std::make_heap()` function +// to make a container a heap. +template +void c_make_heap(RandomAccessContainer& sequence) { + std::make_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_make_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +void c_make_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::make_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_sort_heap() +// +// Container-based version of the `std::sort_heap()` function +// to sort a heap into ascending order (after which it is no longer a heap). +template +void c_sort_heap(RandomAccessContainer& sequence) { + std::sort_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_sort_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +void c_sort_heap(RandomAccessContainer& sequence, LessThan&& comp) { + std::sort_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_is_heap() +// +// Container-based version of the `std::is_heap()` function +// to check whether the given container is a heap. +template +bool c_is_heap(const RandomAccessContainer& sequence) { + return std::is_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_is_heap() for performing heap comparisons using a +// `comp` other than `operator<` +template +bool c_is_heap(const RandomAccessContainer& sequence, LessThan&& comp) { + return std::is_heap(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_is_heap_until() +// +// Container-based version of the `std::is_heap_until()` function +// to find the first element in a given container which is not in heap order. +template +container_algorithm_internal::ContainerIter +c_is_heap_until(RandomAccessContainer& sequence) { + return std::is_heap_until(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_is_heap_until() for performing heap comparisons using a +// `comp` other than `operator<` +template +container_algorithm_internal::ContainerIter +c_is_heap_until(RandomAccessContainer& sequence, LessThan&& comp) { + return std::is_heap_until(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Min/max +//------------------------------------------------------------------------------ + +// c_min_element() +// +// Container-based version of the `std::min_element()` function +// to return an iterator pointing to the element with the smallest value, using +// `operator<` to make the comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence) { + return std::min_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_min_element() for performing a `comp` comparison other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_min_element(Sequence& sequence, LessThan&& comp) { + return std::min_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_max_element() +// +// Container-based version of the `std::max_element()` function +// to return an iterator pointing to the element with the largest value, using +// `operator<` to make the comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence) { + return std::max_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence)); +} + +// Overload of c_max_element() for performing a `comp` comparison other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIter + c_max_element(Sequence& sequence, LessThan&& comp) { + return std::max_element(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(comp)); +} + +// c_minmax_element() +// +// Container-based version of the `std::minmax_element()` function +// to return a pair of iterators pointing to the elements containing the +// smallest and largest values, respectively, using `operator<` to make the +// comparisons. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c) { + return std::minmax_element(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_minmax_element() for performing `comp` comparisons other than +// `operator<`. +template +ABSL_INTERNAL_CONSTEXPR_SINCE_CXX17 + container_algorithm_internal::ContainerIterPairType + c_minmax_element(C& c, LessThan&& comp) { + return std::minmax_element(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// Lexicographical Comparisons +//------------------------------------------------------------------------------ + +// c_lexicographical_compare() +// +// Container-based version of the `std::lexicographical_compare()` +// function to lexicographically compare (e.g. sort words alphabetically) two +// container sequences. The comparison is performed using `operator<`. Note +// that capital letters ("A-Z") have ASCII values less than lowercase letters +// ("a-z"). +template +bool c_lexicographical_compare(const Sequence1& sequence1, + const Sequence2& sequence2) { + return std::lexicographical_compare( + container_algorithm_internal::c_begin(sequence1), + container_algorithm_internal::c_end(sequence1), + container_algorithm_internal::c_begin(sequence2), + container_algorithm_internal::c_end(sequence2)); +} + +// Overload of c_lexicographical_compare() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +bool c_lexicographical_compare(const Sequence1& sequence1, + const Sequence2& sequence2, LessThan&& comp) { + return std::lexicographical_compare( + container_algorithm_internal::c_begin(sequence1), + container_algorithm_internal::c_end(sequence1), + container_algorithm_internal::c_begin(sequence2), + container_algorithm_internal::c_end(sequence2), + std::forward(comp)); +} + +// c_next_permutation() +// +// Container-based version of the `std::next_permutation()` function +// to rearrange a container's elements into the next lexicographically greater +// permutation. +template +bool c_next_permutation(C& c) { + return std::next_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_next_permutation() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +bool c_next_permutation(C& c, LessThan&& comp) { + return std::next_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +// c_prev_permutation() +// +// Container-based version of the `std::prev_permutation()` function +// to rearrange a container's elements into the next lexicographically lesser +// permutation. +template +bool c_prev_permutation(C& c) { + return std::prev_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c)); +} + +// Overload of c_prev_permutation() for performing a lexicographical +// comparison using a `comp` operator instead of `operator<`. +template +bool c_prev_permutation(C& c, LessThan&& comp) { + return std::prev_permutation(container_algorithm_internal::c_begin(c), + container_algorithm_internal::c_end(c), + std::forward(comp)); +} + +//------------------------------------------------------------------------------ +// algorithms +//------------------------------------------------------------------------------ + +// c_iota() +// +// Container-based version of the `std::iota()` function +// to compute successive values of `value`, as if incremented with `++value` +// after each element is written, and write them to the container. +template +void c_iota(Sequence& sequence, const T& value) { + std::iota(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), value); +} + +// c_accumulate() +// +// Container-based version of the `std::accumulate()` function +// to accumulate the element values of a container to `init` and return that +// accumulation by value. +// +// Note: Due to a language technicality this function has return type +// absl::decay_t. As a user of this function you can casually read +// this as "returns T by value" and assume it does the right thing. +template +decay_t c_accumulate(const Sequence& sequence, T&& init) { + return std::accumulate(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(init)); +} + +// Overload of c_accumulate() for using a binary operations other than +// addition for computing the accumulation. +template +decay_t c_accumulate(const Sequence& sequence, T&& init, + BinaryOp&& binary_op) { + return std::accumulate(container_algorithm_internal::c_begin(sequence), + container_algorithm_internal::c_end(sequence), + std::forward(init), + std::forward(binary_op)); +} + +// c_inner_product() +// +// Container-based version of the `std::inner_product()` function +// to compute the cumulative inner product of container element pairs. +// +// Note: Due to a language technicality this function has return type +// absl::decay_t. As a user of this function you can casually read +// this as "returns T by value" and assume it does the right thing. +template +decay_t c_inner_product(const Sequence1& factors1, const Sequence2& factors2, + T&& sum) { + return std::inner_product(container_algorithm_internal::c_begin(factors1), + container_algorithm_internal::c_end(factors1), + container_algorithm_internal::c_begin(factors2), + std::forward(sum)); +} + +// Overload of c_inner_product() for using binary operations other than +// `operator+` (for computing the accumulation) and `operator*` (for computing +// the product between the two container's element pair). +template +decay_t c_inner_product(const Sequence1& factors1, const Sequence2& factors2, + T&& sum, BinaryOp1&& op1, BinaryOp2&& op2) { + return std::inner_product(container_algorithm_internal::c_begin(factors1), + container_algorithm_internal::c_end(factors1), + container_algorithm_internal::c_begin(factors2), + std::forward(sum), std::forward(op1), + std::forward(op2)); +} + +// c_adjacent_difference() +// +// Container-based version of the `std::adjacent_difference()` +// function to compute the difference between each element and the one preceding +// it and write it to an iterator. +template +OutputIt c_adjacent_difference(const InputSequence& input, + OutputIt output_first) { + return std::adjacent_difference(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first); +} + +// Overload of c_adjacent_difference() for using a binary operation other than +// subtraction to compute the adjacent difference. +template +OutputIt c_adjacent_difference(const InputSequence& input, + OutputIt output_first, BinaryOp&& op) { + return std::adjacent_difference(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first, std::forward(op)); +} + +// c_partial_sum() +// +// Container-based version of the `std::partial_sum()` function +// to compute the partial sum of the elements in a sequence and write them +// to an iterator. The partial sum is the sum of all element values so far in +// the sequence. +template +OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first) { + return std::partial_sum(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first); +} + +// Overload of c_partial_sum() for using a binary operation other than addition +// to compute the "partial sum". +template +OutputIt c_partial_sum(const InputSequence& input, OutputIt output_first, + BinaryOp&& op) { + return std::partial_sum(container_algorithm_internal::c_begin(input), + container_algorithm_internal::c_end(input), + output_first, std::forward(op)); +} + +ABSL_NAMESPACE_END +} // namespace absl + +#endif // ABSL_ALGORITHM_CONTAINER_H_ diff --git a/third_party/abseil/absl/algorithm/container_test.cc b/third_party/abseil/absl/algorithm/container_test.cc new file mode 100644 index 0000000000..85e3b1111d --- /dev/null +++ b/third_party/abseil/absl/algorithm/container_test.cc @@ -0,0 +1,1421 @@ +// Copyright 2017 The Abseil Authors. +// +// 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 +// +// https://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. + +#include "absl/algorithm/container.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "gmock/gmock.h" +#include "gtest/gtest.h" +#include "absl/base/casts.h" +#include "absl/base/config.h" +#include "absl/base/macros.h" +#include "absl/memory/memory.h" +#include "absl/types/span.h" + +namespace { + +using ::testing::Each; +using ::testing::ElementsAre; +using ::testing::Gt; +using ::testing::IsNull; +using ::testing::IsSubsetOf; +using ::testing::Lt; +using ::testing::Pointee; +using ::testing::SizeIs; +using ::testing::Truly; +using ::testing::UnorderedElementsAre; + +// Most of these tests just check that the code compiles, not that it +// does the right thing. That's fine since the functions just forward +// to the STL implementation. +class NonMutatingTest : public testing::Test { + protected: + std::unordered_set container_ = {1, 2, 3}; + std::list sequence_ = {1, 2, 3}; + std::vector vector_ = {1, 2, 3}; + int array_[3] = {1, 2, 3}; +}; + +struct AccumulateCalls { + void operator()(int value) { calls.push_back(value); } + std::vector calls; +}; + +bool Predicate(int value) { return value < 3; } +bool BinPredicate(int v1, int v2) { return v1 < v2; } +bool Equals(int v1, int v2) { return v1 == v2; } +bool IsOdd(int x) { return x % 2 != 0; } + +TEST_F(NonMutatingTest, Distance) { + EXPECT_EQ(container_.size(), + static_cast(absl::c_distance(container_))); + EXPECT_EQ(sequence_.size(), static_cast(absl::c_distance(sequence_))); + EXPECT_EQ(vector_.size(), static_cast(absl::c_distance(vector_))); + EXPECT_EQ(ABSL_ARRAYSIZE(array_), + static_cast(absl::c_distance(array_))); + + // Works with a temporary argument. + EXPECT_EQ(vector_.size(), + static_cast(absl::c_distance(std::vector(vector_)))); +} + +TEST_F(NonMutatingTest, Distance_OverloadedBeginEnd) { + // Works with classes which have custom ADL-selected overloads of std::begin + // and std::end. + std::initializer_list a = {1, 2, 3}; + std::valarray b = {1, 2, 3}; + EXPECT_EQ(3, absl::c_distance(a)); + EXPECT_EQ(3, absl::c_distance(b)); + + // It is assumed that other c_* functions use the same mechanism for + // ADL-selecting begin/end overloads. +} + +TEST_F(NonMutatingTest, ForEach) { + AccumulateCalls c = absl::c_for_each(container_, AccumulateCalls()); + // Don't rely on the unordered_set's order. + std::sort(c.calls.begin(), c.calls.end()); + EXPECT_EQ(vector_, c.calls); + + // Works with temporary container, too. + AccumulateCalls c2 = + absl::c_for_each(std::unordered_set(container_), AccumulateCalls()); + std::sort(c2.calls.begin(), c2.calls.end()); + EXPECT_EQ(vector_, c2.calls); +} + +TEST_F(NonMutatingTest, FindReturnsCorrectType) { + auto it = absl::c_find(container_, 3); + EXPECT_EQ(3, *it); + absl::c_find(absl::implicit_cast&>(sequence_), 3); +} + +TEST_F(NonMutatingTest, Contains) { + EXPECT_TRUE(absl::c_contains(container_, 3)); + EXPECT_FALSE(absl::c_contains(container_, 4)); +} + +TEST_F(NonMutatingTest, FindIf) { absl::c_find_if(container_, Predicate); } + +TEST_F(NonMutatingTest, FindIfNot) { + absl::c_find_if_not(container_, Predicate); +} + +TEST_F(NonMutatingTest, FindEnd) { + absl::c_find_end(sequence_, vector_); + absl::c_find_end(vector_, sequence_); +} + +TEST_F(NonMutatingTest, FindEndWithPredicate) { + absl::c_find_end(sequence_, vector_, BinPredicate); + absl::c_find_end(vector_, sequence_, BinPredicate); +} + +TEST_F(NonMutatingTest, FindFirstOf) { + absl::c_find_first_of(container_, sequence_); + absl::c_find_first_of(sequence_, container_); + absl::c_find_first_of(sequence_, std::array{1, 2}); +} + +TEST_F(NonMutatingTest, FindFirstOfWithPredicate) { + absl::c_find_first_of(container_, sequence_, BinPredicate); + absl::c_find_first_of(sequence_, container_, BinPredicate); + absl::c_find_first_of(sequence_, std::array{1, 2}, BinPredicate); +} + +TEST_F(NonMutatingTest, AdjacentFind) { absl::c_adjacent_find(sequence_); } + +TEST_F(NonMutatingTest, AdjacentFindWithPredicate) { + absl::c_adjacent_find(sequence_, BinPredicate); +} + +TEST_F(NonMutatingTest, Count) { EXPECT_EQ(1, absl::c_count(container_, 3)); } + +TEST_F(NonMutatingTest, CountIf) { + EXPECT_EQ(2, absl::c_count_if(container_, Predicate)); + const std::unordered_set& const_container = container_; + EXPECT_EQ(2, absl::c_count_if(const_container, Predicate)); +} + +TEST_F(NonMutatingTest, Mismatch) { + // Testing necessary as absl::c_mismatch executes logic. + { + auto result = absl::c_mismatch(vector_, sequence_); + EXPECT_EQ(result.first, vector_.end()); + EXPECT_EQ(result.second, sequence_.end()); + } + { + auto result = absl::c_mismatch(sequence_, vector_); + EXPECT_EQ(result.first, sequence_.end()); + EXPECT_EQ(result.second, vector_.end()); + } + + sequence_.back() = 5; + { + auto result = absl::c_mismatch(vector_, sequence_); + EXPECT_EQ(result.first, std::prev(vector_.end())); + EXPECT_EQ(result.second, std::prev(sequence_.end())); + } + { + auto result = absl::c_mismatch(sequence_, vector_); + EXPECT_EQ(result.first, std::prev(sequence_.end())); + EXPECT_EQ(result.second, std::prev(vector_.end())); + } + + sequence_.pop_back(); + { + auto result = absl::c_mismatch(vector_, sequence_); + EXPECT_EQ(result.first, std::prev(vector_.end())); + EXPECT_EQ(result.second, sequence_.end()); + } + { + auto result = absl::c_mismatch(sequence_, vector_); + EXPECT_EQ(result.first, sequence_.end()); + EXPECT_EQ(result.second, std::prev(vector_.end())); + } + { + struct NoNotEquals { + constexpr bool operator==(NoNotEquals) const { return true; } + constexpr bool operator!=(NoNotEquals) const = delete; + }; + std::vector first; + std::list second; + + // Check this still compiles. + absl::c_mismatch(first, second); + } +} + +TEST_F(NonMutatingTest, MismatchWithPredicate) { + // Testing necessary as absl::c_mismatch executes logic. + { + auto result = absl::c_mismatch(vector_, sequence_, BinPredicate); + EXPECT_EQ(result.first, vector_.begin()); + EXPECT_EQ(result.second, sequence_.begin()); + } + { + auto result = absl::c_mismatch(sequence_, vector_, BinPredicate); + EXPECT_EQ(result.first, sequence_.begin()); + EXPECT_EQ(result.second, vector_.begin()); + } + + sequence_.front() = 0; + { + auto result = absl::c_mismatch(vector_, sequence_, BinPredicate); + EXPECT_EQ(result.first, vector_.begin()); + EXPECT_EQ(result.second, sequence_.begin()); + } + { + auto result = absl::c_mismatch(sequence_, vector_, BinPredicate); + EXPECT_EQ(result.first, std::next(sequence_.begin())); + EXPECT_EQ(result.second, std::next(vector_.begin())); + } + + sequence_.clear(); + { + auto result = absl::c_mismatch(vector_, sequence_, BinPredicate); + EXPECT_EQ(result.first, vector_.begin()); + EXPECT_EQ(result.second, sequence_.end()); + } + { + auto result = absl::c_mismatch(sequence_, vector_, BinPredicate); + EXPECT_EQ(result.first, sequence_.end()); + EXPECT_EQ(result.second, vector_.begin()); + } +} + +TEST_F(NonMutatingTest, Equal) { + EXPECT_TRUE(absl::c_equal(vector_, sequence_)); + EXPECT_TRUE(absl::c_equal(sequence_, vector_)); + EXPECT_TRUE(absl::c_equal(sequence_, array_)); + EXPECT_TRUE(absl::c_equal(array_, vector_)); + + // Test that behavior appropriately differs from that of equal(). + std::vector vector_plus = {1, 2, 3}; + vector_plus.push_back(4); + EXPECT_FALSE(absl::c_equal(vector_plus, sequence_)); + EXPECT_FALSE(absl::c_equal(sequence_, vector_plus)); + EXPECT_FALSE(absl::c_equal(array_, vector_plus)); +} + +TEST_F(NonMutatingTest, EqualWithPredicate) { + EXPECT_TRUE(absl::c_equal(vector_, sequence_, Equals)); + EXPECT_TRUE(absl::c_equal(sequence_, vector_, Equals)); + EXPECT_TRUE(absl::c_equal(array_, sequence_, Equals)); + EXPECT_TRUE(absl::c_equal(vector_, array_, Equals)); + + // Test that behavior appropriately differs from that of equal(). + std::vector vector_plus = {1, 2, 3}; + vector_plus.push_back(4); + EXPECT_FALSE(absl::c_equal(vector_plus, sequence_, Equals)); + EXPECT_FALSE(absl::c_equal(sequence_, vector_plus, Equals)); + EXPECT_FALSE(absl::c_equal(vector_plus, array_, Equals)); +} + +TEST_F(NonMutatingTest, IsPermutation) { + auto vector_permut_ = vector_; + std::next_permutation(vector_permut_.begin(), vector_permut_.end()); + EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_)); + EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_)); + + // Test that behavior appropriately differs from that of is_permutation(). + std::vector vector_plus = {1, 2, 3}; + vector_plus.push_back(4); + EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_)); + EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus)); +} + +TEST_F(NonMutatingTest, IsPermutationWithPredicate) { + auto vector_permut_ = vector_; + std::next_permutation(vector_permut_.begin(), vector_permut_.end()); + EXPECT_TRUE(absl::c_is_permutation(vector_permut_, sequence_, Equals)); + EXPECT_TRUE(absl::c_is_permutation(sequence_, vector_permut_, Equals)); + + // Test that behavior appropriately differs from that of is_permutation(). + std::vector vector_plus = {1, 2, 3}; + vector_plus.push_back(4); + EXPECT_FALSE(absl::c_is_permutation(vector_plus, sequence_, Equals)); + EXPECT_FALSE(absl::c_is_permutation(sequence_, vector_plus, Equals)); +} + +TEST_F(NonMutatingTest, Search) { + absl::c_search(sequence_, vector_); + absl::c_search(vector_, sequence_); + absl::c_search(array_, sequence_); +} + +TEST_F(NonMutatingTest, SearchWithPredicate) { + absl::c_search(sequence_, vector_, BinPredicate); + absl::c_search(vector_, sequence_, BinPredicate); +} + +TEST_F(NonMutatingTest, ContainsSubrange) { + EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_)); + EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_)); + EXPECT_TRUE(absl::c_contains_subrange(array_, sequence_)); +} + +TEST_F(NonMutatingTest, ContainsSubrangeWithPredicate) { + EXPECT_TRUE(absl::c_contains_subrange(sequence_, vector_, Equals)); + EXPECT_TRUE(absl::c_contains_subrange(vector_, sequence_, Equals)); +} + +TEST_F(NonMutatingTest, SearchN) { absl::c_search_n(sequence_, 3, 1); } + +TEST_F(NonMutatingTest, SearchNWithPredicate) { + absl::c_search_n(sequence_, 3, 1, BinPredicate); +} + +TEST_F(NonMutatingTest, LowerBound) { + std::list::iterator i = absl::c_lower_bound(sequence_, 3); + ASSERT_TRUE(i != sequence_.end()); + EXPECT_EQ(2, std::distance(sequence_.begin(), i)); + EXPECT_EQ(3, *i); +} + +TEST_F(NonMutatingTest, LowerBoundWithPredicate) { + std::vector v(vector_); + std::sort(v.begin(), v.end(), std::greater()); + std::vector::iterator i = absl::c_lower_bound(v, 3, std::greater()); + EXPECT_TRUE(i == v.begin()); + EXPECT_EQ(3, *i); +} + +TEST_F(NonMutatingTest, UpperBound) { + std::list::iterator i = absl::c_upper_bound(sequence_, 1); + ASSERT_TRUE(i != sequence_.end()); + EXPECT_EQ(1, std::distance(sequence_.begin(), i)); + EXPECT_EQ(2, *i); +} + +TEST_F(NonMutatingTest, UpperBoundWithPredicate) { + std::vector v(vector_); + std::sort(v.begin(), v.end(), std::greater()); + std::vector::iterator i = absl::c_upper_bound(v, 1, std::greater()); + EXPECT_EQ(3, i - v.begin()); + EXPECT_TRUE(i == v.end()); +} + +TEST_F(NonMutatingTest, EqualRange) { + std::pair::iterator, std::list::iterator> p = + absl::c_equal_range(sequence_, 2); + EXPECT_EQ(1, std::distance(sequence_.begin(), p.first)); + EXPECT_EQ(2, std::distance(sequence_.begin(), p.second)); +} + +TEST_F(NonMutatingTest, EqualRangeArray) { + auto p = absl::c_equal_range(array_, 2); + EXPECT_EQ(1, std::distance(std::begin(array_), p.first)); + EXPECT_EQ(2, std::distance(std::begin(array_), p.second)); +} + +TEST_F(NonMutatingTest, EqualRangeWithPredicate) { + std::vector v(vector_); + std::sort(v.begin(), v.end(), std::greater()); + std::pair::iterator, std::vector::iterator> p = + absl::c_equal_range(v, 2, std::greater()); + EXPECT_EQ(1, std::distance(v.begin(), p.first)); + EXPECT_EQ(2, std::distance(v.begin(), p.second)); +} + +TEST_F(NonMutatingTest, BinarySearch) { + EXPECT_TRUE(absl::c_binary_search(vector_, 2)); + EXPECT_TRUE(absl::c_binary_search(std::vector(vector_), 2)); +} + +TEST_F(NonMutatingTest, BinarySearchWithPredicate) { + std::vector v(vector_); + std::sort(v.begin(), v.end(), std::greater()); + EXPECT_TRUE(absl::c_binary_search(v, 2, std::greater())); + EXPECT_TRUE( + absl::c_binary_search(std::vector(v), 2, std::greater())); +} + +TEST_F(NonMutatingTest, MinElement) { + std::list::iterator i = absl::c_min_element(sequence_); + ASSERT_TRUE(i != sequence_.end()); + EXPECT_EQ(*i, 1); +} + +TEST_F(NonMutatingTest, MinElementWithPredicate) { + std::list::iterator i = + absl::c_min_element(sequence_, std::greater()); + ASSERT_TRUE(i != sequence_.end()); + EXPECT_EQ(*i, 3); +} + +TEST_F(NonMutatingTest, MaxElement) { + std::list::iterator i = absl::c_max_element(sequence_); + ASSERT_TRUE(i != sequence_.end()); + EXPECT_EQ(*i, 3); +} + +TEST_F(NonMutatingTest, MaxElementWithPredicate) { + std::list::iterator i = + absl::c_max_element(sequence_, std::greater()); + ASSERT_TRUE(i != sequence_.end()); + EXPECT_EQ(*i, 1); +} + +TEST_F(NonMutatingTest, LexicographicalCompare) { + EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_)); + + std::vector v; + v.push_back(1); + v.push_back(2); + v.push_back(4); + + EXPECT_TRUE(absl::c_lexicographical_compare(sequence_, v)); + EXPECT_TRUE(absl::c_lexicographical_compare(std::list(sequence_), v)); +} + +TEST_F(NonMutatingTest, LexicographicalCopmareWithPredicate) { + EXPECT_FALSE(absl::c_lexicographical_compare(sequence_, sequence_, + std::greater())); + + std::vector v; + v.push_back(1); + v.push_back(2); + v.push_back(4); + + EXPECT_TRUE( + absl::c_lexicographical_compare(v, sequence_, std::greater())); + EXPECT_TRUE(absl::c_lexicographical_compare( + std::vector(v), std::list(sequence_), std::greater())); +} + +TEST_F(NonMutatingTest, Includes) { + std::set s(vector_.begin(), vector_.end()); + s.insert(4); + EXPECT_TRUE(absl::c_includes(s, vector_)); +} + +TEST_F(NonMutatingTest, IncludesWithPredicate) { + std::vector v = {3, 2, 1}; + std::set> s(v.begin(), v.end()); + s.insert(4); + EXPECT_TRUE(absl::c_includes(s, v, std::greater())); +} + +class NumericMutatingTest : public testing::Test { + protected: + std::list list_ = {1, 2, 3}; + std::vector output_; +}; + +TEST_F(NumericMutatingTest, Iota) { + absl::c_iota(list_, 5); + std::list expected{5, 6, 7}; + EXPECT_EQ(list_, expected); +} + +TEST_F(NonMutatingTest, Accumulate) { + EXPECT_EQ(absl::c_accumulate(sequence_, 4), 1 + 2 + 3 + 4); +} + +TEST_F(NonMutatingTest, AccumulateWithBinaryOp) { + EXPECT_EQ(absl::c_accumulate(sequence_, 4, std::multiplies()), + 1 * 2 * 3 * 4); +} + +TEST_F(NonMutatingTest, AccumulateLvalueInit) { + int lvalue = 4; + EXPECT_EQ(absl::c_accumulate(sequence_, lvalue), 1 + 2 + 3 + 4); +} + +TEST_F(NonMutatingTest, AccumulateWithBinaryOpLvalueInit) { + int lvalue = 4; + EXPECT_EQ(absl::c_accumulate(sequence_, lvalue, std::multiplies()), + 1 * 2 * 3 * 4); +} + +TEST_F(NonMutatingTest, InnerProduct) { + EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 1000), + 1000 + 1 * 1 + 2 * 2 + 3 * 3); +} + +TEST_F(NonMutatingTest, InnerProductWithBinaryOps) { + EXPECT_EQ(absl::c_inner_product(sequence_, vector_, 10, + std::multiplies(), std::plus()), + 10 * (1 + 1) * (2 + 2) * (3 + 3)); +} + +TEST_F(NonMutatingTest, InnerProductLvalueInit) { + int lvalue = 1000; + EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue), + 1000 + 1 * 1 + 2 * 2 + 3 * 3); +} + +TEST_F(NonMutatingTest, InnerProductWithBinaryOpsLvalueInit) { + int lvalue = 10; + EXPECT_EQ(absl::c_inner_product(sequence_, vector_, lvalue, + std::multiplies(), std::plus()), + 10 * (1 + 1) * (2 + 2) * (3 + 3)); +} + +TEST_F(NumericMutatingTest, AdjacentDifference) { + auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_)); + *last = 1000; + std::vector expected{1, 2 - 1, 3 - 2, 1000}; + EXPECT_EQ(output_, expected); +} + +TEST_F(NumericMutatingTest, AdjacentDifferenceWithBinaryOp) { + auto last = absl::c_adjacent_difference(list_, std::back_inserter(output_), + std::multiplies()); + *last = 1000; + std::vector expected{1, 2 * 1, 3 * 2, 1000}; + EXPECT_EQ(output_, expected); +} + +TEST_F(NumericMutatingTest, PartialSum) { + auto last = absl::c_partial_sum(list_, std::back_inserter(output_)); + *last = 1000; + std::vector expected{1, 1 + 2, 1 + 2 + 3, 1000}; + EXPECT_EQ(output_, expected); +} + +TEST_F(NumericMutatingTest, PartialSumWithBinaryOp) { + auto last = absl::c_partial_sum(list_, std::back_inserter(output_), + std::multiplies()); + *last = 1000; + std::vector expected{1, 1 * 2, 1 * 2 * 3, 1000}; + EXPECT_EQ(output_, expected); +} + +TEST_F(NonMutatingTest, LinearSearch) { + EXPECT_TRUE(absl::c_linear_search(container_, 3)); + EXPECT_FALSE(absl::c_linear_search(container_, 4)); +} + +TEST_F(NonMutatingTest, AllOf) { + const std::vector& v = vector_; + EXPECT_FALSE(absl::c_all_of(v, [](int x) { return x > 1; })); + EXPECT_TRUE(absl::c_all_of(v, [](int x) { return x > 0; })); +} + +TEST_F(NonMutatingTest, AnyOf) { + const std::vector& v = vector_; + EXPECT_TRUE(absl::c_any_of(v, [](int x) { return x > 2; })); + EXPECT_FALSE(absl::c_any_of(v, [](int x) { return x > 5; })); +} + +TEST_F(NonMutatingTest, NoneOf) { + const std::vector& v = vector_; + EXPECT_FALSE(absl::c_none_of(v, [](int x) { return x > 2; })); + EXPECT_TRUE(absl::c_none_of(v, [](int x) { return x > 5; })); +} + +TEST_F(NonMutatingTest, MinMaxElementLess) { + std::pair::const_iterator, std::vector::const_iterator> + p = absl::c_minmax_element(vector_, std::less()); + EXPECT_TRUE(p.first == vector_.begin()); + EXPECT_TRUE(p.second == vector_.begin() + 2); +} + +TEST_F(NonMutatingTest, MinMaxElementGreater) { + std::pair::const_iterator, std::vector::const_iterator> + p = absl::c_minmax_element(vector_, std::greater()); + EXPECT_TRUE(p.first == vector_.begin() + 2); + EXPECT_TRUE(p.second == vector_.begin()); +} + +TEST_F(NonMutatingTest, MinMaxElementNoPredicate) { + std::pair::const_iterator, std::vector::const_iterator> + p = absl::c_minmax_element(vector_); + EXPECT_TRUE(p.first == vector_.begin()); + EXPECT_TRUE(p.second == vector_.begin() + 2); +} + +class SortingTest : public testing::Test { + protected: + std::list sorted_ = {1, 2, 3, 4}; + std::list unsorted_ = {2, 4, 1, 3}; + std::list reversed_ = {4, 3, 2, 1}; +}; + +TEST_F(SortingTest, IsSorted) { + EXPECT_TRUE(absl::c_is_sorted(sorted_)); + EXPECT_FALSE(absl::c_is_sorted(unsorted_)); + EXPECT_FALSE(absl::c_is_sorted(reversed_)); +} + +TEST_F(SortingTest, IsSortedWithPredicate) { + EXPECT_FALSE(absl::c_is_sorted(sorted_, std::greater())); + EXPECT_FALSE(absl::c_is_sorted(unsorted_, std::greater())); + EXPECT_TRUE(absl::c_is_sorted(reversed_, std::greater())); +} + +TEST_F(SortingTest, IsSortedUntil) { + EXPECT_EQ(1, *absl::c_is_sorted_until(unsorted_)); + EXPECT_EQ(4, *absl::c_is_sorted_until(unsorted_, std::greater())); +} + +TEST_F(SortingTest, NthElement) { + std::vector unsorted = {2, 4, 1, 3}; + absl::c_nth_element(unsorted, unsorted.begin() + 2); + EXPECT_THAT(unsorted, ElementsAre(Lt(3), Lt(3), 3, Gt(3))); + absl::c_nth_element(unsorted, unsorted.begin() + 2, std::greater()); + EXPECT_THAT(unsorted, ElementsAre(Gt(2), Gt(2), 2, Lt(2))); +} + +TEST(MutatingTest, IsPartitioned) { + EXPECT_TRUE( + absl::c_is_partitioned(std::vector{1, 3, 5, 2, 4, 6}, IsOdd)); + EXPECT_FALSE( + absl::c_is_partitioned(std::vector{1, 2, 3, 4, 5, 6}, IsOdd)); + EXPECT_FALSE( + absl::c_is_partitioned(std::vector{2, 4, 6, 1, 3, 5}, IsOdd)); +} + +TEST(MutatingTest, Partition) { + std::vector actual = {1, 2, 3, 4, 5}; + absl::c_partition(actual, IsOdd); + EXPECT_THAT(actual, Truly([](const std::vector& c) { + return absl::c_is_partitioned(c, IsOdd); + })); +} + +TEST(MutatingTest, StablePartition) { + std::vector actual = {1, 2, 3, 4, 5}; + absl::c_stable_partition(actual, IsOdd); + EXPECT_THAT(actual, ElementsAre(1, 3, 5, 2, 4)); +} + +TEST(MutatingTest, PartitionCopy) { + const std::vector initial = {1, 2, 3, 4, 5}; + std::vector odds, evens; + auto ends = absl::c_partition_copy(initial, back_inserter(odds), + back_inserter(evens), IsOdd); + *ends.first = 7; + *ends.second = 6; + EXPECT_THAT(odds, ElementsAre(1, 3, 5, 7)); + EXPECT_THAT(evens, ElementsAre(2, 4, 6)); +} + +TEST(MutatingTest, PartitionPoint) { + const std::vector initial = {1, 3, 5, 2, 4}; + auto middle = absl::c_partition_point(initial, IsOdd); + EXPECT_EQ(2, *middle); +} + +TEST(MutatingTest, CopyMiddle) { + const std::vector initial = {4, -1, -2, -3, 5}; + const std::list input = {1, 2, 3}; + const std::vector expected = {4, 1, 2, 3, 5}; + + std::list test_list(initial.begin(), initial.end()); + absl::c_copy(input, ++test_list.begin()); + EXPECT_EQ(std::list(expected.begin(), expected.end()), test_list); + + std::vector test_vector = initial; + absl::c_copy(input, test_vector.begin() + 1); + EXPECT_EQ(expected, test_vector); +} + +TEST(MutatingTest, CopyFrontInserter) { + const std::list initial = {4, 5}; + const std::list input = {1, 2, 3}; + const std::list expected = {3, 2, 1, 4, 5}; + + std::list test_list = initial; + absl::c_copy(input, std::front_inserter(test_list)); + EXPECT_EQ(expected, test_list); +} + +TEST(MutatingTest, CopyBackInserter) { + const std::vector initial = {4, 5}; + const std::list input = {1, 2, 3}; + const std::vector expected = {4, 5, 1, 2, 3}; + + std::list test_list(initial.begin(), initial.end()); + absl::c_copy(input, std::back_inserter(test_list)); + EXPECT_EQ(std::list(expected.begin(), expected.end()), test_list); + + std::vector test_vector = initial; + absl::c_copy(input, std::back_inserter(test_vector)); + EXPECT_EQ(expected, test_vector); +} + +TEST(MutatingTest, CopyN) { + const std::vector initial = {1, 2, 3, 4, 5}; + const std::vector expected = {1, 2}; + std::vector actual; + absl::c_copy_n(initial, 2, back_inserter(actual)); + EXPECT_EQ(expected, actual); +} + +TEST(MutatingTest, CopyIf) { + const std::list input = {1, 2, 3}; + std::vector output; + absl::c_copy_if(input, std::back_inserter(output), + [](int i) { return i != 2; }); + EXPECT_THAT(output, ElementsAre(1, 3)); +} + +TEST(MutatingTest, CopyBackward) { + std::vector actual = {1, 2, 3, 4, 5}; + std::vector expected = {1, 2, 1, 2, 3}; + absl::c_copy_backward(absl::MakeSpan(actual.data(), 3), actual.end()); + EXPECT_EQ(expected, actual); +} + +TEST(MutatingTest, Move) { + std::vector> src; + src.emplace_back(absl::make_unique(1)); + src.emplace_back(absl::make_unique(2)); + src.emplace_back(absl::make_unique(3)); + src.emplace_back(absl::make_unique(4)); + src.emplace_back(absl::make_unique(5)); + + std::vector> dest = {}; + absl::c_move(src, std::back_inserter(dest)); + EXPECT_THAT(src, Each(IsNull())); + EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(4), + Pointee(5))); +} + +TEST(MutatingTest, MoveBackward) { + std::vector> actual; + actual.emplace_back(absl::make_unique(1)); + actual.emplace_back(absl::make_unique(2)); + actual.emplace_back(absl::make_unique(3)); + actual.emplace_back(absl::make_unique(4)); + actual.emplace_back(absl::make_unique(5)); + auto subrange = absl::MakeSpan(actual.data(), 3); + absl::c_move_backward(subrange, actual.end()); + EXPECT_THAT(actual, ElementsAre(IsNull(), IsNull(), Pointee(1), Pointee(2), + Pointee(3))); +} + +TEST(MutatingTest, MoveWithRvalue) { + auto MakeRValueSrc = [] { + std::vector> src; + src.emplace_back(absl::make_unique(1)); + src.emplace_back(absl::make_unique(2)); + src.emplace_back(absl::make_unique(3)); + return src; + }; + + std::vector> dest = MakeRValueSrc(); + absl::c_move(MakeRValueSrc(), std::back_inserter(dest)); + EXPECT_THAT(dest, ElementsAre(Pointee(1), Pointee(2), Pointee(3), Pointee(1), + Pointee(2), Pointee(3))); +} + +TEST(MutatingTest, SwapRanges) { + std::vector odds = {2, 4, 6}; + std::vector evens = {1, 3, 5}; + absl::c_swap_ranges(odds, evens); + EXPECT_THAT(odds, ElementsAre(1, 3, 5)); + EXPECT_THAT(evens, ElementsAre(2, 4, 6)); + + odds.pop_back(); + absl::c_swap_ranges(odds, evens); + EXPECT_THAT(odds, ElementsAre(2, 4)); + EXPECT_THAT(evens, ElementsAre(1, 3, 6)); + + absl::c_swap_ranges(evens, odds); + EXPECT_THAT(odds, ElementsAre(1, 3)); + EXPECT_THAT(evens, ElementsAre(2, 4, 6)); +} + +TEST_F(NonMutatingTest, Transform) { + std::vector x{0, 2, 4}, y, z; + auto end = absl::c_transform(x, back_inserter(y), std::negate()); + EXPECT_EQ(std::vector({0, -2, -4}), y); + *end = 7; + EXPECT_EQ(std::vector({0, -2, -4, 7}), y); + + y = {1, 3, 0}; + end = absl::c_transform(x, y, back_inserter(z), std::plus()); + EXPECT_EQ(std::vector({1, 5, 4}), z); + *end = 7; + EXPECT_EQ(std::vector({1, 5, 4, 7}), z); + + z.clear(); + y.pop_back(); + end = absl::c_transform(x, y, std::back_inserter(z), std::plus()); + EXPECT_EQ(std::vector({1, 5}), z); + *end = 7; + EXPECT_EQ(std::vector({1, 5, 7}), z); + + z.clear(); + std::swap(x, y); + end = absl::c_transform(x, y, std::back_inserter(z), std::plus()); + EXPECT_EQ(std::vector({1, 5}), z); + *end = 7; + EXPECT_EQ(std::vector({1, 5, 7}), z); +} + +TEST(MutatingTest, Replace) { + const std::vector initial = {1, 2, 3, 1, 4, 5}; + const std::vector expected = {4, 2, 3, 4, 4, 5}; + + std::vector test_vector = initial; + absl::c_replace(test_vector, 1, 4); + EXPECT_EQ(expected, test_vector); + + std::list test_list(initial.begin(), initial.end()); + absl::c_replace(test_list, 1, 4); + EXPECT_EQ(std::list(expected.begin(), expected.end()), test_list); +} + +TEST(MutatingTest, ReplaceIf) { + std::vector actual = {1, 2, 3, 4, 5}; + const std::vector expected = {0, 2, 0, 4, 0}; + + absl::c_replace_if(actual, IsOdd, 0); + EXPECT_EQ(expected, actual); +} + +TEST(MutatingTest, ReplaceCopy) { + const std::vector initial = {1, 2, 3, 1, 4, 5}; + const std::vector expected = {4, 2, 3, 4, 4, 5}; + + std::vector actual; + absl::c_replace_copy(initial, back_inserter(actual), 1, 4); + EXPECT_EQ(expected, actual); +} + +TEST(MutatingTest, Sort) { + std::vector test_vector = {2, 3, 1, 4}; + absl::c_sort(test_vector); + EXPECT_THAT(test_vector, ElementsAre(1, 2, 3, 4)); +} + +TEST(MutatingTest, SortWithPredicate) { + std::vector test_vector = {2, 3, 1, 4}; + absl::c_sort(test_vector, std::greater()); + EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1)); +} + +// For absl::c_stable_sort tests. Needs an operator< that does not cover all +// fields so that the test can check the sort preserves order of equal elements. +struct Element { + int key; + int value; + friend bool operator<(const Element& e1, const Element& e2) { + return e1.key < e2.key; + } + // Make gmock print useful diagnostics. + friend std::ostream& operator<<(std::ostream& o, const Element& e) { + return o << "{" << e.key << ", " << e.value << "}"; + } +}; + +MATCHER_P2(IsElement, key, value, "") { + return arg.key == key && arg.value == value; +} + +TEST(MutatingTest, StableSort) { + std::vector test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}}; + absl::c_stable_sort(test_vector); + EXPECT_THAT(test_vector, + ElementsAre(IsElement(1, 1), IsElement(1, 0), IsElement(2, 1), + IsElement(2, 0), IsElement(2, 2))); +} + +TEST(MutatingTest, StableSortWithPredicate) { + std::vector test_vector = {{1, 1}, {2, 1}, {2, 0}, {1, 0}, {2, 2}}; + absl::c_stable_sort(test_vector, [](const Element& e1, const Element& e2) { + return e2 < e1; + }); + EXPECT_THAT(test_vector, + ElementsAre(IsElement(2, 1), IsElement(2, 0), IsElement(2, 2), + IsElement(1, 1), IsElement(1, 0))); +} + +TEST(MutatingTest, ReplaceCopyIf) { + const std::vector initial = {1, 2, 3, 4, 5}; + const std::vector expected = {0, 2, 0, 4, 0}; + + std::vector actual; + absl::c_replace_copy_if(initial, back_inserter(actual), IsOdd, 0); + EXPECT_EQ(expected, actual); +} + +TEST(MutatingTest, Fill) { + std::vector actual(5); + absl::c_fill(actual, 1); + EXPECT_THAT(actual, ElementsAre(1, 1, 1, 1, 1)); +} + +TEST(MutatingTest, FillN) { + std::vector actual(5, 0); + absl::c_fill_n(actual, 2, 1); + EXPECT_THAT(actual, ElementsAre(1, 1, 0, 0, 0)); +} + +TEST(MutatingTest, Generate) { + std::vector actual(5); + int x = 0; + absl::c_generate(actual, [&x]() { return ++x; }); + EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); +} + +TEST(MutatingTest, GenerateN) { + std::vector actual(5, 0); + int x = 0; + absl::c_generate_n(actual, 3, [&x]() { return ++x; }); + EXPECT_THAT(actual, ElementsAre(1, 2, 3, 0, 0)); +} + +TEST(MutatingTest, RemoveCopy) { + std::vector actual; + absl::c_remove_copy(std::vector{1, 2, 3}, back_inserter(actual), 2); + EXPECT_THAT(actual, ElementsAre(1, 3)); +} + +TEST(MutatingTest, RemoveCopyIf) { + std::vector actual; + absl::c_remove_copy_if(std::vector{1, 2, 3}, back_inserter(actual), + IsOdd); + EXPECT_THAT(actual, ElementsAre(2)); +} + +TEST(MutatingTest, UniqueCopy) { + std::vector actual; + absl::c_unique_copy(std::vector{1, 2, 2, 2, 3, 3, 2}, + back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(1, 2, 3, 2)); +} + +TEST(MutatingTest, UniqueCopyWithPredicate) { + std::vector actual; + absl::c_unique_copy(std::vector{1, 2, 3, -1, -2, -3, 1}, + back_inserter(actual), + [](int x, int y) { return (x < 0) == (y < 0); }); + EXPECT_THAT(actual, ElementsAre(1, -1, 1)); +} + +TEST(MutatingTest, Reverse) { + std::vector test_vector = {1, 2, 3, 4}; + absl::c_reverse(test_vector); + EXPECT_THAT(test_vector, ElementsAre(4, 3, 2, 1)); + + std::list test_list = {1, 2, 3, 4}; + absl::c_reverse(test_list); + EXPECT_THAT(test_list, ElementsAre(4, 3, 2, 1)); +} + +TEST(MutatingTest, ReverseCopy) { + std::vector actual; + absl::c_reverse_copy(std::vector{1, 2, 3, 4}, back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(4, 3, 2, 1)); +} + +TEST(MutatingTest, Rotate) { + std::vector actual = {1, 2, 3, 4}; + auto it = absl::c_rotate(actual, actual.begin() + 2); + EXPECT_THAT(actual, testing::ElementsAreArray({3, 4, 1, 2})); + EXPECT_EQ(*it, 1); +} + +TEST(MutatingTest, RotateCopy) { + std::vector initial = {1, 2, 3, 4}; + std::vector actual; + auto end = + absl::c_rotate_copy(initial, initial.begin() + 2, back_inserter(actual)); + *end = 5; + EXPECT_THAT(actual, ElementsAre(3, 4, 1, 2, 5)); +} + +template +T RandomlySeededPrng() { + std::random_device rdev; + std::seed_seq::result_type data[T::state_size]; + std::generate_n(data, T::state_size, std::ref(rdev)); + std::seed_seq prng_seed(data, data + T::state_size); + return T(prng_seed); +} + +TEST(MutatingTest, Shuffle) { + std::vector actual = {1, 2, 3, 4, 5}; + absl::c_shuffle(actual, RandomlySeededPrng()); + EXPECT_THAT(actual, UnorderedElementsAre(1, 2, 3, 4, 5)); +} + +TEST(MutatingTest, Sample) { + std::vector actual; + absl::c_sample(std::vector{1, 2, 3, 4, 5}, std::back_inserter(actual), 3, + RandomlySeededPrng()); + EXPECT_THAT(actual, IsSubsetOf({1, 2, 3, 4, 5})); + EXPECT_THAT(actual, SizeIs(3)); +} + +TEST(MutatingTest, PartialSort) { + std::vector sequence{5, 3, 42, 0}; + absl::c_partial_sort(sequence, sequence.begin() + 2); + EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(0, 3)); + absl::c_partial_sort(sequence, sequence.begin() + 2, std::greater()); + EXPECT_THAT(absl::MakeSpan(sequence.data(), 2), ElementsAre(42, 5)); +} + +TEST(MutatingTest, PartialSortCopy) { + const std::vector initial = {5, 3, 42, 0}; + std::vector actual(2); + absl::c_partial_sort_copy(initial, actual); + EXPECT_THAT(actual, ElementsAre(0, 3)); + absl::c_partial_sort_copy(initial, actual, std::greater()); + EXPECT_THAT(actual, ElementsAre(42, 5)); +} + +TEST(MutatingTest, Merge) { + std::vector actual; + absl::c_merge(std::vector{1, 3, 5}, std::vector{2, 4}, + back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); +} + +TEST(MutatingTest, MergeWithComparator) { + std::vector actual; + absl::c_merge(std::vector{5, 3, 1}, std::vector{4, 2}, + back_inserter(actual), std::greater()); + EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1)); +} + +TEST(MutatingTest, InplaceMerge) { + std::vector actual = {1, 3, 5, 2, 4}; + absl::c_inplace_merge(actual, actual.begin() + 3); + EXPECT_THAT(actual, ElementsAre(1, 2, 3, 4, 5)); +} + +TEST(MutatingTest, InplaceMergeWithComparator) { + std::vector actual = {5, 3, 1, 4, 2}; + absl::c_inplace_merge(actual, actual.begin() + 3, std::greater()); + EXPECT_THAT(actual, ElementsAre(5, 4, 3, 2, 1)); +} + +class SetOperationsTest : public testing::Test { + protected: + std::vector a_ = {1, 2, 3}; + std::vector b_ = {1, 3, 5}; + + std::vector a_reversed_ = {3, 2, 1}; + std::vector b_reversed_ = {5, 3, 1}; +}; + +TEST_F(SetOperationsTest, SetUnion) { + std::vector actual; + absl::c_set_union(a_, b_, back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(1, 2, 3, 5)); +} + +TEST_F(SetOperationsTest, SetUnionWithComparator) { + std::vector actual; + absl::c_set_union(a_reversed_, b_reversed_, back_inserter(actual), + std::greater()); + EXPECT_THAT(actual, ElementsAre(5, 3, 2, 1)); +} + +TEST_F(SetOperationsTest, SetIntersection) { + std::vector actual; + absl::c_set_intersection(a_, b_, back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(1, 3)); +} + +TEST_F(SetOperationsTest, SetIntersectionWithComparator) { + std::vector actual; + absl::c_set_intersection(a_reversed_, b_reversed_, back_inserter(actual), + std::greater()); + EXPECT_THAT(actual, ElementsAre(3, 1)); +} + +TEST_F(SetOperationsTest, SetDifference) { + std::vector actual; + absl::c_set_difference(a_, b_, back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(2)); +} + +TEST_F(SetOperationsTest, SetDifferenceWithComparator) { + std::vector actual; + absl::c_set_difference(a_reversed_, b_reversed_, back_inserter(actual), + std::greater()); + EXPECT_THAT(actual, ElementsAre(2)); +} + +TEST_F(SetOperationsTest, SetSymmetricDifference) { + std::vector actual; + absl::c_set_symmetric_difference(a_, b_, back_inserter(actual)); + EXPECT_THAT(actual, ElementsAre(2, 5)); +} + +TEST_F(SetOperationsTest, SetSymmetricDifferenceWithComparator) { + std::vector actual; + absl::c_set_symmetric_difference(a_reversed_, b_reversed_, + back_inserter(actual), std::greater()); + EXPECT_THAT(actual, ElementsAre(5, 2)); +} + +TEST(HeapOperationsTest, WithoutComparator) { + std::vector heap = {1, 2, 3}; + EXPECT_FALSE(absl::c_is_heap(heap)); + absl::c_make_heap(heap); + EXPECT_TRUE(absl::c_is_heap(heap)); + heap.push_back(4); + EXPECT_EQ(3, absl::c_is_heap_until(heap) - heap.begin()); + absl::c_push_heap(heap); + EXPECT_EQ(4, heap[0]); + absl::c_pop_heap(heap); + EXPECT_EQ(4, heap[3]); + absl::c_make_heap(heap); + absl::c_sort_heap(heap); + EXPECT_THAT(heap, ElementsAre(1, 2, 3, 4)); + EXPECT_FALSE(absl::c_is_heap(heap)); +} + +TEST(HeapOperationsTest, WithComparator) { + using greater = std::greater; + std::vector heap = {3, 2, 1}; + EXPECT_FALSE(absl::c_is_heap(heap, greater())); + absl::c_make_heap(heap, greater()); + EXPECT_TRUE(absl::c_is_heap(heap, greater())); + heap.push_back(0); + EXPECT_EQ(3, absl::c_is_heap_until(heap, greater()) - heap.begin()); + absl::c_push_heap(heap, greater()); + EXPECT_EQ(0, heap[0]); + absl::c_pop_heap(heap, greater()); + EXPECT_EQ(0, heap[3]); + absl::c_make_heap(heap, greater()); + absl::c_sort_heap(heap, greater()); + EXPECT_THAT(heap, ElementsAre(3, 2, 1, 0)); + EXPECT_FALSE(absl::c_is_heap(heap, greater())); +} + +TEST(MutatingTest, PermutationOperations) { + std::vector initial = {1, 2, 3, 4}; + std::vector permuted = initial; + + absl::c_next_permutation(permuted); + EXPECT_TRUE(absl::c_is_permutation(initial, permuted)); + EXPECT_TRUE(absl::c_is_permutation(initial, permuted, std::equal_to())); + + std::vector permuted2 = initial; + absl::c_prev_permutation(permuted2, std::greater()); + EXPECT_EQ(permuted, permuted2); + + absl::c_prev_permutation(permuted); + EXPECT_EQ(initial, permuted); +} + +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L + +TEST(ConstexprTest, Distance) { + // Works at compile time with constexpr containers. + static_assert(absl::c_distance(std::array()) == 3); +} + +TEST(ConstexprTest, MinElement) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_min_element(kArray) == 1); +} + +TEST(ConstexprTest, MinElementWithPredicate) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_min_element(kArray, std::greater()) == 3); +} + +TEST(ConstexprTest, MaxElement) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_max_element(kArray) == 3); +} + +TEST(ConstexprTest, MaxElementWithPredicate) { + constexpr std::array kArray = {1, 2, 3}; + static_assert(*absl::c_max_element(kArray, std::greater()) == 1); +} + +TEST(ConstexprTest, MinMaxElement) { + static constexpr std::array kArray = {1, 2, 3}; + constexpr auto kMinMaxPair = absl::c_minmax_element(kArray); + static_assert(*kMinMaxPair.first == 1); + static_assert(*kMinMaxPair.second == 3); +} + +TEST(ConstexprTest, MinMaxElementWithPredicate) { + static constexpr std::array kArray = {1, 2, 3}; + constexpr auto kMinMaxPair = + absl::c_minmax_element(kArray, std::greater()); + static_assert(*kMinMaxPair.first == 3); + static_assert(*kMinMaxPair.second == 1); +} +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 201703L + +#if defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && \ + ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + +TEST(ConstexprTest, LinearSearch) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_linear_search(kArray, 3)); + static_assert(!absl::c_linear_search(kArray, 4)); +} + +TEST(ConstexprTest, AllOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(!absl::c_all_of(kArray, [](int x) { return x > 1; })); + static_assert(absl::c_all_of(kArray, [](int x) { return x > 0; })); +} + +TEST(ConstexprTest, AnyOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_any_of(kArray, [](int x) { return x > 2; })); + static_assert(!absl::c_any_of(kArray, [](int x) { return x > 5; })); +} + +TEST(ConstexprTest, NoneOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(!absl::c_none_of(kArray, [](int x) { return x > 2; })); + static_assert(absl::c_none_of(kArray, [](int x) { return x > 5; })); +} + +TEST(ConstexprTest, ForEach) { + static constexpr std::array kArray = [] { + std::array array = {1, 2, 3}; + absl::c_for_each(array, [](int& x) { x += 1; }); + return array; + }(); + static_assert(kArray == std::array{2, 3, 4}); +} + +TEST(ConstexprTest, Find) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find(kArray, 1) == kArray.begin()); + static_assert(absl::c_find(kArray, 4) == kArray.end()); +} + +TEST(ConstexprTest, Contains) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_contains(kArray, 1)); + static_assert(!absl::c_contains(kArray, 4)); +} + +TEST(ConstexprTest, FindIf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_if(kArray, [](int x) { return x > 2; }) == + kArray.begin() + 2); + static_assert(absl::c_find_if(kArray, [](int x) { return x > 5; }) == + kArray.end()); +} + +TEST(ConstexprTest, FindIfNot) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 1; }) == + kArray.begin()); + static_assert(absl::c_find_if_not(kArray, [](int x) { return x > 0; }) == + kArray.end()); +} + +TEST(ConstexprTest, FindEnd) { + static constexpr std::array kHaystack = {1, 2, 3, 2, 3}; + static constexpr std::array kNeedle = {2, 3}; + static_assert(absl::c_find_end(kHaystack, kNeedle) == kHaystack.begin() + 3); +} + +TEST(ConstexprTest, FindFirstOf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_find_first_of(kArray, kArray) == kArray.begin()); +} + +TEST(ConstexprTest, AdjacentFind) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_adjacent_find(kArray) == kArray.begin() + 1); +} + +TEST(ConstexprTest, AdjacentFindWithPredicate) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_adjacent_find(kArray, std::less()) == + kArray.begin()); +} + +TEST(ConstexprTest, Count) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_count(kArray, 1) == 1); + static_assert(absl::c_count(kArray, 2) == 1); + static_assert(absl::c_count(kArray, 3) == 1); + static_assert(absl::c_count(kArray, 4) == 0); +} + +TEST(ConstexprTest, CountIf) { + static constexpr std::array kArray = {1, 2, 3}; + static_assert(absl::c_count_if(kArray, [](int x) { return x > 0; }) == 3); + static_assert(absl::c_count_if(kArray, [](int x) { return x > 1; }) == 2); +} + +TEST(ConstexprTest, Mismatch) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_mismatch(kArray1, kArray2) == + std::pair{kArray1.end(), kArray2.end()}); + static_assert(absl::c_mismatch(kArray1, kArray3) == + std::pair{kArray1.begin(), kArray3.begin()}); +} + +TEST(ConstexprTest, MismatchWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_mismatch(kArray1, kArray2, std::not_equal_to()) == + std::pair{kArray1.begin(), kArray2.begin()}); + static_assert(absl::c_mismatch(kArray1, kArray3, std::not_equal_to()) == + std::pair{kArray1.end(), kArray3.end()}); +} + +TEST(ConstexprTest, Equal) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_equal(kArray1, kArray2)); + static_assert(!absl::c_equal(kArray1, kArray3)); +} + +TEST(ConstexprTest, EqualWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(!absl::c_equal(kArray1, kArray2, std::not_equal_to())); + static_assert(absl::c_equal(kArray1, kArray3, std::not_equal_to())); +} + +TEST(ConstexprTest, IsPermutation) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {3, 2, 1}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_is_permutation(kArray1, kArray2)); + static_assert(!absl::c_is_permutation(kArray1, kArray3)); +} + +TEST(ConstexprTest, IsPermutationWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {3, 2, 1}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_is_permutation(kArray1, kArray2, std::equal_to())); + static_assert( + !absl::c_is_permutation(kArray1, kArray3, std::equal_to())); +} + +TEST(ConstexprTest, Search) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_search(kArray1, kArray2) == kArray1.begin()); + static_assert(absl::c_search(kArray1, kArray3) == kArray1.end()); +} + +TEST(ConstexprTest, SearchWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_search(kArray1, kArray2, std::not_equal_to()) == + kArray1.end()); + static_assert(absl::c_search(kArray1, kArray3, std::not_equal_to()) == + kArray1.begin()); +} + +TEST(ConstexprTest, ContainsSubrange) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert(absl::c_contains_subrange(kArray1, kArray2)); + static_assert(!absl::c_contains_subrange(kArray1, kArray3)); +} + +TEST(ConstexprTest, ContainsSubrangeWithPredicate) { + static constexpr std::array kArray1 = {1, 2, 3}; + static constexpr std::array kArray2 = {1, 2, 3}; + static constexpr std::array kArray3 = {2, 3, 4}; + static_assert( + !absl::c_contains_subrange(kArray1, kArray2, std::not_equal_to<>())); + static_assert( + absl::c_contains_subrange(kArray1, kArray3, std::not_equal_to<>())); +} + +TEST(ConstexprTest, SearchN) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_search_n(kArray, 1, 1) == kArray.begin()); + static_assert(absl::c_search_n(kArray, 2, 2) == kArray.begin() + 1); + static_assert(absl::c_search_n(kArray, 1, 4) == kArray.end()); +} + +TEST(ConstexprTest, SearchNWithPredicate) { + static constexpr std::array kArray = {1, 2, 2, 3}; + static_assert(absl::c_search_n(kArray, 1, 1, std::not_equal_to()) == + kArray.begin() + 1); + static_assert(absl::c_search_n(kArray, 2, 2, std::not_equal_to()) == + kArray.end()); + static_assert(absl::c_search_n(kArray, 1, 4, std::not_equal_to()) == + kArray.begin()); +} + +#endif // defined(ABSL_INTERNAL_CPLUSPLUS_LANG) && + // ABSL_INTERNAL_CPLUSPLUS_LANG >= 202002L + +} // namespace diff --git a/third_party/abseil/absl/base/BUILD.bazel b/third_party/abseil/absl/base/BUILD.bazel new file mode 100644 index 0000000000..38ec925826 --- /dev/null +++ b/third_party/abseil/absl/base/BUILD.bazel @@ -0,0 +1,982 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +load( + "//absl:copts/configure_copts.bzl", + "ABSL_DEFAULT_COPTS", + "ABSL_DEFAULT_LINKOPTS", + "ABSL_TEST_COPTS", +) + +package( + default_visibility = ["//visibility:public"], + features = [ + "header_modules", + "layering_check", + "parse_headers", + ], +) + +licenses(["notice"]) + +cc_library( + name = "atomic_hook", + hdrs = ["internal/atomic_hook.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ":core_headers", + ], +) + +cc_library( + name = "errno_saver", + hdrs = ["internal/errno_saver.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [":config"], +) + +cc_library( + name = "log_severity", + srcs = ["log_severity.cc"], + hdrs = ["log_severity.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":core_headers", + ], +) + +cc_library( + name = "no_destructor", + hdrs = ["no_destructor.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":nullability", + ], +) + +cc_library( + name = "nullability", + srcs = ["internal/nullability_impl.h"], + hdrs = ["nullability.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":core_headers", + "//absl/meta:type_traits", + ], +) + +cc_library( + name = "raw_logging_internal", + srcs = ["internal/raw_logging.cc"], + hdrs = ["internal/raw_logging.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":atomic_hook", + ":config", + ":core_headers", + ":errno_saver", + ":log_severity", + ], +) + +cc_library( + name = "spinlock_wait", + srcs = [ + "internal/spinlock_akaros.inc", + "internal/spinlock_linux.inc", + "internal/spinlock_posix.inc", + "internal/spinlock_wait.cc", + "internal/spinlock_win32.inc", + ], + hdrs = ["internal/spinlock_wait.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl/base:__pkg__", + ], + deps = [ + ":base_internal", + ":core_headers", + ":errno_saver", + ], +) + +cc_library( + name = "config", + hdrs = [ + "config.h", + "options.h", + "policy_checks.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, +) + +cc_library( + name = "cycleclock_internal", + hdrs = [ + "internal/cycleclock_config.h", + "internal/unscaledcycleclock_config.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":base_internal", + ":config", + ], +) + +cc_library( + name = "dynamic_annotations", + srcs = [ + "internal/dynamic_annotations.h", + ], + hdrs = [ + "dynamic_annotations.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":core_headers", + ], +) + +cc_library( + name = "core_headers", + hdrs = [ + "attributes.h", + "const_init.h", + "macros.h", + "optimization.h", + "port.h", + "thread_annotations.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ], +) + +cc_library( + name = "malloc_internal", + srcs = [ + "internal/low_level_alloc.cc", + ], + hdrs = [ + "internal/direct_mmap.h", + "internal/low_level_alloc.h", + ], + copts = ABSL_DEFAULT_COPTS + select({ + "//conditions:default": [], + }), + linkopts = select({ + "//absl:msvc_compiler": [], + "//absl:clang-cl_compiler": [], + "//absl:wasm": [], + "//conditions:default": ["-pthread"], + }) + ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//visibility:public", + ], + deps = [ + ":base", + ":base_internal", + ":config", + ":core_headers", + ":dynamic_annotations", + ":raw_logging_internal", + ], +) + +cc_library( + name = "base_internal", + hdrs = [ + "internal/hide_ptr.h", + "internal/identity.h", + "internal/inline_variable.h", + "internal/invoke.h", + "internal/scheduling_mode.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + "//absl/meta:type_traits", + ], +) + +cc_library( + name = "base", + srcs = [ + "internal/cycleclock.cc", + "internal/spinlock.cc", + "internal/sysinfo.cc", + "internal/thread_identity.cc", + "internal/unscaledcycleclock.cc", + ], + hdrs = [ + "call_once.h", + "casts.h", + "internal/cycleclock.h", + "internal/low_level_scheduling.h", + "internal/per_thread_tls.h", + "internal/spinlock.h", + "internal/sysinfo.h", + "internal/thread_identity.h", + "internal/tsan_mutex_interface.h", + "internal/unscaledcycleclock.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = select({ + "//absl:msvc_compiler": [ + "-DEFAULTLIB:advapi32.lib", + ], + "//absl:clang-cl_compiler": [ + "-DEFAULTLIB:advapi32.lib", + ], + "//absl:mingw_compiler": [ + "-DEFAULTLIB:advapi32.lib", + "-ladvapi32", + ], + "//absl:wasm": [], + "//conditions:default": ["-pthread"], + }) + ABSL_DEFAULT_LINKOPTS, + deps = [ + ":atomic_hook", + ":base_internal", + ":config", + ":core_headers", + ":cycleclock_internal", + ":dynamic_annotations", + ":log_severity", + ":nullability", + ":raw_logging_internal", + ":spinlock_wait", + "//absl/meta:type_traits", + ], +) + +cc_library( + name = "atomic_hook_test_helper", + testonly = True, + srcs = ["internal/atomic_hook_test_helper.cc"], + hdrs = ["internal/atomic_hook_test_helper.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":atomic_hook", + ":core_headers", + ], +) + +cc_test( + name = "atomic_hook_test", + size = "small", + srcs = ["internal/atomic_hook_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":atomic_hook", + ":atomic_hook_test_helper", + ":core_headers", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "bit_cast_test", + size = "small", + srcs = [ + "bit_cast_test.cc", + ], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + ":core_headers", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "c_header_test", + srcs = ["c_header_test.c"], + tags = [ + "no_test_wasm", + ], + deps = [ + ":config", + ":core_headers", + ], +) + +cc_library( + name = "throw_delegate", + srcs = ["internal/throw_delegate.cc"], + hdrs = ["internal/throw_delegate.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ":raw_logging_internal", + ], +) + +cc_test( + name = "throw_delegate_test", + srcs = ["throw_delegate_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":throw_delegate", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "errno_saver_test", + size = "small", + srcs = ["internal/errno_saver_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":errno_saver", + ":strerror", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "exception_testing", + testonly = True, + hdrs = ["internal/exception_testing.h"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + "@googletest//:gtest", + ], +) + +cc_library( + name = "pretty_function", + hdrs = ["internal/pretty_function.h"], + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], +) + +cc_library( + name = "exception_safety_testing", + testonly = True, + srcs = ["internal/exception_safety_testing.cc"], + hdrs = ["internal/exception_safety_testing.h"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":pretty_function", + "//absl/memory", + "//absl/meta:type_traits", + "//absl/strings", + "//absl/utility", + "@googletest//:gtest", + ], +) + +cc_test( + name = "exception_safety_testing_test", + srcs = ["exception_safety_testing_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":exception_safety_testing", + "//absl/memory", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "inline_variable_test", + size = "small", + srcs = [ + "inline_variable_test.cc", + "inline_variable_test_a.cc", + "inline_variable_test_b.cc", + "internal/inline_variable_testing.h", + ], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base_internal", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "invoke_test", + size = "small", + srcs = ["invoke_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base_internal", + "//absl/memory", + "//absl/strings", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +# Common test library made available for use in non-absl code that overrides +# AbslInternalSpinLockDelay and AbslInternalSpinLockWake. +cc_library( + name = "spinlock_test_common", + testonly = True, + srcs = ["spinlock_test_common.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + ":base_internal", + ":config", + ":core_headers", + "//absl/synchronization", + "@googletest//:gtest", + ], + alwayslink = 1, +) + +cc_test( + name = "spinlock_test", + size = "medium", + srcs = ["spinlock_test_common.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = [ + "no_test_wasm", + ], + deps = [ + ":base", + ":base_internal", + ":config", + ":core_headers", + "//absl/synchronization", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "spinlock_benchmark_common", + testonly = True, + srcs = ["internal/spinlock_benchmark.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl/base:__pkg__", + ], + deps = [ + ":base", + ":base_internal", + ":no_destructor", + ":raw_logging_internal", + "//absl/synchronization", + "@google_benchmark//:benchmark_main", + ], + alwayslink = 1, +) + +cc_binary( + name = "spinlock_benchmark", + testonly = True, + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":spinlock_benchmark_common", + ], +) + +cc_library( + name = "endian", + hdrs = [ + "internal/endian.h", + "internal/unaligned_access.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + ":config", + ":core_headers", + ":nullability", + ], +) + +cc_test( + name = "endian_test", + srcs = ["internal/endian_test.cc"], + copts = ABSL_TEST_COPTS, + deps = [ + ":config", + ":endian", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "config_test", + srcs = ["config_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + "//absl/synchronization:thread_pool", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "call_once_test", + srcs = ["call_once_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + ":core_headers", + "//absl/synchronization", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "no_destructor_test", + srcs = ["no_destructor_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":no_destructor", + ":raw_logging_internal", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_binary( + name = "no_destructor_benchmark", + testonly = True, + srcs = ["no_destructor_benchmark.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":no_destructor", + ":raw_logging_internal", + "@google_benchmark//:benchmark_main", + ], +) + +cc_test( + name = "nullability_test", + srcs = ["nullability_test.cc"], + deps = [ + ":core_headers", + ":nullability", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "nullability_default_nonnull_test", + srcs = ["nullability_default_nonnull_test.cc"], + deps = [ + ":nullability", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "raw_logging_test", + srcs = ["raw_logging_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":raw_logging_internal", + "//absl/strings", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "sysinfo_test", + size = "small", + srcs = ["internal/sysinfo_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":base", + "//absl/synchronization", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "low_level_alloc_test", + size = "medium", + srcs = ["internal/low_level_alloc_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = [ + "no_test_ios_x86_64", + "no_test_wasm", + ], + deps = [ + ":malloc_internal", + "//absl/container:node_hash_map", + ], +) + +cc_test( + name = "thread_identity_test", + size = "small", + srcs = ["internal/thread_identity_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = [ + "no_test_wasm", + ], + deps = [ + ":base", + ":core_headers", + "//absl/synchronization", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "thread_identity_benchmark", + srcs = ["internal/thread_identity_benchmark.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":base", + "//absl/synchronization", + "@google_benchmark//:benchmark_main", + "@googletest//:gtest", + ], +) + +cc_library( + name = "scoped_set_env", + testonly = True, + srcs = ["internal/scoped_set_env.cc"], + hdrs = ["internal/scoped_set_env.h"], + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ":raw_logging_internal", + ], +) + +cc_test( + name = "scoped_set_env_test", + size = "small", + srcs = ["internal/scoped_set_env_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":scoped_set_env", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "log_severity_test", + size = "small", + srcs = ["log_severity_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":log_severity", + "//absl/flags:flag_internal", + "//absl/flags:marshalling", + "//absl/strings", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "strerror", + srcs = ["internal/strerror.cc"], + hdrs = ["internal/strerror.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ":core_headers", + ":errno_saver", + ], +) + +cc_test( + name = "strerror_test", + size = "small", + srcs = ["internal/strerror_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":strerror", + "//absl/strings", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_binary( + name = "strerror_benchmark", + testonly = True, + srcs = ["internal/strerror_benchmark.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + tags = ["benchmark"], + visibility = ["//visibility:private"], + deps = [ + ":strerror", + "@google_benchmark//:benchmark_main", + ], +) + +cc_library( + name = "fast_type_id", + hdrs = ["internal/fast_type_id.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ], +) + +cc_test( + name = "fast_type_id_test", + size = "small", + srcs = ["internal/fast_type_id_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":fast_type_id", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "prefetch", + hdrs = [ + "prefetch.h", + ], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":core_headers", + ], +) + +cc_test( + name = "prefetch_test", + size = "small", + srcs = [ + "prefetch_test.cc", + ], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":prefetch", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "poison", + srcs = [ + "internal/poison.cc", + ], + hdrs = ["internal/poison.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + ":config", + ":core_headers", + ":malloc_internal", + ], +) + +cc_test( + name = "poison_test", + size = "small", + timeout = "short", + srcs = [ + "internal/poison_test.cc", + ], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":poison", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "unique_small_name_test", + size = "small", + srcs = ["internal/unique_small_name_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + linkstatic = 1, + deps = [ + ":core_headers", + "//absl/strings", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "optimization_test", + size = "small", + srcs = ["optimization_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":core_headers", + "//absl/types:optional", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_library( + name = "tracing_internal", + srcs = ["internal/tracing.cc"], + hdrs = ["internal/tracing.h"], + copts = ABSL_DEFAULT_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + visibility = [ + "//absl:__subpackages__", + ], + deps = [ + "//absl/base:config", + "//absl/base:core_headers", + ], +) + +cc_test( + name = "tracing_internal_weak_test", + srcs = ["internal/tracing_weak_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":tracing_internal", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) + +cc_test( + name = "tracing_internal_strong_test", + srcs = ["internal/tracing_strong_test.cc"], + copts = ABSL_TEST_COPTS, + linkopts = ABSL_DEFAULT_LINKOPTS, + deps = [ + ":config", + ":core_headers", + ":tracing_internal", + "@googletest//:gtest", + "@googletest//:gtest_main", + ], +) diff --git a/third_party/abseil/absl/base/CMakeLists.txt b/third_party/abseil/absl/base/CMakeLists.txt new file mode 100644 index 0000000000..ac62a04f94 --- /dev/null +++ b/third_party/abseil/absl/base/CMakeLists.txt @@ -0,0 +1,823 @@ +# +# Copyright 2017 The Abseil Authors. +# +# 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 +# +# https://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. +# + +find_library(LIBRT rt) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + atomic_hook + HDRS + "internal/atomic_hook.h" + DEPS + absl::config + absl::core_headers + COPTS + ${ABSL_DEFAULT_COPTS} +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + errno_saver + HDRS + "internal/errno_saver.h" + DEPS + absl::config + COPTS + ${ABSL_DEFAULT_COPTS} +) + +absl_cc_library( + NAME + log_severity + HDRS + "log_severity.h" + SRCS + "log_severity.cc" + DEPS + absl::config + absl::core_headers + COPTS + ${ABSL_DEFAULT_COPTS} +) + +absl_cc_library( + NAME + no_destructor + HDRS + "no_destructor.h" + DEPS + absl::config + absl::nullability + COPTS + ${ABSL_DEFAULT_COPTS} +) + +absl_cc_library( + NAME + nullability + HDRS + "nullability.h" + SRCS + "internal/nullability_impl.h" + DEPS + absl::config + absl::core_headers + absl::type_traits + COPTS + ${ABSL_DEFAULT_COPTS} +) + +absl_cc_test( + NAME + nullability_test + SRCS + "nullability_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::core_headers + absl::nullability + GTest::gtest_main +) + +absl_cc_test( + NAME + nullability_default_nonnull_test + SRCS + "nullability_default_nonnull_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::nullability + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + raw_logging_internal + HDRS + "internal/raw_logging.h" + SRCS + "internal/raw_logging.cc" + DEPS + absl::atomic_hook + absl::config + absl::core_headers + absl::errno_saver + absl::log_severity + COPTS + ${ABSL_DEFAULT_COPTS} +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + spinlock_wait + HDRS + "internal/spinlock_wait.h" + SRCS + "internal/spinlock_akaros.inc" + "internal/spinlock_linux.inc" + "internal/spinlock_posix.inc" + "internal/spinlock_wait.cc" + "internal/spinlock_win32.inc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::base_internal + absl::core_headers + absl::errno_saver +) + +absl_cc_library( + NAME + config + HDRS + "config.h" + "options.h" + "policy_checks.h" + COPTS + ${ABSL_DEFAULT_COPTS} + PUBLIC +) + +absl_cc_library( + NAME + dynamic_annotations + HDRS + "dynamic_annotations.h" + SRCS + "internal/dynamic_annotations.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + PUBLIC +) + +absl_cc_library( + NAME + core_headers + HDRS + "attributes.h" + "const_init.h" + "macros.h" + "optimization.h" + "port.h" + "thread_annotations.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + PUBLIC +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + malloc_internal + HDRS + "internal/direct_mmap.h" + "internal/low_level_alloc.h" + SRCS + "internal/low_level_alloc.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::base + absl::base_internal + absl::config + absl::core_headers + absl::dynamic_annotations + absl::raw_logging_internal + Threads::Threads +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + base_internal + HDRS + "internal/hide_ptr.h" + "internal/identity.h" + "internal/inline_variable.h" + "internal/invoke.h" + "internal/scheduling_mode.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + absl::type_traits +) + +absl_cc_library( + NAME + base + HDRS + "call_once.h" + "casts.h" + "internal/cycleclock.h" + "internal/cycleclock_config.h" + "internal/low_level_scheduling.h" + "internal/per_thread_tls.h" + "internal/spinlock.h" + "internal/sysinfo.h" + "internal/thread_identity.h" + "internal/tsan_mutex_interface.h" + "internal/unscaledcycleclock.h" + "internal/unscaledcycleclock_config.h" + SRCS + "internal/cycleclock.cc" + "internal/spinlock.cc" + "internal/sysinfo.cc" + "internal/thread_identity.cc" + "internal/unscaledcycleclock.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + $<$:-lrt> + $<$:-ladvapi32> + DEPS + absl::atomic_hook + absl::base_internal + absl::config + absl::core_headers + absl::dynamic_annotations + absl::log_severity + absl::nullability + absl::raw_logging_internal + absl::spinlock_wait + absl::type_traits + Threads::Threads + PUBLIC +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + throw_delegate + HDRS + "internal/throw_delegate.h" + SRCS + "internal/throw_delegate.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + absl::raw_logging_internal +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + exception_testing + HDRS + "internal/exception_testing.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + GTest::gtest + TESTONLY +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + pretty_function + HDRS + "internal/pretty_function.h" + COPTS + ${ABSL_DEFAULT_COPTS} +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + exception_safety_testing + HDRS + "internal/exception_safety_testing.h" + SRCS + "internal/exception_safety_testing.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::config + absl::pretty_function + absl::memory + absl::meta + absl::strings + absl::utility + GTest::gtest + TESTONLY +) + +absl_cc_test( + NAME + absl_exception_safety_testing_test + SRCS + "exception_safety_testing_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::exception_safety_testing + absl::memory + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + atomic_hook_test_helper + SRCS + "internal/atomic_hook_test_helper.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::atomic_hook + absl::core_headers + TESTONLY +) + +absl_cc_test( + NAME + atomic_hook_test + SRCS + "internal/atomic_hook_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::atomic_hook_test_helper + absl::atomic_hook + absl::core_headers + GTest::gmock + GTest::gtest_main +) + +absl_cc_test( + NAME + bit_cast_test + SRCS + "bit_cast_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::core_headers + GTest::gtest_main +) + +absl_cc_test( + NAME + errno_saver_test + SRCS + "internal/errno_saver_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::errno_saver + absl::strerror + GTest::gmock + GTest::gtest_main +) + +absl_cc_test( + NAME + throw_delegate_test + SRCS + "throw_delegate_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::config + absl::throw_delegate + GTest::gtest_main +) + +absl_cc_test( + NAME + inline_variable_test + SRCS + "internal/inline_variable_testing.h" + "inline_variable_test.cc" + "inline_variable_test_a.cc" + "inline_variable_test_b.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base_internal + GTest::gtest_main +) + +absl_cc_test( + NAME + invoke_test + SRCS + "invoke_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base_internal + absl::memory + absl::strings + GTest::gmock + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + spinlock_test_common + SRCS + "spinlock_test_common.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::config + absl::base_internal + absl::core_headers + absl::synchronization + GTest::gtest + TESTONLY +) + +# On bazel BUILD this target use "alwayslink = 1" which is not implemented here +absl_cc_test( + NAME + spinlock_test + SRCS + "spinlock_test_common.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::base_internal + absl::config + absl::core_headers + absl::synchronization + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + endian + HDRS + "internal/endian.h" + "internal/unaligned_access.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::base + absl::config + absl::core_headers + absl::nullability + PUBLIC +) + +absl_cc_test( + NAME + endian_test + SRCS + "internal/endian_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::config + absl::endian + GTest::gtest_main +) + +absl_cc_test( + NAME + config_test + SRCS + "config_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::config + absl::synchronization + GTest::gtest_main +) + +absl_cc_test( + NAME + call_once_test + SRCS + "call_once_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::core_headers + absl::synchronization + GTest::gtest_main +) + +absl_cc_test( + NAME + no_destructor_test + SRCS + "no_destructor_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::no_destructor + absl::config + absl::raw_logging_internal + GTest::gmock + GTest::gtest_main +) + +absl_cc_test( + NAME + raw_logging_test + SRCS + "raw_logging_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::raw_logging_internal + absl::strings + GTest::gtest_main +) + +absl_cc_test( + NAME + sysinfo_test + SRCS + "internal/sysinfo_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::synchronization + GTest::gtest_main +) + +absl_cc_test( + NAME + low_level_alloc_test + SRCS + "internal/low_level_alloc_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::malloc_internal + absl::node_hash_map + Threads::Threads +) + +absl_cc_test( + NAME + thread_identity_test + SRCS + "internal/thread_identity_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::core_headers + absl::synchronization + Threads::Threads + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + scoped_set_env + SRCS + "internal/scoped_set_env.cc" + HDRS + "internal/scoped_set_env.h" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::config + absl::raw_logging_internal +) + +absl_cc_test( + NAME + scoped_set_env_test + SRCS + "internal/scoped_set_env_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::scoped_set_env + GTest::gtest_main +) + +absl_cc_test( + NAME + cmake_thread_test + SRCS + "internal/cmake_thread_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base +) + +absl_cc_test( + NAME + log_severity_test + SRCS + "log_severity_test.cc" + DEPS + absl::flags_internal + absl::flags_marshalling + absl::log_severity + absl::strings + GTest::gmock + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + strerror + SRCS + "internal/strerror.cc" + HDRS + "internal/strerror.h" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config + absl::core_headers + absl::errno_saver +) + +absl_cc_test( + NAME + strerror_test + SRCS + "internal/strerror_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::strerror + absl::strings + GTest::gmock + GTest::gtest_main +) + +# Internal-only target, do not depend on directly. +absl_cc_library( + NAME + fast_type_id + HDRS + "internal/fast_type_id.h" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config +) + +absl_cc_test( + NAME + fast_type_id_test + SRCS + "internal/fast_type_id_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::fast_type_id + GTest::gtest_main +) + +absl_cc_library( + NAME + prefetch + HDRS + "prefetch.h" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config + absl::core_headers +) + +absl_cc_test( + NAME + prefetch_test + SRCS + "prefetch_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::prefetch + GTest::gtest_main +) + +absl_cc_test( + NAME + optimization_test + SRCS + "optimization_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::core_headers + absl::optional + GTest::gtest_main +) + +absl_cc_library( + NAME + poison + SRCS + "internal/poison.cc" + HDRS + "internal/poison.h" + COPTS + ${ABSL_DEFAULT_COPTS} + LINKOPTS + ${ABSL_DEFAULT_LINKOPTS} + DEPS + absl::config + absl::core_headers + absl::malloc_internal +) + +absl_cc_test( + NAME + poison_test + SRCS + "internal/poison_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::config + absl::poison + GTest::gtest_main +) + +absl_cc_library( + NAME + tracing_internal + HDRS + "internal/tracing.h" + SRCS + "internal/tracing.cc" + COPTS + ${ABSL_DEFAULT_COPTS} + DEPS + absl::base +) + +absl_cc_test( + NAME + tracing_internal_weak_test + SRCS + "internal/tracing_weak_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::tracing_internal + GTest::gtest_main +) + +absl_cc_test( + NAME + tracing_internal_strong_test + SRCS + "internal/tracing_strong_test.cc" + COPTS + ${ABSL_TEST_COPTS} + DEPS + absl::base + absl::tracing_internal + GTest::gtest_main +) diff --git a/third_party/abseil/absl/base/attributes.h b/third_party/abseil/absl/base/attributes.h new file mode 100644 index 0000000000..0b94ae43b7 --- /dev/null +++ b/third_party/abseil/absl/base/attributes.h @@ -0,0 +1,997 @@ +// Copyright 2017 The Abseil Authors. +// +// 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 +// +// https://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. +// +// This header file defines macros for declaring attributes for functions, +// types, and variables. +// +// These macros are used within Abseil and allow the compiler to optimize, where +// applicable, certain function calls. +// +// Most macros here are exposing GCC or Clang features, and are stubbed out for +// other compilers. +// +// GCC attributes documentation: +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Function-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Variable-Attributes.html +// https://gcc.gnu.org/onlinedocs/gcc-4.7.0/gcc/Type-Attributes.html +// +// Most attributes in this file are already supported by GCC 4.7. However, some +// of them are not supported in older version of Clang. Thus, we check +// `__has_attribute()` first. If the check fails, we check if we are on GCC and +// assume the attribute exists on GCC (which is verified on GCC 4.7). + +// SKIP_ABSL_INLINE_NAMESPACE_CHECK + +#ifndef ABSL_BASE_ATTRIBUTES_H_ +#define ABSL_BASE_ATTRIBUTES_H_ + +#include "absl/base/config.h" + +// ABSL_HAVE_ATTRIBUTE +// +// A function-like feature checking macro that is a wrapper around +// `__has_attribute`, which is defined by GCC 5+ and Clang and evaluates to a +// nonzero constant integer if the attribute is supported or 0 if not. +// +// It evaluates to zero if `__has_attribute` is not defined by the compiler. +// +// GCC: https://gcc.gnu.org/gcc-5/changes.html +// Clang: https://clang.llvm.org/docs/LanguageExtensions.html +#ifdef __has_attribute +#define ABSL_HAVE_ATTRIBUTE(x) __has_attribute(x) +#else +#define ABSL_HAVE_ATTRIBUTE(x) 0 +#endif + +// ABSL_HAVE_CPP_ATTRIBUTE +// +// A function-like feature checking macro that accepts C++11 style attributes. +// It's a wrapper around `__has_cpp_attribute`, defined by ISO C++ SD-6 +// (https://en.cppreference.com/w/cpp/experimental/feature_test). If we don't +// find `__has_cpp_attribute`, will evaluate to 0. +#if defined(__cplusplus) && defined(__has_cpp_attribute) +// NOTE: requiring __cplusplus above should not be necessary, but +// works around https://bugs.llvm.org/show_bug.cgi?id=23435. +#define ABSL_HAVE_CPP_ATTRIBUTE(x) __has_cpp_attribute(x) +#else +#define ABSL_HAVE_CPP_ATTRIBUTE(x) 0 +#endif + +// ----------------------------------------------------------------------------- +// Function Attributes +// ----------------------------------------------------------------------------- +// +// GCC: https://gcc.gnu.org/onlinedocs/gcc/Function-Attributes.html +// Clang: https://clang.llvm.org/docs/AttributeReference.html + +// ABSL_PRINTF_ATTRIBUTE +// ABSL_SCANF_ATTRIBUTE +// +// Tells the compiler to perform `printf` format string checking if the +// compiler supports it; see the 'format' attribute in +// . +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +#if ABSL_HAVE_ATTRIBUTE(format) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__printf__, string_index, first_to_check))) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) \ + __attribute__((__format__(__scanf__, string_index, first_to_check))) +#else +#define ABSL_PRINTF_ATTRIBUTE(string_index, first_to_check) +#define ABSL_SCANF_ATTRIBUTE(string_index, first_to_check) +#endif + +// ABSL_ATTRIBUTE_ALWAYS_INLINE +// ABSL_ATTRIBUTE_NOINLINE +// +// Forces functions to either inline or not inline. Introduced in gcc 3.1. +#if ABSL_HAVE_ATTRIBUTE(always_inline) || \ + (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_ALWAYS_INLINE __attribute__((always_inline)) +#define ABSL_HAVE_ATTRIBUTE_ALWAYS_INLINE 1 +#else +#define ABSL_ATTRIBUTE_ALWAYS_INLINE +#endif + +#if ABSL_HAVE_ATTRIBUTE(noinline) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NOINLINE __attribute__((noinline)) +#define ABSL_HAVE_ATTRIBUTE_NOINLINE 1 +#else +#define ABSL_ATTRIBUTE_NOINLINE +#endif + +// ABSL_ATTRIBUTE_NO_TAIL_CALL +// +// Prevents the compiler from optimizing away stack frames for functions which +// end in a call to another function. +#if ABSL_HAVE_ATTRIBUTE(disable_tail_calls) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL __attribute__((disable_tail_calls)) +#elif defined(__GNUC__) && !defined(__clang__) && !defined(__e2k__) +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 1 +#define ABSL_ATTRIBUTE_NO_TAIL_CALL \ + __attribute__((optimize("no-optimize-sibling-calls"))) +#else +#define ABSL_ATTRIBUTE_NO_TAIL_CALL +#define ABSL_HAVE_ATTRIBUTE_NO_TAIL_CALL 0 +#endif + +// ABSL_ATTRIBUTE_WEAK +// +// Tags a function as weak for the purposes of compilation and linking. +// Weak attributes did not work properly in LLVM's Windows backend before +// 9.0.0, so disable them there. See https://bugs.llvm.org/show_bug.cgi?id=37598 +// for further information. Weak attributes do not work across DLL boundary. +// The MinGW compiler doesn't complain about the weak attribute until the link +// step, presumably because Windows doesn't use ELF binaries. +#if (ABSL_HAVE_ATTRIBUTE(weak) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + (!defined(_WIN32) || \ + (defined(__clang__) && __clang_major__ >= 9 && \ + !defined(ABSL_BUILD_DLL) && !defined(ABSL_CONSUME_DLL))) && \ + !defined(__MINGW32__) +#undef ABSL_ATTRIBUTE_WEAK +#define ABSL_ATTRIBUTE_WEAK __attribute__((weak)) +#define ABSL_HAVE_ATTRIBUTE_WEAK 1 +#else +#define ABSL_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_WEAK 0 +#endif + +// ABSL_ATTRIBUTE_NONNULL +// +// Tells the compiler either (a) that a particular function parameter +// should be a non-null pointer, or (b) that all pointer arguments should +// be non-null. +// +// Note: As the GCC manual states, "[s]ince non-static C++ methods +// have an implicit 'this' argument, the arguments of such methods +// should be counted from two, not one." +// +// Args are indexed starting at 1. +// +// For non-static class member functions, the implicit `this` argument +// is arg 1, and the first explicit argument is arg 2. For static class member +// functions, there is no implicit `this`, and the first explicit argument is +// arg 1. +// +// Example: +// +// /* arg_a cannot be null, but arg_b can */ +// void Function(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(1); +// +// class C { +// /* arg_a cannot be null, but arg_b can */ +// void Method(void* arg_a, void* arg_b) ABSL_ATTRIBUTE_NONNULL(2); +// +// /* arg_a cannot be null, but arg_b can */ +// static void StaticMethod(void* arg_a, void* arg_b) +// ABSL_ATTRIBUTE_NONNULL(1); +// }; +// +// If no arguments are provided, then all pointer arguments should be non-null. +// +// /* No pointer arguments may be null. */ +// void Function(void* arg_a, void* arg_b, int arg_c) ABSL_ATTRIBUTE_NONNULL(); +// +// NOTE: The GCC nonnull attribute actually accepts a list of arguments, but +// ABSL_ATTRIBUTE_NONNULL does not. +#if ABSL_HAVE_ATTRIBUTE(nonnull) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NONNULL(arg_index) __attribute__((nonnull(arg_index))) +#else +#define ABSL_ATTRIBUTE_NONNULL(...) +#endif + +// ABSL_ATTRIBUTE_NORETURN +// +// Tells the compiler that a given function never returns. +// +// Deprecated: Prefer the `[[noreturn]]` attribute standardized by C++11 over +// this macro. +#if ABSL_HAVE_ATTRIBUTE(noreturn) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_NORETURN __attribute__((noreturn)) +#elif defined(_MSC_VER) +#define ABSL_ATTRIBUTE_NORETURN __declspec(noreturn) +#else +#define ABSL_ATTRIBUTE_NORETURN +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +// +// Tells the AddressSanitizer (or other memory testing tools) to ignore a given +// function. Useful for cases when a function reads random locations on stack, +// calls _exit from a cloned subprocess, deliberately accesses buffer +// out of bounds or does other scary things with memory. +// NOTE: GCC supports AddressSanitizer(asan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if defined(ABSL_HAVE_ADDRESS_SANITIZER) && \ + ABSL_HAVE_ATTRIBUTE(no_sanitize_address) +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __attribute__((no_sanitize_address)) +#elif defined(ABSL_HAVE_ADDRESS_SANITIZER) && defined(_MSC_VER) && \ + _MSC_VER >= 1928 +// https://docs.microsoft.com/en-us/cpp/cpp/no-sanitize-address +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS __declspec(no_sanitize_address) +#elif defined(ABSL_HAVE_HWADDRESS_SANITIZER) && ABSL_HAVE_ATTRIBUTE(no_sanitize) +// HWAddressSanitizer is a sanitizer similar to AddressSanitizer, which uses CPU +// features to detect similar bugs with less CPU and memory overhead. +// NOTE: GCC supports HWAddressSanitizer(hwasan) since 11. +// https://gcc.gnu.org/gcc-11/changes.html +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS \ + __attribute__((no_sanitize("hwaddress"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +// +// Tells the MemorySanitizer to relax the handling of a given function. All "Use +// of uninitialized value" warnings from such functions will be suppressed, and +// all values loaded from memory will be considered fully initialized. This +// attribute is similar to the ABSL_ATTRIBUTE_NO_SANITIZE_ADDRESS attribute +// above, but deals with initialized-ness rather than addressability issues. +// NOTE: MemorySanitizer(msan) is supported by Clang but not GCC. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_memory) +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY __attribute__((no_sanitize_memory)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_MEMORY +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +// +// Tells the ThreadSanitizer to not instrument a given function. +// NOTE: GCC supports ThreadSanitizer(tsan) since 4.8. +// https://gcc.gnu.org/gcc-4.8/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_thread) +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD __attribute__((no_sanitize_thread)) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_THREAD +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +// +// Tells the UndefinedSanitizer to ignore a given function. Useful for cases +// where certain behavior (eg. division by zero) is being used intentionally. +// NOTE: GCC supports UndefinedBehaviorSanitizer(ubsan) since 4.9. +// https://gcc.gnu.org/gcc-4.9/changes.html +#if ABSL_HAVE_ATTRIBUTE(no_sanitize_undefined) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize_undefined)) +#elif ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED \ + __attribute__((no_sanitize("undefined"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_UNDEFINED +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_CFI +// +// Tells the ControlFlowIntegrity sanitizer to not instrument a given function. +// See https://clang.llvm.org/docs/ControlFlowIntegrity.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) && defined(__llvm__) +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI __attribute__((no_sanitize("cfi"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_CFI +#endif + +// ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +// +// Tells the SafeStack to not instrument a given function. +// See https://clang.llvm.org/docs/SafeStack.html for details. +#if ABSL_HAVE_ATTRIBUTE(no_sanitize) +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK \ + __attribute__((no_sanitize("safe-stack"))) +#else +#define ABSL_ATTRIBUTE_NO_SANITIZE_SAFESTACK +#endif + +// ABSL_ATTRIBUTE_RETURNS_NONNULL +// +// Tells the compiler that a particular function never returns a null pointer. +#if ABSL_HAVE_ATTRIBUTE(returns_nonnull) +#define ABSL_ATTRIBUTE_RETURNS_NONNULL __attribute__((returns_nonnull)) +#else +#define ABSL_ATTRIBUTE_RETURNS_NONNULL +#endif + +// ABSL_HAVE_ATTRIBUTE_SECTION +// +// Indicates whether labeled sections are supported. Weak symbol support is +// a prerequisite. Labeled sections are not supported on Darwin/iOS. +#ifdef ABSL_HAVE_ATTRIBUTE_SECTION +#error ABSL_HAVE_ATTRIBUTE_SECTION cannot be directly set +#elif (ABSL_HAVE_ATTRIBUTE(section) || \ + (defined(__GNUC__) && !defined(__clang__))) && \ + !defined(__APPLE__) && ABSL_HAVE_ATTRIBUTE_WEAK +#define ABSL_HAVE_ATTRIBUTE_SECTION 1 + +// ABSL_ATTRIBUTE_SECTION +// +// Tells the compiler/linker to put a given function into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. Any function annotated with +// `ABSL_ATTRIBUTE_SECTION` must not be inlined, or it will be placed into +// whatever section its caller is placed into. +// +#ifndef ABSL_ATTRIBUTE_SECTION +#define ABSL_ATTRIBUTE_SECTION(name) \ + __attribute__((section(#name))) __attribute__((noinline)) +#endif + +// ABSL_ATTRIBUTE_SECTION_VARIABLE +// +// Tells the compiler/linker to put a given variable into a section and define +// `__start_ ## name` and `__stop_ ## name` symbols to bracket the section. +// This functionality is supported by GNU linker. +#ifndef ABSL_ATTRIBUTE_SECTION_VARIABLE +#ifdef _AIX +// __attribute__((section(#name))) on AIX is achieved by using the `.csect` +// psudo op which includes an additional integer as part of its syntax indcating +// alignment. If data fall under different alignments then you might get a +// compilation error indicating a `Section type conflict`. +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#else +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) __attribute__((section(#name))) +#endif +#endif + +// ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +// +// A weak section declaration to be used as a global declaration +// for ABSL_ATTRIBUTE_SECTION_START|STOP(name) to compile and link +// even without functions with ABSL_ATTRIBUTE_SECTION(name). +// ABSL_DEFINE_ATTRIBUTE_SECTION should be in the exactly one file; it's +// a no-op on ELF but not on Mach-O. +// +#ifndef ABSL_DECLARE_ATTRIBUTE_SECTION_VARS +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) \ + extern char __start_##name[] ABSL_ATTRIBUTE_WEAK; \ + extern char __stop_##name[] ABSL_ATTRIBUTE_WEAK +#endif +#ifndef ABSL_DEFINE_ATTRIBUTE_SECTION_VARS +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#endif + +// ABSL_ATTRIBUTE_SECTION_START +// +// Returns `void*` pointers to start/end of a section of code with +// functions having ABSL_ATTRIBUTE_SECTION(name). +// Returns 0 if no such functions exist. +// One must ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) for this to compile and +// link. +// +#define ABSL_ATTRIBUTE_SECTION_START(name) \ + (reinterpret_cast(__start_##name)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) \ + (reinterpret_cast(__stop_##name)) + +#else // !ABSL_HAVE_ATTRIBUTE_SECTION + +#define ABSL_HAVE_ATTRIBUTE_SECTION 0 + +// provide dummy definitions +#define ABSL_ATTRIBUTE_SECTION(name) +#define ABSL_ATTRIBUTE_SECTION_VARIABLE(name) +#define ABSL_INIT_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DEFINE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_DECLARE_ATTRIBUTE_SECTION_VARS(name) +#define ABSL_ATTRIBUTE_SECTION_START(name) (reinterpret_cast(0)) +#define ABSL_ATTRIBUTE_SECTION_STOP(name) (reinterpret_cast(0)) + +#endif // ABSL_ATTRIBUTE_SECTION + +// ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +// +// Support for aligning the stack on 32-bit x86. +#if ABSL_HAVE_ATTRIBUTE(force_align_arg_pointer) || \ + (defined(__GNUC__) && !defined(__clang__)) +#if defined(__i386__) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC \ + __attribute__((force_align_arg_pointer)) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#elif defined(__x86_64__) +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (1) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#else // !__i386__ && !__x86_64 +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#endif // __i386__ +#else +#define ABSL_ATTRIBUTE_STACK_ALIGN_FOR_OLD_LIBC +#define ABSL_REQUIRE_STACK_ALIGN_TRAMPOLINE (0) +#endif + +// ABSL_MUST_USE_RESULT +// +// Tells the compiler to warn about unused results. +// +// For code or headers that are assured to only build with C++17 and up, prefer +// just using the standard `[[nodiscard]]` directly over this macro. +// +// When annotating a function, it must appear as the first part of the +// declaration or definition. The compiler will warn if the return value from +// such a function is unused: +// +// ABSL_MUST_USE_RESULT Sprocket* AllocateSprocket(); +// AllocateSprocket(); // Triggers a warning. +// +// When annotating a class, it is equivalent to annotating every function which +// returns an instance. +// +// class ABSL_MUST_USE_RESULT Sprocket {}; +// Sprocket(); // Triggers a warning. +// +// Sprocket MakeSprocket(); +// MakeSprocket(); // Triggers a warning. +// +// Note that references and pointers are not instances: +// +// Sprocket* SprocketPointer(); +// SprocketPointer(); // Does *not* trigger a warning. +// +// ABSL_MUST_USE_RESULT allows using cast-to-void to suppress the unused result +// warning. For that, warn_unused_result is used only for clang but not for gcc. +// https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66425 +// +// Note: past advice was to place the macro after the argument list. +// +// TODO(b/176172494): Use ABSL_HAVE_CPP_ATTRIBUTE(nodiscard) when all code is +// compliant with the stricter [[nodiscard]]. +#if defined(__clang__) && ABSL_HAVE_ATTRIBUTE(warn_unused_result) +#define ABSL_MUST_USE_RESULT __attribute__((warn_unused_result)) +#else +#define ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_HOT, ABSL_ATTRIBUTE_COLD +// +// Tells GCC that a function is hot or cold. GCC can use this information to +// improve static analysis, i.e. a conditional branch to a cold function +// is likely to be not-taken. +// This annotation is used for function declarations. +// +// Example: +// +// int foo() ABSL_ATTRIBUTE_HOT; +#if ABSL_HAVE_ATTRIBUTE(hot) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_HOT __attribute__((hot)) +#else +#define ABSL_ATTRIBUTE_HOT +#endif + +#if ABSL_HAVE_ATTRIBUTE(cold) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_COLD __attribute__((cold)) +#else +#define ABSL_ATTRIBUTE_COLD +#endif + +// ABSL_XRAY_ALWAYS_INSTRUMENT, ABSL_XRAY_NEVER_INSTRUMENT, ABSL_XRAY_LOG_ARGS +// +// We define the ABSL_XRAY_ALWAYS_INSTRUMENT and ABSL_XRAY_NEVER_INSTRUMENT +// macro used as an attribute to mark functions that must always or never be +// instrumented by XRay. Currently, this is only supported in Clang/LLVM. +// +// For reference on the LLVM XRay instrumentation, see +// http://llvm.org/docs/XRay.html. +// +// A function with the XRAY_ALWAYS_INSTRUMENT macro attribute in its declaration +// will always get the XRay instrumentation sleds. These sleds may introduce +// some binary size and runtime overhead and must be used sparingly. +// +// These attributes only take effect when the following conditions are met: +// +// * The file/target is built in at least C++11 mode, with a Clang compiler +// that supports XRay attributes. +// * The file/target is built with the -fxray-instrument flag set for the +// Clang/LLVM compiler. +// * The function is defined in the translation unit (the compiler honors the +// attribute in either the definition or the declaration, and must match). +// +// There are cases when, even when building with XRay instrumentation, users +// might want to control specifically which functions are instrumented for a +// particular build using special-case lists provided to the compiler. These +// special case lists are provided to Clang via the +// -fxray-always-instrument=... and -fxray-never-instrument=... flags. The +// attributes in source take precedence over these special-case lists. +// +// To disable the XRay attributes at build-time, users may define +// ABSL_NO_XRAY_ATTRIBUTES. Do NOT define ABSL_NO_XRAY_ATTRIBUTES on specific +// packages/targets, as this may lead to conflicting definitions of functions at +// link-time. +// +// XRay isn't currently supported on Android: +// https://github.com/android/ndk/issues/368 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_always_instrument) && \ + !defined(ABSL_NO_XRAY_ATTRIBUTES) && !defined(__ANDROID__) +#define ABSL_XRAY_ALWAYS_INSTRUMENT [[clang::xray_always_instrument]] +#define ABSL_XRAY_NEVER_INSTRUMENT [[clang::xray_never_instrument]] +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::xray_log_args) +#define ABSL_XRAY_LOG_ARGS(N) \ + [[clang::xray_always_instrument, clang::xray_log_args(N)]] +#else +#define ABSL_XRAY_LOG_ARGS(N) [[clang::xray_always_instrument]] +#endif +#else +#define ABSL_XRAY_ALWAYS_INSTRUMENT +#define ABSL_XRAY_NEVER_INSTRUMENT +#define ABSL_XRAY_LOG_ARGS(N) +#endif + +// ABSL_ATTRIBUTE_REINITIALIZES +// +// Indicates that a member function reinitializes the entire object to a known +// state, independent of the previous state of the object. +// +// The clang-tidy check bugprone-use-after-move allows member functions marked +// with this attribute to be called on objects that have been moved from; +// without the attribute, this would result in a use-after-move warning. +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::reinitializes) +#define ABSL_ATTRIBUTE_REINITIALIZES [[clang::reinitializes]] +#else +#define ABSL_ATTRIBUTE_REINITIALIZES +#endif + +// ----------------------------------------------------------------------------- +// Variable Attributes +// ----------------------------------------------------------------------------- + +// ABSL_ATTRIBUTE_UNUSED +// +// Prevents the compiler from complaining about variables that appear unused. +// +// For code or headers that are assured to only build with C++17 and up, prefer +// just using the standard '[[maybe_unused]]' directly over this macro. +// +// Due to differences in positioning requirements between the old, compiler +// specific __attribute__ syntax and the now standard [[maybe_unused]], this +// macro does not attempt to take advantage of '[[maybe_unused]]'. +#if ABSL_HAVE_ATTRIBUTE(unused) || (defined(__GNUC__) && !defined(__clang__)) +#undef ABSL_ATTRIBUTE_UNUSED +#define ABSL_ATTRIBUTE_UNUSED __attribute__((__unused__)) +#else +#define ABSL_ATTRIBUTE_UNUSED +#endif + +// ABSL_ATTRIBUTE_INITIAL_EXEC +// +// Tells the compiler to use "initial-exec" mode for a thread-local variable. +// See http://people.redhat.com/drepper/tls.pdf for the gory details. +#if ABSL_HAVE_ATTRIBUTE(tls_model) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_INITIAL_EXEC __attribute__((tls_model("initial-exec"))) +#else +#define ABSL_ATTRIBUTE_INITIAL_EXEC +#endif + +// ABSL_ATTRIBUTE_PACKED +// +// Instructs the compiler not to use natural alignment for a tagged data +// structure, but instead to reduce its alignment to 1. +// +// Therefore, DO NOT APPLY THIS ATTRIBUTE TO STRUCTS CONTAINING ATOMICS. Doing +// so can cause atomic variables to be mis-aligned and silently violate +// atomicity on x86. +// +// This attribute can either be applied to members of a structure or to a +// structure in its entirety. Applying this attribute (judiciously) to a +// structure in its entirety to optimize the memory footprint of very +// commonly-used structs is fine. Do not apply this attribute to a structure in +// its entirety if the purpose is to control the offsets of the members in the +// structure. Instead, apply this attribute only to structure members that need +// it. +// +// When applying ABSL_ATTRIBUTE_PACKED only to specific structure members the +// natural alignment of structure members not annotated is preserved. Aligned +// member accesses are faster than non-aligned member accesses even if the +// targeted microprocessor supports non-aligned accesses. +#if ABSL_HAVE_ATTRIBUTE(packed) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_PACKED __attribute__((__packed__)) +#else +#define ABSL_ATTRIBUTE_PACKED +#endif + +// ABSL_ATTRIBUTE_FUNC_ALIGN +// +// Tells the compiler to align the function start at least to certain +// alignment boundary +#if ABSL_HAVE_ATTRIBUTE(aligned) || (defined(__GNUC__) && !defined(__clang__)) +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) __attribute__((aligned(bytes))) +#else +#define ABSL_ATTRIBUTE_FUNC_ALIGN(bytes) +#endif + +// ABSL_FALLTHROUGH_INTENDED +// +// Annotates implicit fall-through between switch labels, allowing a case to +// indicate intentional fallthrough and turn off warnings about any lack of a +// `break` statement. The ABSL_FALLTHROUGH_INTENDED macro should be followed by +// a semicolon and can be used in most places where `break` can, provided that +// no statements exist between it and the next switch label. +// +// Example: +// +// switch (x) { +// case 40: +// case 41: +// if (truth_is_out_there) { +// ++x; +// ABSL_FALLTHROUGH_INTENDED; // Use instead of/along with annotations +// // in comments +// } else { +// return x; +// } +// case 42: +// ... +// +// Notes: When supported, GCC and Clang can issue a warning on switch labels +// with unannotated fallthrough using the warning `-Wimplicit-fallthrough`. See +// clang documentation on language extensions for details: +// https://clang.llvm.org/docs/AttributeReference.html#fallthrough-clang-fallthrough +// +// When used with unsupported compilers, the ABSL_FALLTHROUGH_INTENDED macro has +// no effect on diagnostics. In any case this macro has no effect on runtime +// behavior and performance of code. + +#ifdef ABSL_FALLTHROUGH_INTENDED +#error "ABSL_FALLTHROUGH_INTENDED should not be defined." +#elif ABSL_HAVE_CPP_ATTRIBUTE(fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[clang::fallthrough]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::fallthrough) +#define ABSL_FALLTHROUGH_INTENDED [[gnu::fallthrough]] +#else +#define ABSL_FALLTHROUGH_INTENDED \ + do { \ + } while (0) +#endif + +// ABSL_DEPRECATED() +// +// Marks a deprecated class, struct, enum, function, method and variable +// declarations. The macro argument is used as a custom diagnostic message (e.g. +// suggestion of a better alternative). +// +// For code or headers that are assured to only build with C++14 and up, prefer +// just using the standard `[[deprecated("message")]]` directly over this macro. +// +// Examples: +// +// class ABSL_DEPRECATED("Use Bar instead") Foo {...}; +// +// ABSL_DEPRECATED("Use Baz() instead") void Bar() {...} +// +// template +// ABSL_DEPRECATED("Use DoThat() instead") +// void DoThis(); +// +// enum FooEnum { +// kBar ABSL_DEPRECATED("Use kBaz instead"), +// }; +// +// Every usage of a deprecated entity will trigger a warning when compiled with +// GCC/Clang's `-Wdeprecated-declarations` option. Google's production toolchain +// turns this warning off by default, instead relying on clang-tidy to report +// new uses of deprecated code. +#if ABSL_HAVE_ATTRIBUTE(deprecated) +#define ABSL_DEPRECATED(message) __attribute__((deprecated(message))) +#else +#define ABSL_DEPRECATED(message) +#endif + +// When deprecating Abseil code, it is sometimes necessary to turn off the +// warning within Abseil, until the deprecated code is actually removed. The +// deprecated code can be surrounded with these directives to achieve that +// result. +// +// class ABSL_DEPRECATED("Use Bar instead") Foo; +// +// ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +// Baz ComputeBazFromFoo(Foo f); +// ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#if defined(__GNUC__) || defined(__clang__) +// Clang also supports these GCC pragmas. +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic push") \ + _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"") +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("GCC diagnostic pop") +#elif defined(_MSC_VER) +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("warning(push)") _Pragma("warning(disable: 4996)") +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING \ + _Pragma("warning(pop)") +#else +#define ABSL_INTERNAL_DISABLE_DEPRECATED_DECLARATION_WARNING +#define ABSL_INTERNAL_RESTORE_DEPRECATED_DECLARATION_WARNING +#endif // defined(__GNUC__) || defined(__clang__) + +// ABSL_CONST_INIT +// +// A variable declaration annotated with the `ABSL_CONST_INIT` attribute will +// not compile (on supported platforms) unless the variable has a constant +// initializer. This is useful for variables with static and thread storage +// duration, because it guarantees that they will not suffer from the so-called +// "static init order fiasco". +// +// This attribute must be placed on the initializing declaration of the +// variable. Some compilers will give a -Wmissing-constinit warning when this +// attribute is placed on some other declaration but missing from the +// initializing declaration. +// +// In some cases (notably with thread_local variables), `ABSL_CONST_INIT` can +// also be used in a non-initializing declaration to tell the compiler that a +// variable is already initialized, reducing overhead that would otherwise be +// incurred by a hidden guard variable. Thus annotating all declarations with +// this attribute is recommended to potentially enhance optimization. +// +// Example: +// +// class MyClass { +// public: +// ABSL_CONST_INIT static MyType my_var; +// }; +// +// ABSL_CONST_INIT MyType MyClass::my_var = MakeMyType(...); +// +// For code or headers that are assured to only build with C++20 and up, prefer +// just using the standard `constinit` keyword directly over this macro. +// +// Note that this attribute is redundant if the variable is declared constexpr. +#if defined(__cpp_constinit) && __cpp_constinit >= 201907L +#define ABSL_CONST_INIT constinit +#elif ABSL_HAVE_CPP_ATTRIBUTE(clang::require_constant_initialization) +#define ABSL_CONST_INIT [[clang::require_constant_initialization]] +#else +#define ABSL_CONST_INIT +#endif + +// ABSL_ATTRIBUTE_PURE_FUNCTION +// +// ABSL_ATTRIBUTE_PURE_FUNCTION is used to annotate declarations of "pure" +// functions. A function is pure if its return value is only a function of its +// arguments. The pure attribute prohibits a function from modifying the state +// of the program that is observable by means other than inspecting the +// function's return value. Declaring such functions with the pure attribute +// allows the compiler to avoid emitting some calls in repeated invocations of +// the function with the same argument values. +// +// Example: +// +// ABSL_ATTRIBUTE_PURE_FUNCTION std::string FormatTime(Time t); +#if ABSL_HAVE_CPP_ATTRIBUTE(gnu::pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION [[gnu::pure]] +#elif ABSL_HAVE_ATTRIBUTE(pure) +#define ABSL_ATTRIBUTE_PURE_FUNCTION __attribute__((pure)) +#else +// If the attribute isn't defined, we'll fallback to ABSL_MUST_USE_RESULT since +// pure functions are useless if its return is ignored. +#define ABSL_ATTRIBUTE_PURE_FUNCTION ABSL_MUST_USE_RESULT +#endif + +// ABSL_ATTRIBUTE_CONST_FUNCTION +// +// ABSL_ATTRIBUTE_CONST_FUNCTION is used to annotate declarations of "const" +// functions. A const function is similar to a pure function, with one +// exception: Pure functions may return value that depend on a non-volatile +// object that isn't provided as a function argument, while the const function +// is guaranteed to return the same result given the same arguments. +// +// Example: +// +// ABSL_ATTRIBUTE_CONST_FUNCTION int64_t ToInt64Milliseconds(Duration d); +#if defined(_MSC_VER) && !defined(__clang__) +// Put the MSVC case first since MSVC seems to parse const as a C++ keyword. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#elif ABSL_HAVE_CPP_ATTRIBUTE(gnu::const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION [[gnu::const]] +#elif ABSL_HAVE_ATTRIBUTE(const) +#define ABSL_ATTRIBUTE_CONST_FUNCTION __attribute__((const)) +#else +// Since const functions are more restrictive pure function, we'll fallback to a +// pure function if the const attribute is not handled. +#define ABSL_ATTRIBUTE_CONST_FUNCTION ABSL_ATTRIBUTE_PURE_FUNCTION +#endif + +// ABSL_ATTRIBUTE_LIFETIME_BOUND indicates that a resource owned by a function +// parameter or implicit object parameter is retained by the return value of the +// annotated function (or, for a parameter of a constructor, in the value of the +// constructed object). This attribute causes warnings to be produced if a +// temporary object does not live long enough. +// +// When applied to a reference parameter, the referenced object is assumed to be +// retained by the return value of the function. When applied to a non-reference +// parameter (for example, a pointer or a class type), all temporaries +// referenced by the parameter are assumed to be retained by the return value of +// the function. +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#lifetimebound +// https://learn.microsoft.com/en-us/cpp/code-quality/c26816?view=msvc-170 +#if ABSL_HAVE_CPP_ATTRIBUTE(clang::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[clang::lifetimebound]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(msvc::lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND [[msvc::lifetimebound]] +#elif ABSL_HAVE_ATTRIBUTE(lifetimebound) +#define ABSL_ATTRIBUTE_LIFETIME_BOUND __attribute__((lifetimebound)) +#else +#define ABSL_ATTRIBUTE_LIFETIME_BOUND +#endif + +// ABSL_ATTRIBUTE_VIEW indicates that a type is solely a "view" of data that it +// points to, similarly to a span, string_view, or other non-owning reference +// type. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template +// StringView(const R&); +// }; +// +// StringView f(std::string s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional sv) { return *sv; } +// +// See the following links for details: +// https://reviews.llvm.org/D64448 +// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Pointer) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_VIEW [[gsl::Pointer]] +#else +#define ABSL_ATTRIBUTE_VIEW +#endif + +// ABSL_ATTRIBUTE_OWNER indicates that a type is a container, smart pointer, or +// similar class that owns all the data that it points to. +// This enables diagnosing certain lifetime issues similar to those enabled by +// ABSL_ATTRIBUTE_LIFETIME_BOUND, such as: +// +// struct ABSL_ATTRIBUTE_VIEW StringView { +// template +// StringView(const R&); +// }; +// +// struct ABSL_ATTRIBUTE_OWNER String {}; +// +// StringView f(String s) { +// return s; // warning: address of stack memory returned +// } +// +// We disable this on Clang versions < 13 because of the following +// false-positive: +// +// absl::string_view f(absl::optional sv) { return *sv; } +// +// See the following links for details: +// https://reviews.llvm.org/D64448 +// https://lists.llvm.org/pipermail/cfe-dev/2018-November/060355.html +#if ABSL_HAVE_CPP_ATTRIBUTE(gsl::Owner) && \ + (!defined(__clang_major__) || __clang_major__ >= 13) +#define ABSL_ATTRIBUTE_OWNER [[gsl::Owner]] +#else +#define ABSL_ATTRIBUTE_OWNER +#endif + +// ABSL_ATTRIBUTE_TRIVIAL_ABI +// Indicates that a type is "trivially relocatable" -- meaning it can be +// relocated without invoking the constructor/destructor, using a form of move +// elision. +// +// From a memory safety point of view, putting aside destructor ordering, it's +// safe to apply ABSL_ATTRIBUTE_TRIVIAL_ABI if an object's location +// can change over the course of its lifetime: if a constructor can be run one +// place, and then the object magically teleports to another place where some +// methods are run, and then the object teleports to yet another place where it +// is destroyed. This is notably not true for self-referential types, where the +// move-constructor must keep the self-reference up to date. If the type changed +// location without invoking the move constructor, it would have a dangling +// self-reference. +// +// The use of this teleporting machinery means that the number of paired +// move/destroy operations can change, and so it is a bad idea to apply this to +// a type meant to count the number of moves. +// +// Warning: applying this can, rarely, break callers. Objects passed by value +// will be destroyed at the end of the call, instead of the end of the +// full-expression containing the call. In addition, it changes the ABI +// of functions accepting this type by value (e.g. to pass in registers). +// +// See also the upstream documentation: +// https://clang.llvm.org/docs/AttributeReference.html#trivial-abi +// +// b/321691395 - This is currently disabled in open-source builds since +// compiler support differs. If system libraries compiled with GCC are mixed +// with libraries compiled with Clang, types will have different ideas about +// their ABI, leading to hard to debug crashes. +#define ABSL_ATTRIBUTE_TRIVIAL_ABI + +// ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS +// +// Indicates a data member can be optimized to occupy no space (if it is empty) +// and/or its tail padding can be used for other members. +// +// For code that is assured to only build with C++20 or later, prefer using +// the standard attribute `[[no_unique_address]]` directly instead of this +// macro. +// +// https://devblogs.microsoft.com/cppblog/msvc-cpp20-and-the-std-cpp20-switch/#c20-no_unique_address +// Current versions of MSVC have disabled `[[no_unique_address]]` since it +// breaks ABI compatibility, but offers `[[msvc::no_unique_address]]` for +// situations when it can be assured that it is desired. Since Abseil does not +// claim ABI compatibility in mixed builds, we can offer it unconditionally. +#if defined(_MSC_VER) && _MSC_VER >= 1929 +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[msvc::no_unique_address]] +#elif ABSL_HAVE_CPP_ATTRIBUTE(no_unique_address) +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS [[no_unique_address]] +#else +#define ABSL_ATTRIBUTE_NO_UNIQUE_ADDRESS +#endif + +// ABSL_ATTRIBUTE_UNINITIALIZED +// +// GCC and Clang support a flag `-ftrivial-auto-var-init=