Merge branch 'rc/1.56.8' into release
This commit is contained in:
@@ -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
|
||||
|
||||
+11
-2
@@ -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 "<CMAKE_AR> qc -S <TARGET> <LINK_FLAGS> <OBJECTS>")
|
||||
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)
|
||||
|
||||
+14
-2
@@ -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.*
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -1271,7 +1271,28 @@ public class Engine {
|
||||
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.</p>
|
||||
*/
|
||||
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.
|
||||
*
|
||||
* <p>This is typically used right after destroying the <code>SwapChain</code>,
|
||||
* in cases where a guarantee about the <code>SwapChain</code> destruction is needed in a
|
||||
* timely fashion, such as when responding to Android's
|
||||
* <code>android.view.SurfaceHolder.Callback.surfaceDestroyed</code></p>
|
||||
*
|
||||
* @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);
|
||||
|
||||
+8
@@ -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);
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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.
|
||||
|
||||
|
||||
@@ -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 ..
|
||||
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -33,9 +33,9 @@
|
||||
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <array> // FIXME: STL headers are not allowed in public headers
|
||||
#include <type_traits> // FIXME: STL headers are not allowed in public headers
|
||||
#include <variant> // FIXME: STL headers are not allowed in public headers
|
||||
#include <array>
|
||||
#include <type_traits>
|
||||
#include <variant>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.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<typename B, typename = std::enable_if_t<std::is_base_of<T, B>::value> >
|
||||
template<typename B, typename = std::enable_if_t<std::is_base_of_v<T, B>> >
|
||||
Handle(Handle<B> const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions,google-explicit-constructor)
|
||||
|
||||
private:
|
||||
|
||||
+29
-7
@@ -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 <backend/DriverEnums.h>
|
||||
#include <backend/Platform.h>
|
||||
@@ -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<MTLCommandBuffer> createAndEnqueueCommandBuffer() noexcept;
|
||||
|
||||
private:
|
||||
id<MTLCommandQueue> 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
|
||||
@@ -31,6 +31,7 @@
|
||||
|
||||
#include <cstddef>
|
||||
#include <exception>
|
||||
#include <mutex>
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
@@ -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<HandleBase::HandleId, utils::CString> mDebugTags;
|
||||
};
|
||||
|
||||
/*
|
||||
* A utility class to efficiently allocate and manage Handle<>
|
||||
*/
|
||||
template<size_t P0, size_t P1, size_t P2>
|
||||
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 D, typename B, typename ... ARGS>
|
||||
typename std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
destroyAndConstruct(Handle<B> const& handle, ARGS&& ... args) {
|
||||
assert_invariant(handle);
|
||||
D* addr = handle_cast<D*>(const_cast<Handle<B>&>(handle));
|
||||
@@ -116,7 +132,7 @@ public:
|
||||
* ConcreteTexture* p = construct(h, w, h);
|
||||
*/
|
||||
template<typename D, typename B, typename ... ARGS>
|
||||
typename std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
std::enable_if_t<std::is_base_of_v<B, D>, D>*
|
||||
construct(Handle<B> const& handle, ARGS&& ... args) noexcept {
|
||||
assert_invariant(handle);
|
||||
D* addr = handle_cast<D*>(const_cast<Handle<B>&>(handle));
|
||||
@@ -133,7 +149,7 @@ public:
|
||||
* deallocate(h, p);
|
||||
*/
|
||||
template <typename B, typename D,
|
||||
typename = typename std::enable_if_t<std::is_base_of_v<B, D>, D>>
|
||||
typename = std::enable_if_t<std::is_base_of_v<B, D>, D>>
|
||||
void deallocate(Handle<B>& 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<ConcreteTexture*>(h);
|
||||
*/
|
||||
template<typename Dp, typename B>
|
||||
inline typename std::enable_if_t<
|
||||
inline std::enable_if_t<
|
||||
std::is_pointer_v<Dp> &&
|
||||
std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
|
||||
std::is_base_of_v<B, std::remove_pointer_t<Dp>>, Dp>
|
||||
handle_cast(Handle<B>& handle) {
|
||||
assert_invariant(handle);
|
||||
auto [p, tag] = handleToPointer(handle.getId());
|
||||
@@ -200,6 +216,8 @@ public:
|
||||
return static_cast<Dp>(p);
|
||||
}
|
||||
|
||||
utils::CString getHandleTag(HandleBase::HandleId key) const noexcept;
|
||||
|
||||
template<typename B>
|
||||
bool is_valid(Handle<B>& handle) {
|
||||
if (!handle) {
|
||||
@@ -217,9 +235,9 @@ public:
|
||||
}
|
||||
|
||||
template<typename Dp, typename B>
|
||||
inline typename std::enable_if_t<
|
||||
inline std::enable_if_t<
|
||||
std::is_pointer_v<Dp> &&
|
||||
std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
|
||||
std::is_base_of_v<B, std::remove_pointer_t<Dp>>, Dp>
|
||||
handle_cast(Handle<B> const& handle) {
|
||||
return handle_cast<Dp>(const_cast<Handle<B>&>(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<size_t SIZE>
|
||||
@@ -421,7 +426,6 @@ private:
|
||||
// Below is only used when running out of space in the HandleArena
|
||||
mutable utils::Mutex mLock;
|
||||
tsl::robin_map<HandleBase::HandleId, void*> mOverflowMap;
|
||||
tsl::robin_map<HandleBase::HandleId, utils::CString> mDebugTags;
|
||||
HandleBase::HandleId mId = 0;
|
||||
bool mUseAfterFreeCheckDisabled = false;
|
||||
};
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <backend/Handle.h>
|
||||
|
||||
#include <utils/Allocator.h>
|
||||
#include <utils/CString.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/compiler.h>
|
||||
@@ -29,7 +30,9 @@
|
||||
#include <exception>
|
||||
#include <limits>
|
||||
#include <mutex>
|
||||
#include <utility>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
@@ -80,9 +83,6 @@ HandleAllocator<P0, P1, P2>::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 <size_t P0, size_t P1, size_t P2>
|
||||
@@ -147,6 +147,42 @@ void HandleAllocator<P0, P1, P2>::deallocateHandleSlow(HandleBase::HandleId id,
|
||||
::free(p);
|
||||
}
|
||||
|
||||
template<size_t P0, size_t P1, size_t P2>
|
||||
UTILS_NOINLINE
|
||||
CString HandleAllocator<P0, P1, P2>::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;
|
||||
|
||||
@@ -18,9 +18,9 @@
|
||||
#define TNT_FILAMENT_DRIVER_METALBUFFER_H
|
||||
|
||||
#include "MetalContext.h"
|
||||
#include "MetalPlatform.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/PlatformMetal.h>
|
||||
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
@@ -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<clock_t> 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<MTLBuffer> mBuffer;
|
||||
Type mType = Type::NONE;
|
||||
|
||||
static MetalPlatform* platform;
|
||||
static PlatformMetal* platform;
|
||||
static std::array<uint64_t, TypeCount> aliveBuffers;
|
||||
};
|
||||
|
||||
|
||||
@@ -23,8 +23,8 @@ namespace filament {
|
||||
namespace backend {
|
||||
|
||||
std::array<uint64_t, TrackedMetalBuffer::TypeCount> 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)
|
||||
|
||||
@@ -128,6 +128,7 @@ struct MetalContext {
|
||||
std::atomic<uint64_t> latestCompletedCommandBufferId = 0;
|
||||
id<MTLCommandBuffer> pendingCommandBuffer = nil;
|
||||
id<MTLRenderCommandEncoder> currentRenderPassEncoder = nil;
|
||||
uint32_t currentFrame = 0;
|
||||
|
||||
std::atomic<bool> memorylessLimitsReached = false;
|
||||
|
||||
@@ -156,6 +157,7 @@ struct MetalContext {
|
||||
RenderPassFlags currentRenderPassFlags;
|
||||
MetalRenderTarget* currentRenderTarget = nullptr;
|
||||
bool validPipelineBound = false;
|
||||
bool currentRenderPassAbandoned = false;
|
||||
|
||||
// State trackers.
|
||||
PipelineStateTracker pipelineState;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
#include "MetalState.h"
|
||||
#include "MetalTimerQuery.h"
|
||||
|
||||
#include "MetalPlatform.h"
|
||||
#include <backend/platforms/PlatformMetal.h>
|
||||
|
||||
#include <CoreVideo/CVMetalTexture.h>
|
||||
#include <CoreVideo/CVPixelBuffer.h>
|
||||
@@ -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<HwFence> fh, int dummy) {
|
||||
void MetalDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow, uint64_t flags) {
|
||||
if (UTILS_UNLIKELY(flags & SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER)) {
|
||||
CVPixelBufferRef pixelBuffer = (CVPixelBufferRef) nativeWindow;
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, pixelBuffer, flags);
|
||||
construct_handle<MetalSwapChain>(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<MetalSwapChain>(sch, *mContext, metalLayer, flags);
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, metalLayer, flags);
|
||||
}
|
||||
}
|
||||
|
||||
void MetalDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch,
|
||||
uint32_t width, uint32_t height, uint64_t flags) {
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, width, height, flags);
|
||||
construct_handle<MetalSwapChain>(sch, *mContext, mPlatform, width, height, flags);
|
||||
}
|
||||
|
||||
void MetalDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {
|
||||
@@ -1268,6 +1269,13 @@ void MetalDriver::beginRenderPass(Handle<HwRenderTarget> 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<MetalRenderTarget>(src);
|
||||
auto dstTarget = handle_cast<MetalRenderTarget>(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<HwRenderPrimitive> 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<MetalRenderPrimitive>(rph);
|
||||
ps.primitiveType = rp->type;
|
||||
ps.vertexBufferInfo = rp->vertexBuffer->vbih;
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -30,6 +30,7 @@
|
||||
#include "MetalState.h" // for MetalState::VertexDescription
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/platforms/PlatformMetal.h>
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/CString.h>
|
||||
@@ -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<CAMetalDrawable> drawable = nil;
|
||||
id<MTLTexture> depthStencilTexture = nil;
|
||||
id<MTLTexture> 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);
|
||||
|
||||
@@ -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<std::mutex>()),
|
||||
@@ -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<MTLTexture> MetalSwapChain::acquireDrawable() {
|
||||
if (drawable) {
|
||||
return drawable.texture;
|
||||
@@ -180,7 +190,18 @@ id<MTLTexture> 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;
|
||||
}
|
||||
|
||||
+32
-11
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "MetalPlatform.h"
|
||||
#include <backend/platforms/PlatformMetal.h>
|
||||
|
||||
#include "MetalDriverFactory.h"
|
||||
|
||||
@@ -22,19 +22,32 @@
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#include <atomic>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
struct PlatformMetalImpl {
|
||||
id<MTLCommandQueue> mCommandQueue = nil;
|
||||
// read form driver thread, read/written to from client thread
|
||||
std::atomic<PlatformMetal::DrawableFailureBehavior> 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<MTLDevice> MetalPlatform::createDevice() noexcept {
|
||||
id<MTLDevice> PlatformMetal::createDevice() noexcept {
|
||||
id<MTLDevice> result;
|
||||
|
||||
#if !defined(FILAMENT_IOS)
|
||||
@@ -62,16 +75,24 @@ id<MTLDevice> MetalPlatform::createDevice() noexcept {
|
||||
return result;
|
||||
}
|
||||
|
||||
id<MTLCommandQueue> MetalPlatform::createCommandQueue(id<MTLDevice> device) noexcept {
|
||||
mCommandQueue = [device newCommandQueue];
|
||||
mCommandQueue.label = @"Filament";
|
||||
return mCommandQueue;
|
||||
id<MTLCommandQueue> PlatformMetal::createCommandQueue(id<MTLDevice> device) noexcept {
|
||||
pImpl->mCommandQueue = [device newCommandQueue];
|
||||
pImpl->mCommandQueue.label = @"Filament";
|
||||
return pImpl->mCommandQueue;
|
||||
}
|
||||
|
||||
id<MTLCommandBuffer> MetalPlatform::createAndEnqueueCommandBuffer() noexcept {
|
||||
id<MTLCommandBuffer> commandBuffer = [mCommandQueue commandBuffer];
|
||||
id<MTLCommandBuffer> PlatformMetal::createAndEnqueueCommandBuffer() noexcept {
|
||||
id<MTLCommandBuffer> 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
|
||||
@@ -700,6 +700,11 @@ void VulkanDriver::createFenceR(Handle<HwFence> fh, int) {
|
||||
}
|
||||
|
||||
void VulkanDriver::createSwapChainR(Handle<HwSwapChain> 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;
|
||||
|
||||
@@ -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 << ", "
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
inline resource_ptr() = default;
|
||||
|
||||
// move constructor operator
|
||||
inline resource_ptr(resource_ptr<D>&& rhs) {
|
||||
inline resource_ptr(resource_ptr<D>&& rhs) noexcept {
|
||||
(*this) = std::move(rhs);
|
||||
}
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
}
|
||||
|
||||
// move operator
|
||||
inline resource_ptr<D>& operator=(resource_ptr<D> && rhs) {
|
||||
inline resource_ptr<D>& operator=(resource_ptr<D> && rhs) noexcept {
|
||||
std::swap(mRef, rhs.mRef);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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 },
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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).
|
||||
*
|
||||
|
||||
@@ -194,7 +194,7 @@ inline sRGBColorA Color::toSRGB<ACCURATE>(LinearColorA const& color) {
|
||||
}
|
||||
|
||||
inline LinearColor Color::toLinear(RgbType type, math::float3 color) {
|
||||
return (type == RgbType::LINEAR) ? color : Color::toLinear<ACCURATE>(color);
|
||||
return (type == RgbType::LINEAR) ? color : toLinear<ACCURATE>(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<ACCURATE>(color) * math::float4{color.a, color.a, color.a, 1.0f};
|
||||
return toLinear<ACCURATE>(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<ACCURATE>(color);
|
||||
return toLinear<ACCURATE>(color);
|
||||
case RgbaType::PREMULTIPLIED_LINEAR:
|
||||
return color;
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
*
|
||||
* <p>This is typically used right after destroying the <code>SwapChain</code>,
|
||||
* in cases where a guarantee about the <code>SwapChain</code> destruction is needed in a
|
||||
* timely fashion, such as when responding to Android's
|
||||
* <code>android.view.SurfaceHolder.Callback.surfaceDestroyed</code></p>
|
||||
*
|
||||
* @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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -118,10 +118,10 @@ public:
|
||||
Builder& package(const void* UTILS_NONNULL payload, size_t size);
|
||||
|
||||
template<typename T>
|
||||
using is_supported_constant_parameter_t = typename std::enable_if<
|
||||
std::is_same<int32_t, T>::value ||
|
||||
std::is_same<float, T>::value ||
|
||||
std::is_same<bool, T>::value>::type;
|
||||
using is_supported_constant_parameter_t = std::enable_if_t<
|
||||
std::is_same_v<int32_t, T> ||
|
||||
std::is_same_v<float, T> ||
|
||||
std::is_same_v<bool, T>>;
|
||||
|
||||
/**
|
||||
* 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;
|
||||
};
|
||||
|
||||
@@ -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<typename T>
|
||||
using is_supported_parameter_t = typename std::enable_if<
|
||||
std::is_same<float, T>::value ||
|
||||
std::is_same<int32_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value ||
|
||||
std::is_same<math::int2, T>::value ||
|
||||
std::is_same<math::int3, T>::value ||
|
||||
std::is_same<math::int4, T>::value ||
|
||||
std::is_same<math::uint2, T>::value ||
|
||||
std::is_same<math::uint3, T>::value ||
|
||||
std::is_same<math::uint4, T>::value ||
|
||||
std::is_same<math::float2, T>::value ||
|
||||
std::is_same<math::float3, T>::value ||
|
||||
std::is_same<math::float4, T>::value ||
|
||||
std::is_same<math::mat4f, T>::value ||
|
||||
using is_supported_parameter_t = std::enable_if_t<
|
||||
std::is_same_v<float, T> ||
|
||||
std::is_same_v<int32_t, T> ||
|
||||
std::is_same_v<uint32_t, T> ||
|
||||
std::is_same_v<math::int2, T> ||
|
||||
std::is_same_v<math::int3, T> ||
|
||||
std::is_same_v<math::int4, T> ||
|
||||
std::is_same_v<math::uint2, T> ||
|
||||
std::is_same_v<math::uint3, T> ||
|
||||
std::is_same_v<math::uint4, T> ||
|
||||
std::is_same_v<math::float2, T> ||
|
||||
std::is_same_v<math::float3, T> ||
|
||||
std::is_same_v<math::float4, T> ||
|
||||
std::is_same_v<math::mat4f, T> ||
|
||||
// these types are slower as they need a layout conversion
|
||||
std::is_same<bool, T>::value ||
|
||||
std::is_same<math::bool2, T>::value ||
|
||||
std::is_same<math::bool3, T>::value ||
|
||||
std::is_same<math::bool4, T>::value ||
|
||||
std::is_same<math::mat3f, T>::value
|
||||
>::type;
|
||||
std::is_same_v<bool, T> ||
|
||||
std::is_same_v<math::bool2, T> ||
|
||||
std::is_same_v<math::bool3, T> ||
|
||||
std::is_same_v<math::bool4, T> ||
|
||||
std::is_same_v<math::mat3f, T>
|
||||
>;
|
||||
|
||||
/**
|
||||
* 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<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline void setParameter(StringLiteral name, T const& value) {
|
||||
void setParameter(StringLiteral name, T const& value) {
|
||||
setParameter<T>(name.data, name.size, value);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline void setParameter(const char* UTILS_NONNULL name, T const& value) {
|
||||
void setParameter(const char* UTILS_NONNULL name, T const& value) {
|
||||
setParameter<T>(name, strlen(name), value);
|
||||
}
|
||||
|
||||
@@ -148,14 +148,14 @@ public:
|
||||
|
||||
/** inline helper to provide the name as a null-terminated string literal */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
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<T>(name.data, name.size, values, count);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
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<T>(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<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline T getParameter(StringLiteral name) const {
|
||||
T getParameter(StringLiteral name) const {
|
||||
return getParameter<T>(name.data, name.size);
|
||||
}
|
||||
|
||||
/** inline helper to provide the name as a null-terminated C string */
|
||||
template<typename T, typename = is_supported_parameter_t<T>>
|
||||
inline T getParameter(const char* UTILS_NONNULL name) const {
|
||||
T getParameter(const char* UTILS_NONNULL name) const {
|
||||
return getParameter<T>(name, strlen(name));
|
||||
}
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
|
||||
@@ -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<typename T>
|
||||
struct is_supported_vector_type {
|
||||
using type = typename std::enable_if<
|
||||
std::is_same<math::float4, T>::value ||
|
||||
std::is_same<math::half4, T>::value ||
|
||||
std::is_same<math::float3, T>::value ||
|
||||
std::is_same<math::half3, T>::value
|
||||
>::type;
|
||||
using type = std::enable_if_t<
|
||||
std::is_same_v<math::float4, T> ||
|
||||
std::is_same_v<math::half4, T> ||
|
||||
std::is_same_v<math::float3, T> ||
|
||||
std::is_same_v<math::half3, T>
|
||||
>;
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct is_supported_index_type {
|
||||
using type = typename std::enable_if<
|
||||
std::is_same<uint16_t, T>::value ||
|
||||
std::is_same<uint32_t, T>::value
|
||||
>::type;
|
||||
using type = std::enable_if_t<
|
||||
std::is_same_v<uint16_t, T> ||
|
||||
std::is_same_v<uint32_t, T>
|
||||
>;
|
||||
};
|
||||
/*! \endcond */
|
||||
|
||||
|
||||
@@ -105,7 +105,7 @@ public:
|
||||
* @param historySize requested history size. The returned vector could be smaller.
|
||||
* @return A vector of FrameInfo.
|
||||
*/
|
||||
utils::FixedCapacityVector<Renderer::FrameInfo> getFrameInfoHistory(
|
||||
utils::FixedCapacityVector<FrameInfo> getFrameInfoHistory(
|
||||
size_t historySize = 1) const noexcept;
|
||||
|
||||
/**
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace filament {
|
||||
|
||||
using namespace utils;
|
||||
|
||||
static inline constexpr std::pair<uint8_t, uint8_t> unmorton(uint16_t m) noexcept {
|
||||
static inline constexpr std::pair<uint8_t, uint8_t> 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<uint8_t, uint8_t> 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());
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -103,7 +103,7 @@ void BufferPoolAllocator<POOL_SIZE, ALIGNMENT, AllocatorPolicy, LockingPolicy>::
|
||||
}
|
||||
|
||||
template<size_t POOL_SIZE, size_t ALIGNMENT, typename AllocatorPolicy, typename LockingPolicy>
|
||||
void* BufferPoolAllocator<POOL_SIZE, ALIGNMENT, AllocatorPolicy, LockingPolicy>::get(size_type size) noexcept {
|
||||
void* BufferPoolAllocator<POOL_SIZE, ALIGNMENT, AllocatorPolicy, LockingPolicy>::get(size_type const size) noexcept {
|
||||
std::lock_guard<LockingPolicy> guard(mLock);
|
||||
|
||||
// if the requested size is larger that our buffers in the pool, we just empty the pool
|
||||
|
||||
+23
-23
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
+18
-14
@@ -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<const Engine::FeatureFlag> Engine::getFeatureFlags() const noexcept {
|
||||
Slice<const Engine::FeatureFlag> 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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:
|
||||
//
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -172,9 +172,9 @@ void FrameInfoManager::denoiseFrameTime(FrameHistoryQueue& history, Config const
|
||||
}
|
||||
}
|
||||
|
||||
utils::FixedCapacityVector<Renderer::FrameInfo> FrameInfoManager::getFrameInfoHistory(
|
||||
FixedCapacityVector<Renderer::FrameInfo> FrameInfoManager::getFrameInfoHistory(
|
||||
size_t historySize) const noexcept {
|
||||
auto result = utils::FixedCapacityVector<Renderer::FrameInfo>::with_capacity(MAX_FRAMETIME_HISTORY);
|
||||
auto result = FixedCapacityVector<Renderer::FrameInfo>::with_capacity(MAX_FRAMETIME_HISTORY);
|
||||
auto const& history = mFrameTimeHistory;
|
||||
size_t i = 0;
|
||||
size_t const c = history.size();
|
||||
|
||||
@@ -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<T*>(&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;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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) {
|
||||
}
|
||||
|
||||
|
||||
+42
-22
@@ -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 <private/filament/EngineEnums.h>
|
||||
#include <private/backend/DriverApi.h>
|
||||
|
||||
#include <filament/Box.h>
|
||||
#include <filament/Viewport.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/BinaryTreeArray.h>
|
||||
#include <utils/JobSystem.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/Slice.h>
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <math/mat4.h>
|
||||
#include <math/fast.h>
|
||||
#include <math/mat3.h>
|
||||
#include <math/mat4.h>
|
||||
#include <math/scalar.h>
|
||||
#include <math/vec2.h>
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
|
||||
#include <algorithm>
|
||||
#include <utils/architecture.h>
|
||||
#include <array>
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
#include <type_traits>
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
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<size_t, size_t> 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<LightRecord> records(mLightRecords);
|
||||
Slice<LightRecord> 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<RecordBufferType> const& lightList,
|
||||
Slice<RecordBufferType> 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<FScene::SCREEN_SPACE_Z_RANGE>() + 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),
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,14 +19,20 @@
|
||||
#include "Culler.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#include <math/vec3.h>
|
||||
#include <math/vec4.h>
|
||||
#include <math/mat4.h>
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
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;
|
||||
|
||||
@@ -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<uint8_t const *>(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) {
|
||||
|
||||
@@ -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 });
|
||||
|
||||
@@ -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<uint32_t const*>(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);
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,8 +16,22 @@
|
||||
|
||||
#include "details/Material.h"
|
||||
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialEnums.h>
|
||||
|
||||
#include <backend/CallbackHandler.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/Invocable.h>
|
||||
|
||||
#include <utility>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
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<void(Material*)>&& callback) noexcept {
|
||||
downcast(this)->compile(priority, variantFilter, handler, std::move(callback));
|
||||
void Material::compile(CompilerPriorityQueue const priority, UserVariantFilterMask const variants,
|
||||
CallbackHandler* handler, utils::Invocable<void(Material*)>&& callback) noexcept {
|
||||
downcast(this)->compile(priority, variants, handler, std::move(callback));
|
||||
}
|
||||
|
||||
UserVariantFilterMask Material::getSupportedVariants() const noexcept {
|
||||
|
||||
@@ -29,7 +29,7 @@ using namespace backend;
|
||||
// vec4<float>. This must not be inlined (this is the whole point).
|
||||
template<size_t Size>
|
||||
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>(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<typename T>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline void FMaterialInstance::setParameterImpl(std::string_view name, T const& value) {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
inline void FMaterialInstance::setParameterImpl(std::string_view const name, T const& value) {
|
||||
static_assert(!std::is_same_v<T, mat3f>);
|
||||
setParameterUntypedImpl<sizeof(T)>(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<size_t Size>
|
||||
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>(size_t(offset), value, count);
|
||||
@@ -69,9 +69,9 @@ void FMaterialInstance::setParameterUntypedImpl(std::string_view name,
|
||||
|
||||
template<typename T>
|
||||
UTILS_ALWAYS_INLINE
|
||||
inline void FMaterialInstance::setParameterImpl(std::string_view name,
|
||||
const T* value, size_t count) {
|
||||
static_assert(!std::is_same_v<T, math::mat3f>);
|
||||
inline void FMaterialInstance::setParameterImpl(std::string_view const name,
|
||||
const T* value, size_t const count) {
|
||||
static_assert(!std::is_same_v<T, mat3f>);
|
||||
setParameterUntypedImpl<sizeof(T)>(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<mat3f>(const char* name, size_t nameLength, const mat3f* v, size_t c) {
|
||||
UTILS_PUBLIC void MaterialInstance::setParameter<mat3f>(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<math::float3 const*>(v), c * 3);
|
||||
setParameter(name, nameLength, reinterpret_cast<float3 const*>(v), c * 3);
|
||||
}
|
||||
|
||||
template UTILS_PUBLIC void MaterialInstance::setParameter<float> (const char* name, size_t nameLength, const float *v, size_t c);
|
||||
@@ -184,7 +184,7 @@ template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char*
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
template<typename T>
|
||||
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<T>(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<float3>({ 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<float4>({ 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);
|
||||
}
|
||||
|
||||
|
||||
@@ -54,26 +54,26 @@ using namespace filamat;
|
||||
|
||||
namespace filament {
|
||||
|
||||
constexpr std::pair<ChunkType, ChunkType> shaderLanguageToTags(ShaderLanguage language) {
|
||||
constexpr std::pair<ChunkType, ChunkType> 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<ShaderLanguage> preferredLanguages, const void* data,
|
||||
size_t size)
|
||||
FixedCapacityVector<ShaderLanguage> 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<typename T>
|
||||
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<typename T>
|
||||
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<ShaderLanguage> preferredLanguages,
|
||||
const void* data, size_t size)
|
||||
MaterialParser::MaterialParser(FixedCapacityVector<ShaderLanguage> 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<ChunkDescriptorSetLayoutInfo>(container);
|
||||
}
|
||||
|
||||
bool MaterialParser::getConstants(utils::FixedCapacityVector<MaterialConstant>* container) const noexcept {
|
||||
bool MaterialParser::getConstants(FixedCapacityVector<MaterialConstant>* container) const noexcept {
|
||||
return get<ChunkMaterialConstants>(container);
|
||||
}
|
||||
|
||||
bool MaterialParser::getPushConstants(utils::CString* structVarName,
|
||||
utils::FixedCapacityVector<MaterialPushConstant>* value) const noexcept {
|
||||
auto [start, end] = mImpl.mChunkContainer.getChunkRange(filamat::MaterialPushConstants);
|
||||
bool MaterialParser::getPushConstants(CString* structVarName,
|
||||
FixedCapacityVector<MaterialPushConstant>* 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<uint8_t*>(value));
|
||||
return mImpl.getFromSimpleChunk(MaterialCullingMode, reinterpret_cast<uint8_t*>(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<uint8_t*>(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<uint8_t*>(value));
|
||||
return mImpl.getFromSimpleChunk(MaterialInterpolation, reinterpret_cast<uint8_t*>(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<uint8_t*>(value));
|
||||
return mImpl.getFromSimpleChunk(MaterialVertexDomain, reinterpret_cast<uint8_t*>(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<UserVariantFilterMask*>(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<uint8_t*>(value));
|
||||
return mImpl.getFromSimpleChunk(MaterialBlendingMode, reinterpret_cast<uint8_t*>(value));
|
||||
}
|
||||
|
||||
bool MaterialParser::getCustomBlendFunction(std::array<BlendFunction, 4>* 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<BlendFunction, 4>* 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<uint8_t*>(value));
|
||||
return mImpl.getFromSimpleChunk(MaterialShading, reinterpret_cast<uint8_t*>(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<uint8_t*>(value));
|
||||
return mImpl.getFromSimpleChunk(MaterialStereoscopicType, reinterpret_cast<uint8_t*>(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<MaterialConstant>* materialConstants) {
|
||||
bool ChunkMaterialConstants::unflatten(Unflattener& unflattener,
|
||||
FixedCapacityVector<MaterialConstant>* 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<backend::ConstantType>(constantType);
|
||||
(*materialConstants)[i].type = static_cast<ConstantType>(constantType);
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ChunkMaterialPushConstants::unflatten(filaflat::Unflattener& unflattener,
|
||||
utils::CString* structVarName,
|
||||
utils::FixedCapacityVector<MaterialPushConstant>* materialPushConstants) {
|
||||
bool ChunkMaterialPushConstants::unflatten(Unflattener& unflattener,
|
||||
CString* structVarName,
|
||||
FixedCapacityVector<MaterialPushConstant>* 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<backend::ConstantType>(constantType);
|
||||
(*materialPushConstants)[i].stage = static_cast<backend::ShaderStage>(shaderStage);
|
||||
(*materialPushConstants)[i].type = static_cast<ConstantType>(constantType);
|
||||
(*materialPushConstants)[i].stage = static_cast<ShaderStage>(shaderStage);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
+331
-203
File diff suppressed because it is too large
Load Diff
@@ -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<FrameGraphTexture> screenSpaceAmbientOcclusion(FrameGraph& fg,
|
||||
filament::Viewport const& svp, const CameraInfo& cameraInfo,
|
||||
FrameGraphId<FrameGraphTexture> structure,
|
||||
Viewport const& svp, const CameraInfo& cameraInfo,
|
||||
FrameGraphId<FrameGraphTexture> depth,
|
||||
AmbientOcclusionOptions const& options) noexcept;
|
||||
|
||||
// Gaussian mipmap
|
||||
@@ -201,7 +201,7 @@ public:
|
||||
|
||||
// Color grading, tone mapping, dithering and bloom
|
||||
FrameGraphId<FrameGraphTexture> colorGrading(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, filament::Viewport const& vp,
|
||||
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
|
||||
FrameGraphId<FrameGraphTexture> bloom,
|
||||
FrameGraphId<FrameGraphTexture> flare,
|
||||
const FColorGrading* colorGrading,
|
||||
@@ -226,12 +226,12 @@ public:
|
||||
|
||||
// Anti-aliasing
|
||||
FrameGraphId<FrameGraphTexture> fxaa(FrameGraph& fg,
|
||||
FrameGraphId<FrameGraphTexture> input, filament::Viewport const& vp,
|
||||
backend::TextureFormat outFormat, bool translucent) noexcept;
|
||||
FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> upscale(FrameGraph& fg, bool translucent,
|
||||
bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
|
||||
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
|
||||
FrameGraphTexture::Descriptor const& outDesc, backend::SamplerMagFilter filter) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> upscaleBilinear(FrameGraph& fg, bool translucent,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
|
||||
Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
|
||||
backend::SamplerMagFilter filter) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> upscaleFSR1(FrameGraph& fg,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
|
||||
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> input,
|
||||
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept;
|
||||
|
||||
FrameGraphId<FrameGraphTexture> rcas(
|
||||
FrameGraph& fg,
|
||||
float sharpness,
|
||||
@@ -267,7 +280,7 @@ public:
|
||||
// color blitter using shaders
|
||||
FrameGraphId<FrameGraphTexture> blit(FrameGraph& fg, bool translucent,
|
||||
FrameGraphId<FrameGraphTexture> 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<FrameGraphTexture> debugCombineArrayTexture(FrameGraph& fg, bool translucent,
|
||||
FrameGraphId<FrameGraphTexture> 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<size_t SIZE>
|
||||
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<math::float2, SIZE> positions;
|
||||
};
|
||||
|
||||
|
||||
+48
-39
@@ -26,8 +26,6 @@
|
||||
|
||||
#include "components/RenderableManager.h"
|
||||
|
||||
#include "ds/DescriptorSet.h"
|
||||
|
||||
#include <private/filament/EngineEnums.h>
|
||||
#include <private/filament/UibStructs.h>
|
||||
#include <private/filament/Variant.h>
|
||||
@@ -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<int32_t>::max());
|
||||
assert_invariant(mScissorViewport.height <= std::numeric_limits<int32_t>::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<Command> commands,
|
||||
utils::Range<uint32_t> const vr,
|
||||
Range<uint32_t> 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<JOBS_PARALLEL_FOR_COMMANDS_COUNT>());
|
||||
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<PerRenderableData*>(malloc(stagingBufferSize));
|
||||
uboData = mRenderableSoa.data<FScene::UBO>();
|
||||
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::COLOR>(commandTypeFlags, curr,
|
||||
soa, range,
|
||||
variant, renderFlags, visibilityMask, cameraPosition, cameraForward,
|
||||
stereoEyeCount);
|
||||
instancedStereoEyeCount);
|
||||
break;
|
||||
case CommandTypeFlags::DEPTH:
|
||||
curr = generateCommandsImpl<CommandTypeFlags::DEPTH>(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<RenderPass::CommandTypeFlags commandTypeFlags>
|
||||
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<uint32_t> 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)) +
|
||||
|
||||
+14
-14
@@ -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<typename T>
|
||||
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<RenderPass::CommandTypeFlags commandTypeFlags>
|
||||
static inline RenderPass::Command* generateCommandsImpl(RenderPass::CommandTypeFlags extraFlags,
|
||||
template<CommandTypeFlags commandTypeFlags>
|
||||
static Command* generateCommandsImpl(CommandTypeFlags extraFlags,
|
||||
Command* curr, FScene::RenderableSoa const& soa, utils::Range<uint32_t> 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<uint32_t> vr) noexcept {
|
||||
FScene::RenderableSoa const& soa, utils::Range<uint32_t> 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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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<uint16_t>(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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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::FrameInfo> Renderer::getFrameInfoHistory(size_t historySize) const noexcept {
|
||||
utils::FixedCapacityVector<Renderer::FrameInfo> Renderer::getFrameInfoHistory(size_t const historySize) const noexcept {
|
||||
return downcast(this)->getFrameInfoHistory(historySize);
|
||||
}
|
||||
|
||||
|
||||
@@ -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::ColorPassOutput> 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::ColorPassOutput> 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::ColorPassOutput> 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::ColorPassOutput> RendererUtils::refractionPass(
|
||||
}
|
||||
|
||||
UTILS_NOINLINE
|
||||
void RendererUtils::readPixels(backend::DriverApi& driver, Handle<HwRenderTarget> renderTargetHandle,
|
||||
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
|
||||
backend::PixelBufferDescriptor&& buffer) {
|
||||
void RendererUtils::readPixels(DriverApi& driver, Handle<HwRenderTarget> 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";
|
||||
|
||||
|
||||
@@ -99,7 +99,7 @@ public:
|
||||
PostProcessManager::ColorGradingConfig colorGradingConfig,
|
||||
RenderPass::Executor passExecutor) noexcept;
|
||||
|
||||
static std::optional<RendererUtils::ColorPassOutput> refractionPass(
|
||||
static std::optional<ColorPassOutput> refractionPass(
|
||||
FrameGraph& fg, FEngine& engine, FView const& view,
|
||||
ColorPassInput colorPassInput,
|
||||
ColorPassConfig config,
|
||||
|
||||
@@ -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<backend::TextureSwizzle, 4> 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<TextureSwizzle, 4> 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<backend::TextureSwizzle, 4>{
|
||||
using TS = TextureSwizzle;
|
||||
constexpr const auto defaultSwizzle = std::array<TextureSwizzle, 4>{
|
||||
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<ResourceAllocator::TextureKey> 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());
|
||||
|
||||
@@ -215,8 +215,8 @@ private:
|
||||
|
||||
using CacheContainer = AssociativeContainer<TextureKey, TextureCachePayload>;
|
||||
|
||||
ResourceAllocator::CacheContainer::iterator
|
||||
purge(ResourceAllocator::CacheContainer::iterator const& pos);
|
||||
CacheContainer::iterator
|
||||
purge(CacheContainer::iterator const& pos);
|
||||
|
||||
backend::DriverApi& mBackend;
|
||||
std::shared_ptr<ResourceAllocatorDisposer> mDisposer;
|
||||
|
||||
@@ -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<void(utils::Entity)>&& functor) const noexcept {
|
||||
void Scene::forEach(Invocable<void(Entity)>&& functor) const noexcept {
|
||||
downcast(this)->forEach(std::move(functor));
|
||||
}
|
||||
|
||||
|
||||
+49
-49
@@ -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<float>::lowest(), std::numeric_limits<float>::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<float>::max(), std::numeric_limits<float>::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<float3> const vertices{ wsVertices, count };
|
||||
Slice<float3> 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<typename Casters, typename Receivers>
|
||||
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<float>::lowest(), std::numeric_limits<float>::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);
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user