diff --git a/libs/iblprefilter/src/IBLPrefilterContext.cpp b/libs/iblprefilter/src/IBLPrefilterContext.cpp index b7c16afcb5..8acfc1aa88 100644 --- a/libs/iblprefilter/src/IBLPrefilterContext.cpp +++ b/libs/iblprefilter/src/IBLPrefilterContext.cpp @@ -50,16 +50,18 @@ #include "generated/resources/iblprefilter_materials.h" +namespace { + using namespace filament::math; using namespace filament; -constexpr static float4 sFullScreenTriangleVertices[3] = { - { -1.0f, -1.0f, 1.0f, 1.0f }, - { 3.0f, -1.0f, 1.0f, 1.0f }, - { -1.0f, 3.0f, 1.0f, 1.0f } +constexpr float4 sFullScreenTriangleVertices[3] = { + { -1.0f, -1.0f, 1.0f, 1.0f }, + { 3.0f, -1.0f, 1.0f, 1.0f }, + { -1.0f, 3.0f, 1.0f, 1.0f } }; -constexpr static const uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 }; +constexpr uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 }; static float lodToPerceptualRoughness(float lod) noexcept { // Inverse perceptualRoughness-to-LOD mapping: @@ -75,10 +77,22 @@ static float lodToPerceptualRoughness(float lod) noexcept { } template -static inline constexpr T log4(T x) { +constexpr T log4(T x) { return std::log2(x) * T(0.5); } +static void cleanupMaterialInstance(MaterialInstance const* mi, Engine& engine, RenderableManager& rcm, + RenderableManager::Instance const& ci) { + // mi is already nullptr, there is no need to clean up again. + if (mi == nullptr) + return; + + rcm.clearMaterialInstanceAt(ci, 0); + engine.destroy(mi); +} + +} // anonymous + IBLPrefilterContext::IBLPrefilterContext(Engine& engine) : mEngine(engine) { @@ -256,7 +270,6 @@ Texture* IBLPrefilterContext::EquirectangularToCubemap::operator()( RenderableManager& rcm = engine.getRenderableManager(); auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); - rcm.setMaterialInstanceAt(ci, 0, mi); TextureSampler environmentSampler; environmentSampler.setMagFilter(SamplerMagFilter::LINEAR); @@ -278,8 +291,17 @@ Texture* IBLPrefilterContext::EquirectangularToCubemap::operator()( mi->setParameter("mirror", mConfig.mirror ? -1.0f : 1.0f); for (size_t i = 0; i < 2; i++) { - mi->setParameter("side", i == 0 ? 1.0f : -1.0f); - mi->commit(engine); + // This is a workaround for internal bug b/419664914 to duplicate same material for each draw. + // TODO: properly address the bug and remove this workaround. +#if defined(__EMSCRIPTEN__) + MaterialInstance *const tempMi = MaterialInstance::duplicate(mi); +#else + MaterialInstance *const tempMi = mi; +#endif + rcm.setMaterialInstanceAt(ci, 0, tempMi); + + tempMi->setParameter("side", i == 0 ? 1.0f : -1.0f); + tempMi->commit(engine); builder.face(RenderTarget::AttachmentPoint::COLOR0, faces[i][0]) .face(RenderTarget::AttachmentPoint::COLOR1, faces[i][1]) @@ -289,6 +311,10 @@ Texture* IBLPrefilterContext::EquirectangularToCubemap::operator()( view->setRenderTarget(rt); renderer->renderStandaloneView(view); engine.destroy(rt); + +#if defined(__EMSCRIPTEN__) + cleanupMaterialInstance(tempMi, engine, rcm, ci); +#endif } rcm.clearMaterialInstanceAt(ci, 0); @@ -344,10 +370,8 @@ IBLPrefilterContext::IrradianceFilter::IrradianceFilter(IBLPrefilterContext& con renderer->renderStandaloneView(view); - rcm.clearMaterialInstanceAt(ci, 0); - + cleanupMaterialInstance(mi, engine, rcm, ci); engine.destroy(rt); - engine.destroy(mi); } UTILS_NOINLINE @@ -416,7 +440,6 @@ Texture* IBLPrefilterContext::IrradianceFilter::operator()(Options options, RenderableManager& rcm = engine.getRenderableManager(); auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); - rcm.setMaterialInstanceAt(ci, 0, mi); const uint32_t sampleCount = mSampleCount; const float linear = options.hdrLinear; @@ -448,8 +471,17 @@ Texture* IBLPrefilterContext::IrradianceFilter::operator()(Options options, view->setViewport({ 0, 0, dim, dim }); for (size_t i = 0; i < 2; i++) { - mi->setParameter("side", i == 0 ? 1.0f : -1.0f); - mi->commit(engine); + // This is a workaround for internal bug b/419664914 to duplicate same material for each draw. + // TODO: properly address the bug and remove this workaround. +#if defined(__EMSCRIPTEN__) + MaterialInstance *const tempMi = MaterialInstance::duplicate(mi); +#else + MaterialInstance *const tempMi = mi; +#endif + rcm.setMaterialInstanceAt(ci, 0, tempMi); + + tempMi->setParameter("side", i == 0 ? 1.0f : -1.0f); + tempMi->commit(engine); builder.face(RenderTarget::AttachmentPoint::COLOR0, faces[i][0]) .face(RenderTarget::AttachmentPoint::COLOR1, faces[i][1]) @@ -459,10 +491,13 @@ Texture* IBLPrefilterContext::IrradianceFilter::operator()(Options options, view->setRenderTarget(rt); renderer->renderStandaloneView(view); engine.destroy(rt); + +#if defined(__EMSCRIPTEN__) + cleanupMaterialInstance(tempMi, engine, rcm, ci); +#endif } rcm.clearMaterialInstanceAt(ci, 0); - engine.destroy(mi); return outIrradianceTexture; @@ -554,10 +589,8 @@ IBLPrefilterContext::SpecularFilter::SpecularFilter(IBLPrefilterContext& context renderer->renderStandaloneView(view); - rcm.clearMaterialInstanceAt(ci, 0); - + cleanupMaterialInstance(mi, engine, rcm, ci); engine.destroy(rt); - engine.destroy(mi); } UTILS_NOINLINE @@ -655,7 +688,6 @@ Texture* IBLPrefilterContext::SpecularFilter::operator()( RenderableManager& rcm = engine.getRenderableManager(); auto const ci = rcm.getInstance(mContext.mFullScreenQuadEntity); - rcm.setMaterialInstanceAt(ci, 0, mi); const uint32_t sampleCount = mSampleCount; const float linear = options.hdrLinear; @@ -703,8 +735,17 @@ Texture* IBLPrefilterContext::SpecularFilter::operator()( view->setViewport({ 0, 0, dim, dim }); for (size_t i = 0; i < 2; i++) { - mi->setParameter("side", i == 0 ? 1.0f : -1.0f); - mi->commit(engine); + // This is a workaround for internal bug b/419664914 to duplicate same material for each draw. + // TODO: properly address the bug and remove this workaround. +#if defined(__EMSCRIPTEN__) + MaterialInstance *const tempMi = MaterialInstance::duplicate(mi); +#else + MaterialInstance *const tempMi = mi; +#endif + rcm.setMaterialInstanceAt(ci, 0, tempMi); + + tempMi->setParameter("side", i == 0 ? 1.0f : -1.0f); + tempMi->commit(engine); builder.face(RenderTarget::AttachmentPoint::COLOR0, faces[i][0]) .face(RenderTarget::AttachmentPoint::COLOR1, faces[i][1]) @@ -714,13 +755,16 @@ Texture* IBLPrefilterContext::SpecularFilter::operator()( view->setRenderTarget(rt); renderer->renderStandaloneView(view); engine.destroy(rt); + +#if defined(__EMSCRIPTEN__) + cleanupMaterialInstance(tempMi, engine, rcm, ci); +#endif } dim >>= 1; } rcm.clearMaterialInstanceAt(ci, 0); - engine.destroy(mi); return outReflectionsTexture;