Compare commits

..

1 Commits

Author SHA1 Message Date
Benjamin Doherty
031cd302dd Capture command callstacks for debugging 2023-10-30 14:42:24 -07:00
41 changed files with 287 additions and 332 deletions

View File

@@ -3,14 +3,6 @@
# ==================================================================================================
cmake_minimum_required(VERSION 3.19)
# ==================================================================================================
# Toolchain configuration
# ==================================================================================================
if (APPLE AND NOT IOS)
# This must be set before project() is called
set(CMAKE_OSX_DEPLOYMENT_TARGET 10.15 CACHE STRING "")
endif()
# ==================================================================================================
# Project declaration
# ==================================================================================================

View File

@@ -7,3 +7,9 @@ for next branch cut* header.
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut
- Fix possible NPE when updating fog options from Java/Kotlin
- The `emissive` property was not applied properly to `MASKED` materials, and could cause
dark fringes to appear (recompile materials)
- Allow glTF materials with transmission/volume extensions to choose their alpha mode
instead of forcing `MASKED`

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.42.2'
implementation 'com.google.android.filament:filament-android:1.42.0'
}
```
@@ -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:
```
pod 'Filament', '~> 1.42.2'
pod 'Filament', '~> 1.42.0'
```
### Snapshots

View File

@@ -7,23 +7,8 @@ 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.42.2
- Fix possible NPE when updating fog options from Java/Kotlin
- The `emissive` property was not applied properly to `MASKED` materials, and could cause
dark fringes to appear (recompile materials)
- Allow glTF materials with transmission/volume extensions to choose their alpha mode
instead of forcing `MASKED`
- Fix a crash in gltfio when not using ubershaders
- Use flatmat for mat parameter in jsbinding
- Fix TextureFlags for sheenRoughnessMap when textures of sheenRoughnessMap and sheenColorMap is same
- Directional shadows can now be transformed (b/297095805)
## v1.42.1
- Fix potential `EXC_BAD_ACCESS` with Metal backend: b/297059776
- `setFrameCompletedCallback` now takes a `backend::CallbackHandler`.
## v1.42.0
- engine: add preliminary support for instanced stereoscopic rendering [⚠️ **Recompile materials**]

View File

@@ -79,8 +79,7 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
jfloat shadowFarHint, jboolean stable, jboolean lispsm,
jfloat polygonOffsetConstant, jfloat polygonOffsetSlope,
jboolean screenSpaceContactShadows, jint stepCount,
jfloat maxShadowDistance, jboolean elvsm, jfloat blurWidth, jfloat shadowBulbRadius,
jfloatArray transform) {
jfloat maxShadowDistance, jboolean elvsm, jfloat blurWidth, jfloat shadowBulbRadius) {
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
LightManager::ShadowOptions shadowOptions {
.mapSize = (uint32_t)mapSize,
@@ -103,18 +102,12 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
},
.shadowBulbRadius = shadowBulbRadius
};
jfloat *nativeSplits = env->GetFloatArrayElements(splitPositions, NULL);
const jsize splitCount = std::min((jsize) 3, env->GetArrayLength(splitPositions));
std::copy_n(nativeSplits, splitCount, shadowOptions.cascadeSplitPositions);
for (jsize i = 0; i < splitCount; i++) {
shadowOptions.cascadeSplitPositions[i] = nativeSplits[i];
}
env->ReleaseFloatArrayElements(splitPositions, nativeSplits, 0);
jfloat* nativeTransform = env->GetFloatArrayElements(transform, NULL);
std::copy_n(nativeTransform,
std::min(4, env->GetArrayLength(transform)),
shadowOptions.transform.xyzw.v);
env->ReleaseFloatArrayElements(transform, nativeTransform, 0);
builder->shadowOptions(shadowOptions);
}

View File

@@ -368,17 +368,6 @@ public class LightManager {
* enabled. (2cm by default).
*/
public float shadowBulbRadius = 0.02f;
/**
* Transforms the shadow direction. Must be a unit quaternion.
* The default is identity.
* Ignored if the light type isn't directional. For artistic use. Use with caution.
* The quaternion is stored as the imaginary part in the first 3 elements and the real
* part in the last element of the transform array.
*/
@NonNull
@Size(min = 4, max = 4)
public float[] transform = { 0.0f, 0.0f, 0.0f, 1.0f };
}
public static class ShadowCascades {
@@ -517,7 +506,7 @@ public class LightManager {
options.polygonOffsetConstant, options.polygonOffsetSlope,
options.screenSpaceContactShadows,
options.stepCount, options.maxShadowDistance,
options.elvsm, options.blurWidth, options.shadowBulbRadius, options.transform);
options.elvsm, options.blurWidth, options.shadowBulbRadius);
return this;
}
@@ -1180,7 +1169,7 @@ public class LightManager {
boolean stable, boolean lispsm,
float polygonOffsetConstant, float polygonOffsetSlope,
boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance,
boolean elvsm, float blurWidth, float shadowBulbRadius, float[] transform);
boolean elvsm, float blurWidth, float shadowBulbRadius);
private static native void nBuilderCastLight(long nativeBuilder, boolean enabled);
private static native void nBuilderPosition(long nativeBuilder, float x, float y, float z);
private static native void nBuilderDirection(long nativeBuilder, float x, float y, float z);

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.42.2
VERSION_NAME=1.42.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

View File

@@ -210,10 +210,13 @@ function build_desktop_target {
echo "Building ${lc_target} in out/cmake-${lc_target}..."
mkdir -p "out/cmake-${lc_target}"
pushd "out/cmake-${lc_target}" > /dev/null
cd "out/cmake-${lc_target}"
# On macOS, set the deployment target to 10.15.
local lc_name=$(echo "${UNAME}" | tr '[:upper:]' '[:lower:]')
if [[ "${lc_name}" == "darwin" ]]; then
local deployment_target="-DCMAKE_OSX_DEPLOYMENT_TARGET=10.15"
if [[ "${BUILD_UNIVERSAL_LIBRARIES}" == "true" ]]; then
local architectures="-DCMAKE_OSX_ARCHITECTURES=arm64;x86_64"
fi
@@ -230,6 +233,7 @@ function build_desktop_target {
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${ASAN_UBSAN_OPTION} \
${deployment_target} \
${architectures} \
../..
fi
@@ -243,13 +247,12 @@ function build_desktop_target {
if [[ -d "../${lc_target}/filament" ]]; then
if [[ "${ISSUE_ARCHIVES}" == "true" ]]; then
echo "Generating out/filament-${lc_target}-${LC_UNAME}.tgz..."
pushd "../${lc_target}" > /dev/null
cd "../${lc_target}"
tar -czvf "../filament-${lc_target}-${LC_UNAME}.tgz" filament
popd > /dev/null
fi
fi
popd > /dev/null
cd ../..
}
function build_desktop {
@@ -267,7 +270,7 @@ function build_webgl_with_target {
echo "Building WebGL ${lc_target}..."
mkdir -p "out/cmake-webgl-${lc_target}"
pushd "out/cmake-webgl-${lc_target}" > /dev/null
cd "out/cmake-webgl-${lc_target}"
if [[ ! "${BUILD_TARGETS}" ]]; then
BUILD_TARGETS=${BUILD_CUSTOM_TARGETS}
@@ -304,17 +307,17 @@ function build_webgl_with_target {
if [[ "${ISSUE_ARCHIVES}" == "true" ]]; then
echo "Generating out/filament-${lc_target}-web.tgz..."
pushd web/filament-js > /dev/null
cd web/filament-js
tar -cvf "../../../filament-${lc_target}-web.tar" filament.js
tar -rvf "../../../filament-${lc_target}-web.tar" filament.wasm
tar -rvf "../../../filament-${lc_target}-web.tar" filament.d.ts
popd > /dev/null
cd -
gzip -c "../filament-${lc_target}-web.tar" > "../filament-${lc_target}-web.tgz"
rm "../filament-${lc_target}-web.tar"
fi
fi
popd > /dev/null
cd ../..
}
function build_webgl {
@@ -345,7 +348,7 @@ function build_android_target {
echo "Building Android ${lc_target} (${arch})..."
mkdir -p "out/cmake-android-${lc_target}-${arch}"
pushd "out/cmake-android-${lc_target}-${arch}" > /dev/null
cd "out/cmake-android-${lc_target}-${arch}"
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
cmake \
@@ -364,7 +367,7 @@ function build_android_target {
# We must always install Android libraries to build the AAR
${BUILD_COMMAND} install
popd > /dev/null
cd ../..
}
function build_android_arch {
@@ -385,9 +388,9 @@ function archive_android {
if [[ -d "out/android-${lc_target}/filament" ]]; then
if [[ "${ISSUE_ARCHIVES}" == "true" ]]; then
echo "Generating out/filament-android-${lc_target}-${LC_UNAME}.tgz..."
pushd "out/android-${lc_target}" > /dev/null
cd "out/android-${lc_target}"
tar -czvf "../filament-android-${lc_target}-${LC_UNAME}.tgz" filament
popd > /dev/null
cd ../..
fi
fi
}
@@ -465,7 +468,7 @@ function build_android {
archive_android "Release"
fi
pushd android > /dev/null
cd android
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
./gradlew \
@@ -566,7 +569,7 @@ function build_android {
fi
fi
popd > /dev/null
cd ..
}
function build_ios_target {
@@ -577,7 +580,7 @@ function build_ios_target {
echo "Building iOS ${lc_target} (${arch}) for ${platform}..."
mkdir -p "out/cmake-ios-${lc_target}-${arch}"
pushd "out/cmake-ios-${lc_target}-${arch}" > /dev/null
cd "out/cmake-ios-${lc_target}-${arch}"
if [[ ! -d "CMakeFiles" ]] || [[ "${ISSUE_CMAKE_ALWAYS}" == "true" ]]; then
cmake \
@@ -601,7 +604,7 @@ function build_ios_target {
${BUILD_COMMAND} ${INSTALL_COMMAND}
fi
popd > /dev/null
cd ../..
}
function archive_ios {
@@ -610,9 +613,9 @@ function archive_ios {
if [[ -d "out/ios-${lc_target}/filament" ]]; then
if [[ "${ISSUE_ARCHIVES}" == "true" ]]; then
echo "Generating out/filament-${lc_target}-ios.tgz..."
pushd "out/ios-${lc_target}" > /dev/null
cd "out/ios-${lc_target}"
tar -czvf "../filament-${lc_target}-ios.tgz" filament
popd > /dev/null
cd ../..
fi
fi
}
@@ -671,14 +674,14 @@ function build_web_docs {
mkdir -p out/web-docs
cp -f docs/web-docs-package.json out/web-docs/package.json
pushd out/web-docs > /dev/null
cd out/web-docs
npm install > /dev/null
# Generate documents
npx markdeep-rasterizer ../../docs/Filament.md.html ../../docs/Materials.md.html ../../docs/
popd > /dev/null
cd ../..
}
function validate_build_command {
@@ -751,16 +754,6 @@ function run_tests {
fi
}
function check_debug_release_build {
if [[ "${ISSUE_DEBUG_BUILD}" == "true" || "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
"$@";
else
echo "You must declare a debug or release target for $@ builds."
echo ""
exit 1
fi
}
# Beginning of the script
pushd "$(dirname "$0")" > /dev/null
@@ -769,7 +762,7 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
case ${opt} in
h)
print_help
exit 0
exit 1
;;
a)
ISSUE_ARCHIVES=true
@@ -805,7 +798,7 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
platforms=$(echo "${OPTARG}" | tr ',' '\n')
for platform in ${platforms}
do
case $(echo "${platform}" | tr '[:upper:]' '[:lower:]') in
case ${platform} in
desktop)
ISSUE_DESKTOP_BUILD=true
;;
@@ -824,12 +817,6 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
ISSUE_DESKTOP_BUILD=true
ISSUE_WEBGL_BUILD=false
;;
*)
echo "Unknown platform ${platform}"
echo "Platform must be one of [desktop|android|ios|webgl|all]"
echo ""
exit 1
;;
esac
done
;;
@@ -842,7 +829,7 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
abis=$(echo "${OPTARG}" | tr ',' '\n')
for abi in ${abis}
do
case $(echo "${abi}" | tr '[:upper:]' '[:lower:]') in
case ${abi} in
armeabi-v7a)
ABI_ARMEABI_V7A=true
;;
@@ -861,12 +848,6 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
ABI_X86=true
ABI_X86_64=true
;;
*)
echo "Unknown abi ${abi}"
echo "ABI must be one of [armeabi-v7a|arm64-v8a|x86|x86_64|all]"
echo ""
exit 1
;;
esac
done
;;
@@ -930,9 +911,9 @@ fi
shift $((OPTIND - 1))
for arg; do
if [[ $(echo "${arg}" | tr '[:upper:]' '[:lower:]') == "release" ]]; then
if [[ "${arg}" == "release" ]]; then
ISSUE_RELEASE_BUILD=true
elif [[ $(echo "${arg}" | tr '[:upper:]' '[:lower:]') == "debug" ]]; then
elif [[ "${arg}" == "debug" ]]; then
ISSUE_DEBUG_BUILD=true
else
BUILD_CUSTOM_TARGETS="${BUILD_CUSTOM_TARGETS} ${arg}"
@@ -950,19 +931,19 @@ if [[ "${ISSUE_CLEAN_AGGRESSIVE}" == "true" ]]; then
fi
if [[ "${ISSUE_DESKTOP_BUILD}" == "true" ]]; then
check_debug_release_build build_desktop
build_desktop
fi
if [[ "${ISSUE_ANDROID_BUILD}" == "true" ]]; then
check_debug_release_build build_android
build_android
fi
if [[ "${ISSUE_IOS_BUILD}" == "true" ]]; then
check_debug_release_build build_ios
build_ios
fi
if [[ "${ISSUE_WEBGL_BUILD}" == "true" ]]; then
check_debug_release_build build_webgl
build_webgl
fi
if [[ "${ISSUE_WEB_DOCS}" == "true" ]]; then

View File

@@ -813,22 +813,22 @@ struct SamplerParams { // NOLINT
struct Hasher {
size_t operator()(SamplerParams p) const noexcept {
// we don't use std::hash<> here, so we don't have to include <functional>
return *reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&p));
return *reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&p));
}
};
struct EqualTo {
bool operator()(SamplerParams lhs, SamplerParams rhs) const noexcept {
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
auto* pLhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&lhs));
auto* pRhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&rhs));
return *pLhs == *pRhs;
}
};
struct LessThan {
bool operator()(SamplerParams lhs, SamplerParams rhs) const noexcept {
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
auto* pLhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&lhs));
auto* pRhs = reinterpret_cast<uint64_t const*>(reinterpret_cast<char const*>(&rhs));
return *pLhs == *pRhs;
}
};
@@ -838,7 +838,6 @@ private:
return SamplerParams::LessThan{}(lhs, rhs);
}
};
static_assert(sizeof(SamplerParams) == 4);
// The limitation to 64-bits max comes from how we store a SamplerParams in our JNI code
// see android/.../TextureSampler.cpp

View File

@@ -67,7 +67,7 @@ public:
Program& operator=(const Program& rhs) = delete;
Program(Program&& rhs) noexcept;
Program& operator=(Program&& rhs) noexcept = delete;
Program& operator=(Program&& rhs) noexcept;
~Program() noexcept;
@@ -104,9 +104,8 @@ public:
Sampler const* samplers, size_t count) noexcept;
struct SpecializationConstant {
using Type = std::variant<int32_t, float, bool>;
uint32_t id; // id set in glsl
Type value; // value and type
std::variant<int32_t, float, bool> value; // value and type
};
Program& specializationConstants(

View File

@@ -73,14 +73,32 @@ public:
// a cost here (writing and reading the stack at each iteration), in the end it's
// probably better to pay the cost at just one location.
intptr_t next;
driver.mCurrentExecutingCommand = this;
mExecute(driver, this, &next);
return reinterpret_cast<CommandBase*>(reinterpret_cast<intptr_t>(this) + next);
}
inline void captureCallstack() noexcept {
auto c = utils::CallStack::unwind(4);
size_t i = 0;
for (; i < c.getFrameCount() && i < 16; i++) {
mCallstack[i] = c[i];
}
for (; i < 16; i++) {
mCallstack[i] = 0;
}
}
void printCallstack() noexcept {
auto c = utils::CallStack(mCallstack);
utils::slog.d << c << utils::io::endl;
}
inline ~CommandBase() noexcept = default;
private:
Execute mExecute;
std::array<intptr_t, 16> mCallstack = {0};
};
// ------------------------------------------------------------------------------------------------
@@ -218,6 +236,7 @@ public:
using Cmd = COMMAND_TYPE(methodName); \
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
new(p) Cmd(mDispatcher.methodName##_, APPLY(std::move, params)); \
((Cmd*)p)->captureCallstack(); \
DEBUG_COMMAND_END(methodName, false); \
}
@@ -237,6 +256,7 @@ public:
using Cmd = COMMAND_TYPE(methodName##R); \
void* const p = allocateCommand(CommandBase::align(sizeof(Cmd))); \
new(p) Cmd(mDispatcher.methodName##_, RetType(result), APPLY(std::move, params)); \
((Cmd*)p)->captureCallstack(); \
DEBUG_COMMAND_END(methodName, false); \
return result; \
}

View File

@@ -53,6 +53,7 @@ template<typename T>
class ConcreteDispatcher;
class Dispatcher;
class CommandStream;
class CommandBase;
class Driver {
public:
@@ -83,6 +84,8 @@ public:
virtual void debugCommandEnd(CommandStream* cmds,
bool synchronous, const char* methodName) noexcept = 0;
CommandBase* mCurrentExecutingCommand = nullptr;
/*
* Asynchronous calls here only to provide a type to CommandStream. They must be non-virtual
* so that calling the concrete implementation won't go through a vtable.

View File

@@ -26,6 +26,17 @@ Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
Program::Program(Program&& rhs) noexcept = default;
Program& Program::operator=(Program&& rhs) noexcept {
mUniformBlocks.operator=(rhs.mUniformBlocks);
mSamplerGroups.operator=(std::move(rhs.mSamplerGroups));
mShadersSource.operator=(std::move(rhs.mShadersSource));
mName.operator=(std::move(rhs.mName));
mLogger.operator=(std::move(rhs.mLogger));
mSpecializationConstants.operator=(std::move(rhs.mSpecializationConstants));
mBindingUniformInfo.operator=(std::move(rhs.mBindingUniformInfo));
return *this;
}
Program::~Program() noexcept = default;
Program& Program::priorityQueue(CompilerPriorityQueue priorityQueue) noexcept {

View File

@@ -103,11 +103,6 @@ struct ShaderCompilerService::OpenGLProgramToken : ProgramToken {
return programData;
}
void wait() const noexcept {
std::unique_lock l(lock);
cond.wait(l, [this](){ return signaled; });
}
// Checks if the programBinary is ready.
// This is similar to std::future::wait_for(0s)
bool isReady() const noexcept {
@@ -343,22 +338,6 @@ GLuint ShaderCompilerService::getProgram(ShaderCompilerService::program_token_t&
token->compiler.cancelTickOp(token);
if (token->compiler.mShaderCompilerThreadCount) {
auto job = token->compiler.mCompilerThreadPool.dequeue(token);
if (!job) {
// The job is being executed right now. We need to wait for it to finish to avoid a
// race.
token->wait();
} else {
// The job has not been executed, but we still need to inform the callback manager in
// order for future callbacks to be successfully called.
token->compiler.mCallbackManager.put(token->handle);
}
} else {
// Since the tick op was canceled, we need to .put the token here.
token->compiler.mCallbackManager.put(token->handle);
}
for (GLuint& shader: token->gl.shaders) {
if (shader) {
if (token->gl.program) {

View File

@@ -217,20 +217,6 @@ bool VulkanCommands::flush() {
return false;
}
// Before actually submitting, we need to pop any leftover group markers.
// Note that this needs to occur before vkEndCommandBuffer.
while (mGroupMarkers && !mGroupMarkers->empty()) {
if (!mCarriedOverMarkers) {
mCarriedOverMarkers = std::make_unique<VulkanGroupMarkers>();
}
auto const [marker, time] = mGroupMarkers->top();
mCarriedOverMarkers->push(marker, time);
// We still need to call through to vkCmdEndDebugUtilsLabelEXT.
popGroupMarker();
}
int8_t const index = mCurrentCommandBufferIndex;
VulkanCommandBuffer const* currentbuf = mStorage[index].get();
VkSemaphore const renderingFinished = mSubmissionSignals[index];
@@ -284,6 +270,17 @@ bool VulkanCommands::flush() {
<< io::endl;
#endif
// Before actually submitting, we need to pop any leftover group markers.
while (mGroupMarkers && !mGroupMarkers->empty()) {
if (!mCarriedOverMarkers) {
mCarriedOverMarkers = std::make_unique<VulkanGroupMarkers>();
}
auto const [marker, time] = mGroupMarkers->top();
mCarriedOverMarkers->push(marker, time);
// We still need to call through to vkCmdEndDebugUtilsLabelEXT.
popGroupMarker();
}
auto& cmdfence = currentbuf->fence;
std::unique_lock<utils::Mutex> lock(cmdfence->mutex);
cmdfence->status.store(VK_NOT_READY);

View File

@@ -526,22 +526,21 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
<< utils::io::endl;
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
}
auto swapChain = mResourceAllocator.construct<VulkanSwapChain>(sch, mPlatform, mContext,
mAllocator, mCommands.get(), mStagePool, nativeWindow, flags);
mResourceManager.acquire(swapChain);
mResourceAllocator.construct<VulkanSwapChain>(sch, mPlatform, mContext, mAllocator,
mCommands.get(), mStagePool, nativeWindow, flags);
}
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
uint32_t height, uint64_t flags) {
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 &&
!isSRGBSwapChainSupported()) {
utils::slog.w << "sRGB swapchain requested, but Platform does not support it"
<< utils::io::endl;
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
}
assert_invariant(width > 0 && height > 0 && "Vulkan requires non-zero swap chain dimensions.");
auto swapChain = mResourceAllocator.construct<VulkanSwapChain>(sch, mPlatform, mContext,
mAllocator, mCommands.get(), mStagePool, nullptr, flags, VkExtent2D{width, height});
mResourceManager.acquire(swapChain);
mResourceAllocator.construct<VulkanSwapChain>(sch, mPlatform, mContext, mAllocator,
mCommands.get(), mStagePool, nullptr, flags, VkExtent2D{width, height});
}
void VulkanDriver::createTimerQueryR(Handle<HwTimerQuery> tqh, int) {

View File

@@ -89,26 +89,21 @@ VulkanProgram::VulkanProgram(VkDevice device, const Program& builder) noexcept
};
for (size_t i = 0; i < specializationConstants.size(); i++) {
uint32_t const offset = uint32_t(i) * 4;
pEntries[i] = {
.constantID = specializationConstants[i].id,
.offset = offset,
// Note that bools are 4-bytes in Vulkan
// https://registry.khronos.org/vulkan/specs/1.3-extensions/man/html/VkBool32.html
.size = 4,
};
using SpecConstant = Program::SpecializationConstant::Type;
char const* addr = (char*)pData + offset;
SpecConstant const& arg = specializationConstants[i].value;
if (std::holds_alternative<bool>(arg)) {
*((VkBool32*)addr) = std::get<bool>(arg) ? VK_TRUE : VK_FALSE;
} else if (std::holds_alternative<float>(arg)) {
*((float*)addr) = std::get<float>(arg);
} else {
*((int32_t*)addr) = std::get<int32_t>(arg);
}
const uint32_t offset = uint32_t(i) * 4;
std::visit([&](auto&& arg) {
using T = std::decay_t<decltype(arg)>;
pEntries[i] = {
.constantID = specializationConstants[i].id,
.offset = offset,
// Turns out vulkan expects the size of bool to be 4 (verified through
// validation layer). So all expected types are of 4 bytes.
.size = 4,
};
T* const addr = (T*)((char*)pData + offset);
*addr = arg;
}, specializationConstants[i].value);
}
bundle.specializationInfos = pInfo;
}

View File

@@ -152,7 +152,7 @@ void printDepthFormats(VkPhysicalDevice device) {
}
ExtensionSet getInstanceExtensions() {
std::string_view const TARGET_EXTS[] = {
std::array<std::string_view, 4> const TARGET_EXTS = {
// Request all cross-platform extensions.
VK_KHR_SURFACE_EXTENSION_NAME,
VK_KHR_GET_PHYSICAL_DEVICE_PROPERTIES_2_EXTENSION_NAME,
@@ -160,10 +160,6 @@ ExtensionSet getInstanceExtensions() {
// Request these if available.
VK_EXT_DEBUG_UTILS_EXTENSION_NAME,
VK_KHR_PORTABILITY_ENUMERATION_EXTENSION_NAME,
#if VK_ENABLE_VALIDATION
VK_EXT_DEBUG_REPORT_EXTENSION_NAME,
#endif
};
ExtensionSet exts;
FixedCapacityVector<VkExtensionProperties> const availableExts
@@ -180,7 +176,7 @@ ExtensionSet getInstanceExtensions() {
}
ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
std::string_view const TARGET_EXTS[] = {
std::array<std::string_view, 5> const TARGET_EXTS = {
VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME,
VK_KHR_MAINTENANCE1_EXTENSION_NAME,
@@ -235,10 +231,13 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
// The Platform class can require 1 or 2 instance extensions, plus we'll request at most 5
// instance extensions here in the common code. So that's a max of 7.
static constexpr uint32_t MAX_INSTANCE_EXTENSION_COUNT = 8;
static constexpr uint32_t MAX_INSTANCE_EXTENSION_COUNT = 7;
const char* ppEnabledExtensions[MAX_INSTANCE_EXTENSION_COUNT];
uint32_t enabledExtensionCount = 0;
#if VK_ENABLE_VALIDATION && defined(__ANDROID__)
ppEnabledExtensions[enabledExtensionCount++] = VK_EXT_DEBUG_REPORT_EXTENSION_NAME;
#endif
if (validationFeaturesSupported) {
ppEnabledExtensions[enabledExtensionCount++] = VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME;
}
@@ -513,7 +512,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
VkFormat findSupportedFormat(VkPhysicalDevice device) {
VkFormatFeatureFlags const features = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT;
VkFormat const formats[] = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_X8_D24_UNORM_PACK32};
std::array<VkFormat, 2> const formats = {VK_FORMAT_D32_SFLOAT, VK_FORMAT_X8_D24_UNORM_PACK32};
for (VkFormat format: formats) {
VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(device, format, &props);

View File

@@ -25,7 +25,6 @@
#include <utils/EntityInstance.h>
#include <math/mathfwd.h>
#include <math/quat.h>
namespace utils {
class Entity;
@@ -361,13 +360,6 @@ public:
* enabled. (2cm by default).
*/
float shadowBulbRadius = 0.02f;
/**
* Transforms the shadow direction. Must be a unit quaternion.
* The default is identity.
* Ignored if the light type isn't directional. For artistic use. Use with caution.
*/
math::quatf transform{ 1.0f };
};
struct ShadowCascades {
@@ -679,7 +671,7 @@ public:
* @return true is this light is a type of directional light
*/
inline bool isDirectional(Instance i) const noexcept {
Type const type = getType(i);
Type type = getType(i);
return type == Type::DIRECTIONAL || type == Type::SUN;
}
@@ -700,7 +692,7 @@ public:
* @return true is this light is a type of spot light
*/
inline bool isSpotLight(Instance i) const noexcept {
Type const type = getType(i);
Type type = getType(i);
return type == Type::SPOT || type == Type::FOCUSED_SPOT;
}

View File

@@ -285,7 +285,7 @@ void PerViewUniforms::prepareDirectionalLight(FEngine& engine,
float exposure,
float3 const& sceneSpaceDirection,
PerViewUniforms::LightManagerInstance directionalLight) noexcept {
FLightManager const& lcm = engine.getLightManager();
FLightManager& lcm = engine.getLightManager();
auto& s = mUniforms.edit();
const float3 l = -sceneSpaceDirection; // guaranteed normalized
@@ -302,11 +302,11 @@ void PerViewUniforms::prepareDirectionalLight(FEngine& engine,
// The last parameter must be < 0.0f for regular directional lights
float4 sun{ 0.0f, 0.0f, 0.0f, -1.0f };
if (UTILS_UNLIKELY(isSun && colorIntensity.w > 0.0f)) {
// Currently we have only a single directional light, so it's probably likely that it's
// currently we have only a single directional light, so it's probably likely that it's
// also the Sun. However, conceptually, most directional lights won't be sun lights.
float const radius = lcm.getSunAngularRadius(directionalLight);
float const haloSize = lcm.getSunHaloSize(directionalLight);
float const haloFalloff = lcm.getSunHaloFalloff(directionalLight);
float radius = lcm.getSunAngularRadius(directionalLight);
float haloSize = lcm.getSunHaloSize(directionalLight);
float haloFalloff = lcm.getSunHaloFalloff(directionalLight);
sun.x = std::cos(radius);
sun.y = std::sin(radius);
sun.z = 1.0f / (std::cos(radius * haloSize) - sun.x);

View File

@@ -144,7 +144,7 @@ ShadowMap::ShaderParameters ShadowMap::updateDirectional(FEngine& engine,
return p;
}(camera.cullingProjection) };
const auto direction = params.options.transform * lightData.elementAt<FScene::DIRECTION>(index);
const auto direction = lightData.elementAt<FScene::DIRECTION>(index);
/*
* Compute the light's model matrix

View File

@@ -459,7 +459,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
// entire camera frustum, as if we only had a single cascade.
ShadowMap& shadowMap = *mCascadeShadowMaps[0];
const auto direction = options.transform * lightData.elementAt<FScene::DIRECTION>(0);
const auto direction = lightData.elementAt<FScene::DIRECTION>(0);
// 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.

View File

@@ -127,12 +127,12 @@ public:
}
bool isSpotLight(Instance i) const noexcept {
Type const type = getType(i);
Type type = getType(i);
return type == Type::FOCUSED_SPOT || type == Type::SPOT;
}
bool isDirectionalLight(Instance i) const noexcept {
Type const type = getType(i);
Type type = getType(i);
return type == Type::DIRECTIONAL || type == Type::SUN;
}

View File

@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.42.2"
spec.version = "1.42.0"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.42.2/filament-v1.42.2-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.42.0/filament-v1.42.0-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {

View File

@@ -1467,9 +1467,8 @@ MaterialInstance* FAssetLoader::createMaterialInstance(const cgltf_data* srcAsse
}
}
if (matkey.hasSheenRoughnessTexture) {
bool sameTexture = shConfig.sheen_color_texture.texture == shConfig.sheen_roughness_texture.texture;
mAsset->addTextureBinding(mi, "sheenRoughnessMap",
shConfig.sheen_roughness_texture.texture, sameTexture ? sRGB : LINEAR);
shConfig.sheen_roughness_texture.texture, LINEAR);
if (matkey.hasTextureTransforms) {
const cgltf_texture_transform& uvt = shConfig.sheen_roughness_texture.transform;
auto uvmat = matrixFromUvTransform(uvt.offset, uvt.rotation, uvt.scale);

View File

@@ -287,7 +287,7 @@ std::string shaderFromKey(const MaterialKey& config) {
// TODO: Provided by Filament, but this should really be provided/computed by gltfio
// TODO: This scale is per renderable and should include the scale of the mesh node
float scale = getObjectUserData();
float scale = object_uniforms.userData;
material.thickness = materialParams.volumeThicknessFactor * scale;
)SHADER";

View File

@@ -25,7 +25,10 @@
#include <stdint.h>
#include <sys/types.h>
namespace filament::math::details {
namespace filament {
namespace math {
namespace details {
// -------------------------------------------------------------------------------------
/*
* No user serviceable parts here.
@@ -46,7 +49,7 @@ namespace filament::math::details {
template<template<typename T> class QUATERNION, typename T>
class TQuatProductOperators {
public:
/* compound assignment from another quaternion of the same size but different
/* compound assignment from a another quaternion of the same size but different
* element type.
*/
template<typename OTHER>
@@ -82,7 +85,7 @@ public:
* (the first one, BASE<T> being known).
*/
/* The operators below handle operation between quaternions of the same size
/* The operators below handle operation between quaternion of the same size
* but of a different element type.
*/
template<typename RT>
@@ -124,19 +127,19 @@ public:
*/
friend inline
constexpr QUATERNION<T> MATH_PURE operator*(QUATERNION<T> q, T scalar) {
// don't pass q by reference because we need a copy anyway
// don't pass q by reference because we need a copy anyways
return q *= scalar;
}
friend inline
constexpr QUATERNION<T> MATH_PURE operator*(T scalar, QUATERNION<T> q) {
// don't pass q by reference because we need a copy anyway
// don't pass q by reference because we need a copy anyways
return q *= scalar;
}
friend inline
constexpr QUATERNION<T> MATH_PURE operator/(QUATERNION<T> q, T scalar) {
// don't pass q by reference because we need a copy anyway
// don't pass q by reference because we need a copy anyways
return q /= scalar;
}
};
@@ -280,6 +283,9 @@ public:
}
};
} // namespace filament::math::details
// -------------------------------------------------------------------------------------
} // namespace details
} // namespace math
} // namespace filament
#endif // TNT_MATH_TQUATHELPERS_H

View File

@@ -160,7 +160,7 @@ constexpr inline half makeHalf(uint16_t bits) noexcept {
#endif // __ARM_NEON
inline constexpr half operator""_h(long double v) {
inline constexpr half operator "" _h(long double v) {
return half( static_cast<float>(v) );
}

View File

@@ -33,7 +33,8 @@
#include <stdint.h>
namespace filament::math {
namespace filament {
namespace math {
namespace details {
template<typename T> class TVec2;
@@ -44,8 +45,6 @@ template<typename T> class TMat22;
template<typename T> class TMat33;
template<typename T> class TMat44;
template<typename T> class TQuaternion;
} // namespace details
using double2 = details::TVec2<double>;
@@ -87,10 +86,8 @@ using mat3f = details::TMat33<float>;
using mat4 = details::TMat44<double>;
using mat4f = details::TMat44<float>;
using quat = details::TQuaternion<double>;
using quatf = details::TQuaternion<float>;
} // namespace filament::math
} // namespace math
} // namespace filament
#endif // _MSC_VER

View File

@@ -26,7 +26,10 @@
#include <stdint.h>
#include <sys/types.h>
namespace filament::math {
namespace filament {
namespace math {
// -------------------------------------------------------------------------------------
namespace details {
template<typename T>
@@ -86,15 +89,15 @@ public:
// constructors
// Leaves object uninitialized. Use with caution.
// leaves object uninitialized. use with caution.
explicit constexpr TQuaternion(no_init) {}
// default constructor. sets all values to zero.
constexpr TQuaternion() : x(0), y(0), z(0), w(0) {}
// Handles implicit conversion to a quat. Must not be explicit.
// handles implicit conversion to a quat. must not be explicit.
template<typename A, typename = enable_if_arithmetic_t<A>>
constexpr TQuaternion(A w) : x(0), y(0), z(0), w(w) {} // NOLINT(google-explicit-constructor)
constexpr TQuaternion(A w) : x(0), y(0), z(0), w(w) {}
// initialize from 4 values to w + xi + yj + zk
template<typename A, typename B, typename C, typename D,
@@ -172,29 +175,31 @@ typedef details::TQuaternion<float> quatf;
typedef details::TQuaternion<half> quath;
constexpr inline quat operator "" _i(long double v) {
return { 0.0, double(v), 0.0, 0.0 };
return quat(0.0, double(v), 0.0, 0.0);
}
constexpr inline quat operator "" _j(long double v) {
return { 0.0, 0.0, double(v), 0.0 };
return quat(0.0, 0.0, double(v), 0.0);
}
constexpr inline quat operator "" _k(long double v) {
return { 0.0, 0.0, 0.0, double(v) };
return quat(0.0, 0.0, 0.0, double(v));
}
constexpr inline quat operator "" _i(unsigned long long v) {
return { 0.0, double(v), 0.0, 0.0 };
return quat(0.0, double(v), 0.0, 0.0);
}
constexpr inline quat operator "" _j(unsigned long long v) {
return { 0.0, 0.0, double(v), 0.0 };
return quat(0.0, 0.0, double(v), 0.0);
}
constexpr inline quat operator "" _k(unsigned long long v) {
return { 0.0, 0.0, 0.0, double(v) };
return quat(0.0, 0.0, 0.0, double(v));
}
} // namespace filament::math
// ----------------------------------------------------------------------------------------
} // namespace math
} // namespace filament
#endif // TNT_MATH_QUAT_H

View File

@@ -36,6 +36,13 @@ public:
* @see CallStack::capture()
*/
CallStack() = default;
template <unsigned long N>
explicit CallStack(const std::array<intptr_t, N>& symbols)
: m_frame_count(N) {
for (size_t i = 0; i < N; i++) {
m_stack[i] = symbols[i];
}
}
CallStack(const CallStack&) = default;
~CallStack() = default;
@@ -114,12 +121,10 @@ private:
static constexpr size_t NUM_FRAMES = 20;
struct StackFrameInfo {
intptr_t pc;
};
using StackFrameInfo = intptr_t;
size_t m_frame_count = 0;
StackFrameInfo m_stack[NUM_FRAMES];
StackFrameInfo m_stack[NUM_FRAMES] = {0};
};
} // namespace utils

View File

@@ -70,7 +70,7 @@ intptr_t CallStack::operator[](size_t index) const {
#endif
std::abort();
}
return m_stack[index].pc;
return m_stack[index];
}
size_t CallStack::getFrameCount() const noexcept {
@@ -91,7 +91,7 @@ void CallStack::update_gcc(size_t ignore) noexcept {
size -= ignore;
#endif
for (ssize_t i = 0; i < size; i++) {
m_stack[i].pc = intptr_t(array[ignore + i]);
m_stack[i] = intptr_t(array[ignore + i]);
}
size--; // the last one seems to always be 0x0

View File

@@ -362,13 +362,19 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
LightManager::ShadowOptions* out) {
CHECK_TOKTYPE(tokens[i], JSMN_OBJECT);
int const size = tokens[i++].size;
int size = tokens[i++].size;
math::float3 splitsVector;
for (int j = 0; j < size; ++j) {
const jsmntok_t tok = tokens[i];
CHECK_KEY(tok);
if (compare(tok, jsonChunk, "mapSize") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->mapSize);
} else if (compare(tok, jsonChunk, "stable") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->stable);
} else if (compare(tok, jsonChunk, "lispsm") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->lispsm);
} else if (compare(tok, jsonChunk, "screenSpaceContactShadows") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->screenSpaceContactShadows);
} else if (compare(tok, jsonChunk, "shadowCascades") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->shadowCascades);
} else if (compare(tok, jsonChunk, "cascadeSplitPositions") == 0) {
@@ -376,27 +382,8 @@ static int parse(jsmntok_t const* tokens, int i, const char* jsonChunk,
out->cascadeSplitPositions[0] = splitsVector[0];
out->cascadeSplitPositions[1] = splitsVector[1];
out->cascadeSplitPositions[2] = splitsVector[2];
// TODO: constantBias
// TODO: normalBias
// TODO: shadowFar
// TODO: shadowNearHint
// TODO: shadowFarHint
} else if (compare(tok, jsonChunk, "stable") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->stable);
} else if (compare(tok, jsonChunk, "lispsm") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->lispsm);
// TODO: polygonOffsetConstant
// TODO: polygonOffsetSlope
} else if (compare(tok, jsonChunk, "screenSpaceContactShadows") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->screenSpaceContactShadows);
// TODO: stepCount
// TODO: maxShadowDistance
} else if (compare(tok, jsonChunk, "vsm") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->vsm);
} else if (compare(tok, jsonChunk, "shadowBulbRadius") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->shadowBulbRadius);
} else if (compare(tok, jsonChunk, "transform") == 0) {
i = parse(tokens, i + 1, jsonChunk, &out->transform.xyzw);
} else {
slog.w << "Invalid shadow options key: '" << STR(tok, jsonChunk) << "'" << io::endl;
i = parse(tokens, i + 1);
@@ -725,20 +712,18 @@ static std::ostream& operator<<(std::ostream& out, const ColorGradingSettings& i
static std::ostream& operator<<(std::ostream& out, const LightManager::ShadowOptions& in) {
const float* splits = in.cascadeSplitPositions;
math::float3 const splitsVector = { splits[0], splits[1], splits[2] };
math::float3 splitsVector = { splits[0], splits[1], splits[2] };
return out << "{\n"
<< "\"vsm\": {\n"
<< "\"elvsm\": " << to_string(in.vsm.elvsm) << ",\n"
<< "\"blurWidth\": " << in.vsm.blurWidth << "\n"
<< "},\n"
<< "\"mapSize\": " << in.mapSize << ",\n"
<< "\"shadowCascades\": " << int(in.shadowCascades) << ",\n"
<< "\"cascadeSplitPositions\": " << (splitsVector) << "\n"
<< "\"stable\": " << to_string(in.stable) << ",\n"
<< "\"lispsm\": " << to_string(in.lispsm) << ",\n"
<< "\"screenSpaceContactShadows\": " << to_string(in.screenSpaceContactShadows) << ",\n"
<< "\"shadowBulbRadius\": " << in.shadowBulbRadius << ",\n"
<< "\"transform\": " << in.transform.xyzw << ",\n"
<< "\"shadowCascades\": " << int(in.shadowCascades) << ",\n"
<< "\"cascadeSplitPositions\": " << (splitsVector) << "\n"
<< "}";
}

View File

@@ -853,14 +853,6 @@ void ViewerGui::updateUserInterface() {
ImGui::SliderFloat("Halo falloff", &light.sunlightHaloFalloff, 4.0f, 1024.0f);
ImGui::SliderFloat("Sun radius", &light.sunlightAngularRadius, 0.1f, 10.0f);
ImGuiExt::DirectionWidget("Sun direction", light.sunlightDirection.v);
float3 shadowDirection = light.shadowOptions.transform * light.sunlightDirection;
ImGuiExt::DirectionWidget("Shadow direction", shadowDirection.v);
light.shadowOptions.transform = normalize(quatf{
cross(light.sunlightDirection, shadowDirection),
sqrt(length2(light.sunlightDirection) * length2(shadowDirection))
+ dot(light.sunlightDirection, shadowDirection)
});
}
if (ImGui::CollapsingHeader("All lights")) {
ImGui::Checkbox("Enable shadows", &light.enableShadows);

View File

@@ -1,4 +1,4 @@
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 3.0)
if(POLICY CMP0077)
cmake_policy(SET CMP0077 NEW) # Enables override of options from parent CMakeLists.txt

View File

@@ -12,7 +12,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 2.8.12)
if (POLICY CMP0048)
cmake_policy(SET CMP0048 NEW)
endif()

View File

@@ -28,7 +28,7 @@
# The SPIR-V headers from the SPIR-V Registry
# https://www.khronos.org/registry/spir-v/
#
cmake_minimum_required(VERSION 3.19)
cmake_minimum_required(VERSION 3.0)
project(SPIRV-Headers VERSION 1.5.5)
# There are two ways to use this project.

View File

@@ -21,44 +21,72 @@ $ cmgen [options] <uv[N]>
## Options
--help, -h
Print this message
--license
Print copyright and license information
--quiet, -q
Quiet mode. Suppress all non-error output
--type=[cubemap|equirect|octahedron|ktx], -t [cubemap|equirect|octahedron|ktx]
Specify output type (default: cubemap)
--format=[exr|hdr|psd|rgbm|rgb32f|png|dds|ktx], -f [format]
Specify output file format. ktx implies -type=ktx.
KTX files are always KTX1 files, not KTX2.
They are encoded with 3-channel RGB_10_11_11_REV data
--compression=COMPRESSION, -c COMPRESSION
Format specific compression:
KTX: ignored
PNG: Ignored
PNG RGBM: Ignored
Radiance: Ignored
Photoshop: 16 (default), 32
OpenEXR: RAW, RLE, ZIPS, ZIP, PIZ (default)
DDS: 8, 16 (default), 32
--size=power-of-two, -s power-of-two
Size of the output cubemaps (base level), 256 by default
Also applies to DFG LUT
--deploy=dir, -x dir
Generate everything needed for deployment into <dir>
--extract=dir
Extract faces of the cubemap into <dir>
--extract-blur=roughness
Blurs the cubemap before saving the faces using the roughness blur
--clamp
Clamp environment before processing
--no-mirror
Skip mirroring of generated cubemaps (for assets with mirroring already backed in)
--ibl-samples=numSamples
Number of samples to use for IBL integrations (default 1024)
--ibl-ld=dir
Roughness pre-filter into <dir>
--sh-shader
Generate irradiance SH for shader code
- --license
Print copyright and license information
- --quiet, -q
Quiet mode. Suppress all non-error output
- --type=[cubemap|equirect|octahedron|ktx], -t [cubemap|equirect|octahedron|ktx]
Specify output type (default: cubemap)
- --format=[exr|hdr|psd|rgbm|rgb32f|png|dds|ktx], -f [exr|hdr|psd|rgbm|rgb32f|png|dds|ktx]
Specify output file format. ktx implies -type=ktx.
KTX files are always encoded with 3-channel RGB_10_11_11_REV data
- --compression=COMPRESSION, -c COMPRESSION
Format specific compression:
KTX:
astc_[fast|thorough]_[ldr|hdr]_WxH, where WxH is a valid block size
s3tc_rgba_dxt5
etc_FORMAT_METRIC_EFFORT
FORMAT is rgb8_alpha, srgb8_alpha, rgba8, or srgb8_alpha8
METRIC is rgba, rgbx, rec709, numeric, or normalxyz
EFFORT is an integer between 0 and 100
PNG: Ignored
PNG RGBM: Ignored
Radiance: Ignored
Photoshop: 16 (default), 32
OpenEXR: RAW, RLE, ZIPS, ZIP, PIZ (default)
DDS: 8, 16 (default), 32
- --size=power-of-two, -s power-of-two
Size of the output cubemaps (base level), 256 by default
Also aplies to DFG LUT
- --deploy=dir, -x dir
Generate everything needed for deployment into <dir>
- --extract=dir
Extract faces of the cubemap into <dir>
- --extract-blur=roughness
Blurs the cubemap before saving the faces using the roughness blur
- --clamp
Clamp environment before processing
- --no-mirror
Skip mirroring of generated cubemaps (for assets with mirroring already backed in)
- --ibl-samples=numSamples
Number of samples to use for IBL integrations (default 1024)
- --ibl-ld=dir
Roughness pre-filter into <dir>
- --sh-shader
Generate irradiance SH for shader code
Private use only:
- --ibl-dfg=filename.[exr|hdr|psd|png|rgbm|rgb32f|dds|h|hpp|c|cpp|inc|txt]
Compute the IBL DFG LUT
- --ibl-dfg-multiscatter
If --ibl-dfg is set, computes the DFG for multi-scattering GGX
- --ibl-dfg-cloth
If --ibl-dfg is set, adds a 3rd channel to the DFG for cloth shading
- --ibl-is-mipmap=dir
Generate mipmap for pre-filtered importance sampling
- --ibl-irradiance=dir
Diffuse irradiance into <dir>
- --ibl-no-prefilter
Use importance sampling instead of prefiltered importance sampling
- --ibl-min-lod-size
Minimum LOD size [default: 16]
- --sh=bands
SH decomposition of input cubemap
- --sh-output=filename.[exr|hdr|psd|rgbm|rgb32f|png|dds|txt]
SH output format. The filename extension determines the output format
- --sh-irradiance, -i
Irradiance SH coefficients
- --sh-window=cutoff|no|auto (default), -w cutoff|no|auto (default)
SH windowing to reduce ringing
- --debug, -d
Generate extra data for debugging

View File

@@ -23,26 +23,27 @@ non-compressed variants for each texture, since not all platforms support the sa
formats. First copy over the PNG files from the [monkey folder], then do:
```bash
# Create mipmaps for base color
mipgen albedo.png albedo.ktx2
mipgen --compression=uastc albedo.png albedo.ktx2
# Create mipmaps for base color and two compressed variants.
mipgen albedo.png albedo.ktx
mipgen --compression=astc_fast_ldr_4x4 albedo.png albedo_astc.ktx
mipgen --compression=s3tc_rgb_dxt1 albedo.png albedo_s3tc_srgb.ktx
# Create mipmaps for the normal map and a compressed variant.
mipgen --strip-alpha --kernel=NORMALS --linear normal.png normal.ktx
mipgen --strip-alpha --kernel=NORMALS --linear --compression=uastc_normals \
normal.png normal.ktx2
mipgen --strip-alpha --kernel=NORMALS --linear --compression=etc_rgb8_normalxyz_40 \
normal.png normal_etc.ktx
# Create mipmaps for the single-component roughness map and a compressed variant.
mipgen --grayscale roughness.png roughness.ktx
mipgen --grayscale --compression=uastc roughness.png roughness.ktx2
mipgen --grayscale --compression=etc_r11_numeric_40 roughness.png roughness_etc.ktx
# Create mipmaps for the single-component metallic map and a compressed variant.
mipgen --grayscale metallic.png metallic.ktx
mipgen --grayscale --compression=uastc metallic.png metallic.ktx2
mipgen --grayscale --compression=etc_r11_numeric_40 metallic.png metallic_etc.ktx
# Create mipmaps for the single-component occlusion map and a compressed variant.
mipgen --grayscale ao.png ao.ktx
mipgen --grayscale --compression=uastc ao.png ao.ktx2
mipgen --grayscale --compression=etc_r11_numeric_40 ao.png ao_etc.ktx
```
For more information on mipgen's arguments and supported formats, do `mipgen --help`.
@@ -236,11 +237,11 @@ was created in the app constructor.
```js {fragment="fetch larger assets"}
Filament.fetch([sky_large_url, albedo_url, roughness_url, metallic_url, normal_url, ao_url], () => {
const albedo = this.engine.createTextureFromKtx2(albedo_url, {srgb: true});
const roughness = this.engine.createTextureFromKtx2(roughness_url);
const metallic = this.engine.createTextureFromKtx2(metallic_url);
const normal = this.engine.createTextureFromKtx2(normal_url);
const ao = this.engine.createTextureFromKtx2(ao_url);
const albedo = this.engine.createTextureFromKtx1(albedo_url, {srgb: true});
const roughness = this.engine.createTextureFromKtx1(roughness_url);
const metallic = this.engine.createTextureFromKtx1(metallic_url);
const normal = this.engine.createTextureFromKtx1(normal_url);
const ao = this.engine.createTextureFromKtx1(ao_url);
const sampler = new Filament.TextureSampler(
Filament.MinFilter.LINEAR_MIPMAP_LINEAR,

View File

@@ -330,9 +330,7 @@ value_object<LightManager::ShadowOptions>("LightManager$ShadowOptions")
.field("polygonOffsetSlope", &LightManager::ShadowOptions::polygonOffsetSlope)
.field("screenSpaceContactShadows", &LightManager::ShadowOptions::screenSpaceContactShadows)
.field("stepCount", &LightManager::ShadowOptions::stepCount)
.field("maxShadowDistance", &LightManager::ShadowOptions::maxShadowDistance)
.field("shadowBulbRadius", &LightManager::ShadowOptions::shadowBulbRadius)
.field("transform", &LightManager::ShadowOptions::transform);
.field("maxShadowDistance", &LightManager::ShadowOptions::maxShadowDistance);
// In JavaScript, a flat contiguous representation is best for matrices (see gl-matrix) so we
// need to define a small wrapper here.
@@ -1339,11 +1337,11 @@ class_<MaterialInstance>("MaterialInstance")
(MaterialInstance* self, std::string name, filament::math::float4 value), {
self->setParameter(name.c_str(), value); }), allow_raw_pointers())
.function("setMat3Parameter", EMBIND_LAMBDA(void,
(MaterialInstance* self, std::string name, flatmat3 value), {
self->setParameter(name.c_str(), value.m); }), allow_raw_pointers())
(MaterialInstance* self, std::string name, filament::math::mat3f value), {
self->setParameter(name.c_str(), value); }), allow_raw_pointers())
.function("setMat4Parameter", EMBIND_LAMBDA(void,
(MaterialInstance* self, std::string name, flatmat4 value), {
self->setParameter(name.c_str(), value.m); }), allow_raw_pointers())
(MaterialInstance* self, std::string name, filament::math::mat4f value), {
self->setParameter(name.c_str(), value); }), allow_raw_pointers())
.function("setTextureParameter", EMBIND_LAMBDA(void,
(MaterialInstance* self, std::string name, Texture* value, TextureSampler sampler), {
self->setParameter(name.c_str(), value, sampler); }), allow_raw_pointers())

View File

@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.42.2",
"version": "1.42.0",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",