Compare commits

...

335 Commits

Author SHA1 Message Date
Powei Feng
69fc1f302c vk: testing a robin_map key hash failure
Executable on device with:

./build.sh -p android -q arm64-v8a release test_compiler && adb push out/cmake-android-release-aarch64/filament/test/test_compiler /data/local/tmp/ && adb shell chmod 777 /data/local/tmp/test_compiler && adb shell /data/local/tmp/test_compiler
2024-07-26 12:23:28 +08:00
Mathias Agopian
e7c96cd124 better handle skipped frames and cache eviction
Add Renderer::skipFrame() which should be called when intentionally 
skipping frames, for instance because the screen content hasn't changed,
allowing Filament to performance needed periodic tasks, such as
cache garbage collection and callback dispatches.

We also improve the ResourceAllocator cache eviction policy:
- the cache is aggressively purged when skipping a frame
- we aggressively evict entries older than 3 frames

The default Config is now set to a more agressive setting.
2024-07-25 17:23:04 -07:00
Mathias Agopian
730bc99025 Move the ResourceAllocator from Engine to Renderer
The ResourceAllocator used to be global and owned by the Engine, this
was causing some issues when using several Renderers because each
one could cause the eviction of cache data for another.

We now have a ResourceAllocator per Renderer, which makes more sense
because most resources are allocated by the FrameGraph.

We also introduce a ResourceAllocatorDisposer class, which is used
for checking in and out a texture from the cache, and destroy the
texture when it's checked-out. That objet is still global.
2024-07-25 17:23:04 -07:00
Powei Feng
7441e878bb gltfio: enable escaped unicode for node name (#7989)
Fixes #7846
2024-07-25 09:06:56 +00:00
Grant Commodore
ef4c4a76fc Only sets the layercount if the view has stereo and the stereoscopic type is multiview (#7987)
Co-authored-by: Powei Feng <powei@google.com>
2024-07-25 07:31:51 +00:00
Mathias Agopian
be4f287b07 More improvements to the JobSystem (#7988)
* improve parallel_for a bit

We get about 40% performance increase. The gain comes from not having
to copy the JobData structure each time we create a job, by using a
new emplaceJob() method, we can create the structure directly into
its destination.

* avoid calling wakeAll() when possible

wakeAll() is very expensive and not always needed when a job finishes
because there may not be anyone waiting on that job.

We now maintain a waiter count per job, and use that to determine if
we need to notify or not.

And now that the JobSystem overhead is lower, we can decrease the size
of the jobs, which improves the load balancing.

* mActiveJobs fixes

some comments claimed mActiveJobs needed to be modified before or after
accessing the WorkQueue; this couldn't be correct because there were no
guaranteed global ordering with the workQueue.
2024-07-24 15:34:36 -07:00
Mathias Agopian
d3a35de386 fix a crash with bloom when screen dimension smaller than 16px 2024-07-24 11:49:38 -07:00
Sungun Park
9057c47a56 Release Filament 1.53.2 2024-07-23 01:23:57 +00:00
Mathias Agopian
4a5081388d RenderPass batch size was too small
The batch size was calculated incorrectly, which in theory could lead
to command buffer overflows (albeit unlikely).
2024-07-22 13:53:05 -07:00
Mathias Agopian
a60fe41681 performance improvements to JobSystem
- reduce the number of calls to notify_one() and notify_all().
  notify_one() is not only called when running a new job, and
  notify_all() only when a job finishes.

- don't hold the condition lock while calling notify_*(), as it is not
  strictly needed, and because notify_*() can be very slow, there can
  be a lot of contention on this lock as a result; blocking the whole
  jobsystem thread pool.

- add a new version of run() that takes an opaque thread id that can
  be retrieved from a job's execute function; this is especially
  intended to be used by parallel_for(); it's just a more efficient
  version of run() that avoids a hashmap lookup.


Overall these change yield a significant performance boost:
- running + waiting a job: +200%
- running many jobs: +150%
- running many jobs in parallel: +50%
2024-07-22 11:12:51 -07:00
Mathias Agopian
a8ace2891d improve frame timing info
- we use a circular buffer for the frame history so that 
  we don't have to copy the data when insert a new entry.
  This also allows us to keep a reference to an entry, which
  doesn't get invalidated when an entry is added/removed.

- we now store the gpu frame time in the correct slot (instead of
  always the latest). It didn't matter before because the API wasn't
  public and we only needed some recent frame time.

- a new public API now returns the frame history, which now contains 
  more data; in particular the main and backend thread's begin/end
  frame time.


BUGS=[321110544]
2024-07-18 21:14:44 -07:00
mdagois
669ffc85c0 Minor typo fix and slight optimization (#7978)
Co-authored-by: Powei Feng <powei@google.com>
2024-07-19 03:07:54 +00:00
mdagois
d957dd8082 Fix to barriers in VulkanBuffer (#7979)
Co-authored-by: Powei Feng <powei@google.com>
2024-07-19 10:45:10 +08:00
Ben Doherty
8eda62c957 Update imgui to v1.90.9 (#7977) 2024-07-18 16:38:25 -07:00
Sungun Park
90f079ac2c Add an extra check for renderStandaloneView (#7975)
renderStandaloneView must be called outside of beginFrame() /
endFrame(). This extra check ensures this behavior.
2024-07-18 06:31:02 -07:00
Balaji M
3728f06603 utility::loadCgltfBuffers is done once instead of doing for each primitive (#7969) 2024-07-12 23:22:25 +00:00
Adam Wychowaniec
39cfce641c Fix precondition check when creating static geometry. 2024-07-08 11:53:24 -07:00
Mathias Agopian
3fbf3f7111 fix a couple small bugs when mapping the circular buffer
- in case of failure we were munmap'ing the wrong size for the
  guard page (in practice this never happened)
- the post-condition check was incorrect; it checked for nullptr instead
  of MAP_FAILED. this also never happened in practice.

Also made a couple of small improvements:

- in case the special circular buffer mapping fails, log a message
  as warning instead of debug.

- immediately memset (i.e. populate) the pages for the circular buffer
  since they will all be accessed rather quickly.
2024-07-08 10:48:44 -07:00
Reinar
ef9bbece2a Fix feature level detection for VulkanDriver 2024-07-02 15:09:25 -07:00
Mathias Agopian
eb8fa9ecdf shader compilation could fail on ES 3.0 devices
the failure could happen if the shader didn't have any #extension
strings, which was likely to happen on release builds (e.g. on 
emulator).
2024-07-01 11:25:12 -07:00
Ben Doherty
e1bfe7ca81 Metal: add a more detailed CHECK_POSTCONDITION when creating a texture (#7943) 2024-06-28 13:11:00 -07:00
Ben Doherty
ca4c7ac739 Update cgltf to 1.14 (#7945) 2024-06-28 13:10:41 -07:00
Ben Doherty
9676bc94e8 Fix MetalBumpAllocator (#7951) 2024-06-28 13:09:01 -07:00
Mathias Agopian
f7a5111106 switch to new morphing API
- remove deprecated morphing APIs
- repair gltfio, samples and tests

The new API doesn't allow a MorphTargetBuffer per RenderPrimitive,
instead the MorphTargetBuffer is specified per Renderable.

gltfio separates RenderPrimitives from Renderables, in particular all
RenderPrimitives are created before their Renderable; this was
problematic for this change because all primitives must share
a single MorphTargetBuffer living in the Renderable.

To fix this, we're no longer initializing the morphing paramters
at RenderPrimitive creation, instead we store a reference to the
BufferSlot in the Primtive structure, so that later, when the Renderable
is created we can finally retrieve the BufferSlot and initialize its
morphing paramters, which are not available. The "morphing parameters"
are now expanded to contain the MorphTargetBuffer as before (except now
it's always the same for all the primitives of a Rendrable), as well
as the offset within the buffer and the vertex count.
2024-06-28 12:14:57 -07:00
Sungun Park
56ac7ab902 IBL drag & drop support for desktop gltf_viewer (#7947)
Users now can drag and drop IBL files for desktop gltf_viewer.

It attempts to load gltf files first then tries to load IBL files.
2024-06-27 23:14:13 +00:00
Ben Doherty
44b4de904e Add saveRawVariants flag to matc (#7949) 2024-06-27 14:36:03 -07:00
Tibor Hencz
a2fe9f745c Add ability to disable panning in the OrbitManipulator (#7928) 2024-06-27 00:05:14 +00:00
Benjamin Doherty
659b8b6e03 Release Filament 1.53.1 2024-06-25 11:46:46 -07:00
Ben Doherty
c73f4e64d5 Metal: use a bump allocator for vertex and index uploads (#7926) 2024-06-25 11:45:45 -07:00
Mathias Agopian
fe743523bf fix use-after-free dereference risk
Texture handles were resolved to pointers when updating a SamplerGroup,
as that point the handle was checked for use-after-free. However, the
texture could be destroyed later while still active in the SamplerGroup,
this would result in using the pointer which now contains garbage.

We now keep the handle and resolve the texture when binding samplers
to the program; which will also perform the use-after-free check.
2024-06-24 16:16:12 -07:00
Ryan
2c1044e812 Fix use-after-free of a std::mutex in PresentCallable. (#7934)
If a user is using `setFrameScheduledCallback()`, managing the provided PresentCallable during engine shutdown is tricky -- we'll likely get a final frame scheduled when we flush the engine's work queue, but the PresentCallable will schedule the final CAMetalDrawable to be released on main thread afterwards, even if we call `present(false)` to skip it. If the swap chain is destroyed before that main queue block gets executed, the mutex presenting that drawable will no longer exist, causing a crash.

To make things easier, store the std::mutex in a shared_ptr, so that a PresentCallable can safely outlive the FSwapChain instance that created it and clean itself up afterwards.

Alternatives considered, all of which seem unfortunate:
* Require users to clear out the callback before shutting down the engine, so that any final drawables are immediately discarded instead of using PresentCallable
* Require users to split up the engine teardown across two main queue blocks, ensuring that the PresentCallable cleanup executes before swapchains are destroyed
* Drop the PresentCallable on the ground and leak the memory
2024-06-24 11:00:58 -07:00
Sungun Park
db9183a105 Fix memory leak of asset loading for gltf_viewer (#7933)
When a user drags and drops a gltf file to the gltf_viewer window, it
loads the new asset.

While this happens, the function `checkAsset` tries parsing the gltf
file, but it doesn't free it. Fix this.
2024-06-21 10:37:01 -07:00
toddZ_CG
e4a0bb8fa0 Add support for KHR_materials_Specular (#7564)
Co-authored-by: Todd Zhang <toddzx@amazon.com>
Co-authored-by: Romain Guy <romain.guy@gmail.com>
Co-authored-by: Mathias Agopian <mathias@google.com>
2024-06-21 17:06:17 +00:00
Mathias Agopian
d15c53e530 an easier way to pipe vsync time to beginFrame
BUGS=[343764098]
2024-06-21 09:41:19 -07:00
Mathias Agopian
cc8a3ed96b fix typo that broke glsl compilation on device 2024-06-20 15:48:17 -07:00
Mathias Agopian
213eb6af9e Lit Materials can now specify the quality of SH computations
The number of SH bands used for the indirect light irradiance
computations can be set to 1, 2 or 3 (default) in Material::Builder.

For e.g. in lower-end devices w/ non HDR content, it might be
beneficial to set this value to 2.

BUGS=[341971013]
2024-06-20 10:25:04 -07:00
Mathias Agopian
e04c6d406f inject the missing packing/unpacking function in ESSL 3.0
FIXES=[343784713]
2024-06-18 13:37:20 -07:00
Mathias Agopian
cab799f531 matdbg would cause a crash if program was invalid 2024-06-18 00:27:24 -07:00
Benjamin Doherty
e95edef9d7 Release Filament 1.53.0 2024-06-17 17:26:47 -07:00
Grant Commodore
9cfef925bb Updates vulkan swapchain synchronization (#7915)
Abstracts the synchronization of the vulkan swapchain so that it is easier to override during the acquisition and presentation of images. A new structure (ImageSyncData) is created to hold swapchain synchronization data.

FIXES=[338303279]
2024-06-17 22:29:28 +00:00
Hanno J. Gödecke
3900fc6c37 feat: support getParameter from MaterialInstance (#7686) 2024-06-17 11:31:17 -07:00
Powei Feng
b8ec1658f3 vk: single output stream debug logging (#7925)
In some debug instances, it's nice to have the logs all go to one
output stream so that logs are ordered. We add a FVK_DEBUG flag
for this use case.
2024-06-14 22:31:45 +00:00
Grant Commodore
371bd1f01f Checks/enable if the multiview extension is supported (#7923)
Checks if the vulkan driver supports multiview. The result is stored in the vulkan context.

BUG=[332425392]
FIXES=[346860138]
2024-06-13 10:20:24 -07:00
Benjamin Doherty
df34f92f8f Release Filament 1.52.3 2024-06-11 16:42:10 -07:00
Powei Feng
43331d04e5 gltfio: [extended] Fix generated color default (#7917)
Fixes #7905
2024-06-11 12:21:14 -07:00
Powei Feng
9917d4b7d9 Null out pending edits once latched (#7916)
Otherwise, we'd keep swapping between the edited version and the
original, causing matdbg to not work.
2024-06-10 21:32:49 +00:00
Mathias Agopian
682150ceec add debug option to disable sub-passes 2024-06-10 13:18:59 -07:00
Powei Feng
af2ecf201f vk: workaround extension name length = 0 (adreno) (#7910) 2024-06-07 10:29:38 -07:00
Serge Metral
020668733a Adding the begin frame message for later xtrace post processing. (#7903)
BUG=343930963
2024-06-05 21:58:31 +00:00
Powei Feng
4c6d653d60 samples: Enable backend selection for hellopbr (#7898) 2024-06-05 19:15:45 +00:00
Mathias Agopian
d1022527ac export PanicStream since it's a public API 2024-06-05 11:00:06 -07:00
Romain Guy
68c7a6c7b6 Update Android dependencies to latest (#7902) 2024-06-04 22:33:02 +00:00
Romain Guy
f077fff012 Update actions/checkout to a supported version of Node.js (#7904) 2024-06-04 15:03:43 -07:00
Mathias Agopian
bea02427ed keep the normal transforms in float during skinning
FIXES=[342459864]
2024-06-04 13:37:47 -07:00
Mathias Agopian
b5d7de06bc Engine::unprotected() drops the command queue back to unprotected mode
FIXES=[344021154]
2024-06-04 11:46:00 -07:00
Mathias Agopian
749b063af3 PerformanceHintManager needs a valid Java thread
FIXES=[343965368, 343550453]
2024-06-04 10:22:21 -07:00
Ryan
7aefa99e06 Acquire a mutex before releasing CAMetalDrawables on main thread. (#7888)
PresentDrawable was moved to main thread by default in google#7535 and stopped
most crashes when a drawable is released. But there still appears to be crashes
if a drawable is released on main thread at the same time that -nextDrawable is
called from the Filament render thread. (It's likely that the drawable pool in
CAMetalLayer is completely non-thread-safe.)

So, add a mutex to the swapchain and always acquire it before creating or
releasing a CAMetalDrawable.

Users can opt out of this behavior by passing
-DFILAMENT_LOCK_METAL_DRAWABLE_POOL=0.
2024-06-03 19:37:46 +00:00
Sungun Park
3c46788e06 Release Filament 1.52.2 2024-06-03 18:10:27 +00:00
Ben Doherty
51d749f451 Deprecate use of hat-trie (#7889) 2024-05-30 15:45:33 -07:00
Powei Feng
343be60eb3 vk: flush commands in terminate() (#7890)
Fixes #7866
2024-05-30 17:29:19 +00:00
Powei Feng
783c35e85b Release Filament 1.52.1 2024-05-29 16:19:30 -07:00
Powei Feng
278e706d20 gltfio: fix invalid gltf crash (#7885)
Invalid gltf but valid json should not crash but
return null for asset.

Fixes #7868
2024-05-27 21:33:29 +00:00
Ben Doherty
cf91e42847 Switch ASSERT macros to new stream API (#7881) 2024-05-24 20:46:34 +00:00
Benjamin Doherty
3ec2249b2a Revert "Metal: implement more accurate buffer tracking (#7839)"
This reverts commit 54a800a25d.
2024-05-24 13:11:22 -07:00
Mathias Agopian
a52ae3a7ef fix a few typos in the new panic apis 2024-05-24 12:00:22 -07:00
Ryan
b4b702b977 Throw an exception when failing to build a Metal render pipeline state. (#7878)
Currently, if this fails we log the error message to stderr (which
doesn't get captured by most crash reporting systems) and then crash in
a postcondition assert. By including the error message in an exception
reason and throwing an ObjC exception, we get better discoverability of
error causes.

(Building a render pipeline state from shaders is usually when a shader
actually gets JITted from LLVM IR to GPU-specific code, so if we
accidentally used a feature that's not available on the local GPU, we'll
find out about it here.)
2024-05-23 11:14:29 -07:00
Mathias Agopian
75158847f7 A new stream-based Panic API
going forward, instead of using the printf style syntax for panics
we use the c++ stream syntax

The new macros that replace ASSERT_*CONDITON are

FILAMENT_CHECK_PRECONDITON
FILAMENT_CHECK_POSTCONDITION
FILAMENT_CHECK_ARITIHMETIC

Example usage:

FILAMENT_CHECK_PRECONDITON(condition) << "Message";

It's also now possible to define FILAMENT_PANIC_USES_ABSL=1 to redirect
all these calls to Abseil's CHECK() macro.
2024-05-22 12:31:18 -07:00
Minjae Kim
ddf1d422bc add explicit headers for supporting libstdc++ 2024-05-22 10:40:26 -07:00
Benjamin Doherty
bbb2e1a454 Bump MATERIAL_VERSION to 52 2024-05-21 12:50:35 -07:00
Benjamin Doherty
c7202c575a Release Filament 1.52.0 2024-05-21 12:47:58 -07:00
Powei Feng
8cfdab0c28 Fix stereo variant defines in common_getters (#7879)
This caused a breakage in shader validation at runtime. Repro:
  - Remove ./out
  - ./build.sh release gltf_viewer
  - run gltf_viewer
2024-05-21 17:34:05 +00:00
Benjamin Doherty
180c326bb7 Include sstream.h in distribution headers 2024-05-21 10:11:44 -07:00
Mathias Agopian
7d80975c3c add getReasonLiteral() on TPanic
currently it only returns the format string.
2024-05-17 16:53:31 -07:00
Sungun Park
813e6f805b Update combine_multiview_images flag (#7867)
Set combine_multiview_images to false by default as it's the desirable
setting for most Android devices.

Set the flag to true for GUI by default.

Put the `Combine Multiview Images` checkbox under the `Stereo mode` box
for an easier access.
2024-05-17 19:42:23 +00:00
Powei Feng
450644ccd5 Add vk/gl conditions for enabling clip distance (#7861) 2024-05-17 17:39:32 +00:00
Mathias Agopian
979421c019 fix/remove wrong asserts 2024-05-17 10:01:50 -07:00
Mathias Agopian
18ccf0cd8d change the morphing API so it uses only one buffer per renderable
The current API allowed to have a buffer for each primitive in a
renderable. We instead restrict the API so that there is a single 
MorphTargetBuffer for the whole renderable, shared by all primitives.
The buffer can be shared thanks to the "offset" parameter on
setMorphTargetBufferAt().

Also
- fix FMorphTargetBuffer::updateDataAt()
- add support for the "offset" parameter of setMorphTargetBufferAt()
2024-05-16 14:11:07 -07:00
Ben Doherty
5b80407f6c Implement push constants for Metal (#7858) 2024-05-16 13:20:12 -07:00
Powei Feng
a9f3971989 Refactor stereo build flags and configs (#7857)
- Add option to build.sh to build for paritcular stereo
   techniques (default to NONE). Only applies to samples.
 - Consoldiate viewer checkbox for debugging stereo rendering
 - Add DriverConfig flag for stereoscopic type so that it can
   be used to determine availability of the feature and
   (to be completed) enable corresponding GPU features.

Co-authored-by: Mathias Agopian <mathias@google.com>
2024-05-16 17:37:27 +00:00
Powei Feng
ab12984912 Add Mesa software rasterizer BUILD.md instructions (#7860) 2024-05-16 10:03:50 -07:00
Ben Doherty
1d4f1fe71f Metal, fix callbacks being called only once (#7856) 2024-05-15 10:50:10 -07:00
Mathias Agopian
c93aa4c90d minor libutils improvements 2024-05-14 13:22:38 -07:00
Mathias Agopian
499939ed3c backend: bindPipeline now takes const& 2024-05-14 13:21:38 -07:00
Mathias Agopian
6be97ee01d backend: zero-cost ES2 draw()
we use a different hook for the draw() call when on an ES2 context,
this eliminates completely the overhead of supporting ES2 for the draw
call. draw calls are expected to be the most common calls.
2024-05-14 13:21:24 -07:00
Powei Feng
7267696cbf vk: fix dynamic scissor validation error (#7853) 2024-05-14 19:08:50 +00:00
Powei Feng
85eb724a90 Reduce explicit swiftshader paths (#7848)
- Use custom ICD path to enable Swiftshader instead of
   specifying direct path to the lib.
   - Remove unused `swiftshader` directory in `build`
   - Remove swiftshader options in `build.sh` and cmakefiles
   - Change BUILD.md
 - Correctly handle XCB-only swapchain surface in VulkanPlatform
   for swiftshader.
 - Refactor `VulkanPlatform::ExtensionSet` so that `utils::CString`
   is used instead of string_view, so that we don't get into
   tricky lifetime issues with `const char*`
2024-05-14 17:40:54 +00:00
Mathias Agopian
6dd6db89d5 align android libraries to 16 KiB 2024-05-13 23:14:32 -07:00
Mathias Agopian
c76f67c139 fix typo checking FILAMENT_ENABLE_MATDBG
this macro must be checked with #if not #ifdef
2024-05-13 23:14:13 -07:00
Sungun Park
6fc16bdcda Release Filament 1.51.8 2024-05-13 20:53:36 +00:00
Mathias Agopian
4f021583f1 backend tests were broken by a change in TargetBufferInfo
- a field was added, which broke the layout of the structure. We fix it
by adding constructors which will handle the old and new way of
initializing this structure.

- one of the test needed a hash update

- OpenGLContext wrongly asserted when trying to unbind texture 0
2024-05-10 14:39:22 -07:00
Powei Feng
ef15a29c0c vk: fix missing lib for backend test 2024-05-10 13:00:00 -07:00
Benjamin Doherty
a0472d3c9f Rename Metal log message 2024-05-10 11:25:34 -07:00
Ben Doherty
54a800a25d Metal: implement more accurate buffer tracking (#7839) 2024-05-10 11:14:41 -07:00
Powei Feng
7f8fbe586c gl: push constant small clean-up (#7841) 2024-05-10 10:23:32 -07:00
Powei Feng
6f2c45c76d Add push constants (#7817)
- Push constants is a small set of bytes that can be recorded
   directly on the command buffer.
 - Implemented it for the vulkan/gl backend.
2024-05-09 16:14:03 -07:00
Ryan
ad60008b6a ryanmyers: Improve logging for Metallib function lookup failures (#7836)
If a .metallib was compiled with a target iOS version that's newer than
the current device, loading the .metallib may succeed, but finding main0
(or any other function in it) will fail. Currently, this causes a crash
due to an assert. Logging the error and returning
MetalFunctionBundle::error() makes the crash slightly easier to
diagnose.

(Note that in practice, this will probably be a useless "Compiler
encountered an internal error" message -- the GPU backend is crashing,
and the Metal stub library sees XPC_ERROR_CONNECTION_INTERRUPTED. It
retries up to 3 times (crashing each time) and then gives up.)
2024-05-09 10:49:41 -07:00
Mathias Agopian
d87f9b621b add a simple tranformmanager unit test
this was to test issue #7827
2024-05-09 09:00:41 -07:00
Ben Doherty
1b38cda0d5 Add preferredShaderLanguage Java bindings (#7835) 2024-05-08 14:42:40 -07:00
Ben Doherty
a1dea7b1fa Metal: log slow buffer allocation times (#7834) 2024-05-08 14:39:53 -07:00
Mathias Agopian
744708b5ca remove the single <sstream> usage we have
the STL's stream headers can bring in a lot of code, we don't use them.
2024-05-07 16:23:31 -07:00
Benjamin Doherty
e901837317 Log excess buffer allocations for Metal 2024-05-07 15:39:48 -07:00
Powei Feng
17f71c9b81 Release Filament 1.51.7 2024-05-07 14:35:42 -07:00
Mathias Agopian
b056c126fe Add an Engine debug setting to force GLES 2.0 (#7829)
* Add an Engine debug setting to force GLES 2.0

This setting is only meaningful on GLES backends, it's otherwise
ignored. When set to true, the backend will try to force a ES2 context
if supported. If not supported by the platform,
the backend will pretend it's a ES2 context.

This setting is currently only taken into account by the EGL platform.

* Update filament/backend/include/backend/Platform.h

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2024-05-07 09:53:31 -07:00
Sungun Park
6ac36d1aab Fix a shader error (#7828)
gl_ViewID_OVR is of uint type. Explicitly convert it to int to fix the
error.
2024-05-06 21:03:04 +00:00
Ben Doherty
a1752b363c Add preferredShaderLanguage option to Engine::Config (#7816) 2024-05-06 12:12:38 -07:00
Levente Koncz
e855f4aafb Fix mixed up FBO targets in status check code inside OpenGLDriver::blit() 2024-05-06 09:17:15 -07:00
Ben Doherty
1c693e24cf Metal: track types of buffers (#7796) 2024-05-03 14:32:01 -07:00
Ben Doherty
af92a1f21b Add getEyeIndex vertex API (#7822) 2024-05-03 14:22:24 -07:00
Powei Feng
10ff1ee3e4 Update filament to 1.51.6 for public pages (#7821)
Updated both /viewer and /remote
2024-05-03 20:49:53 +00:00
Vladyslav Popovych
5449f46350 Remove bitcode from iOS builds (#7802)
Co-authored-by: Vladyslav <vlad@arthouse.ar>
2024-05-03 12:25:00 -07:00
Mathias Agopian
2967888d26 repair instanced stereo in debug builds (#7819)
- it was broken by a wrong assertion
- also auto instancing + stereo instancing was
  always broken, but this makes it work
2024-05-03 09:36:09 -07:00
Powei Feng
afe81d6889 vk: Use offset when uploading buffer data (#7818) 2024-05-02 11:17:32 -07:00
Mathias Agopian
95134883d6 add the -a option to skinning and morphing samples (#7815)
* add the `-a` option to skinning and morphing samples

* Update samples/skinningtest.cpp

Co-authored-by: Ben Doherty <bendoherty@google.com>

* Update samples/helloskinningbuffer_morebones.cpp

Co-authored-by: Ben Doherty <bendoherty@google.com>

* Update samples/hellomorphing.cpp

Co-authored-by: Ben Doherty <bendoherty@google.com>

* Update samples/helloskinningbuffer.cpp

Co-authored-by: Ben Doherty <bendoherty@google.com>

---------

Co-authored-by: Ben Doherty <bendoherty@google.com>
2024-05-01 15:24:01 -07:00
Mathias Agopian
600c122761 fix ES2 support
- make sure we can build with ES2 headers only
- make sure to not use ES3 features when in ES2 mode
  (post processing was accidentally creating an R8 texture, 
  which is not supported)
2024-05-01 13:29:58 -07:00
Mathias Agopian
1cf5335964 Skybox doesn't need a commit() method
The material parameter changes are committed automatically in
Engine::prepare(), no need to do it explicitly for SkyBox.
2024-05-01 10:11:39 -07:00
Eliza Velasquez
4ac4ffd8d6 filagui: Split uiBlit material into two
Unfortunately, the external uniform was not optimized out as expected. The only
option is to split it into its own independent material.
2024-04-30 14:14:23 -07:00
Eliza Velasquez
6c40721695 Fix broken ImGui on web
I was unfortunately naive about the way that Filament handled external textures
on non-GLES platforms. This fix restricts the changes to Android (which is the
only place this change is required in the first place). Long story short, the
change broke WebGL. Desktop seems to be unaffected.
2024-04-30 14:14:23 -07:00
Benjamin Doherty
56fa078376 Release Filament 1.51.6 2024-04-29 16:49:28 -07:00
Ben Doherty
883507a26f Remove spirv-opt size optimizations for MSL (#7495) 2024-04-29 16:47:05 -07:00
Powei Feng
d697d42c4a vk: finer-grain barrier at renderpass end (#7808)
- At the end of a renderpass we use a more fine-grained barrier
   for each of the attachments in the render target
 - Make sure that buffer update are barrier'd from previous reads
 - Remove previous Mali workaround barriers.  Seems to be fine
   without them on pixels + Mali.
2024-04-29 11:32:04 -07:00
Ben Doherty
e7feee7d5b Switch setFrameScheduledCallback to use utils::Invocable (#7792) 2024-04-29 10:18:28 -07:00
Powei Feng
4c75e6e9a2 gltfio: enable extended implementation (#7776)
This change will enable proper flat-shading and MikkTSpace.

Caveats:
 - Only for disk-local glTF resources
 - iOS, Web, Android do not work as of now

Fixes #6358, #7444
2024-04-27 00:28:08 +00:00
Mathias Agopian
8ab8525359 fix a missing ubo upload in bloom set-up 2024-04-26 16:49:39 -07:00
Powei Feng
65c794881f vk: various clean up (#7805)
- use namespace for ImageUtility
 - use FILAMENT_BACKEND_DEBUG_FLAG
 - remove unused usage flag type
 - add const list of VKFormat for iteration
 - fix sampler name debug
2024-04-26 22:26:16 +00:00
Powei Feng
08d6d57ad0 vk: simplify VulkanAttachment (#7801) 2024-04-26 21:48:15 +00:00
Mathias Agopian
254cf15f0e a couple of significant improvements to instancing
The main goal of this change is to avoid having to select the 
"per renderable" UBO at execution time. Instead we want the
PrimitiveInfo structure to already know which UBO will be used.
Concretely, this means that this determination must be done when
the RenderPass is created.

When automatic instancing is used, the RenderPass creates a temporary
UBO to store the instance info. This UBO's life-time is dictated by both
the life-time of the RenderPass and the Executors that where created
from it. For this reason we introduce SharedHandle<> to correctly 
account for the owner's lifetime. This fixes a potential bugs where
that handle could have been destroyed and used later; in practice this
bug didn't happen however.

A couple other changes:

- RenderPass has a bunch of fields that were actually temporary, so we
removed those.

- The canonical "per-renderable" UBO was owned by View but accessed 
through Scene. This was confusing, it's now accessed through View.
2024-04-26 14:15:00 -07:00
Mathias Agopian
22d99bac3d simplify generateCommands()
It's been a while that generateCommands() can only generate either 
the depth or color pass but not both at once; we can simplify/de-dup
the code by leveraging that.
2024-04-26 14:15:00 -07:00
Mathias Agopian
420f06bef3 implement 16 and 8 bits clz, ctz and popcount
This is needed for utils::bitset8 and bitset16.
2024-04-26 14:13:48 -07:00
Powei Feng
bf8bcef35c Add option to define a backend debug flag (#7798)
To allow easy enabling/disabling of debug options like vulkan
validation, android systrace, debug printing, and others, we
introduce an option to add a preprocessor flag so that a
backend can (optionally) use it to manage debug options.
2024-04-25 23:42:55 +00:00
Eliza Velasquez
bfab9f9c32 engine: Add isPaused() 2024-04-25 16:11:14 -07:00
Powei Feng
c8335fade7 vk: Fix unsupported depth blitting (#7789)
* vk: Fix unsupported depth blitting

On certain hardware (pixel 4 for example), blitting of depth texture
is not supported as an "optimalTilingFeature".  In these cases, we'd
would need to do a shader-based blit. We
 - Add the shader blit in PostProcessingManager
 - Add a driver API to check for support for blitting depthStencil
   attachments.
 - Fix some debugging ifdefs in vk backend.

The validation fixed is:
`[ VUID-vkCmdBlitImage-dstImage-02000 ] Object 0: handle = 0xb400007c300701d0, type = VK_OBJECT_TYPE_COMMAND_BUFFER; Object 1: handle = 0xf2039b0000000771, type = VK_OBJECT_TYPE_IMAGE; | MessageID = 0x86bc2a78 | In vkCmdBlitImage, VkFormatFeatureFlags (0x1c601) does not support required feature VK_FORMAT_FEATURE_2_BLIT_DST_BIT for format 126 used by VkImage 0xf2039b0000000771[] with tiling VK_IMAGE_TILING_OPTIMAL. The Vulkan spec states: The format features of dstImage must contain VK_FORMAT_FEATURE_BLIT_DST_BIT`
2024-04-24 18:27:57 +00:00
Mathias Agopian
99eac62b4e give proper move semantics to Handle<> 2024-04-23 15:38:29 -07:00
Mathias Agopian
6146d071ba StructureOfArray::push_back(&&) didn't do a move 2024-04-23 15:38:29 -07:00
Mathias Agopian
d26c972f5b add missing includes in RenerableManager 2024-04-23 15:38:29 -07:00
Mathias Agopian
93dc218b83 fix PerShadowMapUniform includes 2024-04-23 15:38:29 -07:00
Ben Doherty
b56379dc0f Add license information to matedit (#7790) 2024-04-23 14:05:53 -06:00
Mathias Agopian
e4442a5eb2 optimize the inner rendering loop
This largely undoes a change I did recently where PrimitiveInfo has
a FRenderPrimitive* to save some space and keep a command at 64 bytes.

This wasn't a good idea because the inner rendering loop shouldn't 
to any dereference in the common case.

This change reorganises PrimitiveInfo such that it stores all the data
necessary to render a primitive in the common case. The less common
cases are when hybrid instancing, morphing or skinning are used; in 
those cases, a dereference into the renderable SOA is needed.

PrimitiveInfo currently has 16 bytes free, which we keep for futur use.
2024-04-23 10:22:33 -07:00
Ben Doherty
490e8cf0d0 Add option to preserve text shaders (#7786) 2024-04-23 10:38:23 -06:00
Mathias Agopian
0d25f79421 gl: simplify how we track bound textures
In opengl it's possible to bind several textures to the same texture
unit as long as they're a different target. Until now we were tracking
that state. In practice it's not very useful to bind several textures
to the same unit (it is a little bit when updating texture data, but
not when rendering). With the coming change to a descriptor set API, it
is better to have a 1-to-1 mapping between bound textures and texture
units.

So with this change, only a single texture can be bound to a texture 
unit. If another texture in bound to the same unit with a different
target, we first unbind the texture from the current target.

There is less state to track, and it allows us to 
"unbind a texture unit" (whereas before we'd have to iterate through 
all the possible targets for that unit and unbind all of them).
2024-04-22 16:03:24 -07:00
Mathias Agopian
d0586743f6 add ADPF support for backend thread 2024-04-22 15:09:08 -07:00
Mathias Agopian
14a99cbc63 add the target refresh interval to the backend beginFrame 2024-04-22 15:09:08 -07:00
Benjamin Doherty
808b51c1cf matedit: fix use-after-free 2024-04-22 16:06:39 -06:00
Sungun Park
315726678e Release Filament 1.51.5 2024-04-22 20:47:55 +00:00
Ben Doherty
bac8e58ee7 Support backends with multiple shader languages and precompiled Metal libraries (#7769) 2024-04-21 21:59:22 -04:00
Mathias Agopian
ec31a516f7 don't rely on FMaterialInstance having a default ctor (#7781)
* don't rely on FMaterialInstance having a default ctor

FMaterialInstance needed a default ctor because it is a field of
FMaterial but cannot be initialized before FMaterial itself is
initialized. So we had a defautl ctor and we'd finish the initialization
later. Conceptually the default material instance should have been 
new'ed and a pointer to it stored instead. 

That's basically what we do now, but to avoid the extra allocation,
we in-place new and delete the default material instance into an
aligned_storage inside FMaterial.

* Update filament/src/details/Material.h

Co-authored-by: Ben Doherty <bendoherty@google.com>

---------

Co-authored-by: Ben Doherty <bendoherty@google.com>
2024-04-19 21:38:30 +00:00
Mathias Agopian
7a3b762b53 cleanup details/Material.h
Should Fix #7774
2024-04-19 12:08:03 -07:00
Eliza Velasquez
67268cb76d filagui: Use material constants in uiBlit 2024-04-18 13:46:46 -07:00
Eliza Velasquez
0b34dc6608 filagui: Add support for external textures
We have an instance of a client trying to render a GL_TEXTURE_EXTERNAL_OES
texture with filagui, which currently fails.
2024-04-18 13:46:46 -07:00
Ben Doherty
afe292986e Introduce new matedit tool (#7759) 2024-04-18 12:18:29 -04:00
Mathias Agopian
83acf0f9de fix hello triangle build 2024-04-18 00:38:26 -07:00
Mathias Agopian
69d9c8b72c fix a GL backend crash when shutting down
the gl backend did some of its cleanup in the its destructor,
including calling into OpenGL, however, the destructor is called from
the main thread, not the GL thread, so these calls would be no-ops at
best, and crashes in the worst case.
2024-04-16 15:08:45 -07:00
Mathias Agopian
3bffd90357 don't crash if we don't have a Camera set on View (#7766)
* don't crash if we don't have a Camera set on View

- also add a method to query if a camera was set

* Update android/filament-android/src/main/java/com/google/android/filament/View.java

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2024-04-16 21:09:21 +00:00
Mathias Agopian
b21dfd5ea2 add a couple way of validating MaterialInstances (#7754)
* add a couple way of validating MaterialInstances

BUGS=[333907416]

* Update filament/include/filament/Engine.h

Co-authored-by: Powei Feng <powei@google.com>

* Update filament/include/filament/Engine.h

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2024-04-16 12:12:20 -07:00
Mathias Agopian
8af2d7512d cleanup and small improvements to JobSystem
- add missing includes
- wake-up one or several threads based on the number of jobs available
2024-04-16 12:11:15 -07:00
Mathias Agopian
785592293c don't use thread affinity for the thread-pool
using thread affinity naively on big.little architectures is very flaky,
for now it's better to simplify and not use it at all, let the kernel
figure things out.

BUGS=[333582569]
2024-04-16 12:11:15 -07:00
Maximilien Dagois
613b1fc246 Fixed a comment 2024-04-16 12:10:49 -07:00
Powei Feng
c8098a4c15 gltfio: add Asset/Resource extended implementations (#7678)
* gltfio: add Asset/Resource extended implementations

 - Add gltfio/src/extended to implement an alternate loader for
   primitives. This is largely based on the implementation in
   AssetLoader/ResourceLoader
 - Able to correctly produce flat shading from gltf that only have
   vertex positions and indices.
 - This is not hooked into current code and should have no
   practical effect on gltfio.
2024-04-16 17:46:48 +00:00
Powei Feng
d8eee061e8 vk: Fix clang-18 compiler warning (#7764)
Fixes #7762
2024-04-16 17:14:57 +00:00
Powei Feng
0ebe888344 Fix broken dynamic resolution (#7763)
Previous PR #7758 accidentally removed the setting of 'resolution'
for shaders other than 'blitLow'.  This PR undoes that.
2024-04-16 09:52:43 -07:00
Powei Feng
c20496a461 Remove unused parameter in blitLow (#7758) 2024-04-15 16:19:54 -07:00
tomnomgoogleuk
8955a61df3 Set VkApplicationInfo.pEngineName to Filament (#7756)
Setting the pEngineName helps with the collection of metrics and is generally good practice.
2024-04-15 19:42:36 +00:00
Powei Feng
9e0e3262c3 Release Filament 1.51.4 2024-04-15 11:05:12 -07:00
Mathias Agopian
d3d5281488 cleanup the Material constructor
We move some large blocks of code out of line.
2024-04-15 10:27:07 -07:00
Mathias Agopian
075f3d0869 fix another ibl-prefilter bug introduced recently
The top and bottom faces were swapped in the reflection map.

FIXES=[333421281]
2024-04-15 10:25:52 -07:00
Mathias Agopian
3ca9b9cd0f don't use thread affinity for the backend thread
Originally we did this because we wanted to run on a big core on 
android. However setting the thread affinity in this way is fragile,
we are not guaranteed to be on a big core, and we don't even know
if some thread is pinned to that core already; which was the case
with some GL drivers. This can also cause scheduling problems with
other threads.

We just remove this logic entirely for now, and we'll figure out 
something better later to run on a big core.

Fixes #7748
BUGS=[333949404]
2024-04-12 15:55:56 -07:00
Mathias Agopian
eb33ce35ef make the Systrace class public
BUGS=[331834298]
2024-04-12 14:44:48 -07:00
Ben Doherty
cddd22da28 Introduce a new precompiled Metal material chunk type (#7749)
This change introduces a new chunk type to material files for precompiled Metal libraries. Previously, SPIR-V was the only binary type, so there's also a couple of refactor commits present here. Nothing is changed in Filament or matc yet.

BUGS=[333547148]
2024-04-12 00:42:10 -04:00
Powei Feng
05ce5ead8d vk: Use new descriptor set caching (#7735)
- Use new descriptor set and layout caching
 - Remove descriptor set related code in VulkanPipelineCache
 -  fix leaks for descriptor sets/layouts

FIXES=248594812,325157400
2024-04-09 23:29:27 +00:00
Sungun Park
4bed88289f Release Filament 1.51.3 2024-04-08 20:49:02 +00:00
Ben Doherty
7a6138597e Metal re-apply: throw an NSException when attempting to draw with invalid program (#7741) 2024-04-05 17:50:07 -07:00
Ben Doherty
28da328815 Export utils::panic function (#7740) 2024-04-05 17:49:56 -07:00
Mathias Agopian
de3c4b6d56 fix a possible leak when editing a material with matdbg
A MaterialParser could be leaked if several edits happened before they
were latched -- this was because the MaterialParser was stored as
a raw pointer instead of a unique_ptr<>, this was done as an attempt
to avoid to use a lock around accessing mPendingEdits.
2024-04-04 10:15:43 -07:00
Mathias Agopian
5d27240e0c clean-up lifetime of MaterialParser 2024-04-04 10:15:43 -07:00
Mathias Agopian
94fc37b8c2 fix missing headers 2024-04-04 10:15:43 -07:00
Powei Feng
532cb28ce9 vk: Introduce caches for descriptor sets/layouts (#7731)
Added
 - Cache for layouts
 - Pools for descriptor sets
 - Cache for descriptor set updates
 - Cache for pipeline layouts

Does not have effect on implementation.
2024-04-03 17:51:42 +00:00
Mathias Agopian
b30d12aca5 split GLTexture and GLBufferObject to their own file 2024-04-02 23:34:30 -07:00
Mathias Agopian
d891a6927f program is now 48 bytes instead of 56 2024-04-02 23:34:30 -07:00
Mathias Agopian
22b5715837 move mSamplerMap and ES2's mUniformBindings to OpenGLContext 2024-04-02 23:34:30 -07:00
Powei Feng
7eb08f11ea vk: add descriptor set/layout types to handles (#7728)
- Move VulkanDescriptorSet to VulkanHandles.h
 - Add VulkanDescriptorSetLayout to VulkanHandles.h
 - Add "input" descriptor set types to VulkanUtility.h. These are
   structs that will be defined in the backend API (shared across
   all backends) and eventually passed from the front-end to the
   vk backend.
 - Logic to parse descriptor set layout from the spirv-v shaders.
 - Move UsageFlags type to VulkanUtility.h
 - Just prep work. No effect to current implementations.
2024-04-02 20:59:24 +00:00
Mathias Agopian
588a05f77c Fix point/spot shadow rendering bug
We were calculating the shadow visibility of spot/point lights. The
visibility was calculated during the "execute" phase of the FrameGraph
but it was used/needed during the setup phase. The result was that
the visibility was always delayed by one frame (really it was stale 
data from the previous calculation).

We are now computing the shadow visibility earlier, during the
setup phase. This is also better because we can now skip culling
of these shadow maps entirely if we know they're not visible.

Fixes #7715
2024-04-01 17:09:34 -07:00
Benjamin Doherty
3ec2b47df7 Release Filament 1.51.2 2024-04-01 16:44:33 -07:00
Mathias Agopian
1c55ad49ee add support for custom blend functions
BUGS=[331610785]
2024-04-01 13:40:34 -07:00
Mathias Agopian
348e61fd76 remove unused code 2024-04-01 13:40:34 -07:00
Mathias Agopian
8ce6d54930 remove wrong noexcept in the backend
going forward we want to be able to throw exceptions from the backend
at the very least, we need to be consistant, currently we are
potentially throwing exceptions from `noexcept` places.

this changes makes it possible to throw exceptions from the backend,
during handle construction and conversion to pointers, which wasn't 
allowed before.

We still can't throw from dtors because it's generally a bad idea, 
better abort in that case.
2024-03-29 14:59:43 -07:00
Mathias Agopian
8db5e700d7 GL backend should only allocate renderbuffers when possible
There was several cases where the the gl backend would wrongly  use a 
renderbuffer instead of a texture.


BUGS=[329491941]
2024-03-29 14:59:29 -07:00
Mathias Agopian
0ec3596440 the user can now set a panic handler callback
BUGS=[331457244]
2024-03-29 12:25:06 -07:00
Ben Doherty
ee4c03d0f1 Fix WebGL build with newer Emscripten (#7721) 2024-03-28 14:15:32 -07:00
Powei Feng
f12e7f9fbf Release Filament 1.51.1 2024-03-28 11:47:52 -07:00
Nimrod Gileadi
a068143953 Add semicolons to code snippet in AssetLoader.h (#7717) 2024-03-27 17:24:10 +00:00
Powei Feng
90d90094dc Bump material version to 51 in MaterialEnums.h 2024-03-26 14:37:13 -07:00
Sungun Park
54df4524eb Improve multiview shader replacement (#7706)
Replace the num_views for OpenGL multiviwe only when
- The engine is initialized with multiview stereo
- The variant for the material contains STE flag
- The program is for surface
- It's vertex shader (this is already in)
2024-03-26 21:36:22 +00:00
Powei Feng
d70f2e1b81 vk: delete instead of ref-count EmptyTexture (#7711) 2024-03-26 13:35:50 -07:00
Powei Feng
2f359b73a4 Add missing include to Platform.h (#7709) 2024-03-26 19:51:57 +00:00
Sungun Park
abb0cbc98e Add FILAMENT_ENABLE_MULTIVIEW option (#7707)
This allows the engine to include multiview shader code for default
materials.
2024-03-25 21:43:04 +00:00
Jacob Su
2763931b47 fix install android samples apk error. (#7230) 2024-03-22 23:05:01 -07:00
Sungun Park
0ead96b606 Replace value of num_views with engine's eye count (#7696)
For OpenGL multiview, it honors the qualifier `layout(num_views = X)`
specified in shader files to determine the number of views for
multiview.

We cannot recompile materials everytime the value changes. So replace
the value of num_views with the engine's eye count when shaders compile.
2024-03-22 21:45:58 +00:00
Ben Doherty
317c1bb7ea Metal: track buffer allocations (#7556) 2024-03-22 12:47:56 -07:00
Ben Doherty
9aaaad9271 Improve Skybox eyeDirection precision (#7685) 2024-03-22 12:03:06 -07:00
Mathias Agopian
d2ce714e73 fix use-after-free disable option 2024-03-22 11:27:30 -07:00
Mathias Agopian
8398175d9c Add an option to disable use-after-free checks in the backend
BUGS=330403836
2024-03-22 10:24:29 -07:00
Sungun Park
26258a4718 Facilitate four views for multiview (#7694)
This change allows the combine function for multiview to be able to
combine more than two views side-by-side.
2024-03-22 17:09:08 +00:00
Mathias Agopian
3644e7f808 Fixes IBL prefilter has floor and ceiling flipped
FIXES=[330603077]
2024-03-21 13:28:24 -07:00
Powei Feng
4d774820d9 gl: Don't reference swapchain obj on Web
Fixes #7693
2024-03-21 13:27:45 -07:00
Eliza Velasquez
aad45d9119 Fix typo 2024-03-21 19:59:47 +00:00
Eliza Velasquez
5389b37002 Incorporate feedback 2024-03-21 19:59:47 +00:00
Eliza Velasquez
d5fe9e236f Allow rendering thread to pause
This PR adds a new `pause()` option to the `Engine` `Builder` and a new function
`setPaused()` to the `Engine`. While paused, the rendering thread will pause
indefinitely for commands as if none are available. As soon as the rendering
thread is unpaused, the commands are immediately executed.
2024-03-21 19:59:47 +00:00
Mathias Agopian
59890ac85a PlatformEGL::createSwapChain never returns a nullptr anymore
in case the swapchain creation fails, it will now return a swapchain
with an EGL_NO_SURFACE handle. this will avoid having to nullptr check
the pointer in various places and will revert to the previous behavior
on failure.

FIXES=[329659681]
2024-03-20 16:07:02 -07:00
Mathias Agopian
435969f565 attempt to detect buffer overflows in Texture::setImage()
We verify that the buffer given to setImage() is at least as large
as needed for the given region to transfer; at least based on the
size given.

This might help catch b/330407429.

BUGS=330407429
2024-03-20 16:06:43 -07:00
Ben Doherty
e3db39105f iOS: fix gltf-viewer crash while destruction ResourceLoader (#7684) 2024-03-19 16:14:45 -07:00
Powei Feng
dfa821d351 vk: fix broken gltf renderings (#7680)
This is due to color attachments being set to store=discard when
they are multi-sampled. It's unclear why that condition exists. For
now, removing it will fix the rendering issues with transparent
object + MSAA. We'll keep it as such until an issue surfaces.

Fixes #7674
2024-03-19 22:38:52 +00:00
Powei Feng
1ab223c965 vk: minor fixes (#7682)
- Add description to a few debug options
- Set correct usage flag for blit-src/dest images
- Correctly initialize a debug-only field in VulkanProgram
2024-03-19 13:59:52 -07:00
Mathias Agopian
29bb60cd94 fix typo that caused a wrong assertion 2024-03-19 13:13:12 -07:00
Mathias Agopian
93b15dac87 The type of geometry of a renderable can now be specified
- dynamic (default) no restriction apply
- static bounds: bounds and world transform can't be changed
- static: additionaly morphing/skinning and vertex/index buffers are
  immutable.

This will allow some optimizations in the future. Currently, we just
store the type but don't do anything with it.
2024-03-19 11:12:25 -07:00
Romain Guy
a8fda9b4d0 Make PBR Neutral invertible (#7677)
Based on model-viewer's change at
https://github.com/google/model-viewer/pull/4716
2024-03-19 11:11:44 -07:00
Benjamin Doherty
ba9cb2fe43 Release Filament 1.51.0 2024-03-17 13:12:32 -07:00
Sungun Park
0f7cffc407 Connect multiview components together (#7671)
Plumb through multiview configurations to the pipeline so that the
engine draws scenes using multiview extension. Users need to prepare
shaders compiled with the `multiview` param and set the
`stereoscopicType` flag to MULTIVIEW in the Engine::Config to enable
multiview feature.

In this change, postprocessings for multiview are not yet supported. So
we all disable them until they're supported.

The debug option `combineMultiviewImages` combines layers as one image,
which allows us to check the final result.
2024-03-15 22:01:38 +00:00
Mathias Agopian
dace5fd695 minor fixes and cleanup to Primitive and BufferInfo factories
- both files use consistent names
- enforce that the keys are not moved around
- don't pass the value (which is 4 bytes) by reference
2024-03-15 11:26:47 -07:00
Powei Feng
b23ee1bce4 gltfio: add extended tangents job (#7666)
- TangentsJobExtended extracts data from cgltf accessor and
   runs geometry::TangentSpaceMesh on the attributes and computes
   the tangent space.
 - The /extended folder is meant for running this process. Note that
   this API might remesh the input and will require corresponding
   changes that might break previous assumptions.
 - The general flow of the code is modeled after src/TangentsJob.h
 - This is not hooked into current code and should have no
   practical effect on gltfio.
2024-03-15 17:46:08 +00:00
Mathias Agopian
25f017b883 fix missing headers 2024-03-14 16:41:21 -07:00
Sungun Park
0def77eaa8 Add layerCount to createRenderTarget (#7660)
This new parameter indicates whether the render target will be created
for multiview.

If the value is greater than 1, it tells the render target should be
created for multiview. Otherwise, 1 or 0, it creates a single layer
render target.
2024-03-14 00:38:34 +00:00
Powei Feng
3c25dab22f vk: clean-up initialization of classes (#7667)
Instead of holding pointers to class instances in VulkanDriver,
we standardize by making the relevant classes have proper
constructors and initialize in VulkanDriver's constructor
initializer list.
2024-03-13 23:51:22 +00:00
Mathias Agopian
93a80fd084 More Platform improvements for protected contexts
- `isSwapChainProtected()` is now virtual
- `createDefaultRenderTarget()` is renamed to `getDefaultFramebufferObject()`
- new `getCurrentContextType()` returns the current context type
- `makeCurrent` now takes an additional `ContextType`
- `PlatformEGL::getContextForType()` to retrieve the `EGLContext` for
   a given type.
- `PlatformEGL::makeCurrent` non-virtual utilities to set only the
  context or swapchains.
2024-03-13 16:13:34 -07:00
Mathias Agopian
963e097bdc handle non-0 default FBO with protected contextes 2024-03-13 16:13:34 -07:00
Mathias Agopian
86479781a5 assert when swapchain creation fails
This is better than risking a null-pointer dereference later.
2024-03-13 16:13:34 -07:00
Hanno J. Gödecke
4ea5872b26 fix: applyCrossFade use correct instance 2024-03-13 16:13:01 -07:00
Hanno J. Gödecke
f27f0ef4fc fix: apply stashCrossFade to correct entity 2024-03-13 16:13:01 -07:00
Ben Doherty
348454781f Remove erroneous assertion (#7661) 2024-03-12 14:29:49 -07:00
Sungun Park
bb6c8ef1c8 Add option FILAMENT_SAMPLES_STEREO_TYPE for samples/gltfio (#7658)
This option can be either "instanced" or "multiview", indicating what
stereoscopic rendering type shaders in samples/gltfio should be built
for.
2024-03-12 13:49:00 -07:00
Powei Feng
fa6b4ebd04 gltfio: refactor for clarity (#7652)
- Pull certain utility functions in a separate header and cpp
- Refactor ResourceLoader::loadeResources into smaller methods
2024-03-12 20:31:19 +00:00
Ben Doherty
9aad4df441 Metal: respect disableParallelShaderCompile config (#7659) 2024-03-12 13:06:43 -07:00
Ben Doherty
2e581be8fd Move SwapChain flags into separate file (#7654) 2024-03-12 12:10:43 -07:00
Sungun Park
6d7eaf31d3 Add multiview filamat for default materials (#7644)
Add prebuilt materials for the engine default materials. They'll be
selected for multiview stereoscopic implementation.
2024-03-12 02:50:54 +00:00
Powei Feng
dea345d28e geometry: fix mikktspace wrapper (#7651)
- Fix missing attributes in TangentSpaceMesh
- Fix missing reference in MikktspaceImpl.cpp
2024-03-11 22:27:46 +00:00
Sungun Park
c1dfd8553d Release Filament 1.50.6 2024-03-11 21:38:10 +00:00
Powei Feng
0c48f40836 vk: add /usr/local/lib to rpath on macos (#7643)
For reasons unknown, after upgrading to XCode 15.3, dlopen can
no longer find libvulkan.1.dylib. We fix it by explicitly adding
/usr/local/lib to rpath for macos.
2024-03-08 23:18:43 +00:00
Mathias Agopian
cac4d2aa94 Modernize draw API.
PipelineState now holds a handle to a HwVertexBufferInfo. 
DriverAPI::draw() is now technically deprecated and replaced by the
more efficient draw2(), which only takes an index offset, index count 
and instance count. The Pipeline to use is now specified with a new
API bindPipeline() and the primitive to use with bindRenderPrimitive().

This allows clients to reuse RenderPrimitives and ultimately Pipelines.

This change reduces CPU usage significantly on Metal and Vulkan, by 
reducing the need to lookup for a pipeline at every draw call.

The application, however, must be a "good citizen" by reusing 
MaterialInstance and RenderPrimitive as much as possible. We do have
RenderPrimitive cache however, so reusing the same VertexBuffer and
associated parameters also works.
2024-03-08 13:42:10 -08:00
Sungun Park
f8973d53d6 Consolidate materials for feature level (#7640)
Some default materials such as defaultMaterial and skybox have discrete
material file for feature level 0.

Combine these materials as one utilizing the `-P` option of matc.
2024-03-08 12:26:53 -08:00
Ben Doherty
d07168f49c Metal: change shader compilation pool size to 1 (#7639) 2024-03-08 10:32:38 -08:00
Mathias Agopian
c3057e17bb add post-lighting mix factor support
This adds a new material property (float postLightingMixFactor) which
is used to mix the original color with the post-lighting blended color.
The default value is 1.0, which keeps the current behavior.

FIXES=[328498606]
2024-03-08 10:32:21 -08:00
Powei Feng
23a8efd3dc vk: clean up debug tools (#7635)
- Fix broken resource leak print out.
 - Add sampler name to debugUtils when enabled
2024-03-08 01:15:24 +00:00
Mathias Agopian
e1973978ae Set the protected attribute on EGLImage
We set the attribute based on the usage bits of the underlaying 
AHardwareBuffer.
2024-03-07 14:23:57 -08:00
Powei Feng
b9a33b7d3e Try fixing windows artifact output again (#7637)
The [previous] change assumed that the shell is powershell, but the shell is actually commands (cmd). 

The [previous] change assumed we're in the root directory.  This assumption is probably correct [ref]. So we keep that change.

[ref]:  https://github.com/google/filament/blob/main/build/windows/build-github.bat#L134
[previous]: 373c5710b1
2024-03-07 01:09:04 +00:00
Mathias Agopian
434c226e8a IBLs were mirrored when using IBLPrefilter
cmgen mirrors environment maps by default so that the reflection map
appears un-mirrored. IBLPrefilter didn't do that. 

EquirectangularToCubemap now takes a Config parameter that allows to
specify the mirroring, which is enabled by default.


FIXES=[320856413]
2024-03-06 15:04:30 -08:00
Sungun Park
0605e9fe82 Fix a warning (#7634)
This fixes a warning for 6601c7c2b5
2024-03-06 21:42:30 +00:00
Powei Feng
7eb3b2aaf5 Release Filament 1.50.5 2024-03-06 13:01:10 -08:00
Mathias Agopian
11d2ac1019 Add support for protected contexts
Protected contexts are now supported by the OpenGLPlatform interface
and implemented in EGLPlatform.

Protected contexts can read from regular and protected resources but
can only write to protected resources (e.g. protected swap chains or
textures backed by protected memory. These can be created on Android
via AHardwareBuffer and EGLImage for instance).

The underlaying EGL implementation must support protected contexts.

Switching to a protected context is achieved by using a
protected-content SwapChain in Renderer::beginFrame().
A protected-content SwapChain can be created using the new
CONFIG_PROTECTED_CONTENT flag at creation time.

The OpenGL backend implementation will then use a protected context for
rendering until an unprotected SwapChain is used again.

The crux of this implementation is to use different VAOs in
the different contexts, because those can't be shared between contexts.
We also need to synchronize the state with our state cache and ensure
VAOs objects are destructed properly in the right context.
2024-03-06 12:17:40 -08:00
Sungun Park
6601c7c2b5 Add new parameter -P for matc (#7632)
* Add new parameter -P for matc

This new matc parameter `-P` or `--material-parameter` allows users to
set material properties to the specified value.

Values passed through this matc parameters have the highest priorities.
I.e., they overwrite material properties specified in the material file.
2024-03-06 12:06:30 -08:00
Mathias Agopian
21d938a59f simplify the ResourceAllocator cache eviction strategy
Previously the cache would try to keep its size below a user-settable
value. This was not effective because when that value was too small,
it would cause a lot of churn every frame without actually keeping
the memory usage below the specified value.

We now evict buffer aggressively after they've not been used
(for two frames by default), but we don't cap the size of the cache.
The cache will naturally settle at the size it needs. When dynamic
resolution is used, it might be needed to increase resources 
maximum age, which is a user-settable value still.

This improves performance on mobile on many scenes because the 64MB
default value was too low, causing the crash to thrash.
2024-03-06 11:00:17 -08:00
mdagois
c84f80be7c Fixed validation error VUID-vkAcquireNextImageKHR-semaphore-01779 (#7626)
The validation error triggers on hellotriangle using AMD (desktop), QCOM (mobile) and Mali (mobile) GPU.
Before this MR, only a single semaphore object was used to synchronize all the calls to vkAcquireNextImage (signal) and vkQueueSubmit (wait).
The issue is that by the time vkQueueSubmit returns, the semaphore is not necessarily reset.
When multiple frames are in flight, the next call to vkAcquireNextImage might try to reuse the semaphore while it is still in the wait status.
The semaphore is reset at a driver/hardware-dependent timing that's likely to be linked to the GPU queue execution.
The solution proposed by this MR is to use a pool of semaphores big enough to cover all possible queue submissions.
2024-03-06 01:27:21 +00:00
Powei Feng
9f33a2d062 Revert "vk: remove subpasses to simplify descriptor set refactor (#7592)" (#7630)
This reverts commit a9793b3cf6.

Due to change in output for swiftshader
2024-03-05 17:01:20 -08:00
Sungun Park
21d2847a6b Update code generator for multiview (#7616)
It generates shader code for multiview based on parameters.
2024-03-05 13:40:31 -08:00
Powei Feng
89d8f8ebbf engine: avoid leaking vertex buffer (#7628)
Previous commit [1] changed the semantic of the index to
mBufferObjects. Here we just make sure that if a buffer has been
allocated, we don't allocate another (otherwise, we'd leak).

Also cleaned up `updateBoneIndicesAndWeights` indexing

[1]: a3131a64b6
2024-03-05 20:09:16 +00:00
Powei Feng
b9a069be05 vk: Initial draft for descriptor set refactoring (#7620)
- Add cache for ds layouts and ds
 - Abstract descriptors API into VulkanDescriptorSetManager
 - Note that this is just a draft and not hooked into the current
   implementation.
2024-03-05 19:05:57 +00:00
Mathias Agopian
7115bd2a34 more cleanup-up of timer queries
- better naming

- TimerQueryFactory doesn't depend  on OpenGLDriver anymore,
only a OpenGLContext.

- timer query factory is now owned by and accessed through OpenGLDriver

- we can't temporarily store a negative number
in the query shared state, because it now indicates an error.
2024-03-04 16:31:45 -08:00
Mathias Agopian
9ce7f32470 Small improvements and cleanup to SwapChain
For debugging we add a way to recreate the SwapChain with different
flags.
2024-03-04 11:28:20 -08:00
Ben Doherty
d21613a5e6 Add SwapChain::getFrameScheduledCallback (#7599) 2024-03-04 09:20:10 -08:00
Mathias Agopian
167ec62667 Add protected mode to the FrameGraph.
In protected mode, the FrameGraph will automatically add the
PROTECTED usage bit to texture resources.
2024-02-29 15:35:46 -08:00
Mathias Agopian
2022be928e Timer queries can now return an error. 2024-02-29 10:58:34 -08:00
Mathias Agopian
b921d78fe7 Add support for protected SwapChain.
This is supported only by the PlatformEGL currently. There is not much
that can be done with it either at this point. A protected swapchain is
one that can only be written by a protected context, however, there
is currently no way to create such context.
2024-02-29 10:58:06 -08:00
Mathias Agopian
9c0c56d6d0 add support for protected textures
This is currently only implemented in the GLES backend and simply
exposes GL_EXT_protected_textures. There is not much that can be done
with this yet. Protected textures can't be read nor written at the
moment.
2024-02-29 10:57:42 -08:00
Sungun Park
43f6c4507e Make glFramebufferTextureMultiviewOVR available for Android (#7615)
This OpenGL function is going to be used for multiview on Android. Make
it available.
2024-02-29 10:32:22 -08:00
Sungun Park
57fff3a636 Add a new material param, stereoscopicType (#7613)
* Add a new material param, stereoscopicType

This new parameter allows us to specify which implementation of
stereoscopic rendering Filament uses for the material.

This change just includes material parameter addition and shader code
changes, so it doesn't affect the current rendering behavior.

These changes will follow as separate commits.
- render pipeline changes
- material parameter override via matc parameter
- material document update
2024-02-28 22:14:44 +00:00
Sungun Park
af8f38d83c Keep supporting API level 19 (#7609)
This is a partial rollback from
d83b3858b3.

Keep supporting API level 19 for some of our clients.
2024-02-28 00:11:33 +00:00
Powei Feng
b425d63b95 Release Filament 1.50.4 2024-02-27 14:14:49 -08:00
Sungun Park
02d2e2f644 Rename InstancedStereo as Stereo (#7608)
We're going to add a new implementation of stereoscopic rendering using
multiview. Thus we want to remove the word `Instanced` from all methods
and properties.
2024-02-27 13:00:24 -08:00
Sungun Park
ef488fdf57 Add blit array shader
This shader takes an array texture and a layer index to draw to the
current render target.

This will be used for debugging purpose to combine an array texture
rendered from the multiview feature that is going to be implemented
later, so that we can verify the feature properly performed.
2024-02-26 22:51:40 +00:00
Yuri Schimke
4836f94635 Update NEW_RELEASE_NOTES.md 2024-02-26 14:24:16 -08:00
Yuri Schimke
c2b5f08bc7 Fix Renderer FrameRateOptions interval default
From https://github.com/google/filament/issues/7539

And I got to the same conclusion based on f0f7e299d2/filament/src/details/View.cpp (L191)
2024-02-26 14:24:16 -08:00
Mathias Agopian
d05c61fe9a fix VulkanResourceBase size on Windows
VulkanResourceBase was intended to be 8 bytes, however, bitfields
are not packed by msvc if they don't use the same type.
2024-02-26 12:58:29 -08:00
Sungun Park
1ae82d325c Fix shader compilation in threadpool mode (#7602)
When shader compilation happens in threadpool mode, shader source code
isn't stored correctly in the token. This leads to empty error messages
if a shader has problems later on.
2024-02-26 09:05:46 -08:00
Mathias Agopian
f0f7e299d2 PlatformEGL cleanup 2024-02-23 16:15:22 -08:00
Mathias Agopian
a3131a64b6 cleanup of attributes management
- added many precondition checks and asserts to VertexBuffer creation
- simplified code in VertexBuffer as well
- enforce BONE_INDICES to integer when specified by user since that's
  what shaders expect.
- better comments about *always* setting BONE_INDICES to integer
- some code simplification in RenderPass + some comments about skinning
- in the GL backend we no longer set the vertex buffer objects at
  renderprimitive creation time, because they might not be available
  yet. Instead, we let the natural age mechanism update them next
  time it's needed.  This allows us to add some asserts about the
  declared buffer being present
2024-02-23 15:48:06 -08:00
Romain Guy
36120106cd Add new PBR Neutral tone mapper (#7597)
This tone mapper was designed to preserve the color apperance
of materials. It provides good saturation and contrast while
controlling the highlights.
2024-02-23 14:33:26 -08:00
Powei Feng
7e96216b6c vk: fix window minimize on Win (#7596)
Fixes #7481
2024-02-23 19:52:05 +00:00
Powei Feng
a9793b3cf6 vk: remove subpasses to simplify descriptor set refactor (#7592)
- Also did some clean up of debug code
2024-02-23 05:29:58 +00:00
Mathias Agopian
2260794a55 remove scissor from PipelineState
We do this to better match Gl, Vulkan and Metal, which don't need
to specify the scissor in the pipeline. In practice, this will also
allow us to set the scissor less often, saving a bit of CPU.
2024-02-22 17:03:40 -08:00
Sungun Park
d83b3858b3 Add missing changes for NDK version update (#7591)
These are missing parts from the commit
111ad96134.

NDK 26.1.10909125 is used by default

Minimum API level on Android is now API 21 instead of API 19. This allows the use of OpenGL ES 3.1
2024-02-22 15:33:05 -08:00
Powei Feng
654a38c3bf Fix broken Android build (#7590)
The math for PrimitiveInfo's size is incorrect. We correct the
padding.

See commit 11a3c06418 to see where
the padding error originated.
2024-02-22 22:10:38 +00:00
Ben Doherty
bf602516ec Metal: throw an NSException when attempting to draw with invalid program (#7581)
Throw an NSException when a program fails to compile and then is used for drawing; this helps aid debugging compiler errors in production, where stdout logs are not available.
2024-02-22 13:25:25 -08:00
Mathias Agopian
859c5edb49 Better fix for OOB when we have no renderable
The OOB would happen is the scene never had any renderables, in that
case the scene's SoA would stay unallocated, but the summedAreaTable
code relies on it have at least a capacity of 1.

It was incorrect to skip the RenderPass entirely because it might have
had some custom commands that needed to be executed (e.g. for applying
post-processing in subpass mode).
2024-02-21 23:52:55 -08:00
Mathias Agopian
11a3c06418 PrimitiveInfo is running out of space
So we now access some of its members through a pointer, this is not
ideal, but we can re-optimize this later.
We will need more space in it soon.
2024-02-21 15:50:44 -08:00
Mathias Agopian
3fab93bf3d Add a HwVertexBufferInfo cache 2024-02-21 15:50:44 -08:00
Mathias Agopian
20caeb3889 Introduce HwVertexBufferInfo
This new backend object holds the information needed to create the
pipeline on vulkan/metal relative to draw calls.

It is used to create HwVertexBuffer.
2024-02-21 15:50:44 -08:00
Mathias Agopian
6e5930c2a0 Bimap is a custom bi-directional map.
It is extracted from HwRenderPrimitiveFactory and cleaned-up a bit.
2024-02-21 15:50:44 -08:00
Powei Feng
486b9eef1e vk: add debug names to shader modules (#7577)
Also removed debugUtils workaround for Mesa since it's been addressed properly from the vk backend.
2024-02-21 23:29:31 +00:00
Ben Doherty
9b0718199f Fix an out-of-bounds memory access when no renderables are visible (#7587) 2024-02-21 21:55:47 +00:00
Mathias Agopian
dc6608350b fix a uninitialized memory access when no renderable are visible 2024-02-21 10:53:58 -08:00
Mathias Agopian
8b24950429 add the disableParallelShaderCompile option to Engine::Config 2024-02-21 08:47:47 -08:00
Powei Feng
5d9337e6c2 geometry: properly reference memcpy usage (#7576) 2024-02-16 13:06:01 -08:00
Sungun Park
142b73d9d7 Add OpenGL extension for multiview (#7569)
* Add OpenGL extension for multiview

This extension is going to be used for multiview implementation in
OpenGL.

Now the API isStereoSupported takes a stereo type as a parameter.
2024-02-15 08:21:00 -08:00
Mathias Agopian
5707043d96 Modernize HwRenderPrimitive and draw() APIs
HwRenderPrimitive doesn't need to know about the index offset and
index count, these parameters are only needed when drawing. draw()
is updated consequently.

This is a first step towards being able to lower the overhead of
draw similar draw calls. 

A side effect of this is that the HwRenderPrimitiveFactory now will
cache buffers regardless of their index count & offset.
2024-02-13 22:34:54 -08:00
Sungun Park
4e6ae2b714 Add stereoscopic type to Engine::Config (#7574)
* Add stereoscopic type to Engine::Config

This new type value will determine the algorithm used when stereoscopic
rendering is enabled.
2024-02-13 20:40:30 -08:00
Sungun Park
a9e8f40287 Release Filament 1.50.3 2024-02-13 00:44:36 +00:00
Mathias Agopian
6ccfeddf26 fix a typo that broke the resourceallocator cache
the cache size is given in MiB not bytes, so we needed to convert it
to bytes.
2024-02-12 16:04:10 -08:00
Mathias Agopian
9c6020a77a Make VulkanResourceBase 8 bytes instead of 16. 2024-02-12 15:59:51 -08:00
Mathias Agopian
e912dc2dc5 PipelineCache didn't need to store a copy of RasterState 2024-02-12 15:59:51 -08:00
Mathias Agopian
a27260b87f lazy initialization of the ShadowMap cache in ShadowMapManager
This reduces resource utilisation for Views that never need shadows.
It saves a UBO, two Entities and about 10KB memory. We also lazily
allocate the debugging DataSource, which saves about 10K per View
in debug builds.

Overall this change makes "simple" Views less than 4KB heavy down from
about 24KB (debug, 14KB release).

The main changes:
- ShadowMapManager is now allocated lazily
- the ShadowMap cache object is also allocated lazily
- debug DataSource is allocated lazily
- ShadowMaps are prepared/initialized with a Builder, which makes it
  clearer that some APIs are only for preparing the ShadowMap cache.
2024-02-12 14:32:50 -08:00
Mathias Agopian
653a015991 fix uninitialized memory access 2024-02-09 15:10:26 -08:00
Mathias Agopian
ef703bb4be Better handle collisions and use-after-free detection
- each handle now has a 4-bits "age", meaning that handles are recycled
  only after 16 alloc/free cycles.
  This is used to detect double-free and use-after free.
  This should also allow us to compare handles, because freeing and
  reallocating an object, won't produce the same Handle (at least
  for 16 rounds).

- removed "type safety" checks because it's almost impossible to
  get it wrong thanks to our compile time type safety checks. This
  didn't provide a useful value added.

- This feature is built on top of being able to set/get a 8 bits tag
  associated with the memory block returned by the pool allocator. We
  use the "extra" parameter of the allocator to allocate a "hidden"
  structure containing the age of that memory block.

- Also we don't allow to compare Handle<> of different types
2024-02-09 12:07:42 -08:00
Mathias Agopian
f9c8e65ef3 fix velocity update in FreeFlightManipulator
when the time step was getting to large, the velocity update could
become unstable and the camera would oscillate and eventually
fly off.
2024-02-09 12:07:13 -08:00
Mathias Agopian
c43051728c fix a typo in handleallocator that could cause corruptions
Fixes #7563
2024-02-08 16:01:47 -08:00
Powei Feng
20acc01fcd [release] update base64 command (#7559)
Seems like a `-i` is now necessary for the command. Note that we recently startede using mac-mx machines.
2024-02-07 09:17:09 -08:00
Mathias Agopian
d640ba853b rework how we size the HandleAllocator's pools
- update the pools sizes for metal and vulkan, which were very outdated.
- add debug code on all backends to print the size of each handle 
  (with a compile time switch)

The most important change is that now the 3 pools of HandleAllocator
are sized so that each can accommodate about the same amount of handles.
This makes it easier to reason about. The total amount of handles is
three times that, since there are 3 pools. 
We also try to allocate the buckets so that handles are evenly
distributed, however, that's very hand wavy.

With the current setup the number of handles per pool is as follows:
- GL : 3240 / pool / MiB
- VK : 1820 / pool / MiB
- MTL: 1310 / pool / MiB
2024-02-06 21:28:04 -08:00
Mathias Agopian
50d9d9f139 Improve memory allocations (#7540)
* Automatically flush CommandStream 

When generating commands, we now automatically flush the CommandStream,
so that we're guaranteed to not overrun the circular buffer.

* clenaup CircularBuffer implementation and API

Also fix a bug in DEBUG mode that could corrupt the CircularBuffer, it
was due to a wrong debugging code attempting to clear the unused
area of the buffer (this was wrong because in "ashmem" mode, there are
no guaranteed unused areas).

* Fix a couple threading vs. allocations

- prepareVisibleLights was run on a dedicated thread (via JobSystem), 
  but was using its own local ArenaScope. This is wrong because it
  could reset the root arena at any later point. This is fixed by
  just not using a local ArenaScope.

- related to the above, the root Arena (LinearAllocatorArena) didn't
  use a locked policy, which cause also cause problems since some
  allocations are done off the main thread. We now pre-allocate the one
  buffer we need.

This PR also renames some variable and types to improve readability.

* Rework RenderPass to improve allocations and API

RenderPass now is a fully immutable object that gets constructed with a
RenderPassBuilder. RenderPassBuilder can be passed around and doesn't
do any (major) allocations.

All RenderPass allocations and heavy lifting is done in 
RenderPassBuilder::Build().

Additionally, RenderPass cannot be copied anymore.

Where allocations happen is now much clearer.

* new LinearAllocatorWithFallback 

LinearAllocatorWithFallback is a linear allocator that can fall back
to the heap allocator. We use it for the high level command buffer to
avoid crashing when running out of memory.

FIXES=[277115740]

* Update filament/src/RenderPass.h

Co-authored-by: Powei Feng <powei@google.com>

* Update libs/utils/include/utils/Allocator.h

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2024-02-06 10:01:41 -08:00
Powei Feng
7be9cdc7f8 Release Filament 1.50.2 2024-02-06 17:40:03 +00:00
Mathias Agopian
af792e3d18 Resource allocator cache params can be set in Engine::Config
FIXES=[323386395]
2024-02-05 10:26:26 -08:00
Ben Doherty
f93677548d Metal: schedule PresentDrawable for destruction on the main thread (#7535) 2024-02-01 10:45:58 -08:00
Mathias Agopian
1eff66e4ec wip: nullability attributes for backend 2024-02-01 10:36:42 -08:00
Mathias Agopian
34f8b9aa20 add nullability attributes to filament public APIs 2024-02-01 10:36:42 -08:00
Mathias Agopian
6d07443188 fixes builds fail when path to build directory contains spaces
fixes #7533
2024-02-01 10:35:06 -08:00
Powei Feng
13a23703ad Release Filament 1.50.1 2024-02-01 00:41:19 +00:00
Powei Feng
57f6ca625c Update mac-continuous.yml (#7537)
ref: https://github.blog/changelog/2024-01-30-github-actions-introducing-the-new-m1-macos-runner-available-to-open-source/
2024-01-30 13:55:43 -08:00
Mathias Agopian
02f5903b67 fix external images
It turns out that many drivers require to rebind the external texture
after its content has changed, so we now always do that.

Bug #6188
2024-01-26 14:17:48 -08:00
Mathias Agopian
c39a870abc fix mobile debug builds, missing incluldes 2024-01-26 11:14:16 -08:00
Mathias Agopian
09b8008e17 add missing public headers in backend 2024-01-26 10:58:28 -08:00
Mathias Agopian
59b59cf6be add missing includes in libutils public headers 2024-01-26 10:58:00 -08:00
Mathias Agopian
0df6013263 update remote ui 2024-01-26 10:57:37 -08:00
Mathias Agopian
d5041fced7 support execinfo.h on Android 33 and above
Note: this currently requires to compile filament with API_LEVEL 33.
2024-01-25 14:50:29 -08:00
Mathias Agopian
9c54b8a777 fix typo that broke FSR upscaling 2024-01-25 10:34:47 -08:00
Mathias Agopian
8a534d0940 Fix missing/extra includes in all public headers 2024-01-24 23:13:14 -08:00
Mathias Agopian
130825422e Shadowmap texture vizualizer
The vizualizer is implemented inside filament itself and activated
using the debug registry. This intended for filament development use.
2024-01-24 11:28:11 -08:00
Powei Feng
984006ee25 geometry: allow additional attributes in TangentSpaceMesh (#7483)
- Add methods for adding attributes to the input mesh
 - Add method in TangentSpaceMesh for when user provides the
   tangents
 - Separate client-side Algorithm enum from implementation algorithm
   (AlgorithmImpl)
 - Fix CMake config for combining static libs
2024-01-23 16:16:35 -08:00
Sungun Park
b676002521 Release Filament 1.50.0 2024-01-23 21:10:06 +00:00
Sungun Park
8bdf7bd1e5 Update material version to 50 2024-01-22 15:25:06 -08:00
Mathias Agopian
1262cb286c backend option to disable parallel shader compile 2024-01-22 12:43:27 -08:00
Mathias Agopian
ee6f3fb1dc Add sharpening option to TAA
We use the RCAS algorithm from FSR1. This is useful for when TAA
upscaling is enabled and similar to to what FSR2 is doing.
2024-01-19 14:40:04 -08:00
Mathias Agopian
b9a9586abb taa: add a 32-sample mode and cleanup
32 sample may be more suited to 2x upsampling, it gives 8 samples per
high-res pixel (instead of 4). This is also what FSR 2.0 is using,
which is useful for comparing.
2024-01-19 14:40:04 -08:00
Mathias Agopian
6ee20a57aa remove all uses of our custom spinlock
This has caused issues and over time we have reduced the use of 
spinlocks, it was only used in few places and we still have evidence
that it's causing ANRs.

We use utils::Mutex instead which is a low overhead mutex implementation
on Linux systems.

FIXES=[321101014]
2024-01-19 12:05:07 -08:00
Mathias Agopian
368fa2bf39 fix IBLPrefilterContext::EquirectangularToCubemap
it was incorrectly mapping the equirect image to a cubemap due to a
typo in our overload of atan2 which was swapping its parameters.

atan2 is now removed, and we use atan(y,x) instead. Also modified the
code slightly so it matches almost exactly cmgen's.

FIXES=[320856413]
2024-01-18 21:10:21 -08:00
Mathias Agopian
8f642892b4 taa: fixes input filtering option=OFF when upscaling is off
when upscaling is off, the confidence value is always 1.
2024-01-18 21:07:13 -08:00
Powei Feng
5435a8ed3b Add missing includes (#7501)
BUG=320668410
2024-01-17 11:04:42 -08:00
Ben Doherty
5fd7a4e153 Don't render in background (#7486) 2024-01-12 10:17:00 -08:00
Sungun Park
20ff230b92 Fix a json parsing bug (#7490)
When parsing a lexeme, we use one less byte than it's intended to be for
comparing the current string.

This results in a success in cases like:
- true and truX
- false and falsX
- null and nulX
where X means an arbitrary character.

Fix this by the full intended length.
2024-01-11 12:47:11 -08:00
Ben Doherty
44ff79ad34 Metal: disable fast math (#7485) 2024-01-10 15:31:23 -08:00
Mathias Agopian
102d2db008 Bokeh aspect ratio (#7482)
* Bokeh aspect ratio

new DoF option to set the bokeh aspect ratio, this can be used to
simulate anamorphic lenses

* Update android/filament-android/src/main/java/com/google/android/filament/View.java

Co-authored-by: Powei Feng <powei@google.com>

* Update web/filament-js/filament.d.ts

Co-authored-by: Powei Feng <powei@google.com>

---------

Co-authored-by: Powei Feng <powei@google.com>
2024-01-10 15:25:28 -08:00
768 changed files with 53758 additions and 32018 deletions

View File

@@ -10,10 +10,10 @@ on:
jobs:
build-android:
name: build-android
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- uses: actions/setup-java@v3
with:
distribution: 'temurin'

View File

@@ -13,7 +13,7 @@ on:
jobs:
cocoapods-deploy:
name: cocoapods-deploy
runs-on: macos-latest
runs-on: macos-14
steps:
- name: Check out iOS/CocoaPods directory
uses: Bhacaz/checkout-files@49fc3050859046bf4f4873678d46099985640e89

View File

@@ -10,10 +10,10 @@ on:
jobs:
build-ios:
name: build-ios
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh continuous

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-22.04
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
cd build/linux && printf "y" | ./build.sh continuous

View File

@@ -10,10 +10,10 @@ on:
jobs:
build-mac:
name: build-mac
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
cd build/mac && printf "y" | ./build.sh continuous

View File

@@ -11,9 +11,9 @@ on:
jobs:
npm-deploy:
name: npm-deploy
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
with:
ref: ${{ github.event.inputs.release_tag }}
# Setup .npmrc file to publish to npm

View File

@@ -15,10 +15,10 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-22.04]
os: [macos-14, ubuntu-22.04]
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
WORKFLOW_OS=`echo \`uname\` | sed "s/Darwin/mac/" | tr [:upper:] [:lower:]`
@@ -32,7 +32,7 @@ jobs:
runs-on: windows-2019
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
build\windows\build-github.bat presubmit
@@ -40,10 +40,10 @@ jobs:
build-android:
name: build-android
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- uses: actions/setup-java@v3
with:
distribution: 'temurin'
@@ -54,10 +54,10 @@ jobs:
build-ios:
name: build-iOS
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
cd build/ios && printf "y" | ./build.sh presubmit
@@ -67,10 +67,10 @@ jobs:
build-web:
name: build-web
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
cd build/web && printf "y" | ./build.sh presubmit

View File

@@ -31,7 +31,7 @@ jobs:
strategy:
matrix:
os: [macos-latest, ubuntu-22.04]
os: [macos-14, ubuntu-22.04]
steps:
- name: Decide Git ref
@@ -41,7 +41,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -65,7 +65,7 @@ jobs:
build-web:
name: build-web
runs-on: macos-latest
runs-on: macos-14
if: github.event_name == 'release' || github.event.inputs.platform == 'web'
steps:
@@ -76,7 +76,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -98,7 +98,7 @@ jobs:
build-android:
name: build-android
runs-on: macos-latest
runs-on: macos-14
if: github.event_name == 'release' || github.event.inputs.platform == 'android'
steps:
@@ -109,7 +109,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
with:
ref: ${{ steps.git_ref.outputs.ref }}
- uses: actions/setup-java@v3
@@ -129,7 +129,7 @@ jobs:
- name: Sign sample-gltf-viewer
run: |
echo "${APK_KEYSTORE_BASE64}" > filament.jks.base64
base64 --decode filament.jks.base64 > filament.jks
base64 --decode -i filament.jks.base64 > filament.jks
BUILD_TOOLS_VERSION=$(ls ${ANDROID_HOME}/build-tools | sort -V | tail -n 1)
APKSIGNER=${ANDROID_HOME}/build-tools/${BUILD_TOOLS_VERSION}/apksigner
IN_FILE="out/sample-gltf-viewer-release.apk"
@@ -152,7 +152,7 @@ jobs:
build-ios:
name: build-ios
runs-on: macos-latest
runs-on: macos-14
if: github.event_name == 'release' || github.event.inputs.platform == 'ios'
steps:
@@ -163,7 +163,7 @@ jobs:
TAG=${REF##*/}
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -197,7 +197,7 @@ jobs:
echo "ref=${REF}" >> $GITHUB_OUTPUT
echo "tag=${TAG}" >> $GITHUB_OUTPUT
shell: bash
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
with:
ref: ${{ steps.git_ref.outputs.ref }}
- name: Run build script
@@ -205,7 +205,7 @@ jobs:
TAG: ${{ steps.git_ref.outputs.tag }}
run: |
build\windows\build-github.bat release
move out\filament-windows.tgz out\filament-$Env:TAG-windows.tgz
move out\filament-windows.tgz out\filament-%TAG%-windows.tgz
shell: cmd
- uses: actions/github-script@v6
env:

View File

@@ -10,10 +10,10 @@ on:
jobs:
build-web:
name: build-web
runs-on: macos-latest
runs-on: macos-14
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
cd build/web && printf "y" | ./build.sh continuous

View File

@@ -13,7 +13,7 @@ jobs:
runs-on: windows-2019
steps:
- uses: actions/checkout@v3.3.0
- uses: actions/checkout@v4.1.6
- name: Run build script
run: |
build\windows\build-github.bat continuous

View File

@@ -73,7 +73,6 @@ The following CMake options are boolean options specific to Filament:
- `FILAMENT_SUPPORTS_VULKAN`: Include the Vulkan backend
- `FILAMENT_INSTALL_BACKEND_TEST`: Install the backend test library so it can be consumed on iOS
- `FILAMENT_USE_EXTERNAL_GLES3`: Experimental: Compile Filament against OpenGL ES 3
- `FILAMENT_USE_SWIFTSHADER`: Compile Filament against SwiftShader
- `FILAMENT_SKIP_SAMPLES`: Don't build sample apps
To turn an option on or off:
@@ -426,7 +425,7 @@ value is the desired roughness between 0 and 1.
## Generating C++ documentation
To generate the documentation you must first install `doxygen` and `graphviz`, then run the
To generate the documentation you must first install `doxygen` and `graphviz`, then run the
following commands:
```shell
@@ -436,32 +435,62 @@ doxygen docs/doxygen/filament.doxygen
Finally simply open `docs/html/index.html` in your web browser.
## SwiftShader
## Software Rasterization
To try out Filament's Vulkan support with SwiftShader, first build SwiftShader and set the
`SWIFTSHADER_LD_LIBRARY_PATH` variable to the folder that contains `libvk_swiftshader.dylib`:
We have tested swiftshader and Mesa for software rasterization on the Vulkan/GL backends.
To use this for Vulkan, please first make sure that the [Vulkan SDK](https://www.lunarg.com/vulkan-sdk/) is
installed on your machine. If you are doing a manual installation of the SDK on Linux, you will have
to source `setup-env.sh` in the SDK's root folder to make sure the Vulkan loader is the first lib loaded.
### Swiftshader (Vulkan) [tested on macOS and Linux]
First, build SwiftShader
```shell
git clone https://github.com/google/swiftshader.git
cd swiftshader/build
cmake .. && make -j
export SWIFTSHADER_LD_LIBRARY_PATH=`pwd`
```
Next, go to your Filament repo and use the [easy build](#easy-build) script with `-t`.
and then set `VK_ICD_FILENAMES` to the ICD json produced in the build. For example,
```shell
export VK_ICD_FILENAMES=/Users/user/swiftshader/build/Darwin/vk_swiftshader_icd.json
```
## SwiftShader for CI
Build and run Filament as usual and specify the Vulkan backend when creating the Engine.
Continuous testing turnaround can be quite slow if you need to build SwiftShader from scratch, so we
provide an Ubuntu-based Docker image that has it already built. The Docker image also includes
everything necessary for building Filament. You can fetch and run the image as follows:
### Mesa's LLVMPipe (GL) and Lavapipe (Vulkan) [tested on Linux]
We will only cover steps that build Mesa from source. The official documentation of Mesa mentioned
that in general precompiled libraries [are **not** made available](https://docs.mesa3d.org/precompiled.html).
Download the repo and make sure you have the build depedencies. For example (assuming an Ubuntu/Debian distro),
```shell
git clone https://gitlab.freedesktop.org/mesa/mesa.git
sudo apt-get build-dep mesa
```
To build both the GL and Vulkan rasterizers,
```shell
docker pull ghcr.io/filament-assets/swiftshader
docker run -it ghcr.io/filament-assets/swiftshader
cd mesa
mkdir -p out
meson setup builddir/ -Dprefix=$(pwd)/out -Dglx=xlib -Dgallium-drivers=swrast -Dvulkan-drivers=swrast
meson install -C builddir/
```
To do more with the container, see the helper script at `build/swiftshader/test.sh`.
For GL, we need to ensure that we load the GL lib from the mesa output directory. For example, to run
the debug `gltf_viewer`, we would execute
```shell
LD_LIBRARY_PATH=/Users/user/mesa/out/lib/x86_64-linux-gnu \
./out/cmake-debug/samples/gltf_viewer -a opengl
```
If you are a team member, you can update the public image to the latest SwiftShader by
following the instructions at the top of `build/swiftshader/Dockerfile`.
For Vulkan, we need to set the path to the ICD json, which tells the loader where to find the driver
library. To run `gltf_viewer`, we would execute
```shell
VK_ICD_FILENAMES=/Users/user/mesa/out/share/vulkan/icd.d/lvp_icd.x86_64.json \
./out/cmake-debug/samples/gltf_viewer -a vulkan
```

View File

@@ -21,8 +21,6 @@ project(TNT)
# ==================================================================================================
option(FILAMENT_USE_EXTERNAL_GLES3 "Experimental: Compile Filament against OpenGL ES 3" OFF)
option(FILAMENT_USE_SWIFTSHADER "Compile Filament against SwiftShader" OFF)
option(FILAMENT_ENABLE_LTO "Enable link-time optimizations if supported by the compiler" OFF)
option(FILAMENT_SKIP_SAMPLES "Don't build samples" OFF)
@@ -45,6 +43,8 @@ option(FILAMENT_ENABLE_TSAN "Enable Thread Sanitizer" OFF)
option(FILAMENT_ENABLE_FEATURE_LEVEL_0 "Enable Feature Level 0" ON)
option(FILAMENT_ENABLE_MULTIVIEW "Enable multiview for Filament" OFF)
set(FILAMENT_NDK_VERSION "" CACHE STRING
"Android NDK version or version prefix to be used when building for Android."
)
@@ -69,6 +69,10 @@ set(FILAMENT_METAL_HANDLE_ARENA_SIZE_IN_MB "8" CACHE STRING
"Size of the Metal handle arena, default 8."
)
set(FILAMENT_BACKEND_DEBUG_FLAG "" CACHE STRING
"A debug flag meant for enabling/disabling backend debugging paths"
)
# Enable exceptions by default in spirv-cross.
set(SPIRV_CROSS_EXCEPTIONS_TO_ASSERTIONS OFF)
@@ -139,11 +143,6 @@ if (LINUX)
add_definitions(-DFILAMENT_SUPPORTS_XCB)
endif()
# Default Swiftshader build does not enable the xlib extension
if (FILAMENT_SUPPORTS_XLIB AND FILAMENT_USE_SWIFTSHADER)
set(FILAMENT_SUPPORTS_XLIB OFF)
endif()
if (FILAMENT_SUPPORTS_XLIB)
add_definitions(-DFILAMENT_SUPPORTS_XLIB)
endif()
@@ -167,15 +166,6 @@ if (NOT ANDROID AND NOT WEBGL AND NOT IOS AND NOT FILAMENT_LINUX_IS_MOBILE)
set(IS_HOST_PLATFORM TRUE)
endif()
if (IOS)
# Remove the headerpad_max_install_names linker flag on iOS. It causes warnings when linking
# executables with bitcode.
string(REPLACE "-Wl,-headerpad_max_install_names" "" CMAKE_C_LINK_FLAGS ${CMAKE_C_LINK_FLAGS})
string(REPLACE "-Wl,-headerpad_max_install_names" "" CMAKE_CXX_LINK_FLAGS ${CMAKE_CXX_LINK_FLAGS})
string(REPLACE "-Wl,-headerpad_max_install_names" "" CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_C_FLAGS})
string(REPLACE "-Wl,-headerpad_max_install_names" "" CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS ${CMAKE_SHARED_LIBRARY_CREATE_CXX_FLAGS})
endif()
if (WIN32)
# Link statically against c/c++ lib to avoid missing redistriburable such as
# "VCRUNTIME140.dll not found. Try reinstalling the app.", but give users
@@ -330,10 +320,6 @@ if (FILAMENT_SUPPORTS_EGL_ON_LINUX)
set(EGL TRUE)
endif()
if (FILAMENT_USE_SWIFTSHADER)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -DFILAMENT_USE_SWIFTSHADER")
endif()
if (WIN32)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -D_USE_MATH_DEFINES=1")
endif()
@@ -387,8 +373,9 @@ endif()
if (NOT MSVC AND NOT IOS)
# Omitting stack frame pointers prevents the generation of readable stack traces in crash reports on iOS
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer")
endif()
# These aren't compatible with -fembed-bitcode (and seem to have no effect on Apple platforms anyway)
if (NOT MSVC)
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
endif()
@@ -453,8 +440,13 @@ endif()
if (NOT WEBGL)
set(GC_SECTIONS "-Wl,--gc-sections")
endif()
set(B_SYMBOLIC_FUNCTIONS "-Wl,-Bsymbolic-functions")
if (ANDROID)
set(BINARY_ALIGNMENT "-Wl,-z,max-page-size=16384")
endif()
if (APPLE)
set(GC_SECTIONS "-Wl,-dead_strip")
set(B_SYMBOLIC_FUNCTIONS "")
@@ -468,7 +460,7 @@ if (APPLE)
endif()
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GC_SECTIONS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GC_SECTIONS} ${B_SYMBOLIC_FUNCTIONS}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GC_SECTIONS} ${B_SYMBOLIC_FUNCTIONS} ${BINARY_ALIGNMENT}")
if (WEBGL_PTHREADS)
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pthread")
@@ -531,6 +523,29 @@ else()
option(FILAMENT_DISABLE_MATOPT "Disable material optimizations" ON)
endif()
# This only affects the prebuilt shader files in gltfio and samples, not filament library.
# The value can be either "instanced", "multiview", or "none"
set(FILAMENT_SAMPLES_STEREO_TYPE "none" CACHE STRING
"Stereoscopic type that shader files in gltfio and samples are built for."
)
string(TOLOWER "${FILAMENT_SAMPLES_STEREO_TYPE}" FILAMENT_SAMPLES_STEREO_TYPE)
if (NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "instanced"
AND NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview"
AND NOT FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "none")
message(FATAL_ERROR "Invalid stereo type: \"${FILAMENT_SAMPLES_STEREO_TYPE}\" choose either \"instanced\", \"multiview\", or \"none\" ")
endif ()
# Compiling samples for multiview implies enabling multiview feature as well.
if (FILAMENT_SAMPLES_STEREO_TYPE STREQUAL "multiview")
set(FILAMENT_ENABLE_MULTIVIEW ON)
endif ()
# Define backend flag for debug only
if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FILAMENT_BACKEND_DEBUG_FLAG STREQUAL "")
add_definitions(-DFILAMENT_BACKEND_DEBUG_FLAG=${FILAMENT_BACKEND_DEBUG_FLAG})
unset(FILAMENT_BACKEND_DEBUG_FLAG)
endif()
# ==================================================================================================
# Material compilation flags
# ==================================================================================================
@@ -634,9 +649,9 @@ function(combine_static_libs TARGET OUTPUT DEPS)
# Loop through the dependent libraries and query their location on disk.
set(DEPS_FILES )
foreach(DEPENDENCY ${DEPS})
if(TARGET ${DEPENDENCY})
if (TARGET ${DEPENDENCY})
get_property(dep_type TARGET ${DEPENDENCY} PROPERTY TYPE)
if(dep_type STREQUAL "STATIC_LIBRARY")
if (dep_type STREQUAL "STATIC_LIBRARY")
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
endif()
endif()
@@ -659,21 +674,6 @@ else()
set(IMPORT_EXECUTABLES ${FILAMENT}/${IMPORT_EXECUTABLES_DIR}/ImportExecutables-${CMAKE_BUILD_TYPE}.cmake)
endif()
# ==================================================================================================
# Try to find Vulkan if the SDK is installed, otherwise fall back to the bundled version.
# This needs to stay in our top-level CMakeLists because it sets up variables that are used by the
# "bluevk" and "samples" targets.
# ==================================================================================================
if (FILAMENT_USE_SWIFTSHADER)
if (NOT FILAMENT_SUPPORTS_VULKAN)
message(ERROR "SwiftShader is only useful when Vulkan is enabled.")
endif()
find_library(SWIFTSHADER_VK NAMES vk_swiftshader HINTS "$ENV{SWIFTSHADER_LD_LIBRARY_PATH}")
message(STATUS "Found SwiftShader VK library in: ${SWIFTSHADER_VK}.")
add_definitions(-DFILAMENT_VKLIBRARY_PATH=\"${SWIFTSHADER_VK}\")
endif()
# ==================================================================================================
# Common Functions
# ==================================================================================================
@@ -706,7 +706,7 @@ function(get_resgen_vars ARCHIVE_DIR ARCHIVE_NAME)
set(RESGEN_OUTPUTS "${OUTPUTS}" PARENT_SCOPE)
set(RESGEN_FLAGS -qx ${ARCHIVE_DIR} -p ${ARCHIVE_NAME} PARENT_SCOPE)
set(RESGEN_SOURCE "${ARCHIVE_DIR}/${ARCHIVE_NAME}${ASM_SUFFIX}.S" PARENT_SCOPE)
set(RESGEN_SOURCE_FLAGS "-I${ARCHIVE_DIR} ${ASM_ARCH_FLAG}" PARENT_SCOPE)
set(RESGEN_SOURCE_FLAGS "-I'${ARCHIVE_DIR}' ${ASM_ARCH_FLAG}" PARENT_SCOPE)
endif()
endfunction()
@@ -721,7 +721,6 @@ add_subdirectory(${LIBRARIES}/filabridge)
add_subdirectory(${LIBRARIES}/filaflat)
add_subdirectory(${LIBRARIES}/filagui)
add_subdirectory(${LIBRARIES}/filameshio)
add_subdirectory(${LIBRARIES}/geometry)
add_subdirectory(${LIBRARIES}/gltfio)
add_subdirectory(${LIBRARIES}/ibl)
add_subdirectory(${LIBRARIES}/iblprefilter)
@@ -736,7 +735,6 @@ add_subdirectory(${FILAMENT}/filament)
add_subdirectory(${FILAMENT}/shaders)
add_subdirectory(${EXTERNAL}/basisu/tnt)
add_subdirectory(${EXTERNAL}/civetweb/tnt)
add_subdirectory(${EXTERNAL}/hat-trie/tnt)
add_subdirectory(${EXTERNAL}/imgui/tnt)
add_subdirectory(${EXTERNAL}/robin-map/tnt)
add_subdirectory(${EXTERNAL}/smol-v/tnt)
@@ -749,6 +747,9 @@ add_subdirectory(${EXTERNAL}/jsmn/tnt)
add_subdirectory(${EXTERNAL}/stb/tnt)
add_subdirectory(${EXTERNAL}/getopt)
# Note that this has to be placed after mikktspace in order for combine_static_libs to work.
add_subdirectory(${LIBRARIES}/geometry)
if (FILAMENT_BUILD_FILAMAT OR IS_HOST_PLATFORM)
# spirv-tools must come before filamat, as filamat relies on the presence of the
# spirv-tools_SOURCE_DIR variable.
@@ -800,6 +801,9 @@ if (IS_HOST_PLATFORM)
add_subdirectory(${TOOLS}/glslminifier)
add_subdirectory(${TOOLS}/matc)
add_subdirectory(${TOOLS}/matinfo)
if (NOT WIN32) # matedit not yet supported on Windows
add_subdirectory(${TOOLS}/matedit)
endif()
add_subdirectory(${TOOLS}/mipgen)
add_subdirectory(${TOOLS}/normal-blending)
add_subdirectory(${TOOLS}/resgen)

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.49.3'
implementation 'com.google.android.filament:filament-android:1.53.2'
}
```
@@ -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.49.3'
pod 'Filament', '~> 1.53.2'
```
### Snapshots
@@ -176,6 +176,7 @@ steps:
- [x] KHR_materials_unlit
- [x] KHR_materials_variants
- [x] KHR_materials_volume
- [x] KHR_materials_specular
- [x] KHR_mesh_quantization
- [x] KHR_texture_basisu
- [x] KHR_texture_transform

View File

@@ -7,6 +7,100 @@ 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.53.3
- Add drag and drop support for IBL files for desktop gltf_viewer.
## v1.53.2
## v1.53.1
## v1.53.0
- engine: fix skinning normals with large transforms (b/342459864) [⚠️ **New Material Version**]
## v1.52.3
## v1.52.2
## v1.52.1
- Add instructions for using Mesa for software rasterization
## v1.51.9
## v1.51.8
- filagui: Fix regression which broke WebGL
- Add a new Engine::Config setting to control preferred shader language
- Add `getEyeIndex` vertex API
- ios: Remove bitcode from iOS builds
## v1.51.7
- Add new matedit tool
- filagui: Support rendering `GL_TEXTURE_EXTERNAL_OES` textures.
- `setFrameScheduledCallback` now takes a `utils::Invocable`.
- engine: Add `isPaused()`
## v1.51.6
- Add new matedit tool
- filagui: Support rendering `GL_TEXTURE_EXTERNAL_OES` textures.
## v1.51.5
## v1.51.4
## v1.51.3
## v1.51.2
- engine: Add experimental APIs `Engine::builder::paused()` and `Engine::setPaused()`
## v1.51.1
## v1.51.0
- materials: add support for post-lighting mix factor (b/328498606) [⚠️ **New Material Version**]
## v1.50.6
- Add new API `SwapChain::getFrameScheduledCallback`
- vulkan: fixed validation error VUID-vkAcquireNextImageKHR-semaphore-01779
- opengl: Add support for protected content swapchains and contexts
## v1.50.5
- android: NDK 26.1.10909125 is used by default
- android: Minimum API level on Android is now API 21 instead of API 19. This allows the use of OpenGL ES 3.1
- rendering: New PBR Neutral tone mapper, designed to preserve materials color appearance
- android: Change default frameRateOptions.interval to 1.0
## v1.50.4
## v1.50.3
## v1.50.2
## v1.50.1
- Metal: fix some shader artifacts by disabling fast math optimizations.
- backend: remove `atan2` overload which had a typo and wasn't useful. Fixes b/320856413.
- utils: remove usages of `SpinLock`. Fixes b/321101014.
## v1.50.0
- engine: TAA now supports 4x upscaling [BETA] [⚠️ **New Material Version**]

View File

@@ -80,15 +80,15 @@ buildscript {
ext.versions = [
'jdk': 17,
'minSdk': 19,
'minSdk': 21,
'targetSdk': 34,
'compileSdk': 34,
'kotlin': '1.9.21',
'kotlin_coroutines': '1.7.3',
'kotlin': '2.0.0',
'kotlin_coroutines': '1.9.0-RC',
'buildTools': '34.0.0',
'ndk': '26.1.10909125',
'androidx_core': '1.12.0',
'androidx_annotations': '1.7.0'
'ndk': '27.0.11718014',
'androidx_core': '1.13.1',
'androidx_annotations': '1.8.0'
]
ext.deps = [
@@ -104,7 +104,7 @@ buildscript {
]
dependencies {
classpath 'com.android.tools.build:gradle:8.2.0'
classpath 'com.android.tools.build:gradle:8.4.1'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}

View File

@@ -38,6 +38,7 @@ set(FILAMAT_INCLUDE_DIRS
include_directories(${FILAMENT_DIR}/include)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_SOURCE_DIR}/libfilamat-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
add_library(filamat-jni SHARED src/main/cpp/MaterialBuilder.cpp)
target_include_directories(filamat-jni PRIVATE ${FILAMAT_INCLUDE_DIRS})

View File

@@ -59,6 +59,7 @@ endif()
set(VERSION_SCRIPT "${CMAKE_CURRENT_SOURCE_DIR}/libfilament-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${VERSION_SCRIPT}")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
add_library(filament-jni SHARED
src/main/cpp/BufferObject.cpp

View File

@@ -342,6 +342,21 @@ Java_com_google_android_filament_Engine_nIsValidMaterial(JNIEnv*, jclass,
return (jboolean)engine->isValid((Material*)nativeMaterial);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidMaterialInstance(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeMaterial, jlong nativeMaterialInstance) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValid((Material*)nativeMaterial,
(MaterialInstance*)nativeMaterialInstance);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidExpensiveMaterialInstance(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeMaterialInstance) {
Engine* engine = (Engine *)nativeEngine;
return (jboolean)engine->isValidExpensive((MaterialInstance*)nativeMaterialInstance);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsValidSkybox(JNIEnv*, jclass,
jlong nativeEngine, jlong nativeSkybox) {
@@ -391,6 +406,27 @@ Java_com_google_android_filament_Engine_nFlush(JNIEnv*, jclass,
engine->flush();
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Engine_nIsPaused(JNIEnv*, jclass,
jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jboolean)engine->isPaused();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nSetPaused(JNIEnv*, jclass,
jlong nativeEngine, jboolean paused) {
Engine* engine = (Engine*) nativeEngine;
engine->setPaused(paused);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Engine_nUnprotected(JNIEnv*, jclass,
jlong nativeEngine, jboolean paused) {
Engine* engine = (Engine*) nativeEngine;
engine->unprotected();
}
// Managers...
extern "C" JNIEXPORT jlong JNICALL
@@ -484,7 +520,13 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBuilderConfig(JNIEnv*,
jclass, jlong nativeBuilder, jlong commandBufferSizeMB, jlong perRenderPassArenaSizeMB,
jlong driverHandleArenaSizeMB, jlong minCommandBufferSizeMB, jlong perFrameCommandsSizeMB,
jlong jobSystemThreadCount, jlong stereoscopicEyeCount) {
jlong jobSystemThreadCount,
jlong textureUseAfterFreePoolSize, jboolean disableParallelShaderCompile,
jint stereoscopicType, jlong stereoscopicEyeCount,
jlong resourceAllocatorCacheSizeMB, jlong resourceAllocatorCacheMaxAge,
jboolean disableHandleUseAfterFreeCheck,
jint preferredShaderLanguage,
jboolean forceGLES2Context) {
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
Engine::Config config = {
.commandBufferSizeMB = (uint32_t) commandBufferSizeMB,
@@ -493,7 +535,15 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
.minCommandBufferSizeMB = (uint32_t) minCommandBufferSizeMB,
.perFrameCommandsSizeMB = (uint32_t) perFrameCommandsSizeMB,
.jobSystemThreadCount = (uint32_t) jobSystemThreadCount,
.textureUseAfterFreePoolSize = (uint32_t) textureUseAfterFreePoolSize,
.disableParallelShaderCompile = (bool) disableParallelShaderCompile,
.stereoscopicType = (Engine::StereoscopicType) stereoscopicType,
.stereoscopicEyeCount = (uint8_t) stereoscopicEyeCount,
.resourceAllocatorCacheSizeMB = (uint32_t) resourceAllocatorCacheSizeMB,
.resourceAllocatorCacheMaxAge = (uint8_t) resourceAllocatorCacheMaxAge,
.disableHandleUseAfterFreeCheck = (bool) disableHandleUseAfterFreeCheck,
.preferredShaderLanguage = (Engine::Config::ShaderLanguage) preferredShaderLanguage,
.forceGLES2Context = (bool) forceGLES2Context,
};
builder->config(&config);
}
@@ -510,8 +560,20 @@ extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBu
builder->sharedContext((void*) sharedContext);
}
extern "C" JNIEXPORT void JNICALL Java_com_google_android_filament_Engine_nSetBuilderPaused(
JNIEnv*, jclass, jlong nativeBuilder, jboolean paused) {
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
builder->paused((bool) paused);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_nBuilderBuild(JNIEnv*, jclass, jlong nativeBuilder) {
Engine::Builder* builder = (Engine::Builder*) nativeBuilder;
return (jlong) builder->build();
}
extern "C"
JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Engine_getSteadyClockTimeNano(JNIEnv *env, jclass clazz) {
return (jlong)Engine::getSteadyClockTimeNano();
}

View File

@@ -25,12 +25,17 @@ using namespace filament;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_Material_nBuilderBuild(JNIEnv *env, jclass,
jlong nativeEngine, jobject buffer_, jint size) {
jlong nativeEngine, jobject buffer_, jint size, jint shBandCount) {
Engine* engine = (Engine*) nativeEngine;
AutoBuffer buffer(env, buffer_, size);
Material* material = Material::Builder()
auto builder = Material::Builder();
if (shBandCount) {
builder.sphericalHarmonicsBandCount(shBandCount);
}
Material* material = builder
.package(buffer.getData(), buffer.getSize())
.build(*engine);
return (jlong) material;
}

View File

@@ -104,6 +104,14 @@ Java_com_google_android_filament_RenderableManager_nBuilderGeometry__JIIJJIIII(J
(size_t) count);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderGeometryType(JNIEnv*, jclass,
jlong nativeBuilder, int type) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->geometryType((RenderableManager::Builder::GeometryType)type);
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderMaterial(JNIEnv*, jclass,
@@ -237,12 +245,18 @@ Java_com_google_android_filament_RenderableManager_nBuilderMorphing(JNIEnv*, jcl
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderSetMorphTargetBufferAt(JNIEnv*, jclass,
jlong nativeBuilder, int level, int primitiveIndex, jlong nativeMorphTargetBuffer,
int offset, int count) {
Java_com_google_android_filament_RenderableManager_nBuilderMorphingStandard(JNIEnv*, jclass,
jlong nativeBuilder, jlong nativeMorphTargetBuffer) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
builder->morphing(level, primitiveIndex, morphTargetBuffer, offset, count);
builder->morphing(morphTargetBuffer);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nBuilderSetMorphTargetBufferOffsetAt(JNIEnv*, jclass,
jlong nativeBuilder, int level, int primitiveIndex, int offset) {
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
builder->morphing(level, primitiveIndex, offset);
}
extern "C" JNIEXPORT void JNICALL
@@ -314,13 +328,12 @@ Java_com_google_android_filament_RenderableManager_nSetMorphWeights(JNIEnv* env,
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferAt(JNIEnv*,
Java_com_google_android_filament_RenderableManager_nSetMorphTargetBufferOffsetAt(JNIEnv*,
jclass, jlong nativeRenderableManager, jint i, int level, jint primitiveIndex,
jlong nativeMorphTargetBuffer, jint offset, jint count) {
jlong, jint offset) {
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
MorphTargetBuffer *morphTargetBuffer = (MorphTargetBuffer *) nativeMorphTargetBuffer;
rm->setMorphTargetBufferAt((RenderableManager::Instance) i, (uint8_t) level,
(size_t) primitiveIndex, morphTargetBuffer, (size_t) offset, (size_t) count);
rm->setMorphTargetBufferOffsetAt((RenderableManager::Instance) i, (uint8_t) level,
(size_t) primitiveIndex, (size_t) offset);
}
extern "C" JNIEXPORT jint JNICALL

View File

@@ -28,6 +28,14 @@
using namespace filament;
using namespace backend;
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nSkipFrame(JNIEnv *, jclass, jlong nativeRenderer,
jlong vsyncSteadyClockTimeNano) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->skipFrame(uint64_t(vsyncSteadyClockTimeNano));
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_Renderer_nBeginFrame(JNIEnv *, jclass, jlong nativeRenderer,
jlong nativeSwapChain, jlong frameTimeNanos) {
@@ -187,3 +195,10 @@ Java_com_google_android_filament_Renderer_nSetPresentationTime(JNIEnv *, jclass
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->setPresentationTime(monotonicClockNanos);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_Renderer_nSetVsyncTime(JNIEnv *, jclass,
jlong nativeRenderer, jlong steadyClockTimeNano) {
Renderer *renderer = (Renderer *) nativeRenderer;
renderer->setVsyncTime(steadyClockTimeNano);
}

View File

@@ -34,7 +34,15 @@ Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* en
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_SwapChain_nIsSRGBSwapChainSupported(JNIEnv *, jclass, jlong nativeEngine) {
Java_com_google_android_filament_SwapChain_nIsSRGBSwapChainSupported(
JNIEnv *, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (bool)SwapChain::isSRGBSwapChainSupported(*engine);
return (jboolean)SwapChain::isSRGBSwapChainSupported(*engine);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_SwapChain_nIsProtectedContentSupported(
JNIEnv *, jclass, jlong nativeEngine) {
Engine* engine = (Engine*) nativeEngine;
return (jboolean)SwapChain::isProtectedContentSupported(*engine);
}

View File

@@ -47,6 +47,11 @@ Java_com_google_android_filament_ToneMapper_nCreateFilmicToneMapper(JNIEnv*, jcl
return (jlong) new FilmicToneMapper();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_ToneMapper_nCreatePBRNeutralToneMapper(JNIEnv*, jclass) {
return (jlong) new PBRNeutralToneMapper();
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_ToneMapper_nCreateAgxToneMapper(JNIEnv*, jclass, jint look) {
return (jlong) new AgxToneMapper(AgxToneMapper::AgxLook(look));

View File

@@ -49,6 +49,12 @@ Java_com_google_android_filament_View_nSetCamera(JNIEnv*, jclass,
view->setCamera(camera);
}
extern "C" JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_View_nHasCamera(JNIEnv*, jclass, jlong nativeView) {
View* view = (View*) nativeView;
return (jboolean)view->hasCamera();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetColorGrading(JNIEnv*, jclass,
jlong nativeView, jlong nativeColorGrading) {
@@ -525,3 +531,12 @@ Java_com_google_android_filament_View_nGetFogEntity(JNIEnv *env, jclass clazz,
View *view = (View *) nativeView;
return (jint)view->getFogEntity().getId();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nClearFrameHistory(JNIEnv *env, jclass clazz,
jlong nativeView, jlong nativeEngine) {
View *view = (View *) nativeView;
Engine *engine = (Engine *) nativeEngine;
view->clearFrameHistory(*engine);
}

View File

@@ -158,6 +158,19 @@ public class Engine {
FEATURE_LEVEL_3,
};
/**
* The type of technique for stereoscopic rendering. (Note that the materials used will need to be
* compatible with the chosen technique.)
*/
public enum StereoscopicType {
/** No stereoscopic rendering. */
NONE,
/** Stereoscopic rendering is performed using instanced rendering technique. */
INSTANCED,
/** Stereoscopic rendering is performed using the multiview feature from the graphics backend. */
MULTIVIEW,
};
/**
* Constructs <code>Engine</code> objects using a builder pattern.
*/
@@ -211,7 +224,13 @@ public class Engine {
nSetBuilderConfig(mNativeBuilder, config.commandBufferSizeMB,
config.perRenderPassArenaSizeMB, config.driverHandleArenaSizeMB,
config.minCommandBufferSizeMB, config.perFrameCommandsSizeMB,
config.jobSystemThreadCount, config.stereoscopicEyeCount);
config.jobSystemThreadCount,
config.textureUseAfterFreePoolSize, config.disableParallelShaderCompile,
config.stereoscopicType.ordinal(), config.stereoscopicEyeCount,
config.resourceAllocatorCacheSizeMB, config.resourceAllocatorCacheMaxAge,
config.disableHandleUseAfterFreeCheck,
config.preferredShaderLanguage.ordinal(),
config.forceGLES2Context);
return this;
}
@@ -226,6 +245,20 @@ public class Engine {
return this;
}
/**
* Sets the initial paused state of the rendering thread.
*
* <p>Warning: This is an experimental API. See {@link Engine#setPaused(boolean)} for
* caveats.
*
* @param paused Whether to start the rendering thread paused.
* @return A reference to this Builder for chaining calls.
*/
public Builder paused(boolean paused) {
nSetBuilderPaused(mNativeBuilder, paused);
return this;
}
/**
* Creates an instance of Engine
*
@@ -348,6 +381,35 @@ public class Engine {
*/
public long jobSystemThreadCount = 0;
/**
* Number of most-recently destroyed textures to track for use-after-free.
*
* This will cause the backend to throw an exception when a texture is freed but still bound
* to a SamplerGroup and used in a draw call. 0 disables completely.
*
* Currently only respected by the Metal backend.
*/
public long textureUseAfterFreePoolSize = 0;
/**
* Set to `true` to forcibly disable parallel shader compilation in the backend.
* Currently only honored by the GL backend.
*/
public boolean disableParallelShaderCompile = false;
/**
* The type of technique for stereoscopic rendering.
*
* This setting determines the algorithm used when stereoscopic rendering is enabled. This
* decision applies to the entire Engine for the lifetime of the Engine. E.g., multiple
* Views created from the Engine must use the same stereoscopic type.
*
* Each view can enable stereoscopic rendering via the StereoscopicOptions::enable flag.
*
* @see View#setStereoscopicOptions
*/
public StereoscopicType stereoscopicType = StereoscopicType.NONE;
/**
* The number of eyes to render when stereoscopic rendering is enabled. Supported values are
* between 1 and Engine#getMaxStereoscopicEyes() (inclusive).
@@ -356,6 +418,53 @@ public class Engine {
* @see Engine#getMaxStereoscopicEyes
*/
public long stereoscopicEyeCount = 2;
/*
* @Deprecated This value is no longer used.
*/
public long resourceAllocatorCacheSizeMB = 64;
/*
* This value determines how many frames texture entries are kept for in the cache. This
* is a soft limit, meaning some texture older than this are allowed to stay in the cache.
* Typically only one texture is evicted per frame.
* The default is 1.
*/
public long resourceAllocatorCacheMaxAge = 1;
/*
* Disable backend handles use-after-free checks.
*/
public boolean disableHandleUseAfterFreeCheck = false;
/*
* Sets a preferred shader language for Filament to use.
*
* The Metal backend supports two shader languages: MSL (Metal Shading Language) and
* METAL_LIBRARY (precompiled .metallib). This option controls which shader language is
* used when materials contain both.
*
* By default, when preferredShaderLanguage is unset, Filament will prefer METAL_LIBRARY
* shaders if present within a material, falling back to MSL. Setting
* preferredShaderLanguage to ShaderLanguage::MSL will instead instruct Filament to check
* for the presence of MSL in a material first, falling back to METAL_LIBRARY if MSL is not
* present.
*
* When using a non-Metal backend, setting this has no effect.
*/
public enum ShaderLanguage {
DEFAULT,
MSL,
METAL_LIBRARY,
};
public ShaderLanguage preferredShaderLanguage = ShaderLanguage.DEFAULT;
/*
* When the OpenGL ES backend is used, setting this value to true will force a GLES2.0
* context if supported by the Platform, or if not, will have the backend pretend
* it's a GLES2 context. Ignored on other backends.
*/
public boolean forceGLES2Context = false;
}
private Engine(long nativeEngine, Config config) {
@@ -602,7 +711,7 @@ public class Engine {
*/
@NonNull
public SwapChain createSwapChain(@NonNull Object surface) {
return createSwapChain(surface, SwapChain.CONFIG_DEFAULT);
return createSwapChain(surface, SwapChainFlags.CONFIG_DEFAULT);
}
/**
@@ -610,15 +719,15 @@ public class Engine {
*
* @param surface on Android, <b>must be</b> an instance of {@link android.view.Surface}
*
* @param flags configuration flags, see {@link SwapChain}
* @param flags configuration flags, see {@link SwapChainFlags}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the SwapChain couldn't be created
*
* @see SwapChain#CONFIG_DEFAULT
* @see SwapChain#CONFIG_TRANSPARENT
* @see SwapChain#CONFIG_READABLE
* @see SwapChainFlags#CONFIG_DEFAULT
* @see SwapChainFlags#CONFIG_TRANSPARENT
* @see SwapChainFlags#CONFIG_READABLE
*
*/
@NonNull
@@ -636,21 +745,22 @@ public class Engine {
*
* @param width width of the rendering buffer
* @param height height of the rendering buffer
* @param flags configuration flags, see {@link SwapChain}
* @param flags configuration flags, see {@link SwapChainFlags}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the SwapChain couldn't be created
*
* @see SwapChain#CONFIG_DEFAULT
* @see SwapChain#CONFIG_TRANSPARENT
* @see SwapChain#CONFIG_READABLE
* @see SwapChainFlags#CONFIG_DEFAULT
* @see SwapChainFlags#CONFIG_TRANSPARENT
* @see SwapChainFlags#CONFIG_READABLE
*
*/
@NonNull
public SwapChain createSwapChain(int width, int height, long flags) {
if (width >= 0 && height >= 0) {
long nativeSwapChain = nCreateSwapChainHeadless(getNativeObject(), width, height, flags);
long nativeSwapChain =
nCreateSwapChainHeadless(getNativeObject(), width, height, flags);
if (nativeSwapChain == 0) throw new IllegalStateException("Couldn't create SwapChain");
return new SwapChain(nativeSwapChain, null);
}
@@ -662,11 +772,12 @@ public class Engine {
*
* @param surface a properly initialized {@link NativeSurface}
*
* @param flags configuration flags, see {@link SwapChain}
* @param flags configuration flags, see {@link SwapChainFlags}
*
* @return a newly created {@link SwapChain} object
*
* @exception IllegalStateException can be thrown if the {@link SwapChain} couldn't be created
* @exception IllegalStateException can be thrown if the {@link SwapChainFlags} couldn't be
* created
*/
@NonNull
public SwapChain createSwapChainFromNativeSurface(@NonNull NativeSurface surface, long flags) {
@@ -775,6 +886,24 @@ public class Engine {
return nIsValidMaterial(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidMaterialInstance(@NonNull Material ma, MaterialInstance mi) {
return nIsValidMaterialInstance(getNativeObject(), ma.getNativeObject(), mi.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
* @return returns true if the specified object is valid.
*/
public boolean isValidExpensiveMaterialInstance(@NonNull MaterialInstance object) {
return nIsValidExpensiveMaterialInstance(getNativeObject(), object.getNativeObject());
}
/**
* Returns whether the object is valid.
* @param object Object to check for validity
@@ -1135,6 +1264,51 @@ public class Engine {
nFlush(getNativeObject());
}
/**
* Get paused state of rendering thread.
*
* <p>Warning: This is an experimental API.
*
* @see #setPaused
*/
public boolean isPaused() {
return nIsPaused(getNativeObject());
}
/**
* Pause or resume the rendering thread.
*
* <p>Warning: This is an experimental API. In particular, note the following caveats.
*
* <ul><li>
* Buffer callbacks will never be called as long as the rendering thread is paused.
* Do not rely on a buffer callback to unpause the thread.
* </li><li>
* While the rendering thread is paused, rendering commands will continue to be queued until the
* buffer limit is reached. When the limit is reached, the program will abort.
* </li></ul>
*/
public void setPaused(boolean paused) {
nSetPaused(getNativeObject(), paused);
}
/**
* Switch the command queue to unprotected mode. Protected mode can be activated via
* Renderer::beginFrame() using a protected SwapChain.
* @see Renderer
* @see SwapChain
*/
public void unprotected() {
nUnprotected(getNativeObject());
}
/**
* Get the current time. This is a convenience function that simply returns the
* time in nanosecond since epoch of std::chrono::steady_clock.
* @return current time in nanosecond since epoch of std::chrono::steady_clock.
* @see Renderer#beginFrame
*/
public static native long getSteadyClockTimeNano();
@UsedByReflection("TextureHelper.java")
public long getNativeObject() {
@@ -1201,6 +1375,8 @@ public class Engine {
private static native boolean nIsValidSkinningBuffer(long nativeEngine, long nativeSkinningBuffer);
private static native boolean nIsValidIndirectLight(long nativeEngine, long nativeIndirectLight);
private static native boolean nIsValidMaterial(long nativeEngine, long nativeMaterial);
private static native boolean nIsValidMaterialInstance(long nativeEngine, long nativeMaterial, long nativeMaterialInstance);
private static native boolean nIsValidExpensiveMaterialInstance(long nativeEngine, long nativeMaterialInstance);
private static native boolean nIsValidSkybox(long nativeEngine, long nativeSkybox);
private static native boolean nIsValidColorGrading(long nativeEngine, long nativeColorGrading);
private static native boolean nIsValidTexture(long nativeEngine, long nativeTexture);
@@ -1209,6 +1385,9 @@ public class Engine {
private static native void nDestroyEntity(long nativeEngine, int entity);
private static native void nFlushAndWait(long nativeEngine);
private static native void nFlush(long nativeEngine);
private static native boolean nIsPaused(long nativeEngine);
private static native void nSetPaused(long nativeEngine, boolean paused);
private static native void nUnprotected(long nativeEngine);
private static native long nGetTransformManager(long nativeEngine);
private static native long nGetLightManager(long nativeEngine);
private static native long nGetRenderableManager(long nativeEngine);
@@ -1227,8 +1406,14 @@ public class Engine {
private static native void nSetBuilderConfig(long nativeBuilder, long commandBufferSizeMB,
long perRenderPassArenaSizeMB, long driverHandleArenaSizeMB,
long minCommandBufferSizeMB, long perFrameCommandsSizeMB, long jobSystemThreadCount,
long stereoscopicEyeCount);
long textureUseAfterFreePoolSize, boolean disableParallelShaderCompile,
int stereoscopicType, long stereoscopicEyeCount,
long resourceAllocatorCacheSizeMB, long resourceAllocatorCacheMaxAge,
boolean disableHandleUseAfterFreeCheck,
int preferredShaderLanguage,
boolean forceGLES2Context);
private static native void nSetBuilderFeatureLevel(long nativeBuilder, int ordinal);
private static native void nSetBuilderSharedContext(long nativeBuilder, long sharedContext);
private static native void nSetBuilderPaused(long nativeBuilder, boolean paused);
private static native long nBuilderBuild(long nativeBuilder);
}

View File

@@ -346,6 +346,7 @@ public class Material {
public static class Builder {
private Buffer mBuffer;
private int mSize;
private int mShBandCount = 0;
/**
* Specifies the material data. The material data is a binary blob produced by
@@ -361,6 +362,22 @@ public class Material {
return this;
}
/**
* Sets the quality of the indirect lights computations. This is only taken into account
* if this material is lit and in the surface domain. This setting will affect the
* IndirectLight computation if one is specified on the Scene and Spherical Harmonics
* are used for the irradiance.
*
* @param shBandCount Number of spherical harmonic bands. Must be 1, 2 or 3 (default).
* @return Reference to this Builder for chaining calls.
* @see IndirectLight
*/
@NonNull
public Builder sphericalHarmonicsBandCount(@IntRange(from = 0) int shBandCount) {
mShBandCount = shBandCount;
return this;
}
/**
* Creates and returns the Material object.
*
@@ -372,7 +389,8 @@ public class Material {
*/
@NonNull
public Material build(@NonNull Engine engine) {
long nativeMaterial = nBuilderBuild(engine.getNativeObject(), mBuffer, mSize);
long nativeMaterial = nBuilderBuild(engine.getNativeObject(),
mBuffer, mSize, mShBandCount);
if (nativeMaterial == 0) throw new IllegalStateException("Couldn't create Material");
return new Material(nativeMaterial);
}
@@ -1023,7 +1041,7 @@ public class Material {
mNativeObject = 0;
}
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size);
private static native long nBuilderBuild(long nativeEngine, @NonNull Buffer buffer, int size, int shBandCount);
private static native long nCreateInstance(long nativeMaterial);
private static native long nCreateInstanceWithName(long nativeMaterial, @NonNull String name);
private static native long nGetDefaultInstance(long nativeMaterial);

View File

@@ -74,7 +74,7 @@ public class MorphTargetBuffer {
*
* @exception IllegalStateException if the MorphTargetBuffer could not be created
*
* @see #setMorphTargetBufferAt
* @see #setMorphTargetBufferOffsetAt
*/
@NonNull
public MorphTargetBuffer build(@NonNull Engine engine) {

View File

@@ -175,6 +175,32 @@ public class RenderableManager {
return this;
}
/**
* Type of geometry for a Renderable
*/
public enum GeometryType {
/** dynamic gemoetry has no restriction */
DYNAMIC,
/** bounds and world space transform are immutable */
STATIC_BOUNDS,
/** skinning/morphing not allowed and Vertex/IndexBuffer immutables */
STATIC
}
/**
* Specify whether this renderable has static bounds. In this context his means that
* the renderable's bounding box cannot change and that the renderable's transform is
* assumed immutable. Changing the renderable's transform via the TransformManager
* can lead to corrupted graphics. Note that skinning and morphing are not forbidden.
* Disabled by default.
* @param enable whether this renderable has static bounds. false by default.
*/
@NonNull
public Builder geometryType(GeometryType type) {
nBuilderGeometryType(mNativeBuilder, type.ordinal());
return this;
}
/**
* Binds a material instance to the specified primitive.
*
@@ -498,14 +524,7 @@ public class RenderableManager {
}
/**
* Controls if the renderable has vertex morphing targets, zero by default. This is
* required to enable GPU morphing.
*
* <p>Filament supports two morphing modes: standard (default) and legacy.</p>
*
* <p>For standard morphing, A {@link MorphTargetBuffer} must be created and provided via
* {@link RenderableManager#setMorphTargetBufferAt}. Standard morphing supports up to
* <code>CONFIG_MAX_MORPH_TARGET_COUNT</code> morph targets.</p>
* Controls if the renderable has legacy vertex morphing targets, zero by default.
*
* For legacy morphing, the attached {@link VertexBuffer} must provide data in the
* appropriate {@link VertexBuffer.VertexAttribute} slots (<code>MORPH_POSITION_0</code> etc).
@@ -523,6 +542,22 @@ public class RenderableManager {
return this;
}
/**
* Controls if the renderable has vertex morphing targets, zero by default.
*
* <p>For standard morphing, A {@link MorphTargetBuffer} must be provided.
* Standard morphing supports up to
* <code>CONFIG_MAX_MORPH_TARGET_COUNT</code> morph targets.</p>
*
* <p>See also {@link RenderableManager#setMorphWeights}, which can be called on a per-frame basis
* to advance the animation.</p>
*/
@NonNull
public Builder morphing(@NonNull MorphTargetBuffer morphTargetBuffer) {
nBuilderMorphingStandard(mNativeBuilder, morphTargetBuffer.getNativeObject());
return this;
}
/**
* Specifies the morph target buffer for a primitive.
*
@@ -534,31 +569,13 @@ public class RenderableManager {
*
* @param level the level of detail (lod), only 0 can be specified
* @param primitiveIndex zero-based index of the primitive, must be less than the count passed to Builder constructor
* @param morphTargetBuffer specifies the morph target buffer
* @param offset specifies where in the morph target buffer to start reading (expressed as a number of vertices)
* @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
*/
@NonNull
public Builder morphing(@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer,
@IntRange(from = 0) int offset,
@IntRange(from = 0) int count) {
nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), offset, count);
return this;
}
/**
* Utility method to specify morph target buffer for a primitive.
* For details, see the {@link RenderableManager.Builder#morphing}.
*/
@NonNull
public Builder morphing(@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer) {
nBuilderSetMorphTargetBufferAt(mNativeBuilder, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), 0, morphTargetBuffer.getVertexCount());
@IntRange(from = 0) int offset) {
nBuilderSetMorphTargetBufferOffsetAt(mNativeBuilder, level, primitiveIndex, offset);
return this;
}
@@ -661,26 +678,11 @@ public class RenderableManager {
*
* @see Builder#morphing
*/
public void setMorphTargetBufferAt(@EntityInstance int i,
public void setMorphTargetBufferOffsetAt(@EntityInstance int i,
@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer,
@IntRange(from = 0) int offset,
@IntRange(from = 0) int count) {
nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), offset, count);
}
/**
* Utility method to change morph target buffer for the given primitive.
* For details, see the {@link RenderableManager#setMorphTargetBufferAt}.
*/
public void setMorphTargetBufferAt(@EntityInstance int i,
@IntRange(from = 0) int level,
@IntRange(from = 0) int primitiveIndex,
@NonNull MorphTargetBuffer morphTargetBuffer) {
nSetMorphTargetBufferAt(mNativeObject, i, level, primitiveIndex,
morphTargetBuffer.getNativeObject(), 0, morphTargetBuffer.getVertexCount());
@IntRange(from = 0) int offset) {
nSetMorphTargetBufferOffsetAt(mNativeObject, i, level, primitiveIndex, 0, offset);
}
/**
@@ -964,6 +966,7 @@ public class RenderableManager {
private static native void nBuilderGeometry(long nativeBuilder, int index, int value, long nativeVertexBuffer, long nativeIndexBuffer);
private static native void nBuilderGeometry(long nativeBuilder, int index, int value, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int count);
private static native void nBuilderGeometry(long nativeBuilder, int index, int value, long nativeVertexBuffer, long nativeIndexBuffer, int offset, int minIndex, int maxIndex, int count);
private static native void nBuilderGeometryType(long nativeBuilder, int type);
private static native void nBuilderMaterial(long nativeBuilder, int index, long nativeMaterialInstance);
private static native void nBuilderBlendOrder(long nativeBuilder, int index, int blendOrder);
private static native void nBuilderGlobalBlendOrderEnabled(long nativeBuilder, int index, boolean enabled);
@@ -979,7 +982,8 @@ public class RenderableManager {
private static native int nBuilderSkinningBones(long nativeBuilder, int boneCount, Buffer bones, int remaining);
private static native void nBuilderSkinningBuffer(long nativeBuilder, long nativeSkinningBuffer, int boneCount, int offset);
private static native void nBuilderMorphing(long nativeBuilder, int targetCount);
private static native void nBuilderSetMorphTargetBufferAt(long nativeBuilder, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count);
private static native void nBuilderMorphingStandard(long nativeBuilder, long nativeMorphTargetBuffer);
private static native void nBuilderSetMorphTargetBufferOffsetAt(long nativeBuilder, int level, int primitiveIndex, int offset);
private static native void nBuilderEnableSkinningBuffers(long nativeBuilder, boolean enabled);
private static native void nBuilderFog(long nativeBuilder, boolean enabled);
private static native void nBuilderLightChannel(long nativeRenderableManager, int channel, boolean enable);
@@ -989,7 +993,7 @@ public class RenderableManager {
private static native int nSetBonesAsMatrices(long nativeObject, int i, Buffer matrices, int remaining, int boneCount, int offset);
private static native int nSetBonesAsQuaternions(long nativeObject, int i, Buffer quaternions, int remaining, int boneCount, int offset);
private static native void nSetMorphWeights(long nativeObject, int instance, float[] weights, int offset);
private static native void nSetMorphTargetBufferAt(long nativeObject, int i, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset, int count);
private static native void nSetMorphTargetBufferOffsetAt(long nativeObject, int i, int level, int primitiveIndex, long nativeMorphTargetBuffer, int offset);
private static native int nGetMorphTargetCount(long nativeObject, int i);
private static native void nSetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float cx, float cy, float cz, float ex, float ey, float ez);
private static native void nSetLayerMask(long nativeRenderableManager, int i, int select, int value);

View File

@@ -101,7 +101,7 @@ public class Renderer {
/**
* Desired frame interval in unit of 1 / DisplayInfo.refreshRate.
*/
public float interval = 1.0f / 60.0f;
public float interval = 1.0f;
/**
* Additional headroom for the GPU as a ratio of the targetFrameTime.
@@ -284,6 +284,33 @@ public class Renderer {
nSetPresentationTime(getNativeObject(), monotonicClockNanos);
}
/**
* The use of this method is optional. It sets the VSYNC time expressed as the duration in
* nanosecond since epoch of std::chrono::steady_clock.
* If called, passing 0 to frameTimeNanos in Renderer.BeginFrame will use this
* time instead.
* @param steadyClockTimeNano duration in nanosecond since epoch of std::chrono::steady_clock
* @see Engine#getSteadyClockTimeNano
* @see Renderer#beginFrame
*/
public void setVsyncTime(long steadyClockTimeNano) {
nSetVsyncTime(getNativeObject(), steadyClockTimeNano);
}
/**
* Call skipFrame when momentarily skipping frames, for instance if the content of the
* scene doesn't change.
*
* @param vsyncSteadyClockTimeNano The time in nanoseconds when the frame started being rendered,
* in the {@link System#nanoTime()} timebase. Divide this value by 1000000 to
* convert it to the {@link android.os.SystemClock#uptimeMillis()}
* time base. This typically comes from
* {@link android.view.Choreographer.FrameCallback}.
*/
public void skipFrame(long vsyncSteadyClockTimeNano) {
nSkipFrame(getNativeObject(), vsyncSteadyClockTimeNano);
}
/**
* Sets up a frame for this <code>Renderer</code>.
* <p><code>beginFrame</code> manages frame pacing, and returns whether or not a frame should be
@@ -702,6 +729,8 @@ public class Renderer {
}
private static native void nSetPresentationTime(long nativeObject, long monotonicClockNanos);
private static native void nSetVsyncTime(long nativeObject, long steadyClockTimeNano);
private static native void nSkipFrame(long nativeObject, long vsyncSteadyClockTimeNano);
private static native boolean nBeginFrame(long nativeRenderer, long nativeSwapChain, long frameTimeNanos);
private static native void nEndFrame(long nativeRenderer);
private static native void nRender(long nativeRenderer, long nativeView);

View File

@@ -68,77 +68,30 @@ public class SwapChain {
private final Object mSurface;
private long mNativeObject;
public static final long CONFIG_DEFAULT = 0x0;
/**
* This flag indicates that the <code>SwapChain</code> must be allocated with an
* alpha-channel.
*/
public static final long CONFIG_TRANSPARENT = 0x1;
/**
* This flag indicates that the <code>SwapChain</code> may be used as a source surface
* for reading back render results. This config must be set when creating
* any <code>SwapChain</code> that will be used as the source for a blit operation.
*
* @see Renderer#copyFrame
*/
public static final long CONFIG_READABLE = 0x2;
/**
* Indicates that the native X11 window is an XCB window rather than an XLIB window.
* This is ignored on non-Linux platforms and in builds that support only one X11 API.
*/
public static final long CONFIG_ENABLE_XCB = 0x4;
/**
* Indicates that the SwapChain must automatically perform linear to sRGB encoding.
*
* This flag is ignored if isSRGBSwapChainSupported() is false.
*
* When using this flag, post-processing should be disabled.
*
* @see SwapChain#isSRGBSwapChainSupported
* @see View#setPostProcessingEnabled
*/
public static final long CONFIG_SRGB_COLORSPACE = 0x10;
/**
* Indicates that this SwapChain should allocate a stencil buffer in addition to a depth buffer.
*
* This flag is necessary when using View::setStencilBufferEnabled and rendering directly into
* the SwapChain (when post-processing is disabled).
*
* The specific format of the stencil buffer depends on platform support. The following pixel
* formats are tried, in order of preference:
*
* Depth only (without CONFIG_HAS_STENCIL_BUFFER):
* - DEPTH32F
* - DEPTH24
*
* Depth + stencil (with CONFIG_HAS_STENCIL_BUFFER):
* - DEPTH32F_STENCIL8
* - DEPTH24F_STENCIL8
*
* Note that enabling the stencil buffer may hinder depth precision and should only be used if
* necessary.
*
* @see View#setStencilBufferEnabled
* @see View#setPostProcessingEnabled
*/
public static final long CONFIG_HAS_STENCIL_BUFFER = 0x20;
SwapChain(long nativeSwapChain, Object surface) {
mNativeObject = nativeSwapChain;
mSurface = surface;
}
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* Return whether createSwapChain supports the CONFIG_PROTECTED_CONTENT flag.
* The default implementation returns false.
*
* @param engine A reference to the filament Engine
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
* @return true if CONFIG_PROTECTED_CONTENT is supported, false otherwise.
* @see SwapChainFlags#CONFIG_PROTECTED_CONTENT
*/
public static boolean isProtectedContentSupported(@NonNull Engine engine) {
return nIsProtectedContentSupported(engine.getNativeObject());
}
/**
* Return whether createSwapChain supports the CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @param engine A reference to the filament Engine
* @return true if CONFIG_SRGB_COLORSPACE is supported, false otherwise.
* @see SwapChainFlags#CONFIG_SRGB_COLORSPACE
*/
public static boolean isSRGBSwapChainSupported(@NonNull Engine engine) {
return nIsSRGBSwapChainSupported(engine.getNativeObject());
@@ -186,4 +139,5 @@ public class SwapChain {
private static native void nSetFrameCompletedCallback(long nativeSwapChain, Object handler, Runnable callback);
private static native boolean nIsSRGBSwapChainSupported(long nativeEngine);
private static native boolean nIsProtectedContentSupported(long nativeEngine);
}

View File

@@ -0,0 +1,97 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.google.android.filament;
// Note: SwapChainFlags is kept separate from SwapChain so that UiHelper does not need to depend
// on SwapChain. This allows clients to use UiHelper without requiring all of Filament's Java
// classes.
/**
* Flags that a <code>SwapChain</code> can be created with to control behavior.
*
* @see Engine#createSwapChain
* @see Engine#createSwapChainFromNativeSurface
*/
public final class SwapChainFlags {
public static final long CONFIG_DEFAULT = 0x0;
/**
* This flag indicates that the <code>SwapChain</code> must be allocated with an
* alpha-channel.
*/
public static final long CONFIG_TRANSPARENT = 0x1;
/**
* This flag indicates that the <code>SwapChain</code> may be used as a source surface
* for reading back render results. This config must be set when creating
* any <code>SwapChain</code> that will be used as the source for a blit operation.
*
* @see Renderer#copyFrame
*/
public static final long CONFIG_READABLE = 0x2;
/**
* Indicates that the native X11 window is an XCB window rather than an XLIB window.
* This is ignored on non-Linux platforms and in builds that support only one X11 API.
*/
public static final long CONFIG_ENABLE_XCB = 0x4;
/**
* Indicates that the SwapChain must automatically perform linear to sRGB encoding.
*
* This flag is ignored if isSRGBSwapChainSupported() is false.
*
* When using this flag, post-processing should be disabled.
*
* @see SwapChain#isSRGBSwapChainSupported
* @see View#setPostProcessingEnabled
*/
public static final long CONFIG_SRGB_COLORSPACE = 0x10;
/**
* Indicates that this SwapChain should allocate a stencil buffer in addition to a depth buffer.
*
* This flag is necessary when using View::setStencilBufferEnabled and rendering directly into
* the SwapChain (when post-processing is disabled).
*
* The specific format of the stencil buffer depends on platform support. The following pixel
* formats are tried, in order of preference:
*
* Depth only (without CONFIG_HAS_STENCIL_BUFFER):
* - DEPTH32F
* - DEPTH24
*
* Depth + stencil (with CONFIG_HAS_STENCIL_BUFFER):
* - DEPTH32F_STENCIL8
* - DEPTH24F_STENCIL8
*
* Note that enabling the stencil buffer may hinder depth precision and should only be used if
* necessary.
*
* @see View#setStencilBufferEnabled
* @see View#setPostProcessingEnabled
*/
public static final long CONFIG_HAS_STENCIL_BUFFER = 0x20;
/**
* The SwapChain contains protected content. Only supported when isProtectedContentSupported()
* is true.
*/
public static final long CONFIG_PROTECTED_CONTENT = 0x40;
}

View File

@@ -16,12 +16,14 @@ package com.google.android.filament;
* <li>Configurable tone mapping operators</li>
* <ul>
* <li>GenericToneMapper</li>
* <li>AgXToneMapper</li>
* </ul>
* <li>Fixed-aesthetic tone mapping operators</li>
* <ul>
* <li>ACESToneMapper</li>
* <li>ACESLegacyToneMapper</li>
* <li>FilmicToneMapper</li>
* <li>PBRNeutralToneMapper</li>
* </ul>
* <li>Debug/validation tone mapping operators</li>
* <ul>
@@ -100,11 +102,21 @@ public class ToneMapper {
}
}
/**
* Khronos PBR Neutral tone mapping operator. This tone mapper was designed
* to preserve the appearance of materials across lighting conditions while
* avoiding artifacts in the highlights in high dynamic range conditions.
*/
public static class PBRNeutralToneMapper extends ToneMapper {
public PBRNeutralToneMapper() {
super(nCreatePBRNeutralToneMapper());
}
}
/**
* AgX tone mapping operator.
*/
public static class Agx extends ToneMapper {
public enum AgxLook {
/**
* Base contrast with no look applied
@@ -233,6 +245,7 @@ public class ToneMapper {
private static native long nCreateACESToneMapper();
private static native long nCreateACESLegacyToneMapper();
private static native long nCreateFilmicToneMapper();
private static native long nCreatePBRNeutralToneMapper();
private static native long nCreateAgxToneMapper(int look);
private static native long nCreateGenericToneMapper(
float contrast, float midGrayIn, float midGrayOut, float hdrMax);

View File

@@ -241,6 +241,15 @@ public class View {
nSetCamera(getNativeObject(), camera == null ? 0 : camera.getNativeObject());
}
/**
* Query whether a camera is set.
* @return true if a camera is set, false otherwise
* @see #setCamera
*/
public boolean hasCamera() {
return nHasCamera(getNativeObject());
}
/**
* Gets this View's associated Camera, or null if none has been assigned.
*
@@ -1224,6 +1233,18 @@ public class View {
return nGetFogEntity(getNativeObject());
}
/**
* When certain temporal features are used (e.g.: TAA or Screen-space reflections), the view
* keeps a history of previous frame renders associated with the Renderer the view was last
* used with. When switching Renderer, it may be necessary to clear that history by calling
* this method. Similarly, if the whole content of the screen change, like when a cut-scene
* starts, clearing the history might be needed to avoid artifacts due to the previous frame
* being very different.
*/
public void clearFrameHistory(Engine engine) {
nClearFrameHistory(getNativeObject(), engine.getNativeObject());
}
public long getNativeObject() {
if (mNativeObject == 0) {
throw new IllegalStateException("Calling method on destroyed View");
@@ -1238,6 +1259,7 @@ public class View {
private static native void nSetName(long nativeView, String name);
private static native void nSetScene(long nativeView, long nativeScene);
private static native void nSetCamera(long nativeView, long nativeCamera);
private static native boolean nHasCamera(long nativeView);
private static native void nSetViewport(long nativeView, int left, int bottom, int width, int height);
private static native void nSetVisibleLayers(long nativeView, int select, int value);
private static native void nSetShadowingEnabled(long nativeView, boolean enabled);
@@ -1284,7 +1306,7 @@ public class View {
private static native void nSetMaterialGlobal(long nativeView, int index, float x, float y, float z, float w);
private static native void nGetMaterialGlobal(long nativeView, int index, float[] out);
private static native int nGetFogEntity(long nativeView);
private static native void nClearFrameHistory(long nativeView, long nativeEngine);
/**
* List of available ambient occlusion techniques.
@@ -1637,6 +1659,10 @@ public class View {
* circle of confusion scale factor (amount of blur)
*/
public float cocScale = 1.0f;
/**
* width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
*/
public float cocAspectRatio = 1.0f;
/**
* maximum aperture diameter in meters (zero to disable rotation)
*/
@@ -1921,6 +1947,7 @@ public class View {
UNIFORM_HELIX_X4,
HALTON_23_X8,
HALTON_23_X16,
HALTON_23_X32,
}
/**
@@ -1935,6 +1962,10 @@ public class View {
* texturing lod bias (typically -1 or -2)
*/
public float lodBias = -1.0f;
/**
* post-TAA sharpen, especially useful when upscaling is true.
*/
public float sharpness = 0.0f;
/**
* enables or disables temporal anti-aliasing
*/

View File

@@ -27,7 +27,7 @@ import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.TextureView;
import com.google.android.filament.SwapChain;
import com.google.android.filament.SwapChainFlags;
/**
* UiHelper is a simple class that can manage either a SurfaceView, TextureView, or a SurfaceHolder
@@ -538,7 +538,7 @@ public class UiHelper {
* the options set on this UiHelper.
*/
public long getSwapChainFlags() {
return isOpaque() ? SwapChain.CONFIG_DEFAULT : SwapChain.CONFIG_TRANSPARENT;
return isOpaque() ? SwapChainFlags.CONFIG_DEFAULT : SwapChainFlags.CONFIG_TRANSPARENT;
}
/**

View File

@@ -31,6 +31,7 @@ set_target_properties(iblprefilter PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libfilament-iblprefilter.a)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libfilament-utils-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
add_library(filament-utils-jni SHARED
src/main/cpp/AutomationEngine.cpp

View File

@@ -125,6 +125,11 @@ extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBu
builder->groundPlane(a, b, c, d);
}
extern "C" JNIEXPORT void Java_com_google_android_filament_utils_Manipulator_nBuilderPanning(JNIEnv*, jclass, jlong nativeBuilder, jboolean enabled) {
Builder* builder = (Builder*) nativeBuilder;
builder->panning(enabled);
}
extern "C" JNIEXPORT long Java_com_google_android_filament_utils_Manipulator_nBuilderBuild(JNIEnv*, jclass, jlong nativeBuilder, jint mode) {
Builder* builder = (Builder*) nativeBuilder;
return (jlong) builder->build((Mode) mode);

View File

@@ -274,6 +274,17 @@ public class Manipulator {
return this;
}
/**
* Sets whether panning is enabled in the manipulator.
*
* @return this <code>Builder</code> object for chaining calls
*/
@NonNull
public Builder panning(Boolean enabled) {
nBuilderPanning(mNativeBuilder, enabled);
return this;
}
/**
* Creates and returns the <code>Manipulator</code> object.
*
@@ -483,6 +494,7 @@ public class Manipulator {
private static native void nBuilderFlightPanSpeed(long nativeBuilder, float x, float y);
private static native void nBuilderFlightMoveDamping(long nativeBuilder, float damping);
private static native void nBuilderGroundPlane(long nativeBuilder, float a, float b, float c, float d);
private static native void nBuilderPanning(long nativeBuilder, Boolean enabled);
private static native long nBuilderBuild(long nativeBuilder, int mode);
private static native void nDestroyManipulator(long nativeManip);

View File

@@ -44,6 +44,7 @@ set_target_properties(uberarchive PROPERTIES IMPORTED_LOCATION
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libuberarchive.a)
set(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map")
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,-z,max-page-size=16384")
set(GLTFIO_SRCS
${GLTFIO_DIR}/include/gltfio/Animator.h
@@ -81,9 +82,20 @@ set(GLTFIO_SRCS
${GLTFIO_DIR}/src/TangentsJob.cpp
${GLTFIO_DIR}/src/TangentsJob.h
${GLTFIO_DIR}/src/UbershaderProvider.cpp
${GLTFIO_DIR}/src/Utility.cpp
${GLTFIO_DIR}/src/Utility.h
${GLTFIO_DIR}/src/Wireframe.cpp
${GLTFIO_DIR}/src/Wireframe.h
${GLTFIO_DIR}/src/downcast.h
${GLTFIO_DIR}/src/extended/AssetLoaderExtended.cpp
${GLTFIO_DIR}/src/extended/AssetLoaderExtended.h
${GLTFIO_DIR}/src/extended/ResourceLoaderExtended.cpp
${GLTFIO_DIR}/src/extended/ResourceLoaderExtended.h
${GLTFIO_DIR}/src/extended/TangentsJobExtended.cpp
${GLTFIO_DIR}/src/extended/TangentsJobExtended.h
${GLTFIO_DIR}/src/extended/TangentSpaceMeshWrapper.cpp
${GLTFIO_DIR}/src/extended/TangentSpaceMeshWrapper.h
src/main/cpp/Animator.cpp
src/main/cpp/AssetLoader.cpp
@@ -108,7 +120,6 @@ set(GLTFIO_INCLUDE_DIRS
../../third_party/cgltf
../../third_party/meshoptimizer/src
../../third_party/robin-map
../../third_party/hat-trie
../../third_party/stb
../../libs/utils/include
../../libs/ktxreader/include

View File

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

View File

@@ -1,6 +1,6 @@
#Wed Nov 17 10:40:18 PST 2021
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.6-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@@ -30,7 +30,7 @@ android {
compileSdkVersion versions.compileSdk
defaultConfig {
applicationId "com.google.android.filament.gltf"
minSdkVersion 19
minSdkVersion versions.minSdk
targetSdkVersion versions.targetSdk
}

View File

@@ -321,7 +321,7 @@ class MainActivity : Activity() {
var flags = uiHelper.swapChainFlags
if (engine.activeFeatureLevel == Engine.FeatureLevel.FEATURE_LEVEL_0) {
if (SwapChain.isSRGBSwapChainSupported(engine)) {
flags = flags or SwapChain.CONFIG_SRGB_COLORSPACE
flags = flags or SwapChainFlags.CONFIG_SRGB_COLORSPACE
}
}

View File

@@ -44,8 +44,6 @@ function print_help {
echo " Exclude Vulkan support from the Android build."
echo " -s"
echo " Add iOS simulator support to the iOS build."
echo " -t"
echo " Enable SwiftShader support for Vulkan in desktop builds."
echo " -e"
echo " Enable EGL on Linux support for desktop builds."
echo " -l"
@@ -61,6 +59,14 @@ function print_help {
echo " -b"
echo " Enable Address and Undefined Behavior Sanitizers (asan/ubsan) for debugging."
echo " This is only for the desktop build."
echo " -x value"
echo " Define a preprocessor flag FILAMENT_BACKEND_DEBUG_FLAG with [value]. This is useful for"
echo " enabling debug paths in the backend from the build script. For example, make a"
echo " systrace-enabled build without directly changing #defines. Remember to add -f when"
echo " changing this option."
echo " -S type"
echo " Enable stereoscopic rendering where type is one of [instanced|multiview]. This is only"
echo " meant for building the samples."
echo ""
echo "Build types:"
echo " release"
@@ -160,8 +166,6 @@ INSTALL_COMMAND=
VULKAN_ANDROID_OPTION="-DFILAMENT_SUPPORTS_VULKAN=ON"
VULKAN_ANDROID_GRADLE_OPTION=""
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=OFF"
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=OFF"
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
@@ -172,6 +176,10 @@ MATOPT_GRADLE_OPTION=""
ASAN_UBSAN_OPTION=""
BACKEND_DEBUG_FLAG_OPTION=""
STEREOSCOPIC_OPTION=""
IOS_BUILD_SIMULATOR=false
BUILD_UNIVERSAL_LIBRARIES=false
@@ -226,11 +234,12 @@ function build_desktop_target {
-DIMPORT_EXECUTABLES_DIR=out \
-DCMAKE_BUILD_TYPE="$1" \
-DCMAKE_INSTALL_PREFIX="../${lc_target}/filament" \
${SWIFTSHADER_OPTION} \
${EGL_ON_LINUX_OPTION} \
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${ASAN_UBSAN_OPTION} \
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
${architectures} \
../..
ln -sf "out/cmake-${lc_target}/compile_commands.json" \
@@ -289,6 +298,7 @@ function build_webgl_with_target {
-DCMAKE_BUILD_TYPE="$1" \
-DCMAKE_INSTALL_PREFIX="../webgl-${lc_target}/filament" \
-DWEBGL=1 \
${BACKEND_DEBUG_FLAG_OPTION} \
../..
ln -sf "out/cmake-webgl-${lc_target}/compile_commands.json" \
../../compile_commands.json
@@ -363,6 +373,8 @@ function build_android_target {
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${VULKAN_ANDROID_OPTION} \
${BACKEND_DEBUG_FLAG_OPTION} \
${STEREOSCOPIC_OPTION} \
../..
ln -sf "out/cmake-android-${lc_target}-${arch}/compile_commands.json" \
../../compile_commands.json
@@ -516,7 +528,7 @@ function build_android {
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
echo "Installing out/${sample}-debug.apk"
cp samples/${sample}/build/outputs/apk/debug/${sample}-debug-unsigned.apk \
cp samples/${sample}/build/outputs/apk/debug/${sample}-debug.apk \
../out/${sample}-debug.apk
done
fi
@@ -597,6 +609,7 @@ function build_ios_target {
-DCMAKE_TOOLCHAIN_FILE=../../third_party/clang/iOS.cmake \
${MATDBG_OPTION} \
${MATOPT_OPTION} \
${STEREOSCOPIC_OPTION} \
../..
ln -sf "out/cmake-ios-${lc_target}-${arch}/compile_commands.json" \
../../compile_commands.json
@@ -730,6 +743,13 @@ function validate_build_command {
exit 1
fi
fi
# Make sure FILAMENT_BACKEND_DEBUG_FLAG is only meant for debug builds
if [[ "${ISSUE_DEBUG_BUILD}" != "true" ]] && [[ ! -z "${BACKEND_DEBUG_FLAG_OPTION}" ]]; then
echo "Error: cannot specify FILAMENT_BACKEND_DEBUG_FLAG in non-debug build"
exit 1
fi
set -e
}
@@ -776,7 +796,7 @@ function check_debug_release_build {
pushd "$(dirname "$0")" > /dev/null
while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
while getopts ":hacCfgijmp:q:uvslwedk:bx:S:" opt; do
case ${opt} in
h)
print_help
@@ -840,7 +860,7 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
echo "Platform must be one of [desktop|android|ios|webgl|all]"
echo ""
exit 1
;;
;;
esac
done
;;
@@ -895,10 +915,6 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
IOS_BUILD_SIMULATOR=true
echo "iOS simulator support enabled."
;;
t)
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=ON"
echo "SwiftShader support enabled."
;;
e)
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=ON -DFILAMENT_SKIP_SDL2=ON -DFILAMENT_SKIP_SAMPLES=ON"
echo "EGL on Linux support enabled; skipping SDL2."
@@ -918,6 +934,22 @@ while getopts ":hacCfgijmp:q:uvslwtedk:b" opt; do
b) ASAN_UBSAN_OPTION="-DFILAMENT_ENABLE_ASAN_UBSAN=ON"
echo "Enabled ASAN/UBSAN"
;;
x) BACKEND_DEBUG_FLAG_OPTION="-DFILAMENT_BACKEND_DEBUG_FLAG=${OPTARG}"
;;
S) case $(echo "${OPTARG}" | tr '[:upper:]' '[:lower:]') in
instanced)
STEREOSCOPIC_OPTION="-DFILAMENT_SAMPLES_STEREO_TYPE=instanced"
;;
multiview)
STEREOSCOPIC_OPTION="-DFILAMENT_SAMPLES_STEREO_TYPE=multiview"
;;
*)
echo "Unknown stereoscopic type ${OPTARG}"
echo "Type must be one of [instanced|multiview]"
echo ""
exit 1
esac
;;
\?)
echo "Invalid option: -${OPTARG}" >&2
echo ""

View File

@@ -57,7 +57,8 @@ FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION:-$(cat `dirname $0`/ndk.version)}
# Install the required NDK version specifically (if not present)
if [[ ! -d "${ANDROID_HOME}/ndk/$FILAMENT_NDK_VERSION" ]]; then
${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION" > /dev/null
yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --licenses
${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION"
fi
# Only build 1 64 bit target during presubmit to cut down build times during presubmit

View File

@@ -1 +1 @@
25.1.8937393
27.0.11718014

View File

@@ -125,7 +125,13 @@ if [[ "${has_universal}" == "true" ]]; then
arch_output="${OUTPUT_PATH%.a}_${arch}.a"
arch_outputs+=("$arch_output")
combine_static_libs "$arch_output" $(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a')
archives=()
while IFS= read -r -d $'\0'; do
archives+=("$REPLY")
done < <(find "$(pwd)/${archs_temp_dir}/${arch}" -iname '*.a' -print0)
combine_static_libs "$arch_output" "$archives"
done
# Finally, combine the single-architecture archives into a universal binary.

View File

@@ -1,53 +0,0 @@
# Build the image:
# docker build --no-cache --tag ssfilament -f build/swiftshader/Dockerfile .
# docker tag ssfilament ghcr.io/filament-assets/swiftshader
#
# Publish the image:
# docker login ghcr.io --username <user> --password <token>
# docker push ghcr.io/filament-assets/swiftshader
#
# Run the image and mount the current directory:
# docker run -it -v `pwd`:/trees/filament -t ssfilament
FROM ubuntu:focal
WORKDIR /trees
ARG DEBIAN_FRONTEND=noninteractive
ENV SWIFTSHADER_LD_LIBRARY_PATH=/trees/swiftshader/build
ENV CXXFLAGS='-fno-builtin -Wno-pass-failed'
RUN apt-get update && \
apt-get --no-install-recommends install -y \
apt-transport-https \
apt-utils \
build-essential \
cmake \
ca-certificates \
git \
ninja-build \
python \
python3 \
xorg-dev \
clang-7 \
libc++-7-dev \
libc++abi-7-dev \
lldb
# Ensure that clang is used instead of gcc.
RUN set -eux ;\
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-7 100 ;\
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-7 100 ;\
update-alternatives --install /usr/bin/cc cc /usr/bin/clang 100 ;\
update-alternatives --install /usr/bin/c++ c++ /usr/bin/clang++ 100
# Get patch files from the local Filament tree.
COPY build/swiftshader/*.diff .
# Clone SwiftShader, apply patches, and build it.
RUN set -eux ;\
git clone https://swiftshader.googlesource.com/SwiftShader swiftshader ;\
cd swiftshader ;\
git checkout 139f5c3 ;\
git apply /trees/*.diff ;\
cd build ;\
cmake .. -GNinja -DCMAKE_BUILD_TYPE=Release ;\
ninja

View File

@@ -1,56 +0,0 @@
#!/usr/bin/env python3
from pathlib import Path
import os
spath = os.path.dirname(os.path.realpath(__file__))
path = Path(spath)
folder = "../../results/"
images = list(path.glob(folder + '*.png'))
images.sort()
gallery = open(path.absolute().joinpath(folder + 'index.html'), 'w')
gallery.write("""<html>
<head>
<script type="module" src="https://unpkg.com/img-comparison-slider@latest/dist/component/component.esm.js"></script>
<script nomodule="" src="https://unpkg.com/img-comparison-slider@latest/dist/component/component.js"></script>
<link rel="stylesheet" href="https://unpkg.com/img-comparison-slider@latest/dist/collection/styles/initial.css"/>
<style>
h2 {
font-weight: normal;
margin-top: 150px;
margin-bottom: 20px;
}
a {
text-decoration: none;
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
color: blue;
}
a:hover {
font-weight: bold;
}
</style>
</head>
<body>
""")
tag = ''
for image in images:
group = image.stem.rstrip('0123456789')
before = f'https://filament-assets.github.io/golden/{group}/{image.name}'
after = image.name
gallery.write('\n')
gallery.write(f'<h2><a href="{image.stem}.json">{image.stem}.json</a></h2>\n')
gallery.write('<img-comparison-slider>\n')
gallery.write(f'<img slot="before" src="{before}" /> <img slot="after" src="{after}" />\n')
gallery.write('</img-comparison-slider>\n')
gallery.write("""</body>
</html>
""")

View File

@@ -1,62 +0,0 @@
diff --git a/src/Vulkan/VkPipeline.cpp b/src/Vulkan/VkPipeline.cpp
index 86913ec72..3b35345af 100644
--- a/src/Vulkan/VkPipeline.cpp
+++ b/src/Vulkan/VkPipeline.cpp
@@ -71,7 +71,56 @@ std::vector<uint32_t> preprocessSpirv(
if(optimize)
{
// Full optimization list taken from spirv-opt.
- opt.RegisterPerformancePasses();
+
+ // We have removed CreateRedundancyEliminationPass because it segfaults when encountering:
+ // %389 = OpCompositeConstruct %7 %386 %387 %388 %86
+ // When inserting an entry into instruction_to_value_ (which is an unordered_map)
+ // This could perhaps be investigated further with help from asan.
+
+ using namespace spvtools;
+ opt.RegisterPass(CreateWrapOpKillPass())
+ .RegisterPass(CreateDeadBranchElimPass())
+ .RegisterPass(CreateMergeReturnPass())
+ .RegisterPass(CreateInlineExhaustivePass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreatePrivateToLocalPass())
+ .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
+ .RegisterPass(CreateLocalSingleStoreElimPass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateScalarReplacementPass())
+ .RegisterPass(CreateLocalAccessChainConvertPass())
+ .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
+ .RegisterPass(CreateLocalSingleStoreElimPass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateLocalMultiStoreElimPass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateCCPPass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateLoopUnrollPass(true))
+ .RegisterPass(CreateDeadBranchElimPass())
+ .RegisterPass(CreateRedundancyEliminationPass()) // workaround for SEGFAULT
+ .RegisterPass(CreateCombineAccessChainsPass())
+ .RegisterPass(CreateSimplificationPass())
+ .RegisterPass(CreateScalarReplacementPass())
+ .RegisterPass(CreateLocalAccessChainConvertPass())
+ .RegisterPass(CreateLocalSingleBlockLoadStoreElimPass())
+ .RegisterPass(CreateLocalSingleStoreElimPass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateSSARewritePass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateVectorDCEPass())
+ .RegisterPass(CreateDeadInsertElimPass())
+ .RegisterPass(CreateDeadBranchElimPass())
+ .RegisterPass(CreateSimplificationPass())
+ .RegisterPass(CreateIfConversionPass())
+ .RegisterPass(CreateCopyPropagateArraysPass())
+ .RegisterPass(CreateReduceLoadSizePass())
+ .RegisterPass(CreateAggressiveDCEPass())
+ .RegisterPass(CreateBlockMergePass())
+ .RegisterPass(CreateRedundancyEliminationPass()) // workaround for SEGFAULT
+ .RegisterPass(CreateDeadBranchElimPass())
+ .RegisterPass(CreateBlockMergePass())
+ .RegisterPass(CreateSimplificationPass());
}
std::vector<uint32_t> optimized;

View File

@@ -1,127 +0,0 @@
#!/bin/bash
set -e
function print_help {
local self_name=$(basename "$0")
echo "This script issues docker commands for testing Filament with SwiftShader."
echo "The usual sequence of commands is: fetch, start, build filament release, and run."
echo ""
echo "Usage:"
echo " $self_name [command]"
echo ""
echo "Commands:"
echo " build filament [debug | release]"
echo " Use the container to build Filament."
echo " build swiftshader [debug | release]"
echo " Use the container to do a clean rebuild of SwiftShader."
echo " (Note that the container already has SwiftShader built.)"
echo " fetch"
echo " Download the docker image from the central repository."
echo " help"
echo " Print this help message."
echo " logs"
echo " Print messages from the container's kernel ring buffer."
echo " This is useful for diagnosing OOM issues."
echo " run [lldb]"
echo " Launch a test inside the container, optionally via lldb."
echo " shell"
echo " Interact with a bash prompt in the container."
echo " start"
echo " Start a container from the image."
echo " stop"
echo " Stop the container."
echo ""
}
# Change the current working directory to the Filament root.
pushd "$(dirname "$0")/../.." > /dev/null
if [[ "$1" == "build" ]] && [[ "$2" == "filament" ]]; then
docker exec runner filament/build.sh -t $3 gltf_viewer
exit $?
fi
if [[ "$1" == "build" ]] && [[ "$2" == "swiftshader" ]]; then
BUILD_TYPE="$3"
BUILD_TYPE="$(tr '[:lower:]' '[:upper:]' <<< ${BUILD_TYPE:0:1})${BUILD_TYPE:1}"
docker exec --workdir /trees/swiftshader runner rm -rf build
docker exec --workdir /trees/swiftshader runner mkdir build
docker exec --workdir /trees/swiftshader/build runner cmake -GNinja -DCMAKE_BUILD_TYPE="$BUILD_TYPE" ..
docker exec --workdir /trees/swiftshader/build runner ninja
exit $?
fi
if [[ "$1" == "fetch" ]]; then
docker pull ghcr.io/filament-assets/swiftshader:latest
docker tag ghcr.io/filament-assets/swiftshader:latest ssfilament
exit $?
fi
if [[ "$1" == "help" ]]; then
print_help
exit 0
fi
if [[ "$1" == "logs" ]]; then
docker exec runner dmesg --human --read-clear
exit $?
fi
if [[ "$1" == "run" ]] && [[ "$2" == "lldb" ]]; then
docker exec -i --workdir /trees/filament/results runner \
lldb --batch -o run -o bt -- \
../out/cmake-release/samples/gltf_viewer \
--headless \
--batch ../libs/viewer/tests/basic.json \
--api vulkan
docker exec runner /trees/filament/build/swiftshader/gallery.py
exit $?
fi
if [[ "$1" == "run" ]]; then
docker exec --tty --workdir /trees/filament/results runner \
/usr/bin/catchsegv \
../out/cmake-release/samples/gltf_viewer \
--headless \
--batch ../libs/viewer/tests/basic.json \
--api vulkan
docker exec runner /trees/filament/build/swiftshader/gallery.py
exit $?
fi
if [[ "$1" == "shell" ]]; then
docker exec --interactive --tty runner /bin/bash
exit $?
fi
# Notes on options being passed to docker's run command:
#
# - The memory constraint seems to prevent an OOM signal in GitHub Actions.
# - The cap / security args allow use of lldb and creation of core dumps.
# - The privileged arg allows use of dmesg for examining OOM logs.
#
# Currently, a GitHub Actions VM has 2 CPUs, 7 GB RAM, and 14 GB of SSD disk space.
#
# Please be aware that Docker Desktop might impose additional resource constraints, and that those
# settings can only be controlled with its GUI. We recommend at least 7 GB of memory and 2 GB swap.
if [[ "$1" == "start" ]]; then
mkdir -p results
docker run --tty --rm --detach --privileged \
--memory 6.5g \
--name runner \
--cap-add=SYS_PTRACE \
--security-opt seccomp=unconfined \
--security-opt apparmor=unconfined \
--volume `pwd`:/trees/filament \
--workdir /trees \
ssfilament
exit $?
fi
if [[ "$1" == "stop" ]]; then
docker container rm runner --force
exit $?
fi
print_help
exit 1

View File

@@ -21,7 +21,7 @@ set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# android
set(API_LEVEL 19)
set(API_LEVEL 21)
# architecture
set(ARCH armv7a-linux-androideabi)

View File

@@ -21,7 +21,7 @@ set(CMAKE_SYSTEM_NAME Linux)
set(CMAKE_SYSTEM_VERSION 1)
# android
set(API_LEVEL 19)
set(API_LEVEL 21)
# architecture
set(ARCH i686-linux-android)

View File

@@ -476,7 +476,7 @@ Energy conservation is one of the key components of a good BRDF for physically b
<p>
For the specular term, \(f_m\) is a mirror BRDF that can be modeled with the Fresnel law, noted \(F\) in the Cook-Torrance approximation of the microfacet model integration:
For the specular term, \(f_r\) is a mirror BRDF that can be modeled with the Fresnel law, noted \(F\) in the Cook-Torrance approximation of the microfacet model integration:
</p><p>
@@ -857,7 +857,7 @@ The full GLSL implementation of the standard model is shown in <a href="#listing
<span class="line"> <span class="hljs-comment">// perceptually linear roughness to roughness (see parameterization)</span></span>
<span class="line"> <span class="hljs-type">float</span> roughness = perceptualRoughness * perceptualRoughness;</span>
<span class="line"></span>
<span class="line"> <span class="hljs-type">float</span> D = D_GGX(NoH, a);</span>
<span class="line"> <span class="hljs-type">float</span> D = D_GGX(NoH, roughness);</span>
<span class="line"> <span class="hljs-type">vec3</span> F = F_Schlick(LoH, f0);</span>
<span class="line"> <span class="hljs-type">float</span> V = V_SmithGGXCorrelated(NoV, NoL, roughness);</span>
<span class="line"></span>

File diff suppressed because one or more lines are too long

View File

@@ -1397,7 +1397,7 @@ Type
: `string`
Value
: Any of `opaque`, `transparent`, `fade`, `add`, `masked`, `multiply`, `screen`. Defaults to `opaque`.
: Any of `opaque`, `transparent`, `fade`, `add`, `masked`, `multiply`, `screen`, `custom`. Defaults to `opaque`.
Description
: Defines how/if the rendered object is blended with the content of the render target.
@@ -1420,6 +1420,7 @@ Description
of the material's output defines whether a fragment is discarded or not. Additionally,
ALPHA_TO_COVERAGE is enabled for non-translucent views. See the maskThreshold section for more
information.
- **Custom**: blending is enabled. But the blending function is user specified. See `blendFunction`.
!!! Note
When `blending` is set to `masked`, alpha to coverage is automatically enabled for the material.
@@ -1432,6 +1433,36 @@ material {
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Blending and transparency: blendFunction
Type
: `object`
Fields
: `srcRGB`, `srcA`, `dstRGB`, `dstA`
Description
: - *srcRGB*: source function applied to the RGB channels
- *srcA*: source function applied to the alpha channel
- *srcRGB*: destination function applied to the RGB channels
- *srcRGB*: destination function applied to the alpha channel
The values possible for each functions are one of `zero`, `one`, `srcColor`, `oneMinusSrcColor`,
`dstColor`, `oneMinusDstColor`, `srcAlpha`, `oneMinusSrcAlpha`, `dstAlpha`,
`oneMinusDstAlpha`, `srcAlphaSaturate`
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
material {
blending : custom,
blendFunction :
{
srcRGB: one,
srcA: one,
dstRGB: oneMinusSrcColor,
dstA: oneMinusSrcAlpha
}
}
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
### Blending and transparency: postLightingBlending
Type
@@ -2394,6 +2425,7 @@ The following APIs are only available from the vertex block:
**getWorldFromModelMatrix()** | float4x4 | Matrix that converts from model (object) space to world space
**getWorldFromModelNormalMatrix()** | float3x3 | Matrix that converts normals from model (object) space to world space
**getVertexIndex()** | int | Index of the current vertex
**getEyeIndex()** | int | Index of the eye being rendered, starting at 0
### Fragment only

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -43,7 +43,7 @@ filament-viewer::part(canvas) {
</p>
</main>
<script src="https://unpkg.com/filament@1.44.0/filament.js"></script>
<script src="https://unpkg.com/filament@1.51.6/filament.js"></script>
<script src="https://unpkg.com/gltumble"></script>
<script src="filament-viewer.js" type="module"></script>
</body>

View File

@@ -66,6 +66,7 @@ set(SRCS
src/Froxelizer.cpp
src/Frustum.cpp
src/HwRenderPrimitiveFactory.cpp
src/HwVertexBufferInfoFactory.cpp
src/IndexBuffer.cpp
src/IndirectLight.cpp
src/InstanceBuffer.cpp
@@ -137,6 +138,7 @@ set(SRCS
set(PRIVATE_HDRS
src/Allocators.h
src/Bimap.h
src/BufferPoolAllocator.h
src/ColorSpaceUtils.h
src/Culler.h
@@ -147,6 +149,7 @@ set(PRIVATE_HDRS
src/FrameSkipper.h
src/Froxelizer.h
src/HwRenderPrimitiveFactory.h
src/HwVertexBufferInfoFactory.h
src/Intersections.h
src/MaterialParser.h
src/PerViewUniforms.h
@@ -160,6 +163,7 @@ set(PRIVATE_HDRS
src/ResourceList.h
src/ShadowMap.h
src/ShadowMapManager.h
src/SharedHandle.h
src/TypedUniformBuffer.h
src/UniformBuffer.h
src/components/CameraManager.h
@@ -211,7 +215,9 @@ set(PRIVATE_HDRS
set(MATERIAL_SRCS
src/materials/antiAliasing/fxaa.mat
src/materials/antiAliasing/taa.mat
src/materials/blitDepth.mat
src/materials/blitLow.mat
src/materials/blitArray.mat
src/materials/bloom/bloomDownsample.mat
src/materials/bloom/bloomDownsample2x.mat
src/materials/bloom/bloomDownsample9.mat
@@ -238,6 +244,7 @@ set(MATERIAL_SRCS
src/materials/resolveDepth.mat
src/materials/separableGaussianBlur.mat
src/materials/skybox.mat
src/materials/shadowmap.mat
src/materials/ssao/bilateralBlur.mat
src/materials/ssao/bilateralBlurBentNormals.mat
src/materials/ssao/mipmapDepth.mat
@@ -247,8 +254,13 @@ set(MATERIAL_SRCS
)
set(MATERIAL_FL0_SRCS
src/materials/defaultMaterial0.mat
src/materials/skybox0.mat
src/materials/defaultMaterial.mat
src/materials/skybox.mat
)
set(MATERIAL_MULTIVIEW_SRCS
src/materials/defaultMaterial.mat
src/materials/skybox.mat
)
# Embed the binary resource blob for materials.
@@ -280,6 +292,11 @@ if (FILAMENT_ENABLE_FEATURE_LEVEL_0)
add_definitions(-DFILAMENT_ENABLE_FEATURE_LEVEL_0)
endif()
# Whether to include MULTIVIEW materials.
if (FILAMENT_ENABLE_MULTIVIEW)
add_definitions(-DFILAMENT_ENABLE_MULTIVIEW)
endif()
# ==================================================================================================
# Definitions
# ==================================================================================================
@@ -310,33 +327,42 @@ foreach (mat_src ${MATERIAL_SRCS})
get_filename_component(localname "${mat_src}" NAME_WE)
get_filename_component(fullname "${mat_src}" ABSOLUTE)
set(output_path "${MATERIAL_DIR}/${localname}.filamat")
add_custom_command(
OUTPUT ${output_path}
COMMAND matc ${MATC_BASE_FLAGS} -o ${output_path} ${fullname}
MAIN_DEPENDENCY ${fullname}
DEPENDS matc
COMMENT "Compiling material ${mat_src} to ${output_path}"
COMMENT "Compiling material ${fullname} to ${output_path}"
)
list(APPEND MATERIAL_BINS ${output_path})
endforeach()
if (FILAMENT_ENABLE_FEATURE_LEVEL_0)
foreach (mat_src ${MATERIAL_FL0_SRCS})
get_filename_component(localname "${mat_src}" NAME_WE)
get_filename_component(fullname "${mat_src}" ABSOLUTE)
set(output_path "${MATERIAL_DIR}/${localname}.filamat")
list(FIND MATERIAL_FL0_SRCS ${mat_src} index)
if (${index} GREATER -1 AND FILAMENT_ENABLE_FEATURE_LEVEL_0)
string(REGEX REPLACE "[.]filamat$" "_fl0.filamat" output_path_fl0 ${output_path})
add_custom_command(
OUTPUT ${output_path}
COMMAND matc ${MATC_BASE_FLAGS} -o ${output_path} ${fullname}
OUTPUT ${output_path_fl0}
COMMAND matc ${MATC_BASE_FLAGS} -PfeatureLevel=0 -o ${output_path_fl0} ${fullname}
MAIN_DEPENDENCY ${fullname}
DEPENDS matc
COMMENT "Compiling material ${mat_src} to ${output_path}"
COMMENT "Compiling material ${fullname} to ${output_path_fl0}"
)
list(APPEND MATERIAL_BINS ${output_path})
endforeach ()
endif ()
list(APPEND MATERIAL_BINS ${output_path_fl0})
endif ()
list(FIND MATERIAL_MULTIVIEW_SRCS ${mat_src} index)
if (${index} GREATER -1 AND FILAMENT_ENABLE_MULTIVIEW)
string(REGEX REPLACE "[.]filamat$" "_multiview.filamat" output_path_multiview ${output_path})
add_custom_command(
OUTPUT ${output_path_multiview}
COMMAND matc ${MATC_BASE_FLAGS} -PstereoscopicType=multiview -o ${output_path_multiview} ${fullname}
MAIN_DEPENDENCY ${fullname}
DEPENDS matc
COMMENT "Compiling material ${fullname} to ${output_path_multiview}"
)
list(APPEND MATERIAL_BINS ${output_path_multiview})
endif ()
endforeach()
# Additional dependencies on included files for materials

View File

@@ -66,11 +66,13 @@ set(PRIVATE_HDRS
# OpenGL / OpenGL ES Sources
# ==================================================================================================
if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMENT_USE_SWIFTSHADER)
if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3)
list(APPEND SRCS
include/backend/platforms/OpenGLPlatform.h
src/opengl/gl_headers.cpp
src/opengl/gl_headers.h
src/opengl/GLBufferObject.h
src/opengl/GLTexture.h
src/opengl/GLUtils.cpp
src/opengl/GLUtils.h
src/opengl/OpenGLBlobCache.cpp
@@ -166,6 +168,10 @@ endif()
if (FILAMENT_SUPPORTS_VULKAN)
list(APPEND SRCS
include/backend/platforms/VulkanPlatform.h
src/vulkan/caching/VulkanDescriptorSetManager.cpp
src/vulkan/caching/VulkanDescriptorSetManager.h
src/vulkan/caching/VulkanPipelineLayoutCache.cpp
src/vulkan/caching/VulkanPipelineLayoutCache.h
src/vulkan/platform/VulkanPlatform.cpp
src/vulkan/platform/VulkanPlatformSwapChainImpl.cpp
src/vulkan/platform/VulkanPlatformSwapChainImpl.h
@@ -411,7 +417,9 @@ if (APPLE OR LINUX)
test/test_MissingRequiredAttributes.cpp
test/test_ReadPixels.cpp
test/test_BufferUpdates.cpp
test/test_Callbacks.cpp
test/test_MRT.cpp
test/test_PushConstants.cpp
test/test_LoadImage.cpp
test/test_StencilBuffer.cpp
test/test_Scissor.cpp
@@ -472,6 +480,10 @@ if (APPLE)
# linker from removing "unused" symbols.
target_link_libraries(backend_test_mac PRIVATE -force_load backend_test)
set_target_properties(backend_test_mac PROPERTIES FOLDER Tests)
# This is needed after XCode 15.3
set_target_properties(backend_test_mac PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
set_target_properties(backend_test_mac PROPERTIES INSTALL_RPATH /usr/local/lib)
endif()
endif()

View File

@@ -23,7 +23,6 @@
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {

View File

@@ -17,8 +17,6 @@
#ifndef TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#include <utils/compiler.h>
namespace filament::backend {
/**

View File

@@ -22,13 +22,17 @@
#include <utils/BitmaskEnum.h>
#include <utils/unwindows.h> // Because we define ERROR in the FenceStatus enum.
#include <backend/Platform.h>
#include <backend/PresentCallable.h>
#include <utils/Invocable.h>
#include <utils/ostream.h>
#include <math/vec4.h>
#include <array> // FIXME: STL headers are not allowed in public headers
#include <array> // FIXME: STL headers are not allowed in public headers
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <variant> // FIXME: STL headers are not allowed in public headers
#include <stddef.h>
#include <stdint.h>
@@ -80,14 +84,24 @@ static constexpr uint64_t SWAP_CHAIN_CONFIG_SRGB_COLORSPACE = 0x10;
/**
* Indicates that the SwapChain should also contain a stencil component.
*/
static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = 0x20;
static constexpr uint64_t SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER = 0x20;
static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER;
/**
* The SwapChain contains protected content. Currently only supported by OpenGLPlatform and
* only when OpenGLPlatform::isProtectedContextSupported() is true.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_PROTECTED_CONTENT = 0x40;
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_SAMPLER_COUNT = 62; // Maximum needed at feature level 3.
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
static constexpr size_t MAX_SSBO_COUNT = 4; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_PUSH_CONSTANT_COUNT = 32; // Vulkan 1.1 spec allows for 128-byte
// of push constant (we assume 4-byte
// types).
// Per feature level caps
// Use (int)FeatureLevel to index this array
static constexpr struct {
@@ -104,7 +118,7 @@ static_assert(MAX_VERTEX_BUFFER_COUNT <= MAX_VERTEX_ATTRIBUTE_COUNT,
"The number of buffer objects that can be attached to a VertexBuffer must be "
"less than or equal to the maximum number of vertex attributes.");
static constexpr size_t CONFIG_UNIFORM_BINDING_COUNT = 10; // This is guaranteed by OpenGL ES.
static constexpr size_t CONFIG_UNIFORM_BINDING_COUNT = 9; // This is guaranteed by OpenGL ES.
static constexpr size_t CONFIG_SAMPLER_BINDING_COUNT = 4; // This is guaranteed by OpenGL ES.
/**
@@ -128,6 +142,12 @@ enum class Backend : uint8_t {
NOOP = 4, //!< Selects the no-op driver for testing purposes.
};
enum class TimerQueryResult : int8_t {
ERROR = -1, // an error occurred, result won't be available
NOT_READY = 0, // result to ready yet
AVAILABLE = 1, // result is available
};
static constexpr const char* backendToString(Backend backend) {
switch (backend) {
case Backend::NOOP:
@@ -144,14 +164,16 @@ static constexpr const char* backendToString(Backend backend) {
}
/**
* Defines the shader language. Similar to the above backend enum, but the OpenGL backend can select
* between two shader languages: ESSL 1.0 and ESSL 3.0.
* Defines the shader language. Similar to the above backend enum, with some differences:
* - The OpenGL backend can select between two shader languages: ESSL 1.0 and ESSL 3.0.
* - The Metal backend can prefer precompiled Metal libraries, while falling back to MSL.
*/
enum class ShaderLanguage {
ESSL1 = 0,
ESSL3 = 1,
SPIRV = 2,
MSL = 3,
METAL_LIBRARY = 4,
};
static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) {
@@ -164,6 +186,8 @@ static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguag
return "SPIR-V";
case ShaderLanguage::MSL:
return "MSL";
case ShaderLanguage::METAL_LIBRARY:
return "Metal precompiled library";
}
}
@@ -313,7 +337,7 @@ enum class UniformType : uint8_t {
/**
* Supported constant parameter types
*/
enum class ConstantType : uint8_t {
enum class ConstantType : uint8_t {
INT,
FLOAT,
BOOL
@@ -658,16 +682,17 @@ enum class TextureFormat : uint16_t {
};
//! Bitmask describing the intended Texture Usage
enum class TextureUsage : uint8_t {
NONE = 0x00,
COLOR_ATTACHMENT = 0x01, //!< Texture can be used as a color attachment
DEPTH_ATTACHMENT = 0x02, //!< Texture can be used as a depth attachment
STENCIL_ATTACHMENT = 0x04, //!< Texture can be used as a stencil attachment
UPLOADABLE = 0x08, //!< Data can be uploaded into this texture (default)
SAMPLEABLE = 0x10, //!< Texture can be sampled (default)
SUBPASS_INPUT = 0x20, //!< Texture can be used as a subpass input
BLIT_SRC = 0x40, //!< Texture can be used the source of a blit()
BLIT_DST = 0x80, //!< Texture can be used the destination of a blit()
enum class TextureUsage : uint16_t {
NONE = 0x0000,
COLOR_ATTACHMENT = 0x0001, //!< Texture can be used as a color attachment
DEPTH_ATTACHMENT = 0x0002, //!< Texture can be used as a depth attachment
STENCIL_ATTACHMENT = 0x0004, //!< Texture can be used as a stencil attachment
UPLOADABLE = 0x0008, //!< Data can be uploaded into this texture (default)
SAMPLEABLE = 0x0010, //!< Texture can be sampled (default)
SUBPASS_INPUT = 0x0020, //!< Texture can be used as a subpass input
BLIT_SRC = 0x0040, //!< Texture can be used the source of a blit()
BLIT_DST = 0x0080, //!< Texture can be used the destination of a blit()
PROTECTED = 0x0100, //!< Texture can be used for protected content
DEFAULT = UPLOADABLE | SAMPLEABLE //!< Default texture usage
};
@@ -1171,11 +1196,27 @@ struct StencilState {
//! Stencil operations for front-facing polygons
StencilOperations front = {
.stencilFunc = StencilFunction::A, .ref = 0, .readMask = 0xff, .writeMask = 0xff };
.stencilFunc = StencilFunction::A,
.stencilOpStencilFail = StencilOperation::KEEP,
.padding0 = 0,
.stencilOpDepthFail = StencilOperation::KEEP,
.stencilOpDepthStencilPass = StencilOperation::KEEP,
.padding1 = 0,
.ref = 0,
.readMask = 0xff,
.writeMask = 0xff };
//! Stencil operations for back-facing polygons
StencilOperations back = {
.stencilFunc = StencilFunction::A, .ref = 0, .readMask = 0xff, .writeMask = 0xff };
.stencilFunc = StencilFunction::A,
.stencilOpStencilFail = StencilOperation::KEEP,
.padding0 = 0,
.stencilOpDepthFail = StencilOperation::KEEP,
.stencilOpDepthStencilPass = StencilOperation::KEEP,
.padding1 = 0,
.ref = 0,
.readMask = 0xff,
.writeMask = 0xff };
//! Whether stencil-buffer writes are enabled
bool stencilWrite = false;
@@ -1183,13 +1224,15 @@ struct StencilState {
uint8_t padding = 0;
};
using PushConstantVariant = std::variant<int32_t, float, bool>;
static_assert(sizeof(StencilState::StencilOperations) == 5u,
"StencilOperations size not what was intended");
static_assert(sizeof(StencilState) == 12u,
"StencilState size not what was intended");
using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
using FrameScheduledCallback = utils::Invocable<void(backend::PresentCallable)>;
enum class Workaround : uint16_t {
// The EASU pass must split because shader compiler flattens early-exit branch
@@ -1206,11 +1249,10 @@ enum class Workaround : uint16_t {
DISABLE_BLIT_INTO_TEXTURE_ARRAY,
// Multiple workarounds needed for PowerVR GPUs
POWER_VR_SHADER_WORKAROUNDS,
// The driver has some threads pinned, and we can't easily know on which core, it can hurt
// performance more if we end-up pinned on the same one.
DISABLE_THREAD_AFFINITY
};
using StereoscopicType = backend::Platform::StereoscopicType;
} // namespace filament::backend
template<> struct utils::EnableBitMaskOperators<filament::backend::ShaderStageFlags>

View File

@@ -17,16 +17,14 @@
#ifndef TNT_FILAMENT_BACKEND_HANDLE_H
#define TNT_FILAMENT_BACKEND_HANDLE_H
#include <utils/compiler.h>
#if !defined(NDEBUG)
#include <utils/Log.h>
#include <utils/ostream.h>
#endif
#include <utils/debug.h>
#include <stdint.h>
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <limits>
#include <type_traits>
#include <stdint.h>
namespace filament::backend {
@@ -41,6 +39,7 @@ struct HwStream;
struct HwSwapChain;
struct HwTexture;
struct HwTimerQuery;
struct HwVertexBufferInfo;
struct HwVertexBuffer;
/*
@@ -54,7 +53,7 @@ struct HwVertexBuffer;
class HandleBase {
public:
using HandleId = uint32_t;
static constexpr const HandleId nullid = HandleId{ std::numeric_limits<HandleId>::max() };
static constexpr const HandleId nullid = HandleId{ UINT32_MAX };
constexpr HandleBase() noexcept: object(nullid) {}
@@ -64,14 +63,6 @@ public:
// clear the handle, this doesn't free associated resources
void clear() noexcept { object = nullid; }
// compare handles
bool operator==(const HandleBase& rhs) const noexcept { return object == rhs.object; }
bool operator!=(const HandleBase& rhs) const noexcept { return object != rhs.object; }
bool operator<(const HandleBase& rhs) const noexcept { return object < rhs.object; }
bool operator<=(const HandleBase& rhs) const noexcept { return object <= rhs.object; }
bool operator>(const HandleBase& rhs) const noexcept { return object > rhs.object; }
bool operator>=(const HandleBase& rhs) const noexcept { return object >= rhs.object; }
// get this handle's handleId
HandleId getId() const noexcept { return object; }
@@ -84,6 +75,19 @@ protected:
HandleBase(HandleBase const& rhs) noexcept = default;
HandleBase& operator=(HandleBase const& rhs) noexcept = default;
HandleBase(HandleBase&& rhs) noexcept
: object(rhs.object) {
rhs.object = nullid;
}
HandleBase& operator=(HandleBase&& rhs) noexcept {
if (this != &rhs) {
object = rhs.object;
rhs.object = nullid;
}
return *this;
}
private:
HandleId object;
};
@@ -98,11 +102,21 @@ struct Handle : public HandleBase {
Handle() noexcept = default;
Handle(Handle const& rhs) noexcept = default;
Handle(Handle&& rhs) noexcept = default;
Handle& operator=(Handle const& rhs) noexcept = default;
Handle& operator=(Handle&& rhs) noexcept = default;
explicit Handle(HandleId id) noexcept : HandleBase(id) { }
// compare handles of the same type
bool operator==(const Handle& rhs) const noexcept { return getId() == rhs.getId(); }
bool operator!=(const Handle& rhs) const noexcept { return getId() != rhs.getId(); }
bool operator<(const Handle& rhs) const noexcept { return getId() < rhs.getId(); }
bool operator<=(const Handle& rhs) const noexcept { return getId() <= rhs.getId(); }
bool operator>(const Handle& rhs) const noexcept { return getId() > rhs.getId(); }
bool operator>=(const Handle& rhs) const noexcept { return getId() >= rhs.getId(); }
// type-safe Handle cast
template<typename B, typename = std::enable_if_t<std::is_base_of<T, B>::value> >
Handle(Handle<B> const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions,google-explicit-constructor)
@@ -116,18 +130,19 @@ private:
// Types used by the command stream
// (we use this renaming because the macro-system doesn't deal well with "<" and ">")
using BufferObjectHandle = Handle<HwBufferObject>;
using FenceHandle = Handle<HwFence>;
using IndexBufferHandle = Handle<HwIndexBuffer>;
using ProgramHandle = Handle<HwProgram>;
using RenderPrimitiveHandle = Handle<HwRenderPrimitive>;
using RenderTargetHandle = Handle<HwRenderTarget>;
using SamplerGroupHandle = Handle<HwSamplerGroup>;
using StreamHandle = Handle<HwStream>;
using SwapChainHandle = Handle<HwSwapChain>;
using TextureHandle = Handle<HwTexture>;
using TimerQueryHandle = Handle<HwTimerQuery>;
using VertexBufferHandle = Handle<HwVertexBuffer>;
using BufferObjectHandle = Handle<HwBufferObject>;
using FenceHandle = Handle<HwFence>;
using IndexBufferHandle = Handle<HwIndexBuffer>;
using ProgramHandle = Handle<HwProgram>;
using RenderPrimitiveHandle = Handle<HwRenderPrimitive>;
using RenderTargetHandle = Handle<HwRenderTarget>;
using SamplerGroupHandle = Handle<HwSamplerGroup>;
using StreamHandle = Handle<HwStream>;
using SwapChainHandle = Handle<HwSwapChain>;
using TextureHandle = Handle<HwTexture>;
using TimerQueryHandle = Handle<HwTimerQuery>;
using VertexBufferHandle = Handle<HwVertexBuffer>;
using VertexBufferInfoHandle = Handle<HwVertexBufferInfo>;
} // namespace filament::backend

View File

@@ -20,7 +20,7 @@
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <limits>
#include <utils/ostream.h>
#include <stdint.h>
@@ -29,14 +29,13 @@ namespace filament::backend {
//! \privatesection
struct PipelineState {
Handle<HwProgram> program;
RasterState rasterState;
StencilState stencilState;
PolygonOffset polygonOffset;
Viewport scissor{ 0, 0,
(uint32_t)std::numeric_limits<int32_t>::max(),
(uint32_t)std::numeric_limits<int32_t>::max()
};
Handle<HwProgram> program; // 4
Handle<HwVertexBufferInfo> vertexBufferInfo; // 4
RasterState rasterState; // 4
StencilState stencilState; // 12
PolygonOffset polygonOffset; // 8
PrimitiveType primitiveType = PrimitiveType::TRIANGLES; // 1
uint8_t padding[3] = {}; // 3
};
} // namespace filament::backend

View File

@@ -24,6 +24,7 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>

View File

@@ -19,11 +19,12 @@
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_H
#define TNT_FILAMENT_BACKEND_PLATFORM_H
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class Driver;
@@ -40,19 +41,63 @@ public:
struct Fence {};
struct Stream {};
/**
* The type of technique for stereoscopic rendering. (Note that the materials used will need to
* be compatible with the chosen technique.)
*/
enum class StereoscopicType : uint8_t {
/**
* No stereoscopic rendering
*/
NONE,
/**
* Stereoscopic rendering is performed using instanced rendering technique.
*/
INSTANCED,
/**
* Stereoscopic rendering is performed using the multiview feature from the graphics
* backend.
*/
MULTIVIEW,
};
struct DriverConfig {
/*
* size of handle arena in bytes. Setting to 0 indicates default value is to be used.
/**
* Size of handle arena in bytes. Setting to 0 indicates default value is to be used.
* Driver clamps to valid values.
*/
size_t handleArenaSize = 0;
/*
* this number of most-recently destroyed textures will be tracked for use-after-free.
/**
* This number of most-recently destroyed textures will be tracked for use-after-free.
* Throws an exception when a texture is freed but still bound to a SamplerGroup and used in
* a draw call. 0 disables completely. Currently only respected by the Metal backend.
*/
size_t textureUseAfterFreePoolSize = 0;
size_t metalUploadBufferSizeBytes = 512 * 1024;
/**
* Set to `true` to forcibly disable parallel shader compilation in the backend.
* Currently only honored by the GL and Metal backends.
*/
bool disableParallelShaderCompile = false;
/**
* Disable backend handles use-after-free checks.
*/
bool disableHandleUseAfterFreeCheck = false;
/**
* Force GLES2 context if supported, or pretend the context is ES2. Only meaningful on
* GLES 3.x backends.
*/
bool forceGLES2Context = false;
/**
* Sets the technique for stereoscopic rendering.
*/
StereoscopicType stereoscopicType = StereoscopicType::NONE;
};
Platform() noexcept;
@@ -78,7 +123,7 @@ public:
*
* @return nullptr on failure, or a pointer to the newly created driver.
*/
virtual backend::Driver* createDriver(void* sharedContext,
virtual backend::Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
const DriverConfig& driverConfig) noexcept = 0;
/**
@@ -96,7 +141,8 @@ public:
* cache.
*/
using InsertBlobFunc = utils::Invocable<
void(const void* key, size_t keySize, const void* value, size_t valueSize)>;
void(const void* UTILS_NONNULL key, size_t keySize,
const void* UTILS_NONNULL value, size_t valueSize)>;
/*
* RetrieveBlobFunc is an Invocable to an application-provided function that a
@@ -104,7 +150,8 @@ public:
* cache.
*/
using RetrieveBlobFunc = utils::Invocable<
size_t(const void* key, size_t keySize, void* value, size_t valueSize)>;
size_t(const void* UTILS_NONNULL key, size_t keySize,
void* UTILS_NONNULL value, size_t valueSize)>;
/**
* Sets the callback functions that the backend can use to interact with caching functionality
@@ -157,7 +204,8 @@ public:
* @param value pointer to the beginning of the value data that is to be inserted
* @param valueSize specifies the size in byte of the data pointed to by <value>
*/
void insertBlob(const void* key, size_t keySize, const void* value, size_t valueSize);
void insertBlob(const void* UTILS_NONNULL key, size_t keySize,
const void* UTILS_NONNULL value, size_t valueSize);
/**
* To retrieve the binary value associated with a given key from the cache, a
@@ -176,11 +224,43 @@ public:
* @return If the cache contains a value associated with the given key then the
* size of that binary value in bytes is returned. Otherwise 0 is returned.
*/
size_t retrieveBlob(const void* key, size_t keySize, void* value, size_t valueSize);
size_t retrieveBlob(const void* UTILS_NONNULL key, size_t keySize,
void* UTILS_NONNULL value, size_t valueSize);
using DebugUpdateStatFunc = utils::Invocable<void(const char* UTILS_NONNULL key, uint64_t value)>;
/**
* Sets the callback function that the backend can use to update backend-specific statistics
* to aid with debugging. This callback is guaranteed to be called on the Filament driver
* thread.
*
* @param debugUpdateStat an Invocable that updates debug statistics
*/
void setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept;
/**
* @return true if debugUpdateStat is valid.
*/
bool hasDebugUpdateStatFunc() const noexcept;
/**
* To track backend-specific statistics, the backend implementation can call the
* application-provided callback function debugUpdateStatFunc to associate or update a value
* with a given key. It is possible for this function to be called multiple times with the
* same key, in which case newer values should overwrite older values.
*
* This function is guaranteed to be called only on a single thread, the Filament driver
* thread.
*
* @param key a null-terminated C-string with the key of the debug statistic
* @param value the updated value of key
*/
void debugUpdateStat(const char* UTILS_NONNULL key, uint64_t value);
private:
InsertBlobFunc mInsertBlob;
RetrieveBlobFunc mRetrieveBlob;
DebugUpdateStatFunc mDebugUpdateStat;
};
} // namespace filament

View File

@@ -21,8 +21,7 @@
#include <utils/compiler.h>
namespace filament {
namespace backend {
namespace filament::backend {
/**
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
@@ -49,7 +48,7 @@ namespace backend {
* and optional user data:
*
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
* swapChain->setFrameScheduledCallback(myFrameScheduledCallback, nullptr);
* swapChain->setFrameScheduledCallback(nullptr, myFrameScheduledCallback);
* if (renderer->beginFrame(swapChain)) {
* renderer->render(view);
* renderer->endFrame();
@@ -59,8 +58,6 @@ namespace backend {
* @remark Only Filament's Metal backend supports PresentCallables and frame callbacks. Other
* backends ignore the callback (which will never be called) and proceed normally.
*
* @remark The SwapChain::FrameScheduledCallback is called on an arbitrary thread.
*
* Applications *must* call each PresentCallable they receive. Each PresentCallable represents a
* frame that is waiting to be presented. If an application fails to call a PresentCallable, a
* memory leak could occur. To "cancel" the presentation of a frame, pass false to the
@@ -98,7 +95,6 @@ private:
*/
using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable, void* user);
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRESENTCALLABLE

View File

@@ -17,17 +17,19 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
#define TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Invocable.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <backend/DriverEnums.h>
#include <array>
#include <variant>
#include <array> // FIXME: STL headers are not allowed in public headers
#include <utility> // FIXME: STL headers are not allowed in public headers
#include <variant> // FIXME: STL headers are not allowed in public headers
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -82,6 +84,9 @@ public:
// null terminating character.
Program& shader(ShaderStage shader, void const* data, size_t size);
// sets the language of the shader sources provided with shader() (defaults to ESSL3)
Program& shaderLanguage(ShaderLanguage shaderLanguage);
// Note: This is only needed for GLES3.0 backends, because the layout(binding=) syntax is
// not permitted in glsl. The backend needs a way to associate a uniform block
// to a binding point.
@@ -112,8 +117,18 @@ public:
Program& specializationConstants(
utils::FixedCapacityVector<SpecializationConstant> specConstants) noexcept;
struct PushConstant {
utils::CString name;
ConstantType type;
};
Program& pushConstants(ShaderStage stage,
utils::FixedCapacityVector<PushConstant> constants) noexcept;
Program& cacheId(uint64_t cacheId) noexcept;
Program& multiview(bool multiview) noexcept;
ShaderSource const& getShadersSource() const noexcept { return mShadersSource; }
ShaderSource& getShadersSource() noexcept { return mShadersSource; }
@@ -132,6 +147,8 @@ public:
utils::CString const& getName() const noexcept { return mName; }
utils::CString& getName() noexcept { return mName; }
auto const& getShaderLanguage() const { return mShaderLanguage; }
utils::FixedCapacityVector<SpecializationConstant> const& getSpecializationConstants() const noexcept {
return mSpecializationConstants;
}
@@ -139,8 +156,19 @@ public:
return mSpecializationConstants;
}
utils::FixedCapacityVector<PushConstant> const& getPushConstants(
ShaderStage stage) const noexcept {
return mPushConstants[static_cast<uint8_t>(stage)];
}
utils::FixedCapacityVector<PushConstant>& getPushConstants(ShaderStage stage) noexcept {
return mPushConstants[static_cast<uint8_t>(stage)];
}
uint64_t getCacheId() const noexcept { return mCacheId; }
bool isMultiview() const noexcept { return mMultiview; }
CompilerPriorityQueue getPriorityQueue() const noexcept { return mPriorityQueue; }
private:
@@ -149,13 +177,20 @@ private:
UniformBlockInfo mUniformBlocks = {};
SamplerGroupInfo mSamplerGroups = {};
ShaderSource mShadersSource;
ShaderLanguage mShaderLanguage = ShaderLanguage::ESSL3;
utils::CString mName;
uint64_t mCacheId{};
utils::Invocable<utils::io::ostream&(utils::io::ostream& out)> mLogger;
utils::FixedCapacityVector<SpecializationConstant> mSpecializationConstants;
std::array<utils::FixedCapacityVector<PushConstant>, SHADER_TYPE_COUNT> mPushConstants;
utils::FixedCapacityVector<std::pair<utils::CString, uint8_t>> mAttributes;
std::array<UniformInfo, Program::UNIFORM_BINDING_COUNT> mBindingUniformInfo;
CompilerPriorityQueue mPriorityQueue = CompilerPriorityQueue::HIGH;
// Indicates the current engine was initialized with multiview stereo, and the variant for this
// program contains STE flag. This will be referred later for the OpenGL shader compiler to
// determine whether shader code replacement for the num_views should be performed.
// This variable could be promoted as a more generic variable later if other similar needs occur.
bool mMultiview = false;
};
} // namespace filament::backend

View File

@@ -24,9 +24,6 @@
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
struct UTILS_PUBLIC SamplerDescriptor {

View File

@@ -17,9 +17,11 @@
#ifndef TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#define TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -27,13 +29,36 @@ namespace filament::backend {
//! \privatesection
struct TargetBufferInfo {
// note: the parameters of this constructor are not in the order of this structure's fields
TargetBufferInfo(Handle<HwTexture> handle, uint8_t level, uint16_t layer, uint8_t baseViewIndex) noexcept
: handle(handle), baseViewIndex(baseViewIndex), level(level), layer(layer) {
}
TargetBufferInfo(Handle<HwTexture> handle, uint8_t level, uint16_t layer) noexcept
: handle(handle), level(level), layer(layer) {
}
TargetBufferInfo(Handle<HwTexture> handle, uint8_t level) noexcept
: handle(handle), level(level) {
}
TargetBufferInfo(Handle<HwTexture> handle) noexcept // NOLINT(*-explicit-constructor)
: handle(handle) {
}
TargetBufferInfo() noexcept = default;
// texture to be used as render target
Handle<HwTexture> handle;
// Starting layer index for multiview. This value is only used when the `layerCount` for the
// render target is greater than 1.
uint8_t baseViewIndex = 0;
// level to be used
uint8_t level = 0;
// for cubemaps and 3D textures. See TextureCubemapFace for the face->layer mapping
// For cubemaps and 3D textures. See TextureCubemapFace for the face->layer mapping
uint16_t layer = 0;
};
@@ -58,7 +83,7 @@ public:
MRT() noexcept = default;
MRT(TargetBufferInfo const& color) noexcept // NOLINT(hicpp-explicit-conversions)
MRT(TargetBufferInfo const& color) noexcept // NOLINT(hicpp-explicit-conversions, *-explicit-constructor)
: mInfos{ color } {
}
@@ -78,7 +103,7 @@ public:
// this is here for backward compatibility
MRT(Handle<HwTexture> handle, uint8_t level, uint16_t layer) noexcept
: mInfos{{ handle, level, layer }} {
: mInfos{{ handle, level, layer, 0 }} {
}
};

View File

@@ -18,8 +18,15 @@
#define TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#include <backend/AcquiredImage.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class Driver;
@@ -38,8 +45,8 @@ protected:
* Derived classes can use this to instantiate the default OpenGLDriver backend.
* This is typically called from your implementation of createDriver()
*/
static Driver* createDefaultDriver(OpenGLPlatform* platform,
void* sharedContext, const DriverConfig& driverConfig);
static Driver* UTILS_NULLABLE createDefaultDriver(OpenGLPlatform* UTILS_NONNULL platform,
void* UTILS_NULLABLE sharedContext, const DriverConfig& driverConfig);
~OpenGLPlatform() noexcept override;
@@ -57,6 +64,22 @@ public:
*/
virtual void terminate() noexcept = 0;
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
*/
virtual bool isSRGBSwapChainSupported() const noexcept;
/**
* Return whether protected contexts are supported by this backend.
* If protected context are supported, the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag can be
* used when creating a SwapChain.
* The default implementation returns false.
*/
virtual bool isProtectedContextSupported() const noexcept;
/**
* Called by the driver to create a SwapChain for this driver.
*
@@ -66,15 +89,8 @@ public:
* @return The driver's SwapChain object.
*
*/
virtual SwapChain* createSwapChain(void* nativeWindow, uint64_t flags) noexcept = 0;
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
*/
virtual bool isSRGBSwapChainSupported() const noexcept;
virtual SwapChain* UTILS_NULLABLE createSwapChain(
void* UTILS_NULLABLE nativeWindow, uint64_t flags) noexcept = 0;
/**
* Called by the driver create a headless SwapChain.
@@ -87,13 +103,14 @@ public:
* TODO: we need a more generic way of passing construction parameters
* A void* might be enough.
*/
virtual SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
virtual SwapChain* UTILS_NULLABLE createSwapChain(
uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
/**
* Called by the driver to destroys the SwapChain
* @param swapChain SwapChain to be destroyed.
*/
virtual void destroySwapChain(SwapChain* swapChain) noexcept = 0;
virtual void destroySwapChain(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
/**
* Returns the set of buffers that must be preserved up to the call to commit().
@@ -106,28 +123,103 @@ public:
* @return buffer that must be preserved
* @see commit()
*/
virtual TargetBufferFlags getPreservedFlags(SwapChain* swapChain) noexcept;
virtual TargetBufferFlags getPreservedFlags(SwapChain* UTILS_NONNULL swapChain) noexcept;
/**
* Returns true if the swapchain is protected
*/
virtual bool isSwapChainProtected(Platform::SwapChain* UTILS_NONNULL swapChain) noexcept;
/**
* Called by the driver to establish the default FBO. The default implementation returns 0.
* @return a GLuint casted to a uint32_t that is an OpenGL framebuffer object.
*
* This method can be called either on the regular or protected OpenGL contexts and can return
* a different or identical name, since these names exist in different namespaces.
*
* @return a GLuint casted to a uint32_t that is an OpenGL framebuffer object.
*/
virtual uint32_t createDefaultRenderTarget() noexcept;
virtual uint32_t getDefaultFramebufferObject() noexcept;
/**
* Called by the backend when a frame starts.
* @param steady_clock_ns vsync time point on the monotonic clock
* @param refreshIntervalNs refresh interval in nanosecond
* @param frameId a frame id
*/
virtual void beginFrame(
int64_t monotonic_clock_ns,
int64_t refreshIntervalNs,
uint32_t frameId) noexcept;
/**
* Called by the backend when a frame ends.
* @param frameId the frame id used in beginFrame
*/
virtual void endFrame(
uint32_t frameId) noexcept;
/**
* Type of contexts available
*/
enum class ContextType {
NONE, //!< No current context
UNPROTECTED, //!< current context is unprotected
PROTECTED //!< current context supports protected content
};
/**
* Returns the type of the context currently in use. This value is updated by makeCurrent()
* and therefore can be cached between calls. ContextType::PROTECTED can only be returned
* if isProtectedContextSupported() is true.
* @return ContextType
*/
virtual ContextType getCurrentContextType() const noexcept;
/**
* Binds the requested context to the current thread and drawSwapChain to the default FBO
* returned by getDefaultFramebufferObject().
*
* @param type type of context to bind to the current thread.
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
* @return true on success, false on error.
*/
virtual bool makeCurrent(ContextType type,
SwapChain* UTILS_NONNULL drawSwapChain,
SwapChain* UTILS_NONNULL readSwapChain) noexcept = 0;
/**
* Called by the driver to make the OpenGL context active on the calling thread and bind
* the drawSwapChain to the default render target (FBO) created with createDefaultRenderTarget.
* the drawSwapChain to the default FBO returned by getDefaultFramebufferObject().
* The context used is either the default context or the protected context. When a context
* change is necessary, the preContextChange and postContextChange callbacks are called,
* before and after the context change respectively. postContextChange is given the index
* of the new context (0 for default and 1 for protected).
* The default implementation just calls makeCurrent(getCurrentContextType(), SwapChain*, SwapChain*).
*
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
* @param preContextChange called before the context changes
* @param postContextChange called after the context changes
*/
virtual void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept = 0;
virtual void makeCurrent(
SwapChain* UTILS_NONNULL drawSwapChain,
SwapChain* UTILS_NONNULL readSwapChain,
utils::Invocable<void()> preContextChange,
utils::Invocable<void(size_t index)> postContextChange) noexcept;
/**
* Called by the backend just before calling commit()
* @see commit()
*/
virtual void preCommit() noexcept;
/**
* Called by the driver once the current frame finishes drawing. Typically, this should present
* the drawSwapChain. This is for example where `eglMakeCurrent()` would be called.
* @param swapChain the SwapChain to present.
*/
virtual void commit(SwapChain* swapChain) noexcept = 0;
virtual void commit(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
/**
* Set the time the next committed buffer should be presented to the user at.
@@ -152,14 +244,14 @@ public:
*
* @return A Fence object. The default implementation returns nullptr.
*/
virtual Fence* createFence() noexcept;
virtual Fence* UTILS_NULLABLE createFence() noexcept;
/**
* Destroys a Fence object. The default implementation does nothing.
*
* @param fence Fence to destroy.
*/
virtual void destroyFence(Fence* fence) noexcept;
virtual void destroyFence(Fence* UTILS_NONNULL fence) noexcept;
/**
* Waits on a Fence.
@@ -169,7 +261,7 @@ public:
* @return Whether the fence signaled or timed out. See backend::FenceStatus.
* The default implementation always return backend::FenceStatus::ERROR.
*/
virtual backend::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept;
virtual backend::FenceStatus waitFence(Fence* UTILS_NONNULL fence, uint64_t timeout) noexcept;
// --------------------------------------------------------------------------------------------
@@ -183,13 +275,13 @@ public:
* @param nativeStream The native stream, this parameter depends on the concrete implementation.
* @return A new Stream object.
*/
virtual Stream* createStream(void* nativeStream) noexcept;
virtual Stream* UTILS_NULLABLE createStream(void* UTILS_NULLABLE nativeStream) noexcept;
/**
* Destroys a Stream.
* @param stream Stream to destroy.
*/
virtual void destroyStream(Stream* stream) noexcept;
virtual void destroyStream(Stream* UTILS_NONNULL stream) noexcept;
/**
* The specified stream takes ownership of the texture (tname) object
@@ -199,20 +291,21 @@ public:
* @param stream Stream to take ownership of the texture
* @param tname GL texture id to "bind" to the Stream.
*/
virtual void attach(Stream* stream, intptr_t tname) noexcept;
virtual void attach(Stream* UTILS_NONNULL stream, intptr_t tname) noexcept;
/**
* Destroys the texture associated to the stream
* @param stream Stream to detach from its texture
*/
virtual void detach(Stream* stream) noexcept;
virtual void detach(Stream* UTILS_NONNULL stream) noexcept;
/**
* Updates the content of the texture attached to the stream.
* @param stream Stream to update
* @param timestamp Output parameter: Timestamp of the image bound to the texture.
*/
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
virtual void updateTexImage(Stream* UTILS_NONNULL stream,
int64_t* UTILS_NONNULL timestamp) noexcept;
// --------------------------------------------------------------------------------------------
@@ -225,13 +318,13 @@ public:
* implementation could just return { 0, GL_TEXTURE_2D } at this point. The actual
* values can be delayed until setExternalImage.
*/
virtual ExternalTexture *createExternalImageTexture() noexcept;
virtual ExternalTexture* UTILS_NULLABLE createExternalImageTexture() noexcept;
/**
* Destroys an external texture handle and associated data.
* @param texture a pointer to the handle to destroy.
*/
virtual void destroyExternalImage(ExternalTexture* texture) noexcept;
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
// called on the application thread to allow Filament to take ownership of the image
@@ -244,7 +337,7 @@ public:
* @param externalImage A token representing the platform's external image.
* @see destroyExternalImage
*/
virtual void retainExternalImage(void* externalImage) noexcept;
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
/**
* Called to bind the platform-specific externalImage to an ExternalTexture.
@@ -258,7 +351,8 @@ public:
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
* @return true on success, false on error.
*/
virtual bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept;
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
ExternalTexture* UTILS_NONNULL texture) noexcept;
/**
* The method allows platforms to convert a user-supplied external image object into a new type

View File

@@ -17,11 +17,10 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <stdint.h>
namespace filament::backend {
@@ -58,7 +57,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;

View File

@@ -30,7 +30,7 @@ struct PlatformCocoaTouchGLImpl;
class PlatformCocoaTouchGL : public OpenGLPlatform {
public:
PlatformCocoaTouchGL();
~PlatformCocoaTouchGL() noexcept;
~PlatformCocoaTouchGL() noexcept override;
// --------------------------------------------------------------------------------------------
// Platform Interface
@@ -45,7 +45,7 @@ public:
void terminate() noexcept override;
uint32_t createDefaultRenderTarget() noexcept override;
uint32_t getDefaultFramebufferObject() noexcept override;
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
@@ -53,7 +53,7 @@ public:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;

View File

@@ -17,18 +17,23 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <utils/Invocable.h>
#include <initializer_list>
#include <utility>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
/**
@@ -38,15 +43,11 @@ class PlatformEGL : public OpenGLPlatform {
public:
PlatformEGL() noexcept;
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
void releaseContext() noexcept override;
// Return true if we're on an OpenGL platform (as opposed to OpenGL ES). false by default.
virtual bool isOpenGL() const noexcept;
protected:
// --------------------------------------------------------------------------------------------
// Helper for EGL configs and attributes parameters
@@ -86,13 +87,30 @@ protected:
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
void releaseContext() noexcept override;
void terminate() noexcept override;
bool isProtectedContextSupported() const noexcept override;
bool isSRGBSwapChainSupported() const noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool isSwapChainProtected(SwapChain* swapChain) noexcept override;
ContextType getCurrentContextType() const noexcept override;
bool makeCurrent(ContextType type,
SwapChain* drawSwapChain,
SwapChain* readSwapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
utils::Invocable<void()> preContextChange,
utils::Invocable<void(size_t index)> postContextChange) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
bool canCreateFence() noexcept override;
@@ -119,16 +137,27 @@ protected:
static void clearGlError() noexcept;
/**
* Always use this instead of eglMakeCurrent().
* Always use this instead of eglMakeCurrent(), as it tracks some state.
*/
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept;
EGLContext getContextForType(ContextType type) const noexcept;
// makes the draw and read surface current without changing the current context
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept {
return egl.makeCurrent(drawSurface, readSurface);
}
// makes context current and set draw and read surfaces to EGL_NO_SURFACE
EGLBoolean makeCurrent(EGLContext context) noexcept {
return egl.makeCurrent(context, mEGLDummySurface, mEGLDummySurface);
}
// TODO: this should probably use getters instead.
EGLDisplay mEGLDisplay = EGL_NO_DISPLAY;
EGLContext mEGLContext = EGL_NO_CONTEXT;
EGLSurface mCurrentDrawSurface = EGL_NO_SURFACE;
EGLSurface mCurrentReadSurface = EGL_NO_SURFACE;
EGLContext mEGLContextProtected = EGL_NO_CONTEXT;
EGLSurface mEGLDummySurface = EGL_NO_SURFACE;
ContextType mCurrentContextType = ContextType::NONE;
// mEGLConfig is valid only if ext.egl.KHR_no_config_context is false
EGLConfig mEGLConfig = EGL_NO_CONFIG_KHR;
Config mContextAttribs;
@@ -145,13 +174,38 @@ protected:
bool KHR_gl_colorspace = false;
bool KHR_no_config_context = false;
bool KHR_surfaceless_context = false;
bool EXT_protected_content = false;
} egl;
} ext;
struct SwapChainEGL : public Platform::SwapChain {
EGLSurface sur = EGL_NO_SURFACE;
Config attribs{};
EGLNativeWindowType nativeWindow{};
EGLConfig config{};
uint64_t flags{};
};
void initializeGlExtensions() noexcept;
protected:
EGLConfig findSwapChainConfig(uint64_t flags, bool window, bool pbuffer) const;
private:
class EGL {
EGLDisplay& mEGLDisplay;
EGLSurface mCurrentDrawSurface = EGL_NO_SURFACE;
EGLSurface mCurrentReadSurface = EGL_NO_SURFACE;
EGLContext mCurrentContext = EGL_NO_CONTEXT;
public:
explicit EGL(EGLDisplay& dpy) : mEGLDisplay(dpy) {}
EGLBoolean makeCurrent(EGLContext context,
EGLSurface drawSurface, EGLSurface readSurface) noexcept;
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept {
return makeCurrent(mCurrentContext, drawSurface, readSurface);
}
} egl{ mEGLDisplay };
};
} // namespace filament::backend

View File

@@ -17,8 +17,18 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#include <backend/AcquiredImage.h>
#include <backend/Platform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/platforms/PlatformEGL.h>
#include <utils/android/PerformanceHintManager.h>
#include <chrono>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class ExternalStreamManagerAndroid;
@@ -52,6 +62,13 @@ protected:
void terminate() noexcept override;
void beginFrame(
int64_t monotonic_clock_ns,
int64_t refreshIntervalNs,
uint32_t frameId) noexcept override;
void preCommit() noexcept override;
/**
* Set the presentation time using `eglPresentationTimeANDROID`
* @param presentationTimeInNanosecond
@@ -73,8 +90,18 @@ protected:
AcquiredImage transformAcquiredImage(AcquiredImage source) noexcept override;
private:
struct InitializeJvmForPerformanceManagerIfNeeded {
InitializeJvmForPerformanceManagerIfNeeded();
};
int mOSVersion;
ExternalStreamManagerAndroid& mExternalStreamManager;
InitializeJvmForPerformanceManagerIfNeeded const mInitializeJvmForPerformanceManagerIfNeeded;
utils::PerformanceHintManager mPerformanceHintManager;
utils::PerformanceHintManager::Session mPerformanceHintSession;
using clock = std::chrono::high_resolution_clock;
clock::time_point mStartTimeOfActualWork;
};
} // namespace filament::backend

View File

@@ -51,7 +51,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
private:

View File

@@ -53,7 +53,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
protected:

View File

@@ -46,7 +46,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
};

View File

@@ -20,13 +20,18 @@
#include <backend/Platform.h>
#include <bluevk/BlueVK.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Hash.h>
#include <utils/PrivateImplementation.h>
#include <tuple>
#include <unordered_set>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
using SwapChain = Platform::SwapChain;
@@ -42,6 +47,14 @@ struct VulkanPlatformPrivate;
class VulkanPlatform : public Platform, utils::PrivateImplementation<VulkanPlatformPrivate> {
public:
struct ExtensionHashFn {
std::size_t operator()(utils::CString const& s) const noexcept {
return std::hash<std::string>{}(s.data());
}
};
// Utility for managing device or instance extensions during initialization.
using ExtensionSet = std::unordered_set<utils::CString, ExtensionHashFn>;
/**
* A collection of handles to objects and metadata that comprises a Vulkan context. The client
* can instantiate this struct and pass to Engine::Builder::sharedContext if they wishes to
@@ -77,6 +90,20 @@ public:
VkExtent2D extent = {0, 0};
};
struct ImageSyncData {
static constexpr uint32_t INVALID_IMAGE_INDEX = UINT32_MAX;
// The index of the next image as returned by vkAcquireNextImage or equivalent.
uint32_t imageIndex = INVALID_IMAGE_INDEX;
// Semaphore to be signaled once the image is available.
VkSemaphore imageReadySemaphore = VK_NULL_HANDLE;
// A function called right before vkQueueSubmit. After this call, the image must be
// available. This pointer can be null if imageReadySemaphore is not VK_NULL_HANDLE.
std::function<void(SwapChainPtr handle)> explicitImageReadyWait = nullptr;
};
VulkanPlatform();
~VulkanPlatform() override;
@@ -114,6 +141,12 @@ public:
* before recreating the swapchain. Default is true.
*/
bool flushAndWaitOnWindowResize = true;
/**
* Whether the swapchain image should be transitioned to a layout suitable for
* presentation. Default is true.
*/
bool transitionSwapChainImageLayoutForPresent = true;
};
/**
@@ -142,13 +175,10 @@ public:
* corresponding VkImage will be used as the output color attachment. The client should signal
* the `clientSignal` semaphore when the image is ready to be used by the backend.
* @param handle The handle returned by createSwapChain()
* @param clientSignal The semaphore that the client will signal to indicate that the backend
* may render into the image.
* @param index Pointer to memory that will be filled with the index that corresponding
* to an image in the `SwapChainBundle.colors` array.
* @param outImageSyncData The synchronization data used for image readiness
* @return Result of acquire
*/
virtual VkResult acquire(SwapChainPtr handle, VkSemaphore clientSignal, uint32_t* index);
virtual VkResult acquire(SwapChainPtr handle, ImageSyncData* outImageSyncData);
/**
* Present the image corresponding to `index` to the display. The client should wait on
@@ -187,6 +217,13 @@ public:
virtual SwapChainPtr createSwapChain(void* nativeWindow, uint64_t flags = 0,
VkExtent2D extent = {0, 0});
/**
* Allows implementers to provide instance extensions that they'd like to include in the
* instance creation.
* @return A set of extensions to enable for the instance.
*/
virtual ExtensionSet getRequiredInstanceExtensions() { return {}; }
/**
* Destroy the swapchain.
* @param handle The handle returned by createSwapChain()
@@ -231,10 +268,9 @@ public:
VkQueue getGraphicsQueue() const noexcept;
private:
// Platform dependent helper methods
using ExtensionSet = std::unordered_set<std::string_view>;
static ExtensionSet getRequiredInstanceExtensions();
static ExtensionSet getSwapchainInstanceExtensions();
// Platform dependent helper methods
using SurfaceBundle = std::tuple<VkSurfaceKHR, VkExtent2D>;
static SurfaceBundle createVkSurfaceKHR(void* nativeWindow, VkInstance instance,
uint64_t flags) noexcept;

View File

@@ -17,7 +17,7 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
#define TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
#include <utils/compiler.h>
#include <utils/debug.h>
#include <stddef.h>
#include <stdint.h>
@@ -40,28 +40,36 @@ public:
~CircularBuffer() noexcept;
// allocates 'size' bytes in the circular buffer and returns a pointer to the memory
// return the current head and moves it forward by size bytes
inline void* allocate(size_t size) noexcept {
static size_t getBlockSize() noexcept { return sPageSize; }
// Total size of circular buffer. This is a constant.
size_t size() const noexcept { return mSize; }
// Allocates `s` bytes in the circular buffer and returns a pointer to the memory. All
// allocations must not exceed size() bytes.
inline void* allocate(size_t s) noexcept {
// We can never allocate more that size().
assert_invariant(getUsed() + s <= size());
char* const cur = static_cast<char*>(mHead);
mHead = cur + size;
mHead = cur + s;
return cur;
}
// Total size of circular buffer
size_t size() const noexcept { return mSize; }
// returns true if the buffer is empty (e.g. after calling flush)
// Returns true if the buffer is empty, i.e.: no allocations were made since
// calling getBuffer();
bool empty() const noexcept { return mTail == mHead; }
void* getHead() const noexcept { return mHead; }
// Returns the size used since the last call to getBuffer()
size_t getUsed() const noexcept { return intptr_t(mHead) - intptr_t(mTail); }
void* getTail() const noexcept { return mTail; }
// call at least once every getRequiredSize() bytes allocated from the buffer
void circularize() noexcept;
static size_t getBlockSize() noexcept { return sPageSize; }
// Retrieves the current allocated range and frees it. It is the responsibility of the caller
// to make sure the returned range is no longer in use by the time allocate() allocates
// (size() - getUsed()) bytes.
struct Range {
void* tail;
void* head;
};
Range getBuffer() noexcept;
private:
void* alloc(size_t size) noexcept;
@@ -69,10 +77,10 @@ private:
// pointer to the beginning of the circular buffer (constant)
void* mData = nullptr;
int mUsesAshmem = -1;
int mAshmemFd = -1;
// size of the circular buffer (constant)
size_t mSize = 0;
size_t const mSize;
// pointer to the beginning of recorded data
void* mTail = nullptr;

View File

@@ -19,19 +19,21 @@
#include "private/backend/CircularBuffer.h"
#include <utils/compiler.h>
#include <utils/Condition.h>
#include <utils/Mutex.h>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
/*
* A producer-consumer command queue that uses a CircularBuffer as main storage
*/
class CommandBufferQueue {
struct Slice {
struct Range {
void* begin;
void* end;
};
@@ -44,29 +46,33 @@ class CommandBufferQueue {
mutable utils::Mutex mLock;
mutable utils::Condition mCondition;
mutable std::vector<Slice> mCommandBuffersToExecute;
mutable std::vector<Range> mCommandBuffersToExecute;
size_t mFreeSpace = 0;
size_t mHighWatermark = 0;
uint32_t mExitRequested = 0;
bool mPaused = false;
static constexpr uint32_t EXIT_REQUESTED = 0x31415926;
public:
// requiredSize: guaranteed available space after flush()
CommandBufferQueue(size_t requiredSize, size_t bufferSize);
CommandBufferQueue(size_t requiredSize, size_t bufferSize, bool paused);
~CommandBufferQueue();
CircularBuffer& getCircularBuffer() { return mCircularBuffer; }
CircularBuffer& getCircularBuffer() noexcept { return mCircularBuffer; }
CircularBuffer const& getCircularBuffer() const noexcept { return mCircularBuffer; }
size_t getCapacity() const noexcept { return mRequiredSize; }
size_t getHighWatermark() const noexcept { return mHighWatermark; }
// wait for commands to be available and returns an array containing these commands
std::vector<Slice> waitForCommands() const;
std::vector<Range> waitForCommands() const;
// return the memory used by this command buffer to the circular buffer
// WARNING: releaseBuffer() must be called in sequence of the Slices returned by
// waitForCommands()
void releaseBuffer(Slice const& buffer);
void releaseBuffer(Range const& buffer);
// all commands buffers (Slices) written to this point are returned by waitForCommand(). This
// call blocks until the CircularBuffer has at least mRequiredSize bytes available.
@@ -75,6 +81,10 @@ public:
// returns from waitForCommands() immediately.
void requestExit();
// suspend or unsuspend the queue.
bool isPaused() const noexcept;
void setPaused(bool paused);
bool isExitRequested() const;
};

View File

@@ -32,11 +32,13 @@
#include <backend/TargetBufferInfo.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ThreadUtils.h>
#include <cstddef>
#include <functional>
#include <tuple>
#include <type_traits>
#include <utility>
#ifndef NDEBUG
@@ -132,7 +134,7 @@ struct CommandType<void (Driver::*)(ARGS...)> {
public:
template<typename M, typename D>
static inline void execute(M&& method, D&& driver, CommandBase* base, intptr_t* next) noexcept {
static inline void execute(M&& method, D&& driver, CommandBase* base, intptr_t* next) {
Command* self = static_cast<Command*>(base);
*next = align(sizeof(Command));
#if DEBUG_COMMAND_STREAM
@@ -152,21 +154,21 @@ struct CommandType<void (Driver::*)(ARGS...)> {
}
// placement new declared as "throw" to avoid the compiler's null-check
inline void* operator new(std::size_t size, void* ptr) {
inline void* operator new(std::size_t, void* ptr) {
assert_invariant(ptr);
return ptr;
}
};
};
// convert an method of "class Driver" into a Command<> type
// convert a method of "class Driver" into a Command<> type
#define COMMAND_TYPE(method) CommandType<decltype(&Driver::method)>::Command<&Driver::method>
// ------------------------------------------------------------------------------------------------
class CustomCommand : public CommandBase {
std::function<void()> mCommand;
static void execute(Driver&, CommandBase* base, intptr_t* next) noexcept;
static void execute(Driver&, CommandBase* base, intptr_t* next);
public:
inline CustomCommand(CustomCommand&& rhs) = default;
inline explicit CustomCommand(std::function<void()> cmd)
@@ -211,6 +213,8 @@ public:
CommandStream(CommandStream const& rhs) noexcept = delete;
CommandStream& operator=(CommandStream const& rhs) noexcept = delete;
CircularBuffer const& getCircularBuffer() const noexcept { return mCurrentBuffer; }
public:
#define DECL_DRIVER_API(methodName, paramsDecl, params) \
inline void methodName(paramsDecl) { \

View File

@@ -29,6 +29,7 @@
#include <functional>
#include <stddef.h>
#include <stdint.h>
// Command debugging off. debugging virtuals are not called.
@@ -75,7 +76,7 @@ public:
// the fn function will execute a batch of driver commands
// this gives the driver a chance to wrap their execution in a meaningful manner
// the default implementation simply calls fn
virtual void execute(std::function<void(void)> const& fn) noexcept;
virtual void execute(std::function<void(void)> const& fn);
// This is called on debug build, or when enabled manually on the backend thread side.
virtual void debugCommandBegin(CommandStream* cmds,

View File

@@ -133,18 +133,18 @@ DECL_DRIVER_API_0(tick)
DECL_DRIVER_API_N(beginFrame,
int64_t, monotonic_clock_ns,
int64_t, refreshIntervalNs,
uint32_t, frameId)
DECL_DRIVER_API_N(setFrameScheduledCallback,
backend::SwapChainHandle, sch,
backend::FrameScheduledCallback, callback,
void*, user)
backend::CallbackHandler*, handler,
backend::FrameScheduledCallback&&, callback)
DECL_DRIVER_API_N(setFrameCompletedCallback,
backend::SwapChainHandle, sch,
backend::CallbackHandler*, handler,
backend::CallbackHandler::Callback, callback,
void*, user)
utils::Invocable<void(void)>&&, callback)
DECL_DRIVER_API_N(setPresentationTime,
int64_t, monotonic_clock_ns)
@@ -167,12 +167,15 @@ DECL_DRIVER_API_0(resetState)
* -----------------------
*/
DECL_DRIVER_API_R_N(backend::VertexBufferHandle, createVertexBuffer,
DECL_DRIVER_API_R_N(backend::VertexBufferInfoHandle, createVertexBufferInfo,
uint8_t, bufferCount,
uint8_t, attributeCount,
uint32_t, vertexCount,
backend::AttributeArray, attributes)
DECL_DRIVER_API_R_N(backend::VertexBufferHandle, createVertexBuffer,
uint32_t, vertexCount,
backend::VertexBufferInfoHandle, vbih)
DECL_DRIVER_API_R_N(backend::IndexBufferHandle, createIndexBuffer,
backend::ElementType, elementType,
uint32_t, indexCount,
@@ -224,11 +227,7 @@ DECL_DRIVER_API_R_N(backend::SamplerGroupHandle, createSamplerGroup,
DECL_DRIVER_API_R_N(backend::RenderPrimitiveHandle, createRenderPrimitive,
backend::VertexBufferHandle, vbh,
backend::IndexBufferHandle, ibh,
backend::PrimitiveType, pt,
uint32_t, offset,
uint32_t, minIndex,
uint32_t, maxIndex,
uint32_t, count)
backend::PrimitiveType, pt)
DECL_DRIVER_API_R_N(backend::ProgramHandle, createProgram,
backend::Program&&, program)
@@ -240,6 +239,7 @@ DECL_DRIVER_API_R_N(backend::RenderTargetHandle, createRenderTarget,
uint32_t, width,
uint32_t, height,
uint8_t, samples,
uint8_t, layerCount,
backend::MRT, color,
backend::TargetBufferInfo, depth,
backend::TargetBufferInfo, stencil)
@@ -264,6 +264,7 @@ DECL_DRIVER_API_R_0(backend::TimerQueryHandle, createTimerQuery)
*/
DECL_DRIVER_API_N(destroyVertexBuffer, backend::VertexBufferHandle, vbh)
DECL_DRIVER_API_N(destroyVertexBufferInfo,backend::VertexBufferInfoHandle, vbih)
DECL_DRIVER_API_N(destroyIndexBuffer, backend::IndexBufferHandle, ibh)
DECL_DRIVER_API_N(destroyBufferObject, backend::BufferObjectHandle, ibh)
DECL_DRIVER_API_N(destroyRenderPrimitive, backend::RenderPrimitiveHandle, rph)
@@ -298,14 +299,17 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchMultiSampleSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameTimeSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isAutoDepthResolveSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isSRGBSwapChainSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedContentSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isStereoSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isParallelShaderCompileSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthStencilResolveSupported)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isDepthStencilBlitSupported, backend::TextureFormat, format)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedTexturesSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setupExternalImage, void*, image)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::TimerQueryResult, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isWorkaroundNeeded, backend::Workaround, workaround)
DECL_DRIVER_API_SYNCHRONOUS_0(backend::FeatureLevel, getFeatureLevel)
@@ -429,6 +433,11 @@ DECL_DRIVER_API_N(bindSamplers,
uint32_t, index,
backend::SamplerGroupHandle, sbh)
DECL_DRIVER_API_N(setPushConstant,
backend::ShaderStage, stage,
uint8_t, index,
backend::PushConstantVariant, value)
DECL_DRIVER_API_N(insertEventMarker,
const char*, string,
uint32_t, len = 0)
@@ -491,15 +500,32 @@ DECL_DRIVER_API_N(blit,
math::uint2, srcOrigin,
math::uint2, size)
DECL_DRIVER_API_N(bindPipeline,
backend::PipelineState const&, state)
DECL_DRIVER_API_N(bindRenderPrimitive,
backend::RenderPrimitiveHandle, rph)
DECL_DRIVER_API_N(draw2,
uint32_t, indexOffset,
uint32_t, indexCount,
uint32_t, instanceCount)
DECL_DRIVER_API_N(draw,
backend::PipelineState, state,
backend::RenderPrimitiveHandle, rph,
uint32_t, indexOffset,
uint32_t, indexCount,
uint32_t, instanceCount)
DECL_DRIVER_API_N(dispatchCompute,
backend::ProgramHandle, program,
math::uint3, workGroupCount)
DECL_DRIVER_API_N(scissor,
Viewport, scissor)
#pragma clang diagnostic pop

View File

@@ -22,29 +22,34 @@
#include <utils/Allocator.h>
#include <utils/Log.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <utils/Panic.h>
#include <tsl/robin_map.h>
#include <cstddef>
#include <exception>
#include <type_traits>
#include <unordered_map>
#include <utility>
#if !defined(NDEBUG) && UTILS_HAS_RTTI
# define HANDLE_TYPE_SAFETY 1
#else
# define HANDLE_TYPE_SAFETY 0
#endif
#include <stddef.h>
#include <stdint.h>
#define HandleAllocatorGL HandleAllocator<16, 64, 208>
#define HandleAllocatorVK HandleAllocator<16, 64, 880>
#define HandleAllocatorMTL HandleAllocator<16, 64, 584>
#define HandleAllocatorGL HandleAllocator<32, 64, 136> // ~4520 / pool / MiB
#define HandleAllocatorVK HandleAllocator<64, 160, 312> // ~1820 / pool / MiB
#define HandleAllocatorMTL HandleAllocator<32, 48, 552> // ~1660 / pool / MiB
namespace filament::backend {
/*
* A utility class to efficiently allocate and manage Handle<>
*/
template <size_t P0, size_t P1, size_t P2>
template<size_t P0, size_t P1, size_t P2>
class HandleAllocator {
public:
HandleAllocator(const char* name, size_t size) noexcept;
HandleAllocator(const char* name, size_t size, bool disableUseAfterFreeCheck) noexcept;
HandleAllocator(HandleAllocator const& rhs) = delete;
HandleAllocator& operator=(HandleAllocator const& rhs) = delete;
~HandleAllocator();
@@ -60,15 +65,10 @@ public:
*
*/
template<typename D, typename ... ARGS>
Handle<D> allocateAndConstruct(ARGS&& ... args) noexcept {
Handle<D> h{ allocateHandle<sizeof(D)>() };
Handle<D> allocateAndConstruct(ARGS&& ... args) {
Handle<D> h{ allocateHandle<D>() };
D* addr = handle_cast<D*>(h);
new(addr) D(std::forward<ARGS>(args)...);
#if HANDLE_TYPE_SAFETY
mLock.lock();
mHandleTypeId[addr] = typeid(D).name();
mLock.unlock();
#endif
return h;
}
@@ -84,13 +84,7 @@ public:
*/
template<typename D>
Handle<D> allocate() noexcept {
Handle<D> h{ allocateHandle<sizeof(D)>() };
#if HANDLE_TYPE_SAFETY
D* addr = handle_cast<D*>(h);
mLock.lock();
mHandleTypeId[addr] = typeid(D).name();
mLock.unlock();
#endif
Handle<D> h{ allocateHandle<D>() };
return h;
}
@@ -103,21 +97,14 @@ public:
*/
template<typename D, typename B, typename ... ARGS>
typename std::enable_if_t<std::is_base_of_v<B, D>, D>*
destroyAndConstruct(Handle<B> const& handle, ARGS&& ... args) noexcept {
destroyAndConstruct(Handle<B> const& handle, ARGS&& ... args) {
assert_invariant(handle);
D* addr = handle_cast<D*>(const_cast<Handle<B>&>(handle));
assert_invariant(addr);
// currently we implement construct<> with dtor+ctor, we could use operator= also
// but all our dtors are trivial, ~D() is actually a noop.
addr->~D();
new(addr) D(std::forward<ARGS>(args)...);
#if HANDLE_TYPE_SAFETY
mLock.lock();
mHandleTypeId[addr] = typeid(D).name();
mLock.unlock();
#endif
return addr;
}
@@ -134,12 +121,6 @@ public:
D* addr = handle_cast<D*>(const_cast<Handle<B>&>(handle));
assert_invariant(addr);
new(addr) D(std::forward<ARGS>(args)...);
#if HANDLE_TYPE_SAFETY
mLock.lock();
mHandleTypeId[addr] = typeid(D).name();
mLock.unlock();
#endif
return addr;
}
@@ -155,19 +136,8 @@ public:
void deallocate(Handle<B>& handle, D const* p) noexcept {
// allow to destroy the nullptr, similarly to operator delete
if (p) {
#if HANDLE_TYPE_SAFETY
mLock.lock();
auto typeId = mHandleTypeId[p];
mHandleTypeId.erase(p);
mLock.unlock();
if (UTILS_UNLIKELY(typeId != typeid(D).name())) {
utils::slog.e << "Destroying handle " << handle.getId() << ", type " << typeid(D).name()
<< ", but handle's actual type is " << typeId << utils::io::endl;
std::terminate();
}
#endif
p->~D();
deallocateHandle<sizeof(D)>(handle.getId());
deallocateHandle<D>(handle.getId());
}
}
@@ -193,46 +163,100 @@ public:
inline typename std::enable_if_t<
std::is_pointer_v<Dp> &&
std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
handle_cast(Handle<B>& handle) noexcept {
handle_cast(Handle<B>& handle) {
assert_invariant(handle);
void* const p = handleToPointer(handle.getId());
auto [p, tag] = handleToPointer(handle.getId());
if (isPoolHandle(handle.getId())) {
// check for use after free
if (UTILS_UNLIKELY(!mUseAfterFreeCheckDisabled)) {
uint8_t const age = (tag & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT;
auto const pNode = static_cast<typename Allocator::Node*>(p);
uint8_t const expectedAge = pNode[-1].age;
FILAMENT_CHECK_POSTCONDITION(expectedAge == age) <<
"use-after-free of Handle with id=" << handle.getId();
}
}
return static_cast<Dp>(p);
}
template<typename B>
bool is_valid(Handle<B>& handle) {
if (handle && isPoolHandle(handle.getId())) {
auto [p, tag] = handleToPointer(handle.getId());
uint8_t const age = (tag & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT;
auto const pNode = static_cast<typename Allocator::Node*>(p);
uint8_t const expectedAge = pNode[-1].age;
return expectedAge == age;
}
return true;
}
template<typename Dp, typename B>
inline typename std::enable_if_t<
std::is_pointer_v<Dp> &&
std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
handle_cast(Handle<B> const& handle) noexcept {
handle_cast(Handle<B> const& handle) {
return handle_cast<Dp>(const_cast<Handle<B>&>(handle));
}
private:
// template <int P0, int P1, int P2>
template<typename D>
static constexpr size_t getBucketSize() noexcept {
if constexpr (sizeof(D) <= P0) { return P0; }
if constexpr (sizeof(D) <= P1) { return P1; }
static_assert(sizeof(D) <= P2);
return P2;
}
class Allocator {
friend class HandleAllocator;
utils::PoolAllocator<P0, 16> mPool0;
utils::PoolAllocator<P1, 16> mPool1;
utils::PoolAllocator<P2, 16> mPool2;
static constexpr size_t MIN_ALIGNMENT = alignof(std::max_align_t);
struct Node { uint8_t age; };
// Note: using the `extra` parameter of PoolAllocator<>, even with a 1-byte structure,
// generally increases all pool allocations by 8-bytes because of alignment restrictions.
template<size_t SIZE>
using Pool = utils::PoolAllocator<SIZE, MIN_ALIGNMENT, sizeof(Node)>;
Pool<P0> mPool0;
Pool<P1> mPool1;
Pool<P2> mPool2;
UTILS_UNUSED_IN_RELEASE const utils::AreaPolicy::HeapArea& mArea;
bool mUseAfterFreeCheckDisabled;
public:
static constexpr size_t MIN_ALIGNMENT_SHIFT = 4;
explicit Allocator(const utils::AreaPolicy::HeapArea& area);
explicit Allocator(const utils::AreaPolicy::HeapArea& area, bool disableUseAfterFreeCheck);
static constexpr size_t getAlignment() noexcept { return MIN_ALIGNMENT; }
// this is in fact always called with a constexpr size argument
[[nodiscard]] inline void* alloc(size_t size, size_t alignment, size_t extra) noexcept {
[[nodiscard]] inline void* alloc(size_t size, size_t, size_t, uint8_t* outAge) noexcept {
void* p = nullptr;
if (size <= mPool0.getSize()) p = mPool0.alloc(size, 16, extra);
else if (size <= mPool1.getSize()) p = mPool1.alloc(size, 16, extra);
else if (size <= mPool2.getSize()) p = mPool2.alloc(size, 16, extra);
if (size <= mPool0.getSize()) p = mPool0.alloc(size);
else if (size <= mPool1.getSize()) p = mPool1.alloc(size);
else if (size <= mPool2.getSize()) p = mPool2.alloc(size);
if (UTILS_LIKELY(p)) {
Node const* const pNode = static_cast<Node const*>(p);
// we are guaranteed to have at least sizeof<Node> bytes of extra storage before
// the allocation address.
*outAge = pNode[-1].age;
}
return p;
}
// this is in fact always called with a constexpr size argument
inline void free(void* p, size_t size) noexcept {
inline void free(void* p, size_t size, uint8_t age) noexcept {
assert_invariant(p >= mArea.begin() && (char*)p + size <= (char*)mArea.end());
// check for double-free
Node* const pNode = static_cast<Node*>(p);
uint8_t& expectedAge = pNode[-1].age;
if (UTILS_UNLIKELY(!mUseAfterFreeCheckDisabled)) {
FILAMENT_CHECK_POSTCONDITION(expectedAge == age) <<
"double-free of Handle of size " << size << " at " << p;
}
expectedAge = (expectedAge + 1) & 0xF; // fixme
if (size <= mPool0.getSize()) { mPool0.free(p); return; }
if (size <= mPool1.getSize()) { mPool1.free(p); return; }
if (size <= mPool2.getSize()) { mPool2.free(p); return; }
@@ -254,24 +278,16 @@ private:
// allocateHandle()/deallocateHandle() selects the pool to use at compile-time based on the
// allocation size this is always inlined, because all these do is to call
// allocateHandleInPool()/deallocateHandleFromPool() with the right pool size.
template<size_t SIZE>
template<typename D>
HandleBase::HandleId allocateHandle() noexcept {
if constexpr (SIZE <= P0) { return allocateHandleInPool<P0>(); }
if constexpr (SIZE <= P1) { return allocateHandleInPool<P1>(); }
static_assert(SIZE <= P2);
return allocateHandleInPool<P2>();
constexpr size_t BUCKET_SIZE = getBucketSize<D>();
return allocateHandleInPool<BUCKET_SIZE>();
}
template<size_t SIZE>
template<typename D>
void deallocateHandle(HandleBase::HandleId id) noexcept {
if constexpr (SIZE <= P0) {
deallocateHandleFromPool<P0>(id);
} else if constexpr (SIZE <= P1) {
deallocateHandleFromPool<P1>(id);
} else {
static_assert(SIZE <= P2);
deallocateHandleFromPool<P2>(id);
}
constexpr size_t BUCKET_SIZE = getBucketSize<D>();
deallocateHandleFromPool<BUCKET_SIZE>(id);
}
// allocateHandleInPool()/deallocateHandleFromPool() is NOT inlined, which will cause three
@@ -280,9 +296,11 @@ private:
template<size_t SIZE>
UTILS_NOINLINE
HandleBase::HandleId allocateHandleInPool() noexcept {
void* p = mHandleArena.alloc(SIZE);
uint8_t age;
void* p = mHandleArena.alloc(SIZE, alignof(std::max_align_t), 0, &age);
if (UTILS_LIKELY(p)) {
return pointerToHandle(p);
uint32_t const tag = (uint32_t(age) << HANDLE_AGE_SHIFT) & HANDLE_AGE_MASK;
return arenaPointerToHandle(p, tag);
} else {
return allocateHandleSlow(SIZE);
}
@@ -292,42 +310,51 @@ private:
UTILS_NOINLINE
void deallocateHandleFromPool(HandleBase::HandleId id) noexcept {
if (UTILS_LIKELY(isPoolHandle(id))) {
void* p = handleToPointer(id);
mHandleArena.free(p, SIZE);
auto [p, tag] = handleToPointer(id);
uint8_t const age = (tag & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT;
mHandleArena.free(p, SIZE, age);
} else {
deallocateHandleSlow(id, SIZE);
}
}
static constexpr uint32_t HEAP_HANDLE_FLAG = 0x80000000u;
// we handle a 4 bits age per address
static constexpr uint32_t HANDLE_HEAP_FLAG = 0x80000000u; // pool vs heap handle
static constexpr uint32_t HANDLE_AGE_MASK = 0x78000000u; // handle's age
static constexpr uint32_t HANDLE_INDEX_MASK = 0x07FFFFFFu; // handle index
static constexpr uint32_t HANDLE_TAG_MASK = HANDLE_AGE_MASK;
static constexpr uint32_t HANDLE_AGE_SHIFT = 27;
static bool isPoolHandle(HandleBase::HandleId id) noexcept {
return (id & HEAP_HANDLE_FLAG) == 0u;
return (id & HANDLE_HEAP_FLAG) == 0u;
}
HandleBase::HandleId allocateHandleSlow(size_t size) noexcept;
HandleBase::HandleId allocateHandleSlow(size_t size);
void deallocateHandleSlow(HandleBase::HandleId id, size_t size) noexcept;
// We inline this because it's just 4 instructions in the fast case
inline void* handleToPointer(HandleBase::HandleId id) const noexcept {
inline std::pair<void*, uint32_t> handleToPointer(HandleBase::HandleId id) const noexcept {
// note: the null handle will end-up returning nullptr b/c it'll be handled as
// a non-pool handle.
if (UTILS_LIKELY(isPoolHandle(id))) {
char* const base = (char*)mHandleArena.getArea().begin();
size_t offset = id << Allocator::MIN_ALIGNMENT_SHIFT;
return static_cast<void*>(base + offset);
uint32_t const tag = id & HANDLE_TAG_MASK;
size_t const offset = (id & HANDLE_INDEX_MASK) * Allocator::getAlignment();
return { static_cast<void*>(base + offset), tag };
}
return handleToPointerSlow(id);
return { handleToPointerSlow(id), 0 };
}
void* handleToPointerSlow(HandleBase::HandleId id) const noexcept;
// We inline this because it's just 3 instructions
inline HandleBase::HandleId pointerToHandle(void* p) const noexcept {
inline HandleBase::HandleId arenaPointerToHandle(void* p, uint32_t tag) const noexcept {
char* const base = (char*)mHandleArena.getArea().begin();
size_t offset = (char*)p - base;
auto id = HandleBase::HandleId(offset >> Allocator::MIN_ALIGNMENT_SHIFT);
assert_invariant((id & HEAP_HANDLE_FLAG) == 0);
size_t const offset = (char*)p - base;
assert_invariant((offset % Allocator::getAlignment()) == 0);
auto id = HandleBase::HandleId(offset / Allocator::getAlignment());
id |= tag & HANDLE_TAG_MASK;
assert_invariant((id & HANDLE_HEAP_FLAG) == 0);
return id;
}
@@ -337,9 +364,7 @@ private:
mutable utils::Mutex mLock;
tsl::robin_map<HandleBase::HandleId, void*> mOverflowMap;
HandleBase::HandleId mId = 0;
#if HANDLE_TYPE_SAFETY
mutable std::unordered_map<const void*, const char*> mHandleTypeId;
#endif
bool mUseAfterFreeCheckDisabled = false;
};
} // namespace filament::backend

View File

@@ -19,9 +19,9 @@
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
#define TNT_FILAMENT_BACKEND_PLATFORM_FACTORY_H
#include "backend/DriverEnums.h"
#include <backend/DriverEnums.h>
#include "utils/compiler.h"
#include <utils/compiler.h>
namespace filament::backend {

View File

@@ -17,15 +17,13 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
#define TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
#include "backend/DriverApiForward.h"
#include <utils/compiler.h>
#include <utils/FixedCapacityVector.h>
#include <backend/DriverApiForward.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/SamplerDescriptor.h>
#include <utils/FixedCapacityVector.h>
#include <utils/ostream.h>
#include <stddef.h>
namespace filament::backend {

View File

@@ -27,8 +27,8 @@ PresentCallable::PresentCallable(PresentFn fn, void* user) noexcept
}
void PresentCallable::operator()(bool presentFrame) noexcept {
ASSERT_PRECONDITION(mPresentFn, "This PresentCallable was already called. " \
"PresentCallables should be called exactly once.");
FILAMENT_CHECK_PRECONDITION(mPresentFn) << "This PresentCallable was already called. "
"PresentCallables should be called exactly once.";
mPresentFn(presentFrame, mUser);
// Set mPresentFn to nullptr to denote that the callable has been called.
mPresentFn = nullptr;

View File

@@ -16,6 +16,14 @@
#include "private/backend/CircularBuffer.h"
#include <utils/Log.h>
#include <utils/Panic.h>
#include <utils/architecture.h>
#include <utils/ashmem.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#if !defined(WIN32) && !defined(__EMSCRIPTEN__) && !defined(IOS)
# include <sys/mman.h>
# include <unistd.h>
@@ -24,13 +32,11 @@
# define HAS_MMAP 0
#endif
#include <stddef.h>
#include <stdint.h>
#include <stdio.h>
#include <utils/architecture.h>
#include <utils/ashmem.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <stdlib.h>
#include <string.h>
using namespace utils;
@@ -38,9 +44,9 @@ namespace filament::backend {
size_t CircularBuffer::sPageSize = arch::getPageSize();
CircularBuffer::CircularBuffer(size_t size) {
CircularBuffer::CircularBuffer(size_t size)
: mSize(size) {
mData = alloc(size);
mSize = size;
mTail = mData;
mHead = mData;
}
@@ -76,6 +82,9 @@ void* CircularBuffer::alloc(size_t size) noexcept {
// map the circular buffer once...
vaddr = mmap(reserve_vaddr, size, PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
if (vaddr != MAP_FAILED) {
// populate the address space with pages (because this is a circular buffer,
// all the pages will be allocated eventually, might as well do it now)
memset(vaddr, 0, size);
// and map the circular buffer again, behind the previous copy...
vaddr_shadow = mmap((char*)vaddr + size, size,
PROT_READ | PROT_WRITE, MAP_PRIVATE, fd, 0);
@@ -85,7 +94,7 @@ void* CircularBuffer::alloc(size_t size) noexcept {
MAP_PRIVATE, fd, (off_t)size);
if (vaddr_guard != MAP_FAILED && (vaddr_guard == (char*)vaddr_shadow + size)) {
// woo-hoo success!
mUsesAshmem = fd;
mAshmemFd = fd;
data = vaddr;
}
}
@@ -93,10 +102,10 @@ void* CircularBuffer::alloc(size_t size) noexcept {
}
}
if (UTILS_UNLIKELY(mUsesAshmem < 0)) {
if (UTILS_UNLIKELY(mAshmemFd < 0)) {
// ashmem failed
if (vaddr_guard != MAP_FAILED) {
munmap(vaddr_guard, size);
munmap(vaddr_guard, BLOCK_SIZE);
}
if (vaddr_shadow != MAP_FAILED) {
@@ -114,12 +123,11 @@ void* CircularBuffer::alloc(size_t size) noexcept {
data = mmap(nullptr, size * 2 + BLOCK_SIZE,
PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ASSERT_POSTCONDITION(data,
"couldn't allocate %u KiB of virtual address space for the command buffer",
(size * 2 / 1024));
FILAMENT_CHECK_POSTCONDITION(data != MAP_FAILED) <<
"couldn't allocate " << (size * 2 / 1024) <<
" KiB of virtual address space for the command buffer";
slog.d << "WARNING: Using soft CircularBuffer (" << (size * 2 / 1024) << " KiB)"
<< io::endl;
slog.w << "Using 'soft' CircularBuffer (" << (size * 2 / 1024) << " KiB)" << io::endl;
// guard page at the end
void* guard = (void*)(uintptr_t(data) + size * 2);
@@ -137,9 +145,9 @@ void CircularBuffer::dealloc() noexcept {
if (mData) {
size_t const BLOCK_SIZE = getBlockSize();
munmap(mData, mSize * 2 + BLOCK_SIZE);
if (mUsesAshmem >= 0) {
close(mUsesAshmem);
mUsesAshmem = -1;
if (mAshmemFd >= 0) {
close(mAshmemFd);
mAshmemFd = -1;
}
}
#else
@@ -149,23 +157,37 @@ void CircularBuffer::dealloc() noexcept {
}
void CircularBuffer::circularize() noexcept {
if (mUsesAshmem > 0) {
intptr_t const overflow = intptr_t(mHead) - (intptr_t(mData) + ssize_t(mSize));
if (overflow >= 0) {
assert_invariant(size_t(overflow) <= mSize);
mHead = (void *) (intptr_t(mData) + overflow);
#ifndef NDEBUG
memset(mData, 0xA5, size_t(overflow));
#endif
}
} else {
// Only circularize if mHead if in the second buffer.
if (intptr_t(mHead) - intptr_t(mData) > ssize_t(mSize)) {
CircularBuffer::Range CircularBuffer::getBuffer() noexcept {
Range const range{ .tail = mTail, .head = mHead };
char* const pData = static_cast<char*>(mData);
char const* const pEnd = pData + mSize;
char const* const pHead = static_cast<char const*>(mHead);
if (UTILS_UNLIKELY(pHead >= pEnd)) {
size_t const overflow = pHead - pEnd;
if (UTILS_LIKELY(mAshmemFd > 0)) {
assert_invariant(overflow <= mSize);
mHead = static_cast<void*>(pData + overflow);
// Data Tail End Head [virtual]
// v v v v
// +-------------:----+-----:--------------+
// | : | : |
// +-----:------------+--------------------+
// Head |<------ copy ------>| [physical]
} else {
// Data Tail End Head
// v v v v
// +-------------:----+-----:--------------+
// | : | : |
// +-----|------------+-----|--------------+
// |<---------------->|
// sliding window
mHead = mData;
}
}
mTail = mHead;
return range;
}
} // namespace filament::backend

View File

@@ -15,23 +15,35 @@
*/
#include "private/backend/CommandBufferQueue.h"
#include "private/backend/CircularBuffer.h"
#include "private/backend/CommandStream.h"
#include <utils/compiler.h>
#include <utils/Log.h>
#include <utils/Systrace.h>
#include <utils/Mutex.h>
#include <utils/ostream.h>
#include <utils/Panic.h>
#include <utils/Systrace.h>
#include <utils/debug.h>
#include "private/backend/BackendUtils.h"
#include "private/backend/CommandStream.h"
#include <algorithm>
#include <mutex>
#include <iterator>
#include <utility>
#include <vector>
#include <stddef.h>
#include <stdint.h>
using namespace utils;
namespace filament::backend {
CommandBufferQueue::CommandBufferQueue(size_t requiredSize, size_t bufferSize)
CommandBufferQueue::CommandBufferQueue(size_t requiredSize, size_t bufferSize, bool paused)
: mRequiredSize((requiredSize + (CircularBuffer::getBlockSize() - 1u)) & ~(CircularBuffer::getBlockSize() -1u)),
mCircularBuffer(bufferSize),
mFreeSpace(mCircularBuffer.size()) {
mFreeSpace(mCircularBuffer.size()),
mPaused(paused) {
assert_invariant(mCircularBuffer.size() > requiredSize);
}
@@ -45,10 +57,23 @@ void CommandBufferQueue::requestExit() {
mCondition.notify_one();
}
bool CommandBufferQueue::isPaused() const noexcept {
std::lock_guard<utils::Mutex> const lock(mLock);
return mPaused;
}
void CommandBufferQueue::setPaused(bool paused) {
std::lock_guard<utils::Mutex> const lock(mLock);
if (paused) {
mPaused = true;
} else {
mPaused = false;
mCondition.notify_one();
}
}
bool CommandBufferQueue::isExitRequested() const {
std::lock_guard<utils::Mutex> const lock(mLock);
ASSERT_PRECONDITION( mExitRequested == 0 || mExitRequested == EXIT_REQUESTED,
"mExitRequested is corrupted (value = 0x%08x)!", mExitRequested);
return (bool)mExitRequested;
}
@@ -65,65 +90,69 @@ void CommandBufferQueue::flush() noexcept {
// always guaranteed to have enough space for the NoopCommand
new(circularBuffer.allocate(sizeof(NoopCommand))) NoopCommand(nullptr);
// end of this slice
void* const head = circularBuffer.getHead();
const size_t requiredSize = mRequiredSize;
// beginning of this slice
void* const tail = circularBuffer.getTail();
// get the current buffer
auto const [begin, end] = circularBuffer.getBuffer();
// size of this slice
uint32_t const used = uint32_t(intptr_t(head) - intptr_t(tail));
assert_invariant(circularBuffer.empty());
circularBuffer.circularize();
// size of the current buffer
size_t const used = std::distance(
static_cast<char const*>(begin), static_cast<char const*>(end));
std::unique_lock<utils::Mutex> lock(mLock);
mCommandBuffersToExecute.push_back({ tail, head });
mCommandBuffersToExecute.push_back({ begin, end });
mCondition.notify_one();
// circular buffer is too small, we corrupted the stream
ASSERT_POSTCONDITION(used <= mFreeSpace,
FILAMENT_CHECK_POSTCONDITION(used <= mFreeSpace) <<
"Backend CommandStream overflow. Commands are corrupted and unrecoverable.\n"
"Please increase minCommandBufferSizeMB inside the Config passed to Engine::create.\n"
"Space used at this time: %u bytes",
(unsigned)used);
"Space used at this time: " << used <<
" bytes, overflow: " << used - mFreeSpace << " bytes";
// wait until there is enough space in the buffer
mFreeSpace -= used;
const size_t requiredSize = mRequiredSize;
if (UTILS_UNLIKELY(mFreeSpace < requiredSize)) {
#ifndef NDEBUG
size_t totalUsed = circularBuffer.size() - mFreeSpace;
mHighWatermark = std::max(mHighWatermark, totalUsed);
if (UTILS_UNLIKELY(totalUsed > requiredSize)) {
slog.d << "CommandStream used too much space: " << totalUsed
<< ", out of " << requiredSize << " (will block)" << io::endl;
}
size_t const totalUsed = circularBuffer.size() - mFreeSpace;
slog.d << "CommandStream used too much space (will block): "
<< "needed space " << requiredSize << " out of " << mFreeSpace
<< ", totalUsed=" << totalUsed << ", current=" << used
<< ", queue size=" << mCommandBuffersToExecute.size() << " buffers"
<< io::endl;
mHighWatermark = std::max(mHighWatermark, totalUsed);
#endif
mCondition.notify_one();
if (UTILS_LIKELY(mFreeSpace < requiredSize)) {
SYSTRACE_NAME("waiting: CircularBuffer::flush()");
FILAMENT_CHECK_POSTCONDITION(!mPaused) <<
"CommandStream is full, but since the rendering thread is paused, "
"the buffer cannot flush and we will deadlock. Instead, abort.";
mCondition.wait(lock, [this, requiredSize]() -> bool {
// TODO: on macOS, we need to call pumpEvents from time to time
return mFreeSpace >= requiredSize;
});
}
}
std::vector<CommandBufferQueue::Slice> CommandBufferQueue::waitForCommands() const {
std::vector<CommandBufferQueue::Range> CommandBufferQueue::waitForCommands() const {
if (!UTILS_HAS_THREADING) {
return std::move(mCommandBuffersToExecute);
}
std::unique_lock<utils::Mutex> lock(mLock);
while (mCommandBuffersToExecute.empty() && !mExitRequested) {
while ((mCommandBuffersToExecute.empty() || mPaused) && !mExitRequested) {
mCondition.wait(lock);
}
ASSERT_PRECONDITION( mExitRequested == 0 || mExitRequested == EXIT_REQUESTED,
"mExitRequested is corrupted (value = 0x%08x)!", mExitRequested);
return std::move(mCommandBuffersToExecute);
}
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Slice const& buffer) {
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Range const& buffer) {
std::lock_guard<utils::Mutex> const lock(mLock);
mFreeSpace += uintptr_t(buffer.end) - uintptr_t(buffer.begin);
mCondition.notify_one();

View File

@@ -149,7 +149,7 @@ void CommandType<void (Driver::*)(ARGS...)>::Command<METHOD>::log() noexcept {
// ------------------------------------------------------------------------------------------------
void CustomCommand::execute(Driver&, CommandBase* base, intptr_t* next) noexcept {
void CustomCommand::execute(Driver&, CommandBase* base, intptr_t* next) {
*next = CustomCommand::align(sizeof(CustomCommand));
static_cast<CustomCommand*>(base)->mCommand();
static_cast<CustomCommand*>(base)->~CustomCommand();

View File

@@ -19,6 +19,7 @@
#include <backend/PixelBufferDescriptor.h>
#include <cstring>
#include <stddef.h>
#include <stdint.h>

View File

@@ -21,7 +21,12 @@
#include <backend/AcquiredImage.h>
#include <backend/BufferDescriptor.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <utils/Systrace.h>
#include <math/half.h>
@@ -29,6 +34,13 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <functional>
#include <mutex>
#include <utility>
#include <stddef.h>
#include <stdint.h>
using namespace utils;
using namespace filament::math;
@@ -119,7 +131,8 @@ void DriverBase::purge() noexcept {
// ------------------------------------------------------------------------------------------------
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
scheduleCallback(buffer.getHandler(), [buffer = std::move(buffer)]() {
auto const handler = buffer.getHandler();
scheduleCallback(handler, [buffer = std::move(buffer)]() {
// user callback is called when BufferDescriptor gets destroyed
});
}
@@ -201,7 +214,7 @@ size_t Driver::getElementTypeSize(ElementType type) noexcept {
Driver::~Driver() noexcept = default;
void Driver::execute(std::function<void(void)> const& fn) noexcept {
void Driver::execute(std::function<void(void)> const& fn) {
fn();
}

View File

@@ -49,24 +49,28 @@ struct AcquiredImage;
struct HwBase {
};
struct HwVertexBuffer : public HwBase {
AttributeArray attributes{}; // 8 * MAX_VERTEX_ATTRIBUTE_COUNT
uint32_t vertexCount{}; // 4
struct HwVertexBufferInfo : public HwBase {
uint8_t bufferCount{}; // 1
uint8_t attributeCount{}; // 1
bool padding{}; // 1
uint8_t bufferObjectsVersion{}; // 1 -> total struct is 136 bytes
HwVertexBuffer() noexcept = default;
HwVertexBuffer(uint8_t bufferCount, uint8_t attributeCount, uint32_t elementCount,
AttributeArray const& attributes) noexcept
: attributes(attributes),
vertexCount(elementCount),
bufferCount(bufferCount),
bool padding[2]{}; // 2
HwVertexBufferInfo() noexcept = default;
HwVertexBufferInfo(uint8_t bufferCount, uint8_t attributeCount) noexcept
: bufferCount(bufferCount),
attributeCount(attributeCount) {
}
};
struct HwVertexBuffer : public HwBase {
uint32_t vertexCount{}; // 4
uint8_t bufferObjectsVersion{0xff}; // 1
bool padding[3]{}; // 2
HwVertexBuffer() noexcept = default;
explicit HwVertexBuffer(uint32_t vertextCount) noexcept
: vertexCount(vertextCount) {
}
};
struct HwBufferObject : public HwBase {
uint32_t byteCount{};
@@ -88,11 +92,6 @@ struct HwIndexBuffer : public HwBase {
};
struct HwRenderPrimitive : public HwBase {
uint32_t offset{};
uint32_t minIndex{};
uint32_t maxIndex{};
uint32_t count{};
uint32_t maxVertexCount{};
PrimitiveType type = PrimitiveType::TRIANGLES;
};
@@ -114,7 +113,9 @@ struct HwTexture : public HwBase {
uint8_t levels : 4; // This allows up to 15 levels (max texture size of 32768 x 32768)
uint8_t samples : 4; // Sample count per pixel (should always be a power of 2)
TextureFormat format{};
uint8_t reserved0 = 0;
TextureUsage usage{};
uint16_t reserved1 = 0;
HwStream* hwStream = nullptr;
HwTexture() noexcept : levels{}, samples{} {}

View File

@@ -16,9 +16,22 @@
#include "private/backend/HandleAllocator.h"
#include <backend/Handle.h>
#include <utils/Allocator.h>
#include <utils/Log.h>
#include <utils/Panic.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <algorithm>
#include <exception>
#include <limits>
#include <mutex>
#include <stdlib.h>
#include <string.h>
namespace filament::backend {
@@ -26,23 +39,47 @@ using namespace utils;
template <size_t P0, size_t P1, size_t P2>
UTILS_NOINLINE
HandleAllocator<P0, P1, P2>::Allocator::Allocator(AreaPolicy::HeapArea const& area)
: mArea(area) {
// TODO: we probably need a better way to set the size of these pools
const size_t unit = area.size() / 32;
const size_t offsetPool1 = unit;
const size_t offsetPool2 = 16 * unit;
char* const p = (char*)area.begin();
mPool0 = PoolAllocator< P0, 16>(p, p + offsetPool1);
mPool1 = PoolAllocator< P1, 16>(p + offsetPool1, p + offsetPool2);
mPool2 = PoolAllocator< P2, 16>(p + offsetPool2, area.end());
HandleAllocator<P0, P1, P2>::Allocator::Allocator(AreaPolicy::HeapArea const& area,
bool disableUseAfterFreeCheck)
: mArea(area),
mUseAfterFreeCheckDisabled(disableUseAfterFreeCheck) {
// The largest handle this allocator can generate currently depends on the architecture's
// min alignment, typically 8 or 16 bytes.
// e.g. On Android armv8, the alignment is 16 bytes, so for a 1 MiB heap, the largest handle
// index will be 65536. Note that this is not the same as the number of handles (which
// will always be less).
// Because our maximum representable handle currently is 0x07FFFFFF, the maximum no-nonsensical
// heap size is 2 GiB, which amounts to 7.6 millions handles per pool (in the GL case).
size_t const maxHeapSize = std::min(area.size(), HANDLE_INDEX_MASK * getAlignment());
if (UTILS_UNLIKELY(maxHeapSize != area.size())) {
slog.w << "HandleAllocator heap size reduced to "
<< maxHeapSize << " from " << area.size() << io::endl;
}
// make sure we start with a clean arena. This is needed to ensure that all blocks start
// with an age of 0.
memset(area.data(), 0, maxHeapSize);
// size the different pools so that they can all contain the same number of handles
size_t const count = maxHeapSize / (P0 + P1 + P2);
char* const p0 = static_cast<char*>(area.begin());
char* const p1 = p0 + count * P0;
char* const p2 = p1 + count * P1;
mPool0 = Pool<P0>(p0, count * P0);
mPool1 = Pool<P1>(p1, count * P1);
mPool2 = Pool<P2>(p2, count * P2);
}
// ------------------------------------------------------------------------------------------------
template <size_t P0, size_t P1, size_t P2>
HandleAllocator<P0, P1, P2>::HandleAllocator(const char* name, size_t size) noexcept
: mHandleArena(name, size) {
HandleAllocator<P0, P1, P2>::HandleAllocator(const char* name, size_t size,
bool disableUseAfterFreeCheck) noexcept
: mHandleArena(name, size, disableUseAfterFreeCheck),
mUseAfterFreeCheckDisabled(disableUseAfterFreeCheck) {
}
template <size_t P0, size_t P1, size_t P2>
@@ -70,14 +107,20 @@ void* HandleAllocator<P0, P1, P2>::handleToPointerSlow(HandleBase::HandleId id)
}
template <size_t P0, size_t P1, size_t P2>
HandleBase::HandleId HandleAllocator<P0, P1, P2>::allocateHandleSlow(size_t size) noexcept {
HandleBase::HandleId HandleAllocator<P0, P1, P2>::allocateHandleSlow(size_t size) {
void* p = ::malloc(size);
std::unique_lock lock(mLock);
HandleBase::HandleId id = (++mId) | HEAP_HANDLE_FLAG;
HandleBase::HandleId id = (++mId) | HANDLE_HEAP_FLAG;
FILAMENT_CHECK_POSTCONDITION(mId < HANDLE_HEAP_FLAG) <<
"No more Handle ids available! This can happen if HandleAllocator arena has been full"
" for a while. Please increase FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB";
mOverflowMap.emplace(id, p);
lock.unlock();
if (UTILS_UNLIKELY(id == (HEAP_HANDLE_FLAG|1u))) { // meaning id was zero
if (UTILS_UNLIKELY(id == (HANDLE_HEAP_FLAG | 1u))) { // meaning id was zero
PANIC_LOG("HandleAllocator arena is full, using slower system heap. Please increase "
"the appropriate constant (e.g. FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB).");
}
@@ -86,7 +129,7 @@ HandleBase::HandleId HandleAllocator<P0, P1, P2>::allocateHandleSlow(size_t size
template <size_t P0, size_t P1, size_t P2>
void HandleAllocator<P0, P1, P2>::deallocateHandleSlow(HandleBase::HandleId id, size_t) noexcept {
assert_invariant(id & HEAP_HANDLE_FLAG);
assert_invariant(id & HANDLE_HEAP_FLAG);
void* p = nullptr;
auto& overflowMap = mOverflowMap;

View File

@@ -53,4 +53,18 @@ size_t Platform::retrieveBlob(void const* key, size_t keySize, void* value, size
return 0;
}
void Platform::setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept {
mDebugUpdateStat = std::move(debugUpdateStat);
}
bool Platform::hasDebugUpdateStatFunc() const noexcept {
return bool(mDebugUpdateStat);
}
void Platform::debugUpdateStat(const char* key, uint64_t value) {
if (mDebugUpdateStat) {
mDebugUpdateStat(key, value);
}
}
} // namespace filament::backend

View File

@@ -29,21 +29,21 @@
#include "backend/platforms/PlatformCocoaTouchGL.h"
#endif
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include <backend/platforms/PlatformCocoaGL.h>
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_X11)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformGLX.h"
#endif
#elif defined(FILAMENT_SUPPORTS_EGL_ON_LINUX)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformEGLHeadless.h"
#endif
#endif
#elif defined(WIN32)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "backend/platforms/PlatformWGL.h"
#endif
#elif defined(__EMSCRIPTEN__)
@@ -111,8 +111,7 @@ Platform* PlatformFactory::create(Backend* backend) noexcept {
}
assert_invariant(*backend == Backend::OPENGL);
#if defined(FILAMENT_SUPPORTS_OPENGL)
#if defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(FILAMENT_USE_SWIFTSHADER)
// Swiftshader OpenGLES support is deprecated and incomplete
#if defined(FILAMENT_USE_EXTERNAL_GLES3)
return nullptr;
#elif defined(__ANDROID__)
return new PlatformEGLAndroid();

View File

@@ -21,7 +21,7 @@ namespace filament::backend {
using namespace utils;
// We want these in the .cpp file, so they're not inlined (not worth it)
Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
}
Program::Program(Program&& rhs) noexcept = default;
@@ -47,6 +47,11 @@ Program& Program::shader(ShaderStage shader, void const* data, size_t size) {
return *this;
}
Program& Program::shaderLanguage(ShaderLanguage shaderLanguage) {
mShaderLanguage = shaderLanguage;
return *this;
}
Program& Program::uniformBlockBindings(
FixedCapacityVector<std::pair<utils::CString, uint8_t>> const& uniformBlockBindings) noexcept {
for (auto const& item : uniformBlockBindings) {
@@ -86,11 +91,22 @@ Program& Program::specializationConstants(
return *this;
}
Program& Program::pushConstants(ShaderStage stage,
utils::FixedCapacityVector<PushConstant> constants) noexcept {
mPushConstants[static_cast<uint8_t>(stage)] = std::move(constants);
return *this;
}
Program& Program::cacheId(uint64_t cacheId) noexcept {
mCacheId = cacheId;
return *this;
}
Program& Program::multiview(bool multiview) noexcept {
mMultiview = multiview;
return *this;
}
io::ostream& operator<<(io::ostream& out, const Program& builder) {
out << "Program{";
builder.mLogger(out);

View File

@@ -16,13 +16,23 @@
#include "private/backend/VirtualMachineEnv.h"
#include <utils/compiler.h>
#include <utils/debug.h>
#include <jni.h>
namespace filament {
JavaVM* VirtualMachineEnv::sVirtualMachine = nullptr;
// This is called when the library is loaded. We need this to get a reference to the global VM
/*
* This is typically called by filament_jni.so when it is loaded. If filament_jni.so is not used,
* then this must be called manually -- however, this is a problem because VirtualMachineEnv.h
* is currently private and part of backend.
* For now, we authorize this usage, but we will need to fix it; by making a proper public
* API for this.
*/
UTILS_PUBLIC
UTILS_NOINLINE
jint VirtualMachineEnv::JNI_OnLoad(JavaVM* vm) noexcept {
JNIEnv* env = nullptr;

Some files were not shown because too many files have changed in this diff Show More