From fe3790cb9cc46c1ace64514bdcd2e51dc38d7200 Mon Sep 17 00:00:00 2001 From: Philip Rideout Date: Wed, 24 Aug 2022 14:10:56 -0700 Subject: [PATCH] WASM: Set CONFIG_MAX_INSTANCES to a small value + hack the GLSL. Temporary fix until spec constants arrive. Second attempt, fixes #5859. --- RELEASE_NOTES.md | 1 + filament/backend/src/opengl/OpenGLProgram.cpp | 28 +++++++++++++++++++ .../include/private/filament/EngineEnums.h | 10 +++++++ 3 files changed, 39 insertions(+) diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md index 13b7334cc0..5a48331eec 100644 --- a/RELEASE_NOTES.md +++ b/RELEASE_NOTES.md @@ -5,6 +5,7 @@ A new header is inserted each time a *tag* is created. ## main branch +- WebGL: reduce max instance count to work around Chrome issues [⚠️ **Recompile Materials**] - engine: rework material/shader sampler binding code [⚠️ **Recompile Materials**] ## v1.26.0 diff --git a/filament/backend/src/opengl/OpenGLProgram.cpp b/filament/backend/src/opengl/OpenGLProgram.cpp index 9edd4b4bd2..2b87935b98 100644 --- a/filament/backend/src/opengl/OpenGLProgram.cpp +++ b/filament/backend/src/opengl/OpenGLProgram.cpp @@ -131,6 +131,34 @@ void OpenGLProgram::compileShaders(OpenGLContext& context, } } +#ifdef __EMSCRIPTEN__ + // HACK ALERT + // ---------- + // The values below are based on CONFIG_MAX_INSTANCES, which is not accessible here. + // Since matc cannot know if it's building for WebGL, we replace the constant at run + // time. This will go away after we support specialization constants. The name of the + // struct field might be changed by the GLSL optimizer, so we search for any codeline + // that has the pattern: "PerRenderableData(.*)[64]" + const std::string_view type = "PerRenderableData"; + const std::string_view source = "[64]"; + const std::string_view target = "[8] "; + assert_invariant(source.size() == target.size()); + const size_t npos = std::string_view::npos; + for (size_t typePos = shaderView.find(type); typePos != npos;) { + size_t newlinePos = shaderView.find('\n', typePos + type.size()); + std::string_view codeline = shaderView.substr(typePos, newlinePos - typePos); + if (size_t sourcePos = codeline.find(source, type.size()); sourcePos != npos) { + if (temp.empty()) { + temp = shaderView; + } + target.copy(temp.data() + typePos + sourcePos, target.size()); + shaderView = temp; + break; + } + typePos = shaderView.find(type, newlinePos + 1); + } +#endif + // Tragically, OpenGL 4.1 doesn't support unpackHalf2x16 and // MacOS doesn't support GL_ARB_shading_language_packing if constexpr (BACKEND_OPENGL_VERSION == BACKEND_OPENGL_VERSION_GL) { diff --git a/libs/filabridge/include/private/filament/EngineEnums.h b/libs/filabridge/include/private/filament/EngineEnums.h index 9a9ed10a7e..3d9c16430b 100644 --- a/libs/filabridge/include/private/filament/EngineEnums.h +++ b/libs/filabridge/include/private/filament/EngineEnums.h @@ -65,8 +65,18 @@ constexpr size_t CONFIG_MAX_SHADOW_CASCADES = 4; // instances, and shadow casting spotlights. constexpr size_t CONFIG_MINSPEC_UBO_SIZE = 16384; +// HACK ALERT +// ---------- +// If you modify the values below, you will need to update the hack in OpenGLProgram.cpp! // The maximum number of instances that Filament automatically creates as an optimization. +// Use a much smaller number for WebGL as a workaround for the following Chrome issues: +// https://crbug.com/1348017 Compiling GLSL is very slow with struct arrays +// https://crbug.com/1348363 Lighting looks wrong with D3D11 but not OpenGL +#if defined(__EMSCRIPTEN__) +constexpr size_t CONFIG_MAX_INSTANCES = 8; +#else constexpr size_t CONFIG_MAX_INSTANCES = 64; +#endif // The maximum number of bones that can be associated with a single renderable. // We store 32 bytes per bone. Must be a power-of-two, and must fit within CONFIG_MINSPEC_UBO_SIZE.