Merge branch 'google:main' into main

This commit is contained in:
Serge Metral
2025-01-29 20:49:02 -08:00
committed by GitHub
25 changed files with 559 additions and 131 deletions
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.56.6'
implementation 'com.google.android.filament:filament-android:1.56.7'
}
```
@@ -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.6'
pod 'Filament', '~> 1.56.7'
```
## Documentation
+3
View File
@@ -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
@@ -1271,7 +1271,28 @@ public class Engine {
* {@link android.view.SurfaceHolder.Callback#surfaceDestroyed surfaceDestroyed}.</p>
*/
public void flushAndWait() {
nFlushAndWait(getNativeObject());
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);
@@ -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 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.56.6
VERSION_NAME=1.56.7
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+7
View File
@@ -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
+19
View File
@@ -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.
+2 -2
View File
@@ -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.
*/
+4
View File
@@ -338,6 +338,10 @@ void Engine::flushAndWait() {
downcast(this)->flushAndWait();
}
bool Engine::flushAndWait(uint64_t timeout) {
return downcast(this)->flushAndWait(timeout);
}
void Engine::flush() {
downcast(this)->flush();
}
+174 -48
View File
@@ -311,6 +311,7 @@ static const PostProcessManager::StaticMaterialInfo sMaterialList[] = {
{ "fsr_easu_mobile", MATERIAL(FSR_EASU_MOBILE) },
{ "fsr_easu_mobileF", MATERIAL(FSR_EASU_MOBILEF) },
{ "fsr_rcas", MATERIAL(FSR_RCAS) },
{ "sgsr1", MATERIAL(SGSR1) },
{ "debugShadowCascades", MATERIAL(DEBUGSHADOWCASCADES) },
{ "resolveDepth", MATERIAL(RESOLVEDEPTH) },
{ "shadowmap", MATERIAL(SHADOWMAP) },
@@ -2328,7 +2329,7 @@ void PostProcessManager::colorGradingPrepareSubpass(DriverApi& driver,
mi->setParameter("vignette", vignetteParameters);
mi->setParameter("vignetteColor", vignetteOptions.color);
mi->setParameter("dithering", colorGradingConfig.dithering);
mi->setParameter("fxaa", colorGradingConfig.fxaa);
mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
mi->setParameter("temporalNoise", temporalNoise);
mi->commit(driver);
@@ -2544,7 +2545,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
mi->setParameter("bloom", bloomParameters);
mi->setParameter("vignette", vignetteParameters);
mi->setParameter("vignetteColor", vignetteOptions.color);
mi->setParameter("fxaa", colorGradingConfig.fxaa);
mi->setParameter("outputLuminance", colorGradingConfig.outputLuminance);
mi->setParameter("temporalNoise", temporalNoise);
mi->setParameter("viewport", float4{
float(vp.left) / input.width,
@@ -2562,7 +2563,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::colorGrading(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> PostProcessManager::fxaa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> const input, filament::Viewport const& vp,
TextureFormat const outFormat, bool const translucent) noexcept {
TextureFormat const outFormat, bool const preserveAlphaChannel) noexcept {
struct PostProcessFXAA {
FrameGraphId<FrameGraphTexture> input;
@@ -2587,7 +2588,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::fxaa(FrameGraph& fg,
auto const& material = getPostProcessMaterial("fxaa");
PostProcessVariant const variant = translucent ?
PostProcessVariant const variant = preserveAlphaChannel ?
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
FMaterialInstance* const mi =
@@ -2920,20 +2921,171 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::rcas(
}
FrameGraphId<FrameGraphTexture> PostProcessManager::upscale(FrameGraph& fg, bool translucent,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
SamplerMagFilter filter) noexcept {
bool sourceHasLuminance, DynamicResolutionOptions dsrOptions,
FrameGraphId<FrameGraphTexture> const input, filament::Viewport const& vp,
FrameGraphTexture::Descriptor const& outDesc, SamplerMagFilter filter) noexcept {
// The code below cannot handle sub-resources
assert_invariant(fg.getSubResourceDescriptor(input).layer == 0);
assert_invariant(fg.getSubResourceDescriptor(input).level == 0);
const bool lowQualityFallback = translucent && dsrOptions.quality != QualityLevel::LOW;
const bool lowQualityFallback = translucent;
if (lowQualityFallback) {
// FidelityFX-FSR doesn't support the alpha channel currently
// FidelityFX-FSR nor SGSR support the source alpha channel currently
dsrOptions.quality = QualityLevel::LOW;
}
if (dsrOptions.quality == QualityLevel::LOW) {
return upscaleBilinear(fg, translucent, dsrOptions, input, vp, outDesc, filter);
}
if (dsrOptions.quality == QualityLevel::MEDIUM) {
return upscaleSGSR1(fg, sourceHasLuminance, dsrOptions, input, vp, outDesc);
}
return upscaleFSR1(fg, dsrOptions, input, vp, outDesc);
}
FrameGraphId<FrameGraphTexture> PostProcessManager::upscaleBilinear(FrameGraph& fg, bool translucent,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc,
SamplerMagFilter filter) noexcept {
struct QuadBlitData {
FrameGraphId<FrameGraphTexture> input;
FrameGraphId<FrameGraphTexture> output;
};
auto const& ppQuadBlit = fg.addPass<QuadBlitData>(dsrOptions.enabled ? "upscaling" : "compositing",
[&](FrameGraph::Builder& builder, auto& data) {
data.input = builder.sample(input);
data.output = builder.createTexture("upscaled output", outDesc);
data.output = builder.write(data.output, FrameGraphTexture::Usage::COLOR_ATTACHMENT);
builder.declareRenderPass(builder.getName(data.output), {
.attachments = { .color = { data.output } },
.clearFlags = TargetBufferFlags::DEPTH });
},
[this, vp, translucent, filter](FrameGraphResources const& resources,
auto const& data, DriverApi& driver) {
bindPostProcessDescriptorSet(driver);
// helper to enable blending
auto enableTranslucentBlending = [](PipelineState& pipeline) {
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA;
pipeline.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA;
};
auto color = resources.getTexture(data.input);
auto const& inputDesc = resources.getDescriptor(data.input);
// --------------------------------------------------------------------------------
// set uniforms
auto& material = getPostProcessMaterial("blitLow");
FMaterialInstance* const mi =
PostProcessMaterial::getMaterialInstance(mEngine, material);
mi->setParameter("color", color, {
.filterMag = filter
});
mi->setParameter("levelOfDetail", 0.0f);
mi->setParameter("viewport", float4{
float(vp.left) / inputDesc.width,
float(vp.bottom) / inputDesc.height,
float(vp.width) / inputDesc.width,
float(vp.height) / inputDesc.height
});
mi->commit(driver);
mi->use(driver);
auto out = resources.getRenderPassInfo();
auto pipeline = getPipelineState(material.getMaterial(mEngine));
if (translucent) {
enableTranslucentBlending(pipeline);
}
renderFullScreenQuad(out, pipeline, driver);
});
auto output = ppQuadBlit->output;
// if we had to take the low quality fallback, we still do the "sharpen pass"
if (dsrOptions.sharpness > 0.0f) {
output = rcas(fg, dsrOptions.sharpness, output, outDesc, translucent);
}
// we rely on automatic culling of unused render passes
return output;
}
FrameGraphId<FrameGraphTexture> PostProcessManager::upscaleSGSR1(FrameGraph& fg, bool sourceHasLuminance,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
filament::Viewport const&, FrameGraphTexture::Descriptor const& outDesc) noexcept {
struct QuadBlitData {
FrameGraphId<FrameGraphTexture> input;
FrameGraphId<FrameGraphTexture> output;
};
auto const& ppQuadBlit = fg.addPass<QuadBlitData>(dsrOptions.enabled ? "upscaling" : "compositing",
[&](FrameGraph::Builder& builder, auto& data) {
data.input = builder.sample(input);
data.output = builder.createTexture("upscaled output", outDesc);
data.output = builder.write(data.output, FrameGraphTexture::Usage::COLOR_ATTACHMENT);
builder.declareRenderPass(builder.getName(data.output), {
.attachments = { .color = { data.output } },
.clearFlags = TargetBufferFlags::DEPTH });
},
[this, sourceHasLuminance](FrameGraphResources const& resources,
auto const& data, DriverApi& driver) {
bindPostProcessDescriptorSet(driver);
auto color = resources.getTexture(data.input);
auto const& inputDesc = resources.getDescriptor(data.input);
// --------------------------------------------------------------------------------
// set uniforms
auto const& material = getPostProcessMaterial("sgsr1");
PostProcessVariant const variant = sourceHasLuminance ?
PostProcessVariant::TRANSLUCENT : PostProcessVariant::OPAQUE;
FMaterialInstance* const mi =
PostProcessMaterial::getMaterialInstance(mEngine, material, variant);
mi->setParameter("color", color, {
// The SGSR documentation doesn't clarify if LINEAR or NEAREST should be used. The
// sample code uses NEAREST, but that doesn't seem right, since it would mean the
// LERP mode would not be a LERP, and the non-edges would be sampled as NEAREST.
.filterMag = SamplerMagFilter::LINEAR
});
mi->setParameter("viewport", float4{
1.0f / inputDesc.width,
1.0f / inputDesc.height,
float(inputDesc.width),
float(inputDesc.height),
});
mi->commit(driver);
mi->use(driver);
auto out = resources.getRenderPassInfo();
commitAndRenderFullScreenQuad(driver, out, mi, variant);
});
auto output = ppQuadBlit->output;
// we rely on automatic culling of unused render passes
return output;
}
FrameGraphId<FrameGraphTexture> PostProcessManager::upscaleFSR1(FrameGraph& fg,
DynamicResolutionOptions dsrOptions, FrameGraphId<FrameGraphTexture> const input,
filament::Viewport const& vp, FrameGraphTexture::Descriptor const& outDesc) noexcept {
const bool twoPassesEASU = mWorkaroundSplitEasu &&
(dsrOptions.quality == QualityLevel::MEDIUM
|| dsrOptions.quality == QualityLevel::HIGH);
@@ -2964,7 +3116,7 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscale(FrameGraph& fg, bool
.attachments = { .color = { data.output }, .depth = { data.depth }},
.clearFlags = TargetBufferFlags::DEPTH });
},
[this, twoPassesEASU, dsrOptions, vp, translucent, filter](FrameGraphResources const& resources,
[this, twoPassesEASU, dsrOptions, vp](FrameGraphResources const& resources,
auto const& data, DriverApi& driver) {
bindPostProcessDescriptorSet(driver);
@@ -2989,14 +3141,6 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscale(FrameGraph& fg, bool
float2{ inputDesc.width, inputDesc.height });
};
// helper to enable blending
auto enableTranslucentBlending = [](PipelineState& pipeline) {
pipeline.rasterState.blendFunctionSrcRGB = BlendFunction::ONE;
pipeline.rasterState.blendFunctionSrcAlpha = BlendFunction::ONE;
pipeline.rasterState.blendFunctionDstRGB = BlendFunction::ONE_MINUS_SRC_ALPHA;
pipeline.rasterState.blendFunctionDstAlpha = BlendFunction::ONE_MINUS_SRC_ALPHA;
};
auto color = resources.getTexture(data.input);
auto const& inputDesc = resources.getDescriptor(data.input);
auto const& outputDesc = resources.getDescriptor(data.output);
@@ -3023,29 +3167,21 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscale(FrameGraph& fg, bool
}
{ // just a scope to not leak local variables
const std::string_view blitterNames[4] = {
"blitLow", "fsr_easu_mobile", "fsr_easu_mobile", "fsr_easu" };
unsigned const index = std::min(3u, unsigned(dsrOptions.quality));
const std::string_view blitterNames[2] = { "fsr_easu_mobile", "fsr_easu" };
unsigned const index = std::min(1u, unsigned(dsrOptions.quality) - 2);
easuMaterial = &getPostProcessMaterial(blitterNames[index]);
FMaterialInstance* const mi =
PostProcessMaterial::getMaterialInstance(mEngine, *easuMaterial);
if (dsrOptions.quality != QualityLevel::LOW) {
setEasuUniforms(mi, inputDesc, outputDesc);
}
setEasuUniforms(mi, inputDesc, outputDesc);
mi->setParameter("color", color, {
.filterMag = (dsrOptions.quality == QualityLevel::LOW) ?
filter : SamplerMagFilter::LINEAR
.filterMag = SamplerMagFilter::LINEAR
});
if (blitterNames[index] != "blitLow") {
mi->setParameter("resolution",
float4{outputDesc.width, outputDesc.height, 1.0f / outputDesc.width,
1.0f / outputDesc.height});
}
if (blitterNames[index] == "blitLow") {
mi->setParameter("levelOfDetail", 0.0f);
}
mi->setParameter("resolution",
float4{outputDesc.width, outputDesc.height, 1.0f / outputDesc.width,
1.0f / outputDesc.height});
mi->setParameter("viewport", float4{
float(vp.left) / inputDesc.width,
@@ -3066,29 +3202,19 @@ FrameGraphId<FrameGraphTexture> PostProcessManager::upscale(FrameGraph& fg, bool
auto pipeline0 = getPipelineState(splitEasuMaterial->getMaterial(mEngine));
auto pipeline1 = getPipelineState(easuMaterial->getMaterial(mEngine));
pipeline1.rasterState.depthFunc = SamplerCompareFunc::NE;
if (translucent) {
enableTranslucentBlending(pipeline0);
enableTranslucentBlending(pipeline1);
}
driver.beginRenderPass(out.target, out.params);
driver.draw(pipeline0, mFullScreenQuadRph, 0, 3, 1);
driver.draw(pipeline1, mFullScreenQuadRph, 0, 3, 1);
driver.endRenderPass();
} else {
auto pipeline = getPipelineState(easuMaterial->getMaterial(mEngine));
if (translucent) {
enableTranslucentBlending(pipeline);
}
renderFullScreenQuad(out, pipeline, driver);
}
});
auto output = ppQuadBlit->output;
// if we had to take the low quality fallback, we still do the "sharpen pass"
if (dsrOptions.sharpness > 0.0f &&
(dsrOptions.quality != QualityLevel::LOW || lowQualityFallback)) {
output = rcas(fg, dsrOptions.sharpness, output, outDesc, translucent);
if (dsrOptions.sharpness > 0.0f) {
output = rcas(fg, dsrOptions.sharpness, output, outDesc, false);
}
// we rely on automatic culling of unused render passes
+16 -3
View File
@@ -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{};
};
@@ -227,7 +227,7 @@ public:
// Anti-aliasing
FrameGraphId<FrameGraphTexture> fxaa(FrameGraph& fg,
FrameGraphId<FrameGraphTexture> input, Viewport const& vp,
backend::TextureFormat outFormat, bool translucent) noexcept;
backend::TextureFormat outFormat, bool preserveAlphaChannel) noexcept;
// Temporal Anti-aliasing
void TaaJitterCamera(
@@ -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,
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,
+1 -1
View File
@@ -230,7 +230,7 @@ private:
// Inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
// Because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
// Each ShadowMap is currently 88 bytes (total of ~12KB for 128 shadow maps)
using ShadowMapStorage = std::aligned_storage<sizeof(ShadowMap)>::type;
using ShadowMapStorage = std::aligned_storage_t<sizeof(ShadowMap), alignof(ShadowMap)>;
using ShadowMapCacheContainer = std::array<ShadowMapStorage, CONFIG_MAX_SHADOWMAPS>;
ShadowMapCacheContainer mShadowMapCache;
uint32_t mDirectionalShadowMapCount = 0;
+10 -32
View File
@@ -665,50 +665,28 @@ void FEngine::flush() {
}
void FEngine::flushAndWait() {
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused())
<< "Cannot call flushAndWait() when rendering thread is paused!";
flushAndWait(FENCE_WAIT_FOR_EVER);
}
#if defined(__ANDROID__)
bool FEngine::flushAndWait(uint64_t timeout) {
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused())
<< "Cannot call Engine::flushAndWait() when rendering thread is paused!";
// first make sure we've not terminated filament
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isExitRequested())
<< "calling Engine::flushAndWait() after Engine::shutdown()!";
#endif
<< "Calling Engine::flushAndWait() after Engine::shutdown()!";
// enqueue finish command -- this will stall in the driver until the GPU is done
getDriverApi().finish();
#if defined(__ANDROID__) && !defined(NDEBUG)
// then create a fence that will trigger when we're past the finish() above
size_t tryCount = 8;
FFence* fence = FEngine::createFence();
UTILS_NOUNROLL
do {
FenceStatus status = fence->wait(FFence::Mode::FLUSH,250000000u);
// if the fence didn't trigger after 250ms, check that the command queue thread is still
// running (otherwise indicating a precondition violation).
if (UTILS_UNLIKELY(status == FenceStatus::TIMEOUT_EXPIRED)) {
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isExitRequested())
<< "called Engine::shutdown() WHILE in Engine::flushAndWait()!";
tryCount--;
FILAMENT_CHECK_POSTCONDITION(tryCount) << "flushAndWait() failed inexplicably after 2s";
// if the thread is still running, maybe we just need to give it more time
continue;
}
break;
} while (true);
FFence* fence = createFence();
FenceStatus const status = fence->wait(FFence::Mode::FLUSH, timeout);
destroy(fence);
#else
FFence::waitAndDestroy(createFence(), FFence::Mode::FLUSH);
#endif
// finally, execute callbacks that might have been scheduled
getDriver().purge();
return status == FenceStatus::CONDITION_SATISFIED;
}
// -----------------------------------------------------------------------------------------------
+2 -1
View File
@@ -394,6 +394,7 @@ public:
void setPaused(bool paused);
void flushAndWait();
bool flushAndWait(uint64_t timeout);
// flush the current buffer
void flush();
@@ -716,7 +717,7 @@ public:
&features.backend.opengl.assert_native_window_is_valid, true },
{ "engine.shadows.use_shadow_atlas",
"Uses an array of atlases to store shadow maps.",
&features.engine.shadows.use_shadow_atlas, true },
&features.engine.shadows.use_shadow_atlas, false },
{ "features.engine.debug.assert_material_instance_in_use",
"Assert when a MaterialInstance is destroyed while it is in use by RenderableManager.",
&features.engine.debug.assert_material_instance_in_use, false }
+13 -10
View File
@@ -681,6 +681,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
hasColorGrading &&
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled;
// whether we're scaled at all
bool scaled = any(notEqual(scale, float2(1.0f)));
// asSubpass is disabled with TAA (although it's supported) because performance was degraded
// on qualcomm hardware -- we might need a backend dependent toggle at some point
const PostProcessManager::ColorGradingConfig colorGradingConfig{
@@ -695,18 +698,15 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
hasColorGrading &&
!engine.debug.renderer.disable_subpasses,
.translucent = needsAlphaChannel,
.fxaa = hasFXAA,
.outputLuminance = hasFXAA || scaled, // ignored by translucent variants (false)
.dithering = hasDithering,
.ldrFormat = (hasColorGrading && hasFXAA) ?
.ldrFormat = (hasColorGrading && (hasFXAA || scaled)) ?
TextureFormat::RGBA8 : getLdrFormat(needsAlphaChannel)
};
// by construction (msaaSampleCount) both asSubpass and customResolve can't be true
assert_invariant(colorGradingConfig.asSubpass + colorGradingConfig.customResolve < 2);
// whether we're scaled at all
bool scaled = any(notEqual(scale, float2(1.0f)));
// vp is the user defined viewport within the View
filament::Viewport const& vp = view.getViewport();
@@ -1351,8 +1351,9 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
}
if (hasFXAA) {
input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat,
!hasColorGrading || needsAlphaChannel);
bool const preserveAlphaChannel = needsAlphaChannel ||
(hasColorGrading && colorGradingConfig.outputLuminance);
input = ppm.fxaa(fg, input, xvp, colorGradingConfig.ldrFormat, preserveAlphaChannel);
// the padded buffer is resolved now
xvp.left = xvp.bottom = 0;
svp = xvp;
@@ -1360,9 +1361,11 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
if (scaled) {
mightNeedFinalBlit = false;
auto viewport = DEBUG_DYNAMIC_SCALING ? xvp : vp;
input = ppm.upscale(fg, needsAlphaChannel, dsrOptions, input, xvp, {
.width = viewport.width, .height = viewport.height,
.format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR);
bool const sourceHasLuminance = !needsAlphaChannel &&
(hasColorGrading && colorGradingConfig.outputLuminance);
input = ppm.upscale(fg, needsAlphaChannel, sourceHasLuminance, dsrOptions, input, xvp, {
.width = viewport.width, .height = viewport.height,
.format = colorGradingConfig.ldrFormat }, SamplerMagFilter::LINEAR);
xvp.left = xvp.bottom = 0;
svp = xvp;
}
@@ -41,7 +41,7 @@ material {
},
{
type : int,
name : fxaa
name : outputLuminance
},
{
type : float,
@@ -166,10 +166,10 @@ void postProcess(inout PostProcessInputs postProcess) {
color = dither(color, materialParams.temporalNoise);
}
// kill alpha computations when opaque / fxaa luminance
// kill alpha computations when opaque / luminance
#if POST_PROCESS_OPAQUE
color.a = 1.0;
if (materialParams.fxaa > 0) {
if (materialParams.outputLuminance > 0) {
color.a = luminance(color.rgb);
}
#endif
+29
View File
@@ -0,0 +1,29 @@
Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
1. Redistributions of source code must retain the above copyright notice,
this list of conditions and the following disclaimer.
2. Redistributions in binary form must reproduce the above copyright notice,
this list of conditions and the following disclaimer in the documentation
and/or other materials provided with the distribution.
3. Neither the name of the copyright holder nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE
LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
POSSIBILITY OF SUCH DAMAGE.
SPDX-License-Identifier: BSD-3-Clause
+80
View File
@@ -0,0 +1,80 @@
material {
name : sgsr1,
parameters : [
{
type : sampler2d,
name : color,
precision: medium
},
{
type : float4,
name : viewport,
precision: high
}
],
variables : [
vertex
],
depthWrite : false,
depthCulling : false,
domain: postprocess
}
vertex {
void postProcessVertex(inout PostProcessVertexInputs postProcess) {
postProcess.normalizedUV = uvToRenderTargetUV(postProcess.normalizedUV);
postProcess.vertex.xy = postProcess.normalizedUV;
}
}
fragment {
void dummy(){}
precision mediump float;
precision highp int;
#if defined(FILAMENT_HAS_FEATURE_TEXTURE_GATHER)
#define gather textureGather
#else
vec4 gather(const mediump sampler2D color, highp vec2 p, const int comp) {
highp ivec2 i = ivec2(p * materialParams.viewport.zw - 0.5);
vec4 d;
d[0] = texelFetchOffset(color, i, 0, ivec2(0, 1))[comp];
d[1] = texelFetchOffset(color, i, 0, ivec2(1, 1))[comp];
d[2] = texelFetchOffset(color, i, 0, ivec2(1, 0))[comp];
d[3] = texelFetchOffset(color, i, 0, ivec2(0, 0))[comp];
return d;
}
#endif
/*
* Operation modes:
* RGBA -> 1
* RGBY -> 3
* LERP -> 4
*/
// SGSR cannot support translucency;
// So we hijack the POST_PROCESS variant to select whether a luminance channel is present
#if POST_PROCESS_OPAQUE
# define OperationMode 1
#else
# define OperationMode 3
#endif
/*
* If set, will use edge direction to improve visual quality
* Expect a minimal cost increase
*/
#define UseEdgeDirection
#define EdgeThreshold 8.0 / 255.0
#define EdgeSharpness 2.0
#include "sgsr1_shader_mobile.fs"
void postProcess(inout PostProcessInputs postProcess) {
highp vec4 vp[1] = vec4[1]( materialParams.viewport );
postProcess.color = sgsr(materialParams_color, variable_vertex.xy, vp);
}
}
@@ -0,0 +1,132 @@
//============================================================================================================
//
//
// Copyright (c) 2023, Qualcomm Innovation Center, Inc. All rights reserved.
// SPDX-License-Identifier: BSD-3-Clause
//
//============================================================================================================
////////////////////////
// USER CONFIGURATION //
////////////////////////
float fastLanczos2(float x)
{
float wA = x-4.0;
float wB = x*wA-wA;
wA *= wA;
return wB*wA;
}
#if defined(UseEdgeDirection)
vec2 weightY(float dx, float dy, float c, vec3 data)
#else
vec2 weightY(float dx, float dy, float c, float data)
#endif
{
#if defined(UseEdgeDirection)
float std = data.x;
vec2 dir = data.yz;
float edgeDis = ((dx*dir.y)+(dy*dir.x));
float x = (((dx*dx)+(dy*dy))+((edgeDis*edgeDis)*((clamp(((c*c)*std),0.0,1.0)*0.7)+-1.0)));
#else
float std = data;
float x = ((dx*dx)+(dy*dy))* 0.55 + clamp(abs(c)*std, 0.0, 1.0);
#endif
float w = fastLanczos2(x);
return vec2(w, w * c);
}
vec2 edgeDirection(vec4 left, vec4 right)
{
vec2 dir;
float RxLz = (right.x + (-left.z));
float RwLy = (right.w + (-left.y));
vec2 delta;
delta.x = (RxLz + RwLy);
delta.y = (RxLz + (-RwLy));
float lengthInv = inversesqrt((delta.x * delta.x+ 3.075740e-05) + (delta.y * delta.y));
dir.x = (delta.x * lengthInv);
dir.y = (delta.y * lengthInv);
return dir;
}
vec4 sgsr(mediump sampler2D ps0, highp vec2 in_TEXCOORD0, highp vec4 ViewportInfo[1])
{
vec4 color;
if(OperationMode == 1)
color.xyz = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyz;
else
color.xyzw = textureLod(ps0,in_TEXCOORD0.xy,0.0).xyzw;
#if OperationMode != 4
if (OperationMode!=4)
{
highp vec2 imgCoord = ((in_TEXCOORD0.xy*ViewportInfo[0].zw)+vec2(-0.5,0.5));
highp vec2 imgCoordPixel = floor(imgCoord);
highp vec2 coord = (imgCoordPixel*ViewportInfo[0].xy);
vec2 pl = (imgCoord+(-imgCoordPixel));
vec4 left = gather(ps0,coord, OperationMode);
float edgeVote = abs(left.z - left.y) + abs(color[OperationMode] - left.y) + abs(color[OperationMode] - left.z) ;
if(edgeVote > EdgeThreshold)
{
coord.x += ViewportInfo[0].x;
vec4 right = gather(ps0,coord + vec2(ViewportInfo[0].x, 0.0), OperationMode);
vec4 upDown;
upDown.xy = gather(ps0,coord + vec2(0.0, -ViewportInfo[0].y),OperationMode).wz;
upDown.zw = gather(ps0,coord+ vec2(0.0, ViewportInfo[0].y), OperationMode).yx;
float mean = (left.y+left.z+right.x+right.w)*0.25;
left = left - vec4(mean);
right = right - vec4(mean);
upDown = upDown - vec4(mean);
color.w = color[OperationMode] - mean;
float sum = (((((abs(left.x)+abs(left.y))+abs(left.z))+abs(left.w)) +
(((abs(right.x)+abs(right.y))+abs(right.z))+abs(right.w))) +
(((abs(upDown.x)+abs(upDown.y))+abs(upDown.z))+abs(upDown.w)));
#if defined(UseEdgeDirection)
float sumMean = 1.014185e+01 / sum;
float std = (sumMean * sumMean);
vec3 data = vec3(std, edgeDirection(left, right));
#else
// taken from sgsr sample
float data = 2.181818 / sum;
#endif
vec2 aWY = weightY(pl.x, pl.y+1.0, upDown.x,data);
aWY += weightY(pl.x-1.0, pl.y+1.0, upDown.y,data);
aWY += weightY(pl.x-1.0, pl.y-2.0, upDown.z,data);
aWY += weightY(pl.x, pl.y-2.0, upDown.w,data);
aWY += weightY(pl.x+1.0, pl.y-1.0, left.x,data);
aWY += weightY(pl.x, pl.y-1.0, left.y,data);
aWY += weightY(pl.x, pl.y, left.z,data);
aWY += weightY(pl.x+1.0, pl.y, left.w,data);
aWY += weightY(pl.x-1.0, pl.y-1.0, right.x,data);
aWY += weightY(pl.x-2.0, pl.y-1.0, right.y,data);
aWY += weightY(pl.x-2.0, pl.y, right.z,data);
aWY += weightY(pl.x-1.0, pl.y, right.w,data);
float finalY = aWY.y/aWY.x;
float maxY = max(max(left.y,left.z),max(right.x,right.w));
float minY = min(min(left.y,left.z),min(right.x,right.w));
float deltaY = clamp(EdgeSharpness*finalY, minY, maxY) -color.w;
//smooth high contrast input
deltaY = clamp(deltaY, -23.0 / 255.0, 23.0 / 255.0);
color.x = clamp(color.x+deltaY, 0.0, 1.0);
color.y = clamp(color.y+deltaY, 0.0, 1.0);
color.z = clamp(color.z+deltaY, 0.0, 1.0);
}
}
#endif
color.w = 1.0; //assume alpha channel is not used
return color;
}
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.56.6"
spec.version = "1.56.7"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC."
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
spec.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.6/filament-v1.56.6-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.7/filament-v1.56.7-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = {
+1 -1
View File
@@ -33,7 +33,7 @@ public:
SRGB
};
// Returns linear floating-point data, or a non-valid image if an error occured.
// Returns linear floating-point data, or a non-valid image if an error occurred.
static LinearImage decode(std::istream& stream, const std::string& sourceName,
ColorSpace sourceSpace = ColorSpace::SRGB);
+27 -15
View File
@@ -25,14 +25,32 @@ namespace filament::matdbg {
#if defined(__linux__) || defined(__APPLE__)
std::string SourceFormatter::format(char const* source) {
std::string const TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp";
char output[1024];
std::string original(source);
FILE* fp;
fp = fopen(TMP_FILENAME.c_str(), "w");
if (!fp) {
return original;
// First check if clang-format is available.
FILE* fp = popen("clang-format -version", "r");
// Need to drain the output
while (fgets(output, 1024, fp) != NULL) {}
int status = pclose(fp);
if (!fp || !WEXITSTATUS(status)) {
std::call_once(mClangWarningFlag, []() {
utils::slog.w << "[matdbg] unable to run clang-format to format shader file. "
<< "Please make sure it's installed." << utils::io::endl;
});
return source;
}
// Write the source to a temp file for formatting
char const* TMP_FILENAME = "/tmp/matdbg-tmp-src.cpp";
fp = fopen(TMP_FILENAME, "w");
if (!fp) {
return source;
}
// Unknown if the input is 0-terminated so we put it in a string first.
std::string original(source);
fputs(original.c_str(), fp);
fflush(fp);
pclose(fp);
@@ -45,22 +63,16 @@ std::string SourceFormatter::format(char const* source) {
"}'";
fp = popen(("clang-format " + CLANG_FORMAT_OPTIONS + "< " + TMP_FILENAME).c_str(), "r");
if (!fp) {
std::call_once(mClangWarningFlag, []() {
utils::slog.w << "[matdbg] unable to run clang-format to format shader file. "
<< "Please make sure it's installed.";
});
return original;
}
char output[1024];
std::stringstream outStream;
while (fgets(output, 1024, fp) != NULL) {
outStream << output;
}
int status = pclose(fp);
status = pclose(fp);
if (WEXITSTATUS(status)) {
utils::slog.w << "[matdbg] clang-format failed with code=" << WEXITSTATUS(status)
<< utils::io::endl;
@@ -69,11 +81,11 @@ std::string SourceFormatter::format(char const* source) {
}
#else
std::string SourceFormatter::format(char const* source) {
std::call_once(mClangWarningFlag, []() {
std::call_once(mClangWarningFlag, []() {
utils::slog.w <<"[matdbg]: source formatting is not available on this platform" <<
utils::io::endl;
});
return "";
return source;
}
#endif
+2 -2
View File
@@ -43,7 +43,7 @@ class UserPanicHandler {
struct CallBack {
Panic::PanicHandlerCallback handler = nullptr;
void* user = nullptr;
void call(Panic const& panic) const noexcept {
void call(Panic const& panic) const {
if (UTILS_UNLIKELY(handler)) {
handler(user, panic);
}
@@ -64,7 +64,7 @@ public:
return data;
}
void call(Panic const& panic) const noexcept {
void call(Panic const& panic) const {
getCallback().call(panic);
}
+1 -1
View File
@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.56.6",
"version": "1.56.7",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",