Compare commits

..

94 Commits

Author SHA1 Message Date
Benjamin Doherty
44125926d1 Disable configuration-cache 2021-11-08 17:05:34 -08:00
Benjamin Doherty
fbfd5ec0ec Merge branch 'rc/1.13.0' into release 2021-11-08 11:50:19 -08:00
Ben Doherty
a74a95cc65 Call VirtualMachineEnv::JNI_OnLoad for non-Android Java builds (better fix) (#4779) 2021-11-04 13:28:17 -07:00
Benjamin Doherty
bc0ea16ff0 Update RELEASE_NOTES for 1.13.0 2021-11-02 13:15:53 -07:00
Mathias Agopian
b2dc8aa84c Fix typo that broke the directional shadowmap 2021-11-02 13:11:44 -07:00
Benjamin Doherty
9987e8b6ab Bump version to 1.13.0 2021-11-01 14:59:11 -07:00
Benjamin Doherty
0d9bdcc008 Merge branch 'rc/1.12.11' into release 2021-11-01 14:55:58 -07:00
Benjamin Doherty
81fa33abeb Release Filament 1.12.11 2021-11-01 14:55:54 -07:00
Mathias Agopian
af7f87e19b make sure the near plane for spot shadows is not negative 2021-11-01 14:19:13 -07:00
Mathias Agopian
3073b03d56 Improve computation of spotlight near/far plane
Near/far plane is now computed dynamically, this significantly
improves the shadowmap depth resolution.

Quite a bit of refactoring was necessary to get all the right data 
in the right place, in particular SceneInfo is now passed around for
both directional and spot shadows.
2021-10-29 18:57:26 -07:00
Mathias Agopian
23dab0a013 Fix very narrow spotlight lighting and other minor issues
The froxel code was failing when a spotlight cone was too narrow. This
is fixed here by never using a cone smaller than 0.5 degrees during
forxelization. 

Additionally we now silently clamp the cone angles to 0.5 degrees at
the API level because, the falloff was also failing due to floating
point precision in the shader.

Finally, we clamp the inner cone upper value to the outer cone's
instead of the other way around. i.e. the outer cone defines the 
spotlight while the inner cone just controls the falloff.
2021-10-29 15:08:05 -07:00
Mathias Agopian
fd68144ba2 fix depth precision with VSM
When calculating the linear depth for VSM, we were using the whole
range between 0 and the far plane, the near plane wasn't taken into
account.

This can be a problem is the light is very far, but it's near plane is
closer to the camera/scene, in this case the depth precision wasn't
used optimally.

Note that we don't hit this problem currently, because the directional
light is constructed such that its origin is at the near plane, and the
spotlights have a fixed near plane (which is a problem and will be 
fixed at a later time).
2021-10-29 12:03:41 -07:00
Mathias Agopian
51e92cd142 Fix spotlight direction and falloff
Direction and falloff were recently changed to fp16 int the shader,
which is not enough (far from it) when a spotlight is over 100m away.
2021-10-28 21:59:01 -07:00
Mathias Agopian
50f33f7196 fix some warnings and typos 2021-10-28 21:58:45 -07:00
Benjamin Doherty
b5c634045e Update RELEASE_NOTES for 1.12.11 2021-10-28 16:13:50 -07:00
Ben Doherty
1f05531d53 Call VirtualMachineEnv::JNI_OnLoad for non-Android Java builds (better fix) (#4779) 2021-10-28 16:02:23 -07:00
Benjamin Doherty
88f382f0e3 Revert "refactor colorgrading materials"
This reverts commit fb86a77cf8.
2021-10-28 15:56:50 -07:00
Benjamin Doherty
3e59925900 Remove problematic configuration-cache setting for release build 2021-10-28 15:56:26 -07:00
Mathias Agopian
1182d30fb9 MSAA VSMs seem to now work on Qualcomm h/w
The bug that prevented them to work has been worked around, but we 
don't know when or how. The original bug still exists as demonstrated
by our standalone test apk.

For now, we reenable MSAA VSM on Adreno.
2021-10-26 16:06:20 -07:00
Romain Guy
095179eeb3 Enabled Gradle configuration caching and rename properties (#4769)
* Fix configurationg caching problems

* Enable Gradle configuration caching

* Update BUILDING.md

* Update RELEASE_NOTES.md

Co-authored-by: Mathias Agopian <mathias@google.com>

Co-authored-by: Benjamin Doherty <bendoherty@google.com>
2021-10-26 12:47:35 -07:00
Romain Guy
69b48eaadb Fix erroenous warning 2021-10-26 12:05:49 -07:00
Timo Röhling
4031c6f0d3 Simplify devendoring (#4765)
* Perform sanity check when combining static libraries

This is a small modification that simplifies Debian packaging when one
or more vendored dependencies are replaced by system shared libraries
and no longer need to be combined with a Filament library.

* Verify vendoring before including license texts

This is another small modification to simplify Debian packaging when one
or more vendored dependencies are removed and replaced by system
libraries, so they no longer need to be considered when compiling the
license texts.
2021-10-26 11:31:35 -07:00
Mathias Agopian
7a22f7dfc5 move some VSM computations into the vertex shader 2021-10-26 11:26:21 -07:00
Mathias Agopian
728ebf5023 cleanup shadowing shader code
- remove PCF MEDIUM and HIGH quality -- these were never used in
practice, and "quality" really meant "blurriness", now we have VSM
for doing that with much more control and more efficiently.

PCF_HARD is now the default. PCF_LOW is still available at compile time
for now. It shouldn't be needed though because VSM can achieve the same.

Moved the divide-by-w of light space into the shadow() method -- which
known if it should be done or not.
2021-10-26 11:26:21 -07:00
Timo Röhling
62476d2f06 Fix compatibility with libstdc++ (#4763)
The codebase needs only a few additional standard #includes to compile
against libstdc++ on Linux; presumably those headers are implicitly
included with MSVC's and Clang's standard C++ library, but even if
libstdc++ compatibility is not a goal, it is advisable to have them
included directly.
2021-10-26 11:07:39 -07:00
Benjamin Doherty
ea404f8d4f Remove problematic configuration-cache setting for release build 2021-10-26 10:09:51 -07:00
Benjamin Doherty
602a550d93 Bump version to 1.12.11 2021-10-25 12:30:37 -07:00
Benjamin Doherty
12abbe2d23 Merge branch 'rc/1.12.10' into release 2021-10-25 11:06:18 -07:00
Benjamin Doherty
5fea428243 Release Filament 1.12.10 2021-10-25 11:06:12 -07:00
Benjamin Doherty
fb0ee97588 Update RELEASE_NOTES for 1.12.10 2021-10-25 11:00:06 -07:00
Ben Doherty
56ef48c9c3 Fix, call VirtualMachineEnv::JNI_OnLoad for non-Android Java builds (#4749) 2021-10-25 10:39:24 -07:00
Benjamin Doherty
47c3dd3dd1 Revert "refactor colorgrading materials"
This reverts commit fb86a77cf8.
2021-10-25 10:37:52 -07:00
clayly
9a3c9ccbf3 android-samples-gradle-plugin-id (#4740) 2021-10-24 11:12:15 -07:00
Ben Doherty
ef4dfcecd6 Metal: support framebuffer fetch on M1 devices (#4735) 2021-10-21 11:27:05 -07:00
Ben Doherty
5943382d23 iOS: avoid precision issues with CACurrentMediaTime (#4753) 2021-10-21 11:13:51 -07:00
Benjamin Doherty
c181648bfa Bump version to 1.12.10 2021-10-20 12:15:51 -07:00
Benjamin Doherty
0cf78b3abe Merge branch 'rc/1.12.9' into release 2021-10-20 12:12:33 -07:00
Benjamin Doherty
1dcf347b87 Release Filament 1.12.9 2021-10-20 12:11:46 -07:00
Ben Doherty
47714007f7 Fix VirtualMachineEnv.cpp with older JNI versions (#4752) 2021-10-20 11:18:03 -07:00
Ben Doherty
22889a7ad9 Fix VirtualMachineEnv.cpp with older JNI versions (#4752) 2021-10-20 11:16:55 -07:00
Ben Doherty
a14451d0ac Fix, call VirtualMachineEnv::JNI_OnLoad for non-Android Java builds (#4749) 2021-10-20 10:41:34 -07:00
Benjamin Doherty
5dfdab10b7 Revert "refactor colorgrading materials"
This reverts commit fb86a77cf8.
2021-10-19 16:13:21 -07:00
Mathias Agopian
54277572d2 code health: cleanup FrameInfo and FrameSkipper a bit
in particular add a terminate() method to FrameSkipper instead of
destroying driver objects in the destructor -- this matches all other
objects.

also remove dependency on FEngine which wasn't needed.
2021-10-18 18:41:59 -07:00
Mathias Agopian
52f2c0e107 don't use static initialization when not needed
static init/destruction is always dangerous
2021-10-18 15:36:17 -07:00
Mathias Agopian
59abc8cc20 use NEAREST filtering for the final blit
the final blit, when used, is never upscaling, so always use the 
NEAREST filter.
2021-10-18 12:18:57 -07:00
Mathias Agopian
e15796b348 Rewrite controller for dynamic resolution scaling
- move the control code out of FrameInfo and into
  View itself. FrameInfo now just gathers information about the 
  frames instead of also doing part of the control.

- the control code has been refactored into a more formal PIDController.

- a few bugs were fixed in the control loop and default parameters
  tuned. 


The control loop itself now outputs a relative scale factor instead
of an absolute one. The relative scale factor seems easier to
control and is less jittery, and doesn't have to rely on the "integral"
term of the PID.

It's possible that more tuning is needed, but the scaling is now 
more stable.
2021-10-18 10:06:44 -07:00
Mathias Agopian
1711eaa4d6 Minor improvements to DebugRegistry
- remove getProperties() we'll put it back if we need it some day

- use unordered_map because it generates less code than robin_map and
  here performance is not critical
2021-10-18 10:06:44 -07:00
Mathias Agopian
acbd6a5ca8 Improve dynamic resolution scaling
- defaults to 31 history points instead of 3, this gives a much better 
  estimate of the frame rate.

- make sure the calculations work for any definition of our internal
  duration<> (it's useful to use milliseconds when dealing with
  refresh periods).

- don't round to 8 pixels if the scale factor is exactly 1

- fix a few comments and warnings
2021-10-18 10:06:44 -07:00
Romain Guy
775090fdda Re-fix tests 2021-10-15 17:30:06 -07:00
Romain Guy
0915b86927 Fix tests 2021-10-15 16:23:45 -07:00
BStringhamVRSK
c10f7b01f4 Fixes normal map issues in mipgen and exposes a couple of SurfaceOrientation functions for Web
* mipgen: Linearized PNG bitmaps (such as normal maps) no longer perform gamma transform on read.

* mipgen: Using "-k normals" argument now works for all file types, not just KTX

* Web: Exposed SurfaceOrientation functions getQuatsHalf4() and getQuatsFloat()
2021-10-15 14:23:41 -07:00
Mathias Agopian
84142ac506 move platform related files into a platforms directory
this is just to improve source code readability.
2021-10-14 22:48:16 -07:00
Mathias Agopian
ff190847a1 ExternalStreamManagerAndroid actually depends on GLES
Since ExternalStreamManagerAndroid depends on GLES, move it to the 
opengl directory.
2021-10-14 22:48:16 -07:00
Mathias Agopian
3ceec28189 added a way to check for adreno driver version
not used yet, but good too have.
2021-10-14 19:35:17 -07:00
Benjamin Doherty
d6f2e3b8e9 Update RELEASE_NOTES for 1.12.9 2021-10-14 18:22:20 -07:00
Romain Guy
481038152f Cleanup of Android projects (#4730) 2021-10-13 18:17:12 -07:00
Rupert Rawnsley
60bd72730d ASTC texture enum missing in JNI interface 2021-10-13 10:18:54 -07:00
Benjamin Doherty
df30517743 Bump version to 1.12.9 2021-10-11 11:06:43 -07:00
Benjamin Doherty
8f80643c1a Merge branch 'rc/1.12.8' into release 2021-10-11 11:02:56 -07:00
Benjamin Doherty
eabfd08473 Release Filament 1.12.8 2021-10-11 11:02:30 -07:00
Mathias Agopian
a66af0ac58 Minor settings cleanup
- set sensical default for gltf-viewer
- fix some warnings in ToneMapper
- fix some warnings in Settings.cpp
- minor refactor in Settings.h
2021-10-08 18:10:05 -07:00
Mathias Agopian
15187e9d99 Workaround for incorrect glInvalidateFramebuffer on Adreno
Unfortunately this bug appeared in recent drivers on some devices, it's
virtually impossible to know which device/drivers have this issue, so
the workaround is active for all Adreno GPUs.

glInvalidateFramebuffer is too aggressive and prevents loading of the
GMEM even if it's only called at the end of the render pass.
2021-10-07 20:58:34 -07:00
Mathias Agopian
681e8f8b59 Add VERBOSE log level
It is accessible through slog.v. On android it goes to the VERBOSE
log, on desktop, it's suppressed in release.
2021-10-07 20:58:34 -07:00
Mathias Agopian
fbb406ca7d fix dynamic scaling internal debugging 2021-10-07 19:51:55 -07:00
Benjamin Doherty
5aea9be2fb Update RELEASE_NOTES for 1.12.8 2021-10-07 11:03:45 -07:00
Ben Doherty
aacaf5055e Fix typo in View.java 2021-10-07 10:55:41 -07:00
Romain Guy
a5dbddfd12 Fix release distribution (#4713)
Statically link SDL2 to make our samples (glTF Viewer, etc.) completely
standalone, and include missing resources (fonts and default environment
map for the IBL).
2021-10-07 10:11:27 -07:00
Mathias Agopian
764a0df669 Add DynamicResolution to Settings
update remote ui
2021-10-06 21:25:17 -07:00
BStringhamVRSK
f04864c216 Expose ColorGrading$Builder, View.setPostProcessingEnabled()/View.setAntiAliasing() JS bindings
Co-authored-by: Romain Guy <romainguy@curious-creature.com>
2021-10-06 14:21:18 -07:00
Mathias Agopian
11a1b31a4c HDR aware MSAA resolve
When supported and enabled, resolve MSAA using an HDR aware filter,
which improves anti-aliasing quality.

This is only supported with backends that support multi-sampled
framebuffer-fetch. Currently, only Metal on iOS and GLES.

Update remote ui.
2021-10-06 14:15:09 -07:00
Mathias Agopian
fb86a77cf8 refactor colorgrading materials 2021-10-06 14:15:09 -07:00
Mathias Agopian
d512357928 update remote ui 2021-10-06 12:45:41 -07:00
Mathias Agopian
b850bc827e Fix MSAA settings ostream operator 2021-10-06 08:54:04 -07:00
Mathias Agopian
0229077293 added some missing javascript APIs 2021-10-06 08:08:18 -07:00
Mathias Agopian
23f2679bbe MoltenVk actually does support subpasses on M1
The actual problem is with the basic "blit" functionality which
is broken, and is sometimes triggered when subpasses are used.
2021-10-06 08:07:32 -07:00
Mathias Agopian
e6243b3df3 better API for MSAA options 2021-10-05 22:58:16 -07:00
Mathias Agopian
375b46d866 fix an issue where we'd use the FSR scaling instead of a dumb blit
The DSR options were carried all the way to the final blit that is 
sometimes needed to impedence-match our rendering features with the
swapchain. This blit is never a scaling blit, but we were using the
FSR option, which would sometimes trigger the FSR scaling code.
2021-10-05 20:07:13 -07:00
Mathias Agopian
4577c8d57f don't use quotes with #error 2021-10-04 23:35:35 -07:00
Mathias Agopian
24d1e9c3d2 dont use ES 3.1+ APIs
FSR assumes modern OpenGL. The functions that pose problem are in fact
never used in filament, so it doesn't matter how they're implemented.
We use the HLSL version instead.
2021-10-04 23:35:35 -07:00
Mathias Agopian
f7a630d614 Use a dedicated thread for dispatching callbacks
This isolates our backend thread from user code and the java VM.
2021-10-04 10:56:43 -07:00
Mathias Agopian
1c1cb11cf5 Use the new CallbackHandler in the java bindings
Java callbacks are now directly dispatched to their handler, instead
of first going through filament's opportunistic dispatch, reducing
callback latency.
2021-10-04 10:56:43 -07:00
Mathias Agopian
3ac8a6a21c Improvement to callbacks throughout filament
All APIs that take a callback as argument now also takes a 
CallbackHandler* which is a new interface used to dispatch the
callback.

CallbackHandler* can always be nullptr in which case the behavior is
unchanged. 

When CallbackHandler* is specified however, it is used to dispatch the
callback: its post() method is called from a service thread as soon
as possible (this will NEVER be the main thread), CallbackHandler::post
is then responsible for scheduling the callback onto the thread the
user desires. This is intended to make callbacks interoperate with
the platform/OS's own messaging system.
2021-10-04 10:56:43 -07:00
Mathias Agopian
c524c39867 Fix JNI bindings for depth of field options 2021-10-04 10:56:43 -07:00
Benjamin Doherty
ad02e483d0 Bump version to 1.12.8 2021-10-04 10:26:57 -07:00
Benjamin Doherty
e203edc12a Release Filament 1.12.7 2021-10-04 10:21:10 -07:00
Mathias Agopian
5447baab00 rework Vulkan image layout transitions
The main issue that gets fixed here are:

- VK_IMAGE_LAYOUT_UNDEFINED cannot be used if the image content is to 
be preserved after the transition. Unfortunately, there is more than a 
few places in the VK backend where we use VK_IMAGE_LAYOUT_UNDEFINED on
images that are later used as sources.

- accessing an image memory from the host is only supported if the the 
layout is PREINITIALIZED or GENERAL. However, images in the staging
pool were transitioned to other layouts and put back into the pool,
later they would be mapped/memcpy'ed into. Instead we now always use
the GENERAL layout and never change it.

- images that where in the pool where transitioned using the miplevel
of the texture we were copying into, however this didn't make sense
because images from the pool don't have mip levels.


As part of these fixes, we also refactor imageLayoutTranstion(),
because there was two copies of this function, one specific to texture
and another one more generic. We now always use the more generic one,
with a new helper for textures.


Note: didn't fix "readPixels" which has at least problem (1), because
it's a tricky implementation, and it requires more toughts.
2021-10-01 13:20:21 -07:00
Mathias Agopian
904989f7f4 improve user callbacks latency
A new Engine::pumpMessageQueues() method can be used to trigger all
pending user callbacks right away. This can help reducing latency
of certain callbacks such as picking queries.
This is typically called once before calculating the next frame's
parameters (e.g. object positions or appearance that may depend on a 
callback result).

Fix some comments and documentation.
2021-09-30 16:55:17 -07:00
Romain Guy
4846ccd86d Use the more common EOTF/OETF acronyms (#4691)
Nothing wrong with EOCF/OECF but the "T" version is more common and readers will
therefore be more likely to be more familiar with it.
2021-09-30 14:44:46 -07:00
Ben Doherty
0fd1c3182e Add script to check that public headers can compile independently (#4675) 2021-09-29 13:47:47 -07:00
Mathias Agopian
7d80052dae Implement picking functionality
This is a pixel accurate implementation of picking. Picking queries
can be created on view, and upon completion a user provided callback
is called with the Entity of the renderable at the queried coordinates
in the viewport.

Picking queries typically have 1 or 2 frame of latency and may impact
performance on some drivers.

It is mostly intended for use by editors, or when latency is not a major
concern. This api should not be used for dragging/moving objects, it is
intended for initial picking only.

Picking is implemented in the structure pass.

The depth buffer value is retrieved and the fragment coordinate is
reconstructed and passed to PickingQueryResult. This can be used in
turn to calculate the view and/or world space position.
2021-09-29 13:02:05 -07:00
Mathias Agopian
b71ee48477 vulkan: add some format to data reshaper
This is just a minimal change to get the R_INTEGER format to work.

- if src/dst types are identical, just copy (this avoids a mul and a div)
- add R,RG and INTEGER types
2021-09-29 13:02:05 -07:00
Ben Doherty
7a285dc55a Metal: support integer formats with readPixels (#4682) 2021-09-29 12:30:02 -07:00
Mathias Agopian
a0f3a4d9bb new helpers for setting {Pixel}BufferDescriptor callbacks
There a just new inline helpers to more easily use lambdas, functors and 
method callbacks with {Pixel}BufferDescriptor.

A BufferDescriptor can be constructed like this:

auto bd = BufferDescriptor::make(buffer, size, [](void* b, size_t s){ });

or

auto bd = BufferDescriptor::make(buffer, size, &Foo::bar, *foo);
2021-09-28 15:26:10 -07:00
Mathias Agopian
304090d39f fix readPixels vertical offset in vk backend
vulkan expected a vertical offset from the top, but the api is in
gl convention with the offset from the bottom.
2021-09-28 14:02:26 -07:00
210 changed files with 3824 additions and 1625 deletions

View File

@@ -21,3 +21,6 @@ jobs:
with:
name: filament-mac
path: out/filament-release-darwin.tgz
- name: Check public headers
run: |
build/common/check-headers.sh out/release/filament/include

View File

@@ -291,11 +291,11 @@ Alternatively you can build the AAR from the command line by executing the follo
`android/` directory:
```
$ ./gradlew -Pfilament_dist_dir=../../out/android-release/filament assembleRelease
$ ./gradlew -Pcom.google.android.filament.dist-dir=../../out/android-release/filament assembleRelease
```
The `-Pfilament_dist_dir` can be used to specify a different installation directory (it must match
the CMake install prefix used in the previous steps).
The `-Pcom.google.android.filament.dist-dir` can be used to specify a different installation
directory (it must match the CMake install prefix used in the previous steps).
#### Using Filament's AAR

View File

@@ -502,11 +502,15 @@ function(list_licenses OUTPUT MODULES)
foreach(module ${_MODULES})
set(license_path "../../third_party/${module}/LICENSE")
get_filename_component(fullname "${license_path}" ABSOLUTE)
string(APPEND CONTENT "${STR_OPENER}License and copyrights for ${module}:\n${STR_CLOSER},\n")
file(READ ${license_path} license_long)
string(REPLACE "\n" "${STR_CLOSER},\n${STR_OPENER}" license ${license_long})
string(APPEND CONTENT ${STR_OPENER}${license}\n${STR_CLOSER},)
string(APPEND CONTENT "\n\n")
if(EXISTS ${fullname})
string(APPEND CONTENT "${STR_OPENER}License and copyrights for ${module}:\n${STR_CLOSER},\n")
file(READ ${license_path} license_long)
string(REPLACE "\n" "${STR_CLOSER},\n${STR_OPENER}" license ${license_long})
string(APPEND CONTENT ${STR_OPENER}${license}\n${STR_CLOSER},)
string(APPEND CONTENT "\n\n")
else()
message(AUTHOR_WARNING "${license_path} not found. You can ignore this warning if you have devendored ${module}.")
endif()
endforeach()
configure_file(${FILAMENT}/build/licenses.inc.in ${OUTPUT})
endfunction(list_licenses)
@@ -522,7 +526,12 @@ function(combine_static_libs TARGET OUTPUT DEPS)
# Loop through the dependent libraries and query their location on disk.
set(DEPS_FILES )
foreach(DEPENDENCY ${DEPS})
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
if(TARGET ${DEPENDENCY})
get_property(dep_type TARGET ${DEPENDENCY} PROPERTY TYPE)
if(dep_type STREQUAL "STATIC_LIBRARY")
list(APPEND DEPS_FILES "$<TARGET_FILE:${DEPENDENCY}>")
endif()
endif()
endforeach()
add_custom_command(

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.12.7'
implementation 'com.google.android.filament:filament-android:1.13.0'
}
```
@@ -52,7 +52,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
iOS projects can use CocoaPods to install the latest release:
```
pod 'Filament', '~> 1.12.7'
pod 'Filament', '~> 1.13.0'
```
### Snapshots

View File

@@ -3,7 +3,52 @@
This file contains one line summaries of commits that are worthy of mentioning in release notes.
A new header is inserted each time a *tag* is created.
## v1.12.8 (currently main branch)
## v1.13.1 (currently main branch)
## v1.13.0
- Android: Gradle configuration caching is now enabled.
- Android: Filament's Gradle properties have all been renamed to `com.google.android.filament.xxx`
where `xxx` is the property name. See `android/build.gradle` for a complete list [⚠️]
- Android: The Gradle property `filament_tools_dir` (now called
`com.google.android.filament.tools-dir`) does not have a default value anymore. Please specify one
in your `gradle.properties` if you reuse the Gradle plugin in your projects [⚠️]
- engine: Fix spotlights direction and falloff [⚠️ **Material breakage**].
- engine: Improvements to VSM and spotlight shadows.
## v1.12.11
- Metal: Color grading performance improvement on M1 devices.
- samples: Fix glitchy animation seen in gltf-viewer iOS sample.
## v1.12.10
- engine: rewrite dynamic resolution scaling controller for better accuracy and less jittering.
- Java: fix missing ASTC texture enum.
- tools: Fix normal map issues in mipgen.
- WebGL: expose some `SurfaceOrientation` functions.
## v1.12.9
- engine: New API: `MultiSampleAntiAliasingOptions` and HDR-aware MSAA resolve. When `customResolve`
is enabled, improves anti-aliasing quality [**NEW API**].
- engine: Fixes and improvements for FSR.
- engine: All APIs that take a callback as argument now also take a `CallbackHandler*`, a new
interface that provides more flexibility around callback dispatch [**NEW API**].
- Android: Fix JNI bindings for `DepthOfFieldOptions`.
- Android: workarounds for Adreno-specific fraembuffer issue.
- JavaScript: updates to JS bindings.
## v1.12.8
- engine: Added picking API to `View` [⚠️ **Materials need to be rebuilt to access this new feature**].
- engine: A new `Engine::pumpMessageQueues()` method can be used to trigger all pending user
callbacks right away [**NEW API**].
- engine: new inline helpers to more easily use lambdas, functors and method callbacks with
`{Pixel}BufferDescriptor`.
- Vulkan: fix vertical offset for `readPixels`.
- Vulkan: various internal improvements.
- Metal: support integer formats with `readPixels`.
## v1.12.7

View File

@@ -122,20 +122,20 @@ The Gradle project used to generate the AAR is located at `<filament>\android`.
```
cd android
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease
copy filament-android\build\outputs\aar\filament-android-release.aar ..\..\out\
```
If you're only interested in building for a single ABI, you'll need to pass a `filament_abis` parameter:
If you're only interested in building for a single ABI, you'll need to pass a `com.google.android.filament.abis` parameter:
```
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease -Pfilament_abis=x86
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease -Pcom.google.android.filament.abis=x86
```
If you're only interested in building SDK, you may skip samples build by passing a `filament_skip_samples` flag:
If you're only interested in building SDK, you may skip samples build by passing a `com.google.android.filament.skip-samples` flag:
```
gradlew -Pfilament_dist_dir=..\out\android-release\filament assembleRelease -Pfilament_skip_samples
gradlew -Pcom.google.android.filament.dist-dir=..\out\android-release\filament assembleRelease -Pfilament_skip_samples
```

View File

@@ -1,26 +1,28 @@
// This script accepts the following parameters:
//
// filament_dist_dir
// com.google.android.filament.dist-dir
// Path to the Filament distribution/install directory for Android
// (produced by make/ninja install). This directory must contain lib/arm64-v8a/ etc.
//
// filament_tools_dir
// com.google.android.filament.tools-dir
// Path to the Filament distribution/install directory for desktop.
// This directory must contain bin/matc.
//
// filament_exclude_vulkan
// com.google.android.filament.exclude-vulkan
// When set, support for Vulkan will be excluded.
//
// filament_skip_samples
// com.google.android.filament.skip-samples
// Exclude samples from the project. Useful to speed up compilation.
//
// filament_abis
// com.google.android.filament.abis
// List of supported ABIs to build as a comma separated list. Available options are:
// arm64-v8a, armeabi-v7a, x86_64, x86, all
// Defaults to all.
//
// Example:
// ./gradlew -Pfilament_dist_dir=../dist-android-release assembleRelease -Pfilament_abis=x86
// ./gradlew -Pcom.google.android.filament.dist-dir=../dist-android-release \
// -Pcom.google.android.filament.abis=x86 \
// assembleRelease
// Publishing to Maven Central:
// - Build and upload artifacts with ./gradlew publish
@@ -41,19 +43,19 @@
buildscript {
def filamentPath = file("../out/android-release/filament").absolutePath
if (project.hasProperty("filament_dist_dir")) {
filamentPath = file(project.property("filament_dist_dir")).absolutePath
if (project.hasProperty("com.google.android.filament.dist-dir")) {
filamentPath = file(project.property("com.google.android.filament.dist-dir")).absolutePath
}
// Our CMake scripts require a forward-slash path for the FILAMENT_DIST_DIR
// variable, so here we convert the native path to a forward-slash path.
filamentPath = filamentPath.replace(File.separator, '/')
// Warning: changing this property does not work well with incremental builds.
def excludeVulkan = project.hasProperty("filament_exclude_vulkan")
def excludeVulkan = project.hasProperty("com.google.android.filament.exclude-vulkan")
def abis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
if (project.hasProperty("filament_abis")) {
def newAbis = project.property("filament_abis").split(',')
if (project.hasProperty("com.google.android.filament.abis")) {
def newAbis = project.property("com.google.android.filament.abis").split(',')
if (!newAbis.contains("all")) {
abis = newAbis
}
@@ -63,7 +65,7 @@ buildscript {
'minSdk': 19,
'targetSdk': 30,
'compileSdk': 30,
'kotlin': '1.5.30',
'kotlin': '1.5.31',
'buildTools': '30.0.3',
'ndk': '22.1.7171670'
]
@@ -77,7 +79,7 @@ buildscript {
]
dependencies {
classpath 'com.android.tools.build:gradle:7.0.2'
classpath 'com.android.tools.build:gradle:7.0.3'
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
}
@@ -187,7 +189,8 @@ subprojects {
gradle.taskGraph.whenReady {
gradle.taskGraph.allTasks.each {
it.onlyIf {
!it.project.ext.has('isSample') || !project.hasProperty('filament_skip_samples')
!it.project.ext.has('isSample') ||
!project.hasProperty('com.google.android.filament.skip-samples')
}
}
}

View File

@@ -1,3 +1,17 @@
plugins {
id 'groovy-gradle-plugin'
}
gradlePlugin {
plugins {
create("filament-tools-plugin") {
id = "filament-tools-plugin"
implementationClass = "FilamentToolsPlugin"
}
}
}
repositories {
mavenCentral()
}

View File

@@ -1,20 +1,22 @@
// This plugin accepts the following parameters:
//
// filament_tools_dir
// com.google.android.filament.tools-dir
// Path to the Filament distribution/install directory for desktop.
// This directory must contain bin/matc.
//
// filament_exclude_vulkan
// com.google.android.filament.exclude-vulkan
// When set, support for Vulkan will be excluded.
//
// Example:
// ./gradlew -Pfilament_tools_dir=../../dist-release assembleDebug
// ./gradlew -Pcom.google.android.filament.tools-dir=../../dist-release assembleDebug
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
import org.gradle.api.Plugin
import org.gradle.api.Project
import org.gradle.api.provider.ProviderFactory
import org.gradle.api.file.DirectoryProperty
import org.gradle.api.file.FileSystemOperations
import org.gradle.api.file.FileType
import org.gradle.api.file.RegularFileProperty
import org.gradle.api.logging.LogLevel
@@ -27,14 +29,18 @@ import org.gradle.api.tasks.Optional
import org.gradle.api.tasks.OutputDirectory
import org.gradle.api.tasks.TaskAction
import org.gradle.api.tasks.incremental.InputFileDetails
import org.gradle.api.model.ObjectFactory
import org.gradle.internal.os.OperatingSystem
import org.gradle.process.ExecOperations
import org.gradle.work.ChangeType
import org.gradle.work.Incremental
import org.gradle.work.InputChanges
import java.nio.file.Paths
class TaskWithBinary extends DefaultTask {
import javax.inject.Inject
abstract class TaskWithBinary extends DefaultTask {
private final String binaryName
private Property<String> binaryPath = null
@@ -42,15 +48,23 @@ class TaskWithBinary extends DefaultTask {
binaryName = name
}
@Inject abstract ObjectFactory getObjects()
@Inject abstract ProviderFactory getProviders()
@Input
Property<String> getBinary() {
if (binaryPath == null) {
def tool = ["/bin/${binaryName}.exe", "/bin/${binaryName}"]
def fullPath = tool.collect { path ->
Paths.get(project.ext.filamentToolsPath.absolutePath, path).toFile()
def filamentToolsPath = providers
.gradleProperty("com.google.android.filament.tools-dir")
.forUseAtConfigurationTime().get()
def directory = objects.fileProperty()
.fileValue(new File(filamentToolsPath)).getAsFile().get()
Paths.get(directory.absolutePath, path).toFile()
}
binaryPath = project.objects.property(String.class)
binaryPath = objects.property(String.class)
binaryPath.set(
(OperatingSystem.current().isWindows() ? fullPath[0] : fullPath[1]).toString())
}
@@ -84,6 +98,11 @@ abstract class MaterialCompiler extends TaskWithBinary {
@OutputDirectory
abstract DirectoryProperty getOutputDir()
@Inject abstract FileSystemOperations getFs()
@Inject abstract ExecOperations getExec()
@Inject abstract ObjectFactory getObjects()
@Inject abstract ProviderFactory getProviders()
MaterialCompiler() {
super("matc")
}
@@ -91,7 +110,9 @@ abstract class MaterialCompiler extends TaskWithBinary {
@TaskAction
void execute(InputChanges inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir.asFile.get()).matching { include '*.filamat' })
fs.delete({
delete(objects.fileTree().from(outputDir).matching { include '*.filamat' })
})
}
inputs.getFileChanges(inputDir).each { InputFileDetails change ->
@@ -115,12 +136,15 @@ abstract class MaterialCompiler extends TaskWithBinary {
}
def matcArgs = []
if (!project.hasProperty("filament_exclude_vulkan")) {
def exclude_vulkan = providers
.gradleProperty("com.google.android.filament.exclude-vulkan")
.forUseAtConfigurationTime().present
if (!exclude_vulkan) {
matcArgs += ['-a', 'vulkan']
}
matcArgs += ['-a', 'opengl', '-p', 'mobile', '-o', getOutputFile(file), file]
project.exec {
exec.exec {
standardOutput out
errorOutput err
executable "${binary.get()}"
@@ -149,6 +173,10 @@ abstract class IblGenerator extends TaskWithBinary {
@OutputDirectory
abstract DirectoryProperty getOutputDir()
@Inject abstract FileSystemOperations getFs()
@Inject abstract ExecOperations getExec()
@Inject abstract ObjectFactory getObjects()
IblGenerator() {
super("cmgen")
}
@@ -156,7 +184,9 @@ abstract class IblGenerator extends TaskWithBinary {
@TaskAction
void execute(InputChanges inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir.asFile.get()).matching { include '*' })
fs.delete({
delete(objects.fileTree().from(outputDir).matching { include '*' })
})
}
inputs.getFileChanges(inputFile).each { InputFileDetails change ->
@@ -188,7 +218,7 @@ abstract class IblGenerator extends TaskWithBinary {
}
commandArgs = commandArgs + " " + file
project.exec {
exec.exec {
standardOutput out
errorOutput err
executable "${binary.get()}"
@@ -213,6 +243,9 @@ abstract class MeshCompiler extends TaskWithBinary {
@OutputDirectory
abstract DirectoryProperty getOutputDir()
@Inject abstract FileSystemOperations getFs()
@Inject abstract ExecOperations getExec()
MeshCompiler() {
super("filamesh")
}
@@ -220,7 +253,9 @@ abstract class MeshCompiler extends TaskWithBinary {
@TaskAction
void execute(InputChanges inputs) {
if (!inputs.incremental) {
project.delete(project.fileTree(outputDir.asFile.get()).matching { include '*.filamesh' })
fs.delete({
delete(objects.fileTree().from(outputDir).matching { include '*.filamesh' })
})
}
inputs.getFileChanges(inputFile).each { InputFileDetails change ->
@@ -243,7 +278,7 @@ abstract class MeshCompiler extends TaskWithBinary {
" Ensure Filament has been built/installed before building this app.")
}
project.exec {
exec.exec {
standardOutput out
errorOutput err
executable "${binary.get()}"
@@ -280,11 +315,6 @@ class FilamentToolsPlugin implements Plugin<Project> {
extension.meshInputFile = project.objects.fileProperty()
extension.meshOutputDir = project.objects.directoryProperty()
project.ext.filamentToolsPath = project.file("../../../out/release/filament")
if (project.hasProperty("filament_tools_dir")) {
project.ext.filamentToolsPath = project.file(project.property("filament_tools_dir"))
}
project.tasks.register("filamentCompileMaterials", MaterialCompiler) {
enabled =
extension.materialInputDir.isPresent() &&

View File

@@ -16,6 +16,8 @@
#include "CallbackUtils.h"
#include "private/backend/VirtualMachineEnv.h"
void acquireCallbackJni(JNIEnv* env, CallbackJni& callbackUtils) {
#ifdef ANDROID
callbackUtils.handlerClass = env->FindClass("android/os/Handler");
@@ -49,53 +51,6 @@ void releaseCallbackJni(JNIEnv* env, CallbackJni callbackUtils, jobject handler,
env->DeleteGlobalRef(callbackUtils.executorClass);
}
JniBufferCallback* JniBufferCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
return new JniBufferCallback(env, handler, callback, std::move(buffer));
}
JniBufferCallback::JniBufferCallback(JNIEnv* env, jobject handler, jobject callback,
AutoBuffer&& buffer)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback))
, mBuffer(std::move(buffer)) {
acquireCallbackJni(env, mCallbackUtils);
}
JniBufferCallback::~JniBufferCallback() {
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
}
void JniBufferCallback::invoke(void*, size_t, void* user) {
JniBufferCallback* data = reinterpret_cast<JniBufferCallback*>(user);
delete data;
}
// -----------------------------------------------------------------------------------------------
JniImageCallback* JniImageCallback::make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, long image) {
return new JniImageCallback(env, handler, callback, image);
}
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback))
, mImage(image) {
acquireCallbackJni(env, mCallbackUtils);
}
JniImageCallback::~JniImageCallback() {
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
}
void JniImageCallback::invoke(void*, void* user) {
JniImageCallback* data = reinterpret_cast<JniImageCallback*>(user);
delete data;
}
// -----------------------------------------------------------------------------------------------
JniCallback* JniCallback::make(JNIEnv* env, jobject handler, jobject callback) {
@@ -103,17 +58,65 @@ JniCallback* JniCallback::make(JNIEnv* env, jobject handler, jobject callback) {
}
JniCallback::JniCallback(JNIEnv* env, jobject handler, jobject callback)
: mEnv(env)
, mHandler(env->NewGlobalRef(handler))
, mCallback(env->NewGlobalRef(callback)) {
: mHandler(env->NewGlobalRef(handler)),
mCallback(env->NewGlobalRef(callback)) {
acquireCallbackJni(env, mCallbackUtils);
}
JniCallback::~JniCallback() {
releaseCallbackJni(mEnv, mCallbackUtils, mHandler, mCallback);
JniCallback::~JniCallback() = default;
void JniCallback::post(void* user, filament::backend::CallbackHandler::Callback callback) {
callback(user);
}
void JniCallback::invoke(void* user) {
JniCallback* data = reinterpret_cast<JniCallback*>(user);
delete data;
void JniCallback::postToJavaAndDestroy(JniCallback* callback) {
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
delete callback;
}
// -----------------------------------------------------------------------------------------------
JniBufferCallback* JniBufferCallback::make(filament::Engine*,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer) {
return new JniBufferCallback(env, handler, callback, std::move(buffer));
}
JniBufferCallback::JniBufferCallback(JNIEnv* env, jobject handler, jobject callback,
AutoBuffer&& buffer)
: JniCallback(env, handler, callback),
mBuffer(std::move(buffer)) {
acquireCallbackJni(env, mCallbackUtils);
}
JniBufferCallback::~JniBufferCallback() = default;
void JniBufferCallback::postToJavaAndDestroy(void*, size_t, void* user) {
JniBufferCallback* callback = (JniBufferCallback*)user;
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
callback->mBuffer.attachToJniThread(env);
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
delete callback;
}
// -----------------------------------------------------------------------------------------------
JniImageCallback* JniImageCallback::make(filament::Engine*,
JNIEnv* env, jobject handler, jobject callback, long image) {
return new JniImageCallback(env, handler, callback, image);
}
JniImageCallback::JniImageCallback(JNIEnv* env, jobject handler, jobject callback, long image)
: JniCallback(env, handler, callback),
mImage(image) {
acquireCallbackJni(env, mCallbackUtils);
}
JniImageCallback::~JniImageCallback() = default;
void JniImageCallback::postToJavaAndDestroy(void*, void* user) {
JniImageCallback* callback = (JniImageCallback*)user;
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
releaseCallbackJni(env, callback->mCallbackUtils, callback->mHandler, callback->mCallback);
delete callback;
}

View File

@@ -18,9 +18,10 @@
#include <jni.h>
#include "common/CallbackUtils.h"
#include "common/NioUtils.h"
#include <backend/CallbackHandler.h>
#include <filament/Engine.h>
struct CallbackJni {
@@ -35,57 +36,49 @@ struct CallbackJni {
void acquireCallbackJni(JNIEnv* env, CallbackJni& callbackUtils);
void releaseCallbackJni(JNIEnv* env, CallbackJni callbackUtils, jobject handler, jobject callback);
struct JniBufferCallback {
struct JniCallback : private filament::backend::CallbackHandler {
JniCallback(JniCallback const &) = delete;
JniCallback(JniCallback&&) = delete;
static JniCallback* make(JNIEnv* env, jobject handler, jobject runnable);
static void postToJavaAndDestroy(JniCallback* callback);
void post(void* user, Callback callback) override;
filament::backend::CallbackHandler* getHandler() noexcept { return this; }
jobject getCallbackObject() { return mCallback; }
protected:
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
virtual ~JniCallback();
jobject mHandler;
jobject mCallback;
CallbackJni mCallbackUtils;
};
struct JniBufferCallback : public JniCallback {
static JniBufferCallback* make(filament::Engine* engine,
JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
static void invoke(void* buffer, size_t n, void* user);
static void postToJavaAndDestroy(void*, size_t, void* user);
private:
JniBufferCallback(JNIEnv* env, jobject handler, jobject callback, AutoBuffer&& buffer);
JniBufferCallback(JniBufferCallback const &) = delete;
JniBufferCallback(JniBufferCallback&&) = delete;
~JniBufferCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
virtual ~JniBufferCallback();
AutoBuffer mBuffer;
CallbackJni mCallbackUtils;
};
struct JniImageCallback {
struct JniImageCallback : public JniCallback {
static JniImageCallback* make(filament::Engine* engine, JNIEnv* env, jobject handler,
jobject runnable, long image);
static void invoke(void* image, void* user);
static void postToJavaAndDestroy(void*, void* user);
private:
JniImageCallback(JNIEnv* env, jobject handler, jobject runnable, long image);
JniImageCallback(JniImageCallback const &) = delete;
JniImageCallback(JniImageCallback&&) = delete;
~JniImageCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
virtual ~JniImageCallback();
long mImage;
CallbackJni mCallbackUtils;
};
struct JniCallback {
static JniCallback* make(JNIEnv* env, jobject handler, jobject runnable);
static void invoke(void* user);
private:
JniCallback(JNIEnv* env, jobject handler, jobject runnable);
JniCallback(JniCallback const &) = delete;
JniCallback(JniCallback&&) = delete;
~JniCallback();
JNIEnv* mEnv;
jobject mHandler;
jobject mCallback;
CallbackJni mCallbackUtils;
};

View File

@@ -38,6 +38,10 @@ public:
AutoBuffer(AutoBuffer&& rhs) noexcept;
~AutoBuffer() noexcept;
void attachToJniThread(JNIEnv* env) noexcept {
mEnv = env;
}
void* getData() const noexcept {
return mUserData;
}

View File

@@ -125,6 +125,7 @@ target_link_libraries(filament-jni
target_include_directories(filament-jni PRIVATE
..
${FILAMENT_DIR}/include
../../filament/backend/include
../../third_party/robin-map
../../libs/utils/include)

View File

@@ -91,7 +91,8 @@ Java_com_google_android_filament_BufferObject_nSetBuffer(JNIEnv *env, jclass typ
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
bufferObject->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);

View File

@@ -16,9 +16,7 @@
#include <jni.h>
namespace filament {
extern jint JNI_OnLoad(JavaVM* vm, void* reserved);
};
#include "private/backend/VirtualMachineEnv.h"
JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env;
@@ -26,9 +24,9 @@ JNIEXPORT jint JNI_OnLoad(JavaVM* vm, void* reserved) {
return -1;
}
#if ANDROID
::filament::JNI_OnLoad(vm, reserved);
#endif
// This must be called when the library is loaded. We need this to get a reference to the
// global VM
::filament::VirtualMachineEnv::JNI_OnLoad(vm);
return JNI_VERSION_1_6;
}

View File

@@ -91,7 +91,8 @@ Java_com_google_android_filament_IndexBuffer_nSetBuffer(JNIEnv *env, jclass type
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
indexBuffer->setBuffer(*engine, std::move(desc), (uint32_t) destOffsetInBytes);

View File

@@ -97,7 +97,8 @@ Java_com_google_android_filament_Renderer_nReadPixels(JNIEnv *env, jclass,
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
renderer->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
@@ -132,7 +133,8 @@ Java_com_google_android_filament_Renderer_nReadPixelsEx(JNIEnv *env, jclass,
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
renderer->readPixels(renderTarget,
uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),

View File

@@ -169,7 +169,8 @@ Java_com_google_android_filament_Stream_nReadPixels(JNIEnv *env, jclass,
PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
stream->readPixels(uint32_t(xoffset), uint32_t(yoffset), uint32_t(width), uint32_t(height),
std::move(desc));
@@ -221,5 +222,6 @@ Java_com_google_android_filament_Stream_nSetAcquiredImage(JNIEnv* env, jclass, j
#endif
stream->setAcquiredImage((void*) nativeBuffer, &JniImageCallback::invoke, callback);
stream->setAcquiredImage((void*) nativeBuffer,
callback->getHandler(), &JniImageCallback::postToJavaAndDestroy, callback);
}

View File

@@ -27,5 +27,8 @@ Java_com_google_android_filament_SwapChain_nSetFrameCompletedCallback(JNIEnv* en
jlong nativeSwapChain, jobject handler, jobject runnable) {
SwapChain* swapChain = (SwapChain*) nativeSwapChain;
auto *callback = JniCallback::make(env, handler, runnable);
swapChain->setFrameCompletedCallback(&JniCallback::invoke, callback);
swapChain->setFrameCompletedCallback([](void* user) {
JniCallback* callback = (JniCallback*)user;
JniCallback::postToJavaAndDestroy(callback);
}, callback);
}

View File

@@ -210,7 +210,8 @@ Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong na
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level, (uint32_t) xoffset, (uint32_t) yoffset,
(uint32_t) width, (uint32_t) height, std::move(desc));
@@ -240,7 +241,7 @@ Java_com_google_android_filament_Texture_nSetImageCompressed(JNIEnv *env, jclass
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
&JniBufferCallback::invoke, callback);
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level, (uint32_t) xoffset, (uint32_t) yoffset,
(uint32_t) width, (uint32_t) height, std::move(desc));
@@ -274,7 +275,8 @@ Java_com_google_android_filament_Texture_nSetImage3D(JNIEnv* env, jclass, jlong
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
@@ -308,7 +310,7 @@ Java_com_google_android_filament_Texture_nSetImage3DCompressed(JNIEnv *env, jcla
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
&JniBufferCallback::invoke, callback);
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level,
(uint32_t) xoffset, (uint32_t) yoffset, (uint32_t) zoffset,
@@ -346,7 +348,8 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
(uint32_t) stride, &JniBufferCallback::invoke, callback);
(uint32_t) stride,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
@@ -381,7 +384,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env,
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
&JniBufferCallback::invoke, callback);
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
@@ -454,7 +457,7 @@ Java_com_google_android_filament_Texture_nGeneratePrefilterMipmap(JNIEnv *env, j
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
(backend::PixelDataType) type, (uint8_t) alignment,
(uint32_t) left, (uint32_t) top, (uint32_t) stride,
&JniBufferCallback::invoke, callback);
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
Texture::PrefilterOptions options;
options.sampleCount = sampleCount;
@@ -563,7 +566,7 @@ private:
jobject mBitmap = nullptr;
jobject mHandler = nullptr;
jobject mCallback = nullptr;
AndroidBitmapInfo mInfo;
AndroidBitmapInfo mInfo{};
CallbackJni mCallbackUtils;
};

View File

@@ -32,40 +32,40 @@ using namespace filament::math;
using namespace backend;
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_VertexBuffer_nCreateBuilder(JNIEnv *env, jclass type) {
Java_com_google_android_filament_VertexBuffer_nCreateBuilder(JNIEnv*, jclass) {
return (jlong) new VertexBuffer::Builder();
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nDestroyBuilder(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nDestroyBuilder(JNIEnv*, jclass,
jlong nativeBuilder) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
delete builder;
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderVertexCount(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nBuilderVertexCount(JNIEnv*, jclass,
jlong nativeBuilder, jint vertexCount) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
builder->vertexCount((uint32_t) vertexCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderEnableBufferObjects(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nBuilderEnableBufferObjects(JNIEnv*, jclass,
jlong nativeBuilder, jboolean enabled) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
builder->enableBufferObjects(enabled);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderBufferCount(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nBuilderBufferCount(JNIEnv*, jclass,
jlong nativeBuilder, jint bufferCount) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
builder->bufferCount((uint8_t) bufferCount);
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv*, jclass,
jlong nativeBuilder, jint attribute, jint bufferIndex, jint attributeType, jint byteOffset,
jint byteStride) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
@@ -75,14 +75,14 @@ Java_com_google_android_filament_VertexBuffer_nBuilderAttribute(JNIEnv *env, jcl
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderNormalized(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nBuilderNormalized(JNIEnv*, jclass,
jlong nativeBuilder, jint attribute, jboolean normalized) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
builder->normalized((VertexAttribute) attribute, normalized);
}
extern "C" JNIEXPORT jlong JNICALL
Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv*, jclass,
jlong nativeBuilder, jlong nativeEngine) {
VertexBuffer::Builder* builder = (VertexBuffer::Builder *) nativeBuilder;
Engine *engine = (Engine *) nativeEngine;
@@ -90,14 +90,14 @@ Java_com_google_android_filament_VertexBuffer_nBuilderBuild(JNIEnv *env, jclass
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_VertexBuffer_nGetVertexCount(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nGetVertexCount(JNIEnv*, jclass,
jlong nativeVertexBuffer) {
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
return (jint) vertexBuffer->getVertexCount();
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass,
jlong nativeVertexBuffer, jlong nativeEngine, jint bufferIndex,
jobject buffer, jint remaining,
jint destOffsetInBytes, jint count, jobject handler, jobject runnable) {
@@ -114,7 +114,8 @@ Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass t
auto* callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
BufferDescriptor desc(data, sizeInBytes, &JniBufferCallback::invoke, callback);
BufferDescriptor desc(data, sizeInBytes,
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
vertexBuffer->setBufferAt(*engine, (uint8_t) bufferIndex, std::move(desc),
(uint32_t) destOffsetInBytes);
@@ -123,7 +124,7 @@ Java_com_google_android_filament_VertexBuffer_nSetBufferAt(JNIEnv *env, jclass t
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv *env, jclass type,
Java_com_google_android_filament_VertexBuffer_nSetBufferObjectAt(JNIEnv*, jclass,
jlong nativeVertexBuffer, jlong nativeEngine, jint bufferIndex, jlong nativeBufferObject) {
VertexBuffer *vertexBuffer = (VertexBuffer *) nativeVertexBuffer;
Engine *engine = (Engine *) nativeEngine;

View File

@@ -20,6 +20,10 @@
#include <filament/View.h>
#include <filament/Viewport.h>
#include "common/CallbackUtils.h"
#include "private/backend/VirtualMachineEnv.h"
using namespace filament;
extern "C" JNIEXPORT void JNICALL
@@ -82,13 +86,19 @@ Java_com_google_android_filament_View_nSetRenderTarget(JNIEnv*, jclass,
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetSampleCount(JNIEnv*, jclass, jlong nativeView, jint count) {
View* view = (View*) nativeView;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
view->setSampleCount((uint8_t) count);
#pragma clang diagnostic pop
}
extern "C" JNIEXPORT jint JNICALL
Java_com_google_android_filament_View_nGetSampleCount(JNIEnv*, jclass, jlong nativeView) {
View* view = (View*) nativeView;
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
return view->getSampleCount();
#pragma clang diagnostic pop
}
extern "C" JNIEXPORT void JNICALL
@@ -321,8 +331,8 @@ Java_com_google_android_filament_View_nSetBlendMode(JNIEnv *, jclass , jlong nat
}
extern "C" JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass ,
jlong nativeView, jfloat focusDistance, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter,
Java_com_google_android_filament_View_nSetDepthOfFieldOptions(JNIEnv *, jclass,
jlong nativeView, jfloat cocScale, jfloat maxApertureDiameter, jboolean enabled, jint filter,
jboolean nativeResolution, jint foregroundRingCount, jint backgroundRingCount, jint fastGatherRingCount,
jint maxForegroundCOC, jint maxBackgroundCOC) {
View* view = (View*) nativeView;
@@ -351,6 +361,17 @@ Java_com_google_android_filament_View_nSetVignetteOptions(JNIEnv*, jclass, jlong
.color = LinearColorA{r, g, b, a}, .enabled = (bool)enabled});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetMultiSampleAntiAliasingOptions(JNIEnv* env, jclass clazz,
jlong nativeView, jboolean enabled, jint sampleCount, jboolean customResolve) {
View* view = (View*) nativeView;
view->setMultiSampleAntiAliasingOptions({
.enabled = (bool)enabled,
.sampleCount = (uint8_t)sampleCount,
.customResolve = (bool)customResolve});
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nSetTemporalAntiAliasingOptions(JNIEnv *, jclass,
@@ -382,3 +403,42 @@ Java_com_google_android_filament_View_nIsScreenSpaceRefractionEnabled(JNIEnv *,
View* view = (View*) nativeView;
return (jboolean)view->isScreenSpaceRefractionEnabled();
}
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass,
jlong nativeView,
jint x, jint y, jobject handler, jobject internalCallback) {
// jniState will be initialized the first time this method is called
static const struct JniState {
jclass internalOnPickCallbackClass;
jfieldID renderableFieldId;
jfieldID depthFieldId;
jfieldID fragCoordXFieldId;
jfieldID fragCoordYFieldId;
jfieldID fragCoordZFieldId;
explicit JniState(JNIEnv* env) noexcept {
internalOnPickCallbackClass = env->FindClass("com/google/android/filament/View$InternalOnPickCallback");
renderableFieldId = env->GetFieldID(internalOnPickCallbackClass, "mRenderable", "I");
depthFieldId = env->GetFieldID(internalOnPickCallbackClass, "mDepth", "F");
fragCoordXFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsX", "F");
fragCoordYFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsY", "F");
fragCoordZFieldId = env->GetFieldID(internalOnPickCallbackClass, "mFragCoordsZ", "F");
}
} jniState(env);
View* view = (View*) nativeView;
JniCallback *callback = JniCallback::make(env, handler, internalCallback);
view->pick(x, y, [callback](View::PickingQueryResult const& result) {
// this is executed on the backend/service thread
jobject obj = callback->getCallbackObject();
JNIEnv* env = filament::VirtualMachineEnv::get().getEnvironment();
env->SetIntField(obj, jniState.renderableFieldId, (jint)result.renderable.getId());
env->SetFloatField(obj, jniState.depthFieldId, result.depth);
env->SetFloatField(obj, jniState.fragCoordXFieldId, result.fragCoords.x);
env->SetFloatField(obj, jniState.fragCoordYFieldId, result.fragCoords.y);
env->SetFloatField(obj, jniState.fragCoordZFieldId, result.fragCoords.z);
JniCallback::postToJavaAndDestroy(callback);
}, callback->getHandler());
}

View File

@@ -631,7 +631,7 @@ public class Engine {
/**
* Kicks the hardware thread (e.g.: the OpenGL, Vulkan or Metal thread) and blocks until
* all commands to this point are executed. Note that this doesn't guarantee that the
* all commands to this point are executed. Note that this does guarantee that the
* hardware is actually finished.
*
* <p>This is typically used right after destroying the <code>SwapChain</code>,

View File

@@ -107,12 +107,12 @@ public class Renderer {
/**
* Rate at which the scale will change to reach the target frame rate.
*/
public float scaleRate = 0.125f;
public float scaleRate = 1.0f / 15.0f;
/**
* History size. higher values, tend to filter more (clamped to 30).
* History size. higher values, tend to filter more (clamped to 31).
*/
public int history = 9;
public int history = 15;
}
/**

View File

@@ -216,7 +216,38 @@ public class Texture {
ETC2_EAC_RGBA8, ETC2_EAC_SRGBA8,
// Available everywhere except Android/iOS
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA,
DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA,
// ASTC formats are available with a GLES extension
RGBA_ASTC_4x4,
RGBA_ASTC_5x4,
RGBA_ASTC_5x5,
RGBA_ASTC_6x5,
RGBA_ASTC_6x6,
RGBA_ASTC_8x5,
RGBA_ASTC_8x6,
RGBA_ASTC_8x8,
RGBA_ASTC_10x5,
RGBA_ASTC_10x6,
RGBA_ASTC_10x8,
RGBA_ASTC_10x10,
RGBA_ASTC_12x10,
RGBA_ASTC_12x12,
SRGB8_ALPHA8_ASTC_4x4,
SRGB8_ALPHA8_ASTC_5x4,
SRGB8_ALPHA8_ASTC_5x5,
SRGB8_ALPHA8_ASTC_6x5,
SRGB8_ALPHA8_ASTC_6x6,
SRGB8_ALPHA8_ASTC_8x5,
SRGB8_ALPHA8_ASTC_8x6,
SRGB8_ALPHA8_ASTC_8x8,
SRGB8_ALPHA8_ASTC_10x5,
SRGB8_ALPHA8_ASTC_10x6,
SRGB8_ALPHA8_ASTC_10x8,
SRGB8_ALPHA8_ASTC_10x10,
SRGB8_ALPHA8_ASTC_12x10,
SRGB8_ALPHA8_ASTC_12x12
}
/**
@@ -231,7 +262,38 @@ public class Texture {
ETC2_EAC_RGBA8, ETC2_EAC_SRGBA8,
// Available everywhere except Android/iOS
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA
DXT1_RGB, DXT1_RGBA, DXT3_RGBA, DXT5_RGBA,
DXT1_SRGB, DXT1_SRGBA, DXT3_SRGBA, DXT5_SRGBA,
// ASTC formats are available with a GLES extension
RGBA_ASTC_4x4,
RGBA_ASTC_5x4,
RGBA_ASTC_5x5,
RGBA_ASTC_6x5,
RGBA_ASTC_6x6,
RGBA_ASTC_8x5,
RGBA_ASTC_8x6,
RGBA_ASTC_8x8,
RGBA_ASTC_10x5,
RGBA_ASTC_10x6,
RGBA_ASTC_10x8,
RGBA_ASTC_10x10,
RGBA_ASTC_12x10,
RGBA_ASTC_12x12,
SRGB8_ALPHA8_ASTC_4x4,
SRGB8_ALPHA8_ASTC_5x4,
SRGB8_ALPHA8_ASTC_5x5,
SRGB8_ALPHA8_ASTC_6x5,
SRGB8_ALPHA8_ASTC_6x6,
SRGB8_ALPHA8_ASTC_8x5,
SRGB8_ALPHA8_ASTC_8x6,
SRGB8_ALPHA8_ASTC_8x8,
SRGB8_ALPHA8_ASTC_10x5,
SRGB8_ALPHA8_ASTC_10x6,
SRGB8_ALPHA8_ASTC_10x8,
SRGB8_ALPHA8_ASTC_10x10,
SRGB8_ALPHA8_ASTC_12x10,
SRGB8_ALPHA8_ASTC_12x12
}
/**

View File

@@ -75,6 +75,7 @@ public class View {
private VignetteOptions mVignetteOptions;
private ColorGrading mColorGrading;
private TemporalAntiAliasingOptions mTemporalAntiAliasingOptions;
private MultiSampleAntiAliasingOptions mMultiSampleAntiAliasingOptions;
private VsmShadowOptions mVsmShadowOptions;
/**
@@ -291,6 +292,29 @@ public class View {
public boolean ssctEnabled = false;
}
/**
* Options for Multi-sample Anti-aliasing (MSAA)
* @see View#setMultiSampleAntiAliasingOptions
*/
public static class MultiSampleAntiAliasingOptions {
/** enables or disables temporal anti-aliasing */
public boolean enabled = false;
/**
* number of samples to use for multi-sampled anti-aliasing.\n
* 0: treated as 1
* 1: no anti-aliasing
* n: sample count. Effective sample could be different depending on the
* GPU capabilities.
*/
public int sampleCount = 4;
/**
* custom resolve improves quality for HDR scenes, but may impact performance.
*/
public boolean customResolve = false;
};
/**
* Options for Temporal Anti-aliasing (TAA)
* @see View#setTemporalAntiAliasingOptions
@@ -1047,7 +1071,10 @@ public class View {
* </p>
*
* @param count number of samples to use for multi-sampled anti-aliasing.
*
* @deprecated use setMultiSampleAntiAliasingOptions instead
*/
@Deprecated
public void setSampleCount(int count) {
nSetSampleCount(getNativeObject(), count);
}
@@ -1060,7 +1087,10 @@ public class View {
* </p>
*
* @return value set by {@link #setSampleCount}
*
* @deprecated use getMultiSampleAntiAliasingOptions instead
*/
@Deprecated
public int getSampleCount() {
return nGetSampleCount(getNativeObject());
}
@@ -1089,6 +1119,30 @@ public class View {
return AntiAliasing.values()[nGetAntiAliasing(getNativeObject())];
}
/**
* Enables or disable multi-sample anti-aliasing (MSAA). Disabled by default.
*
* @param options multi-sample anti-aliasing options
*/
public void setMultiSampleAntiAliasingOptions(@NonNull MultiSampleAntiAliasingOptions options) {
mMultiSampleAntiAliasingOptions = options;
nSetMultiSampleAntiAliasingOptions(getNativeObject(),
options.enabled, options.sampleCount, options.customResolve);
}
/**
* Returns multi-sample anti-aliasing options.
*
* @return multi-sample anti-aliasing options
*/
@NonNull
public MultiSampleAntiAliasingOptions getMultiSampleAntiAliasingOptions() {
if (mMultiSampleAntiAliasingOptions == null) {
mMultiSampleAntiAliasingOptions = new MultiSampleAntiAliasingOptions();
}
return mMultiSampleAntiAliasingOptions;
}
/**
* Enables or disable temporal anti-aliasing (TAA). Disabled by default.
*
@@ -1548,6 +1602,71 @@ public class View {
return mDepthOfFieldOptions;
}
/**
* A class containing the result of a picking query
*/
public static class PickingQueryResult {
/** The entity of the renderable at the picking query location */
@Entity public int renderable;
/** The value of the depth buffer at the picking query location */
public float depth;
/** The fragment coordinate in GL convention at the picking query location */
@NonNull public float[] fragCoords = new float[3];
};
/**
* An interface to implement a custom class to receive results of picking queries.
*/
public interface OnPickCallback {
/**
* onPick() is called by the specified Handler in {@link View#pick} when the picking query
* result is available.
* @param result An instance of {@link PickingQueryResult}.
*/
void onPick(@NonNull PickingQueryResult result);
}
/**
* Creates a picking query. Multiple queries can be created (e.g.: multi-touch).
* Picking queries are all executed when {@link Renderer#render} is called on this View.
* The provided callback is guaranteed to be called at some point in the future.
*
* Typically it takes a couple frames to receive the result of a picking query.
*
* @param x Horizontal coordinate to query in the viewport with origin on the left.
* @param y Vertical coordinate to query on the viewport with origin at the bottom.
* @param handler An {@link java.util.concurrent.Executor Executor}.
* On Android this can also be a {@link android.os.Handler Handler}.
* @param callback User callback executed by <code>handler</code> when the picking query
* result is available.
*/
public void pick(int x, int y,
@Nullable Object handler, @Nullable OnPickCallback callback) {
InternalOnPickCallback internalCallback = new InternalOnPickCallback(callback);
nPick(getNativeObject(), x, y, handler, internalCallback);
}
private static class InternalOnPickCallback implements Runnable {
public InternalOnPickCallback(OnPickCallback mUserCallback) {
this.mUserCallback = mUserCallback;
}
@Override
public void run() {
mPickingQueryResult.renderable = mRenderable;
mPickingQueryResult.depth = mDepth;
mPickingQueryResult.fragCoords[0] = mFragCoordsX;
mPickingQueryResult.fragCoords[1] = mFragCoordsY;
mPickingQueryResult.fragCoords[2] = mFragCoordsZ;
mUserCallback.onPick(mPickingQueryResult);
}
private final OnPickCallback mUserCallback;
private final PickingQueryResult mPickingQueryResult = new PickingQueryResult();
@Entity int mRenderable;
float mDepth;
float mFragCoordsX;
float mFragCoordsY;
float mFragCoordsZ;
}
public long getNativeObject() {
if (mNativeObject == 0) {
@@ -1595,7 +1714,9 @@ public class View {
boolean nativeResolution, int foregroundRingCount, int backgroundRingCount, int fastGatherRingCount, int maxForegroundCOC, int maxBackgroundCOC);
private static native void nSetVignetteOptions(long nativeView, float midPoint, float roundness, float feather, float r, float g, float b, float a, boolean enabled);
private static native void nSetTemporalAntiAliasingOptions(long nativeView, float feedback, float filterWidth, boolean enabled);
private static native void nSetMultiSampleAntiAliasingOptions(long nativeView, boolean enabled, int sampleCount, boolean customResolve);
private static native boolean nIsShadowingEnabled(long nativeView);
private static native void nSetScreenSpaceRefractionEnabled(long nativeView, boolean enabled);
private static native boolean nIsScreenSpaceRefractionEnabled(long nativeView);
private static native void nPick(long nativeView, int x, int y, Object handler, InternalOnPickCallback internalCallback);
}

View File

@@ -50,6 +50,7 @@ target_compile_definitions(filament-utils-jni PUBLIC IMAGEIO_LITE=1)
target_include_directories(filament-utils-jni PRIVATE
${FILAMENT_DIR}/include
..
../../filament/backend/include
${IMAGEIO_DIR}/include
../../libs/utils/include)

View File

@@ -76,6 +76,8 @@ set(GLTFIO_INCLUDE_DIRS
..
${FILAMENT_DIR}/include
${FILAMENT_DIR}/include/gltfio/resources
../../filament/backend/include
../../libs/gltfio/include
../../third_party/cgltf
../../third_party/robin-map
../../third_party/hat-trie

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.12.7
VERSION_NAME=1.13.0
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
@@ -18,3 +18,7 @@ POM_DEVELOPER_NAME=Filament Team
org.gradle.jvmargs=-Xmx1536m
android.useAndroidX=true
org.gradle.unsafe.configuration-cache=false
com.google.android.filament.tools-dir=../../../out/release/filament

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -96,15 +96,36 @@ class MainActivity : Activity() {
setStatusText("To load a new model, go to the above URL on your host machine.")
val view = modelViewer.view
/*
* Note: The settings below are overriden when connecting to the remote UI.
*/
// on mobile, better use lower quality color buffer
view.renderQuality = view.renderQuality.apply {
hdrColorBuffer = View.QualityLevel.MEDIUM
}
// dynamic resolution often helps a lot
view.dynamicResolutionOptions = view.dynamicResolutionOptions.apply {
enabled = true
quality = View.QualityLevel.MEDIUM
}
// MSAA is needed with dynamic resolution MEDIUM
view.multiSampleAntiAliasingOptions = view.multiSampleAntiAliasingOptions.apply {
enabled = true
}
// FXAA is pretty cheap and helps a lot
view.antiAliasing = View.AntiAliasing.FXAA;
// ambient occlusion is the cheapest effect that adds a lot of quality
view.ambientOcclusionOptions = view.ambientOcclusionOptions.apply {
enabled = true
}
// bloom is pretty expensive but adds a fair amount of realism
view.bloomOptions = view.bloomOptions.apply {
enabled = true
}

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true
@@ -17,7 +19,7 @@ android {
compileSdkVersion versions.compileSdk
defaultConfig {
applicationId "com.google.android.filament.hellocamera"
minSdkVersion versions.minSdk
minSdkVersion 23
targetSdkVersion versions.targetSdk
}

View File

@@ -33,7 +33,9 @@ import android.graphics.ImageFormat
import android.hardware.HardwareBuffer
import android.media.ImageReader
import android.opengl.Matrix
import android.view.Display
import android.os.Build
import android.os.Looper
import androidx.annotation.RequiresApi
import com.google.android.filament.*
@@ -44,7 +46,7 @@ import java.util.concurrent.TimeUnit
* Toy class that handles all interaction with the Android camera2 API.
* Sets the "textureTransform" and "videoTexture" parameters on the given Filament material.
*/
class CameraHelper(val activity: Activity, private val filamentEngine: Engine, private val filamentMaterial: MaterialInstance, private val display: Display) {
class CameraHelper(val activity: Activity, private val filamentEngine: Engine, private val filamentMaterial: MaterialInstance) {
private lateinit var cameraId: String
private lateinit var captureRequest: CaptureRequest
@@ -63,6 +65,20 @@ class CameraHelper(val activity: Activity, private val filamentEngine: Engine, p
kImageReaderMaxImages,
HardwareBuffer.USAGE_GPU_SAMPLED_IMAGE)
@Suppress("deprecation")
private val display = if (Build.VERSION.SDK_INT >= 30) {
Api30Impl.getDisplay(activity)
} else {
activity.windowManager.defaultDisplay!!
}
@RequiresApi(30)
class Api30Impl {
companion object {
fun getDisplay(context: Context) = context.display!!
}
}
private val cameraCallback = object : CameraDevice.StateCallback() {
override fun onOpened(cameraDevice: CameraDevice) {
cameraOpenCloseLock.release()
@@ -87,7 +103,9 @@ class CameraHelper(val activity: Activity, private val filamentEngine: Engine, p
val stream = filamentStream
if (stream != null) {
imageReader.acquireLatestImage()?.also {
stream.setAcquiredImage(it.hardwareBuffer, Handler()) { it.close() }
stream.setAcquiredImage(it.hardwareBuffer, Handler(Looper.getMainLooper())) {
it.close()
}
}
}
}

View File

@@ -94,7 +94,7 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
setupView()
setupScene()
cameraHelper = CameraHelper(this, engine, materialInstance, windowManager.defaultDisplay)
cameraHelper = CameraHelper(this, engine, materialInstance)
cameraHelper.openCamera()
}

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -14,5 +14,6 @@ android {
dependencies {
implementation deps.kotlin
implementation deps.androidx.annotations
implementation project(':filament-android')
}

View File

@@ -18,19 +18,21 @@ package com.google.android.filament.livewallpaper
import android.animation.ValueAnimator
import android.app.Service
import android.content.Context
import android.graphics.Color
import android.graphics.PixelFormat
import android.os.Build
import android.service.wallpaper.WallpaperService
import android.view.Choreographer
import android.view.Surface
import android.view.SurfaceHolder
import android.view.WindowManager
import android.view.animation.LinearInterpolator
import androidx.annotation.RequiresApi
import com.google.android.filament.*
import com.google.android.filament.android.DisplayHelper
import com.google.android.filament.android.UiHelper
class FilamentLiveWallpaper : WallpaperService() {
// Make sure to initialize Filament first
// This loads the JNI library needed by most API calls
@@ -196,9 +198,14 @@ class FilamentLiveWallpaper : WallpaperService() {
override fun onNativeWindowChanged(surface: Surface) {
swapChain?.let { engine.destroySwapChain(it) }
swapChain = engine.createSwapChain(surface)
val display =
(application.getSystemService(Service.WINDOW_SERVICE) as WindowManager)
.defaultDisplay
@Suppress("deprecation")
val display = if (Build.VERSION.SDK_INT >= 30) {
Api30Impl.getDisplay(displayContext!!)
} else {
(getSystemService(Service.WINDOW_SERVICE) as WindowManager).defaultDisplay
}
displayHelper.attach(renderer, display)
}
@@ -222,4 +229,11 @@ class FilamentLiveWallpaper : WallpaperService() {
}
}
}
@RequiresApi(30)
class Api30Impl {
companion object {
fun getDisplay(context: Context) = context.display!!
}
}
}

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -1,5 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -70,11 +70,11 @@ public class MainActivity extends Activity
private Page mPage;
private PageMaterials mPageMaterials;
private Scene mScene;
private Texture[] mTextures = new Texture[2];
private final Texture[] mTextures = new Texture[2];
private @Entity int mLight;
private IndirectLight mIndirectLight;
private float[] mTouchDownPoint = new float[2];
private final float[] mTouchDownPoint = new float[2];
private float mTouchDownValue = 0;
private float mPageAnimationRadians = 0;
private float mPageAnimationValue = 0;

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true
@@ -17,7 +19,7 @@ android {
compileSdkVersion versions.compileSdk
defaultConfig {
applicationId "com.google.android.filament.streamtest"
minSdkVersion versions.minSdk
minSdkVersion 23
targetSdkVersion versions.targetSdk
}

View File

@@ -18,6 +18,7 @@ package com.google.android.filament.streamtest
import android.annotation.SuppressLint
import android.app.Activity
import android.content.Context
import android.os.Bundle
import android.view.Choreographer
import android.view.Surface
@@ -33,7 +34,9 @@ import java.nio.ByteBuffer
import java.nio.ByteOrder
import java.nio.channels.Channels
import android.opengl.*
import android.os.Build
import android.view.MotionEvent
import androidx.annotation.RequiresApi
import com.google.android.filament.android.DisplayHelper
@@ -78,6 +81,13 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
private var externalTextureID: Int = 0
@RequiresApi(30)
class Api30Impl {
companion object {
fun getDisplay(context: Context) = context.display!!
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -94,7 +104,15 @@ class MainActivity : Activity(), ActivityCompat.OnRequestPermissionsResultCallba
setupScene()
externalTextureID = createExternalTexture()
streamHelper = StreamHelper(engine, materialInstance, windowManager.defaultDisplay, externalTextureID)
@Suppress("deprecation")
val display = if (Build.VERSION.SDK_INT >= 30) {
Api30Impl.getDisplay(this)
} else {
windowManager.defaultDisplay!!
}
streamHelper = StreamHelper(engine, materialInstance, display, externalTextureID)
this.title = streamHelper.getTestName()
}

View File

@@ -24,6 +24,7 @@ import android.view.Surface
import android.graphics.*
import android.media.ImageReader
import android.opengl.Matrix
import android.os.Looper
import android.view.Display
import com.google.android.filament.*
@@ -32,7 +33,12 @@ import com.google.android.filament.*
/**
* Demonstrates Filament's various texture sharing mechanisms.
*/
class StreamHelper(private val filamentEngine: Engine, private val filamentMaterial: MaterialInstance, private val display: Display, private val externalTextureId: Int) {
class StreamHelper(
private val filamentEngine: Engine,
private val filamentMaterial: MaterialInstance,
private val display: Display,
private val externalTextureId: Int
) {
/**
* The StreamSource configures the source data for the texture.
*
@@ -50,7 +56,7 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
}
private var streamSource = StreamSource.CANVAS_STREAM_NATIVE
private val directImageHandler = Handler()
private val directImageHandler = Handler(Looper.getMainLooper())
private var resolution = Size(640, 480)
private var surfaceTexture: SurfaceTexture? = null
private var imageReader: ImageReader? = null
@@ -93,11 +99,30 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
val canvas = surface.lockCanvas(null)
val movingPaint = Paint()
movingPaint.shader = LinearGradient(kGradientOffset, 0.0f, kGradientOffset + kGradientScale, 0.0f, kGradientColors, kGradientStops, Shader.TileMode.REPEAT)
canvas.drawRect(Rect(0, resolution.height / 2, resolution.width, resolution.height), movingPaint)
movingPaint.shader = LinearGradient(
kGradientOffset,
0.0f,
kGradientOffset + kGradientScale,
0.0f,
kGradientColors,
kGradientStops,
Shader.TileMode.REPEAT
)
canvas.drawRect(
Rect(0, resolution.height / 2, resolution.width, resolution.height),
movingPaint
)
val staticPaint = Paint()
staticPaint.shader = LinearGradient(0.0f, 0.0f, kGradientScale, 0.0f, kGradientColors, kGradientStops, Shader.TileMode.REPEAT)
staticPaint.shader = LinearGradient(
0.0f,
0.0f,
kGradientScale,
0.0f,
kGradientColors,
kGradientStops,
Shader.TileMode.REPEAT
)
canvas.drawRect(Rect(0, 0, resolution.width, resolution.height / 2), staticPaint)
surface.unlockCanvasAndPost(canvas)
@@ -108,7 +133,10 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
if (streamSource == StreamSource.CANVAS_STREAM_ACQUIRED) {
val image = imageReader!!.acquireLatestImage()
filamentStream!!.setAcquiredImage(image.hardwareBuffer!!, directImageHandler) { image.close() }
filamentStream!!.setAcquiredImage(
image.hardwareBuffer!!,
directImageHandler
) { image.close() }
}
}
@@ -136,7 +164,9 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
val filamentTexture = this.filamentTexture!!
val sampler = TextureSampler(TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR, TextureSampler.WrapMode.REPEAT)
val sampler = TextureSampler(
TextureSampler.MinFilter.LINEAR, TextureSampler.MagFilter.LINEAR,
TextureSampler.WrapMode.REPEAT)
// We are texturing a front-facing square shape so we need to generate a matrix that transforms (u, v, 0, 1)
// into a new UV coordinate according to the screen rotation and the aspect ratio of the camera image.
@@ -164,7 +194,8 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
// Connect the Stream to the Texture and the Texture to the MaterialInstance.
filamentMaterial.setParameter("videoTexture", filamentTexture, sampler)
filamentMaterial.setParameter("textureTransform", MaterialInstance.FloatElement.MAT4, textureTransform, 0, 1)
filamentMaterial.setParameter("textureTransform",
MaterialInstance.FloatElement.MAT4, textureTransform, 0, 1)
if (streamSource == StreamSource.CANVAS_STREAM_NATIVE) {
@@ -207,7 +238,9 @@ class StreamHelper(private val filamentEngine: Engine, private val filamentMater
filamentTexture.setExternalStream(filamentEngine, filamentStream!!)
this.imageReader = ImageReader.newInstance(resolution.width, resolution.height, ImageFormat.RGB_565, kImageReaderMaxImages).apply {
this.imageReader = ImageReader.newInstance(
resolution.width, resolution.height, ImageFormat.RGB_565, kImageReaderMaxImages
).apply {
canvasSurface = surface
}
}

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -1,6 +1,8 @@
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
apply plugin: FilamentToolsPlugin
plugins {
id 'com.android.application'
id 'kotlin-android'
id 'filament-tools-plugin'
}
project.ext.isSample = true

View File

@@ -453,23 +453,23 @@ function build_android {
if [[ "${ISSUE_DEBUG_BUILD}" == "true" ]]; then
./gradlew \
-Pfilament_dist_dir=../out/android-debug/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
:filament-android:assembleDebug \
:gltfio-android:assembleDebug \
:filament-utils-android:assembleDebug
./gradlew \
-Pfilament_dist_dir=../out/android-debug/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
:filamat-android:assembleDebug
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
./gradlew \
-Pfilament_dist_dir=../out/android-debug/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
-Pcom.google.android.filament.dist-dir=../out/android-debug/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
:samples:${sample}:assembleDebug
done
fi
@@ -502,23 +502,23 @@ function build_android {
if [[ "${ISSUE_RELEASE_BUILD}" == "true" ]]; then
./gradlew \
-Pfilament_dist_dir=../out/android-release/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
${VULKAN_ANDROID_GRADLE_OPTION} \
:filament-android:assembleRelease \
:gltfio-android:assembleRelease \
:filament-utils-android:assembleRelease
./gradlew \
-Pfilament_dist_dir=../out/android-release/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
:filamat-android:assembleRelease
if [[ "${BUILD_ANDROID_SAMPLES}" == "true" ]]; then
for sample in ${ANDROID_SAMPLES}; do
./gradlew \
-Pfilament_dist_dir=../out/android-release/filament \
-Pfilament_abis=${ABI_GRADLE_OPTION} \
-Pcom.google.android.filament.dist-dir=../out/android-release/filament \
-Pcom.google.android.filament.abis=${ABI_GRADLE_OPTION} \
:samples:${sample}:assembleRelease
done
fi
@@ -831,7 +831,7 @@ while getopts ":hacCfijmp:q:uvslwtdk:" opt; do
;;
v)
VULKAN_ANDROID_OPTION="-DFILAMENT_SUPPORTS_VULKAN=OFF"
VULKAN_ANDROID_GRADLE_OPTION="-Pfilament_exclude_vulkan"
VULKAN_ANDROID_GRADLE_OPTION="-Pcom.google.android.filament.exclude-vulkan"
echo "Disabling support for Vulkan in the core Filament library."
echo "Consider using -c after changing this option to clear the Gradle cache."
;;

61
build/common/check-headers.sh Executable file
View File

@@ -0,0 +1,61 @@
#!/usr/bin/env bash
set -e
function print_help {
local SELF_NAME
SELF_NAME=$(basename "$0")
echo "$SELF_NAME. Check that public headers compile independently."
echo ""
echo "Usage:"
echo " $SELF_NAME <public include directory>"
echo ""
echo "Example:"
echo " $SELF_NAME out/release/filament/include"
echo ""
echo "Dependencies: clang"
echo ""
echo "Options:"
echo " -h"
echo " Print this help message and exit."
}
while getopts "h" opt; do
case ${opt} in
h)
print_help
exit 0
;;
*)
print_help
exit 1
;;
esac
done
shift $((OPTIND - 1))
if [[ "$#" -ne 1 ]]; then
print_help
exit 1
fi
FILAMENT_HEADERS="$1"
includes=()
pushd "$FILAMENT_HEADERS" >/dev/null
for f in $(find . -name '*.h'); do
include_path="${f#./}" # strip leading ./
includes+=("${include_path}")
done
popd >/dev/null
rm -rf out/check-headers
mkdir -p out/check-headers
echo "Checking that public headers compile independently..."
for include in "${includes[@]}"; do
echo "Checking ${include}"
echo "#include <${include}>" >> out/check-headers/temp.cpp
clang -std=c++17 -I "${FILAMENT_HEADERS}" out/check-headers/temp.cpp -c -o /dev/null
done
echo "Done!"

File diff suppressed because one or more lines are too long

Binary file not shown.

View File

@@ -116,6 +116,7 @@ set(PRIVATE_HDRS
src/Intersections.h
src/MaterialParser.h
src/PerViewUniforms.h
src/PIDController.h
src/PostProcessManager.h
src/RenderPass.h
src/RenderPrimitive.h
@@ -176,6 +177,7 @@ set(MATERIAL_SRCS
src/materials/fsr/fsr_rcas.mat
src/materials/colorGrading/colorGrading.mat
src/materials/colorGrading/colorGradingAsSubpass.mat
src/materials/colorGrading/customResolveAsSubpass.mat
src/materials/defaultMaterial.mat
src/materials/dof/dof.mat
src/materials/dof/dofCoc.mat
@@ -273,6 +275,7 @@ add_custom_command(
OUTPUT "${MATERIAL_DIR}/colorGrading.filamat"
DEPENDS ../shaders/src/dithering.fs
DEPENDS ../shaders/src/vignette.fs
DEPENDS src/materials/colorGrading/colorGrading.fs
APPEND
)
@@ -280,6 +283,7 @@ add_custom_command(
OUTPUT "${MATERIAL_DIR}/colorGradingAsSubpass.filamat"
DEPENDS ../shaders/src/dithering.fs
DEPENDS ../shaders/src/vignette.fs
DEPENDS src/materials/colorGrading/colorGrading.fs
APPEND
)

View File

@@ -10,6 +10,7 @@ set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR})
# ==================================================================================================
set(PUBLIC_HDRS
include/backend/BufferDescriptor.h
include/backend/CallbackHandler.h
include/backend/DriverEnums.h
include/backend/Handle.h
include/backend/PipelineState.h
@@ -21,6 +22,7 @@ set(PUBLIC_HDRS
set(SRCS
src/BackendUtils.cpp
src/Callable.cpp
src/CallbackHandler.cpp
src/CircularBuffer.cpp
src/CommandBufferQueue.cpp
src/CommandStream.cpp
@@ -77,26 +79,30 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
include/private/backend/OpenGLPlatform.h
)
if (EGL)
list(APPEND SRCS src/opengl/PlatformEGL.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformEGL.cpp)
endif()
if (ANDROID)
list(APPEND SRCS src/android/ExternalStreamManagerAndroid.cpp)
# FIXME: this should be included when we build for JAVA (which is implied by ANDROID)
# but is not specific to ANDROID
list(APPEND SRCS src/VirtualMachineEnv.cpp)
endif ()
if (ANDROID)
list(APPEND SRCS src/opengl/platforms/ExternalStreamManagerAndroid.cpp)
list(APPEND SRCS src/android/ExternalTextureManagerAndroid.cpp)
list(APPEND SRCS src/android/VirtualMachineEnv.cpp)
list(APPEND SRCS src/opengl/PlatformEGLAndroid.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformEGLAndroid.cpp)
elseif (IOS)
list(APPEND SRCS src/opengl/PlatformCocoaTouchGL.mm)
list(APPEND SRCS src/opengl/CocoaTouchExternalImage.mm)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaTouchGL.mm)
list(APPEND SRCS src/opengl/platforms/CocoaTouchExternalImage.mm)
elseif (APPLE)
list(APPEND SRCS src/opengl/PlatformCocoaGL.mm)
list(APPEND SRCS src/opengl/platforms/PlatformCocoaGL.mm)
elseif (WEBGL)
list(APPEND SRCS src/opengl/PlatformWebGL.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformWebGL.cpp)
elseif (LINUX)
list(APPEND SRCS src/opengl/PlatformGLX.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformGLX.cpp)
elseif (WIN32)
list(APPEND SRCS src/opengl/PlatformWGL.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformWGL.cpp)
else()
list(APPEND SRCS src/opengl/PlatformDummyGL.cpp)
list(APPEND SRCS src/opengl/platforms/PlatformDummyGL.cpp)
endif()
endif()
@@ -127,9 +133,9 @@ if (FILAMENT_SUPPORTS_METAL)
# Objective-C++ sources need an additional compiler flag on iOS to disable exceptions.
set_property(SOURCE
${METAL_SRCS}
src/opengl/PlatformCocoaTouchGL.mm
src/opengl/CocoaTouchExternalImage.mm
src/opengl/PlatformCocoaGL.mm
src/opengl/platforms/PlatformCocoaTouchGL.mm
src/opengl/platforms/CocoaTouchExternalImage.mm
src/opengl/platforms/PlatformCocoaGL.mm
PROPERTY COMPILE_FLAGS -fno-objc-exceptions)
endif()

View File

@@ -27,6 +27,8 @@
namespace filament::backend {
class CallbackHandler;
/**
* A CPU memory-buffer descriptor, typically used to transfer data from the CPU to the GPU.
*
@@ -53,8 +55,8 @@ public:
//! calls the callback to advertise BufferDescriptor no-longer owns the buffer
~BufferDescriptor() noexcept {
if (callback) {
callback(buffer, size, user);
if (mCallback) {
mCallback(buffer, size, mUser);
}
}
@@ -62,19 +64,21 @@ public:
BufferDescriptor& operator=(const BufferDescriptor& rhs) = delete;
BufferDescriptor(BufferDescriptor&& rhs) noexcept
: buffer(rhs.buffer), size(rhs.size), callback(rhs.callback), user(rhs.user) {
: buffer(rhs.buffer), size(rhs.size),
mCallback(rhs.mCallback), mUser(rhs.mUser), mHandler(rhs.mHandler) {
rhs.buffer = nullptr;
rhs.callback = nullptr;
rhs.mCallback = nullptr;
}
BufferDescriptor& operator=(BufferDescriptor&& rhs) noexcept {
if (this != &rhs) {
buffer = rhs.buffer;
size = rhs.size;
callback = rhs.callback;
user = rhs.user;
mCallback = rhs.mCallback;
mUser = rhs.mUser;
mHandler = rhs.mHandler;
rhs.buffer = nullptr;
rhs.callback = nullptr;
rhs.mCallback = nullptr;
}
return *this;
}
@@ -88,30 +92,113 @@ public:
*/
BufferDescriptor(void const* buffer, size_t size,
Callback callback = nullptr, void* user = nullptr) noexcept
: buffer(const_cast<void*>(buffer)), size(size), callback(callback), user(user) {
: buffer(const_cast<void*>(buffer)), size(size), mCallback(callback), mUser(user) {
}
/**
* Creates a BufferDescriptor that references a CPU memory-buffer
* @param buffer Memory address of the CPU buffer to reference
* @param size Size of the CPU buffer in bytes
* @param callback A callback used to release the CPU buffer from this BufferDescriptor
* @param user An opaque user pointer passed to the callback function when it's called
*/
BufferDescriptor(void const* buffer, size_t size,
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
: buffer(const_cast<void*>(buffer)), size(size),
mCallback(callback), mUser(user), mHandler(handler) {
}
// --------------------------------------------------------------------------------------------
/**
* Helper to create a BufferDescriptor that uses a KNOWN method pointer w/ object passed
* by pointer as the callback. e.g.:
* auto bd = BufferDescriptor::make(buffer, size, &Foo::method, foo);
*
* @param buffer Memory address of the CPU buffer to reference
* @param size Size of the CPU buffer in bytes
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
* @return a new BufferDescriptor
*/
template<typename T, void(T::*method)(void const*, size_t)>
static BufferDescriptor make(
void const* buffer, size_t size, T* data, CallbackHandler* handler = nullptr) noexcept {
return {
buffer, size,
handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s);
}, data
};
}
/**
* Helper to create a BufferDescriptor that uses a functor as the callback.
*
* Caveats:
* - DO NOT CALL setCallback() when using this helper.
* - This make a heap allocation
*
* @param buffer Memory address of the CPU buffer to reference
* @param size Size of the CPU buffer in bytes
* @param functor functor of type f(void const* buffer, size_t size)
* @param handler Handler to use to dispatch the callback, or nullptr for the default handler
* @return a new BufferDescriptor
*/
template<typename T>
static BufferDescriptor make(
void const* buffer, size_t size, T&& functor, CallbackHandler* handler = nullptr) noexcept {
return {
buffer, size,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
},
new T(std::forward<T>(functor))
};
}
// --------------------------------------------------------------------------------------------
/**
* Set or replace the release callback function
* @param callback The new callback function
* @param user An opaque user pointer passed to the callbeck function when it's called
*/
void setCallback(Callback callback, void* user = nullptr) noexcept {
this->callback = callback;
this->user = user;
this->mCallback = callback;
this->mUser = user;
this->mHandler = nullptr;
}
/**
* Set or replace the release callback function
* @param handler The Handler to use to dispatch the callback
* @param callback The new callback function
* @param user An opaque user pointer passed to the callbeck function when it's called
*/
void setCallback(CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept {
mCallback = callback;
mUser = user;
mHandler = handler;
}
//! Returns whether a release callback is set
bool hasCallback() const noexcept { return callback != nullptr; }
bool hasCallback() const noexcept { return mCallback != nullptr; }
//! Returns the currently set release callback function
Callback getCallback() const noexcept {
return callback;
return mCallback;
}
//! Returns the handler for this callback or nullptr if the default handler is to be used.
CallbackHandler* getHandler() const noexcept {
return mHandler;
}
//! Returns the user opaque pointer associated to this BufferDescriptor
void* getUser() const noexcept {
return user;
return mUser;
}
//! CPU mempry-buffer virtual address
@@ -122,8 +209,9 @@ public:
private:
// callback when the buffer is consumed.
Callback callback = nullptr;
void* user = nullptr;
Callback mCallback = nullptr;
void* mUser = nullptr;
CallbackHandler* mHandler = nullptr;
};
} // namespace filament::backend

View File

@@ -0,0 +1,74 @@
/*
* Copyright (C) 2021 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.
*/
#ifndef TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#include <utils/compiler.h>
namespace filament::backend {
/**
* A generic interface to dispatch callbacks.
*
* All APIs that take a callback as argument also take a
* CallbackHandler* which is used to dispatch the
* callback: CallbackHandler::post() method is called from a service thread as soon
* as possible (this will NEVER be the main thread), CallbackHandler::post()
* is responsible for scheduling the callback onto the thread the
* user desires.
*
* This is intended to make callbacks interoperate with
* the platform/OS's own messaging system.
*
* CallbackHandler* can always be nullptr in which case the default handler is used. The
* default handler always dispatches callbacks on filament's main thread opportunistically.
*
* Life time:
* ---------
*
* Filament make no attempts to manage the life time of the CallbackHandler* and never takes
* ownership.
* In particular, this means that the CallbackHandler instance must stay valid until all
* pending callbacks are been dispatched.
*
* Similarly, when shutting down filament, care must be taken to ensure that all pending callbacks
* that might access filament's state have been dispatched. Filament can no longer ensure this
* because callback execution is the responsibility of the CallbackHandler, which is external to
* filament.
* Typically, the concrete CallbackHandler would have a mechanism to drain and/or wait for all
* callbacks to be processed.
*
*/
class CallbackHandler {
public:
using Callback = void(*)(void* user);
/**
* Schedules the callback to be called onto the appropriate thread.
* Typically this will be the application's main thead.
*
* Must be thread-safe.
*/
virtual void post(void* user, Callback callback) = 0;
protected:
virtual ~CallbackHandler();
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H

View File

@@ -320,7 +320,7 @@ enum class PixelDataType : uint8_t {
BYTE, //!< signed byte
USHORT, //!< unsigned short (16-bit)
SHORT, //!< signed short (16-bit)
UINT, //!< unsigned int (16-bit)
UINT, //!< unsigned int (32-bit)
INT, //!< signed int (32-bit)
HALF, //!< half-float (16-bit float)
FLOAT, //!< float (32-bits float)
@@ -563,6 +563,48 @@ static constexpr bool isDepthFormat(TextureFormat format) noexcept {
}
}
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8UI:
case TextureFormat::R16UI:
case TextureFormat::R32UI:
case TextureFormat::RG8UI:
case TextureFormat::RG16UI:
case TextureFormat::RG32UI:
case TextureFormat::RGB8UI:
case TextureFormat::RGB16UI:
case TextureFormat::RGB32UI:
case TextureFormat::RGBA8UI:
case TextureFormat::RGBA16UI:
case TextureFormat::RGBA32UI:
return true;
default:
return false;
}
}
static constexpr bool isSignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8I:
case TextureFormat::R16I:
case TextureFormat::R32I:
case TextureFormat::RG8I:
case TextureFormat::RG16I:
case TextureFormat::RG32I:
case TextureFormat::RGB8I:
case TextureFormat::RGB16I:
case TextureFormat::RGB32I:
case TextureFormat::RGBA8I:
case TextureFormat::RGBA16I:
case TextureFormat::RGBA32I:
return true;
default:
return false;
}
}
//! returns whether this format a compressed format
static constexpr bool isCompressedFormat(TextureFormat format) noexcept {
return format >= TextureFormat::EAC_R11;

View File

@@ -21,6 +21,8 @@
#include <utils/Log.h>
#include <utils/debug.h>
#include <limits>
namespace filament {
namespace backend {

View File

@@ -28,8 +28,7 @@
#include <stddef.h>
#include <stdint.h>
namespace filament {
namespace backend {
namespace filament::backend {
/**
* A descriptor to an image in main memory, typically used to transfer image data from the CPU
@@ -58,9 +57,19 @@ public:
* @param left Left coordinate in pixels
* @param top Top coordinate in pixels
* @param stride Stride of a row in pixels
* @param handler Handler to dispatch the callback or nullptr for the default handler
* @param callback A callback used to release the CPU buffer
* @param user An opaque user pointer passed to the callback function when it's called
*/
PixelBufferDescriptor(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, uint8_t alignment,
uint32_t left, uint32_t top, uint32_t stride,
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
: BufferDescriptor(buffer, size, handler, callback, user),
left(left), top(top), stride(stride),
format(format), type(type), alignment(alignment) {
}
PixelBufferDescriptor(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, uint8_t alignment = 1,
uint32_t left = 0, uint32_t top = 0, uint32_t stride = 0,
@@ -77,9 +86,17 @@ public:
* @param size Size in bytes of the buffer containing the image
* @param format Format of the image pixels
* @param type Type of the image pixels
* @param handler Handler to dispatch the callback or nullptr for the default handler
* @param callback A callback used to release the CPU buffer
* @param user An opaque user pointer passed to the callback function when it's called
*/
PixelBufferDescriptor(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type,
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
: BufferDescriptor(buffer, size, handler, callback, user),
stride(0), format(format), type(type), alignment(1) {
}
PixelBufferDescriptor(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type,
Callback callback, void* user = nullptr) noexcept
@@ -87,6 +104,7 @@ public:
stride(0), format(format), type(type), alignment(1) {
}
/**
* Creates a new PixelBufferDescriptor referencing a compressed image in main memory
*
@@ -94,9 +112,18 @@ public:
* @param size Size in bytes of the buffer containing the image
* @param format Compressed format of the image
* @param imageSize Compressed size of the image
* @param handler Handler to dispatch the callback or nullptr for the default handler
* @param callback A callback used to release the CPU buffer
* @param user An opaque user pointer passed to the callback function when it's called
*/
PixelBufferDescriptor(void const* buffer, size_t size,
backend::CompressedPixelDataType format, uint32_t imageSize,
CallbackHandler* handler, Callback callback, void* user = nullptr) noexcept
: BufferDescriptor(buffer, size, handler, callback, user),
imageSize(imageSize), compressedFormat(format), type(PixelDataType::COMPRESSED),
alignment(1) {
}
PixelBufferDescriptor(void const* buffer, size_t size,
backend::CompressedPixelDataType format, uint32_t imageSize,
Callback callback, void* user = nullptr) noexcept
@@ -105,6 +132,77 @@ public:
alignment(1) {
}
// --------------------------------------------------------------------------------------------
template<typename T, void(T::*method)(void const*, size_t)>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, uint8_t alignment,
uint32_t left, uint32_t top, uint32_t stride, T* data,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type, alignment, left, top, stride,
handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data };
}
template<typename T, void(T::*method)(void const*, size_t)>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, T* data,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type, handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data };
}
template<typename T, void(T::*method)(void const*, size_t)>
static PixelBufferDescriptor make(void const* buffer, size_t size,
backend::CompressedPixelDataType format, uint32_t imageSize, T* data,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, imageSize, handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data
};
}
template<typename T>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, uint8_t alignment,
uint32_t left, uint32_t top, uint32_t stride, T&& functor,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type, alignment, left, top, stride,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
}, new T(std::forward<T>(functor))
};
}
template<typename T>
static PixelBufferDescriptor make(void const* buffer, size_t size,
PixelDataFormat format, PixelDataType type, T&& functor,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
}, new T(std::forward<T>(functor))
};
}
template<typename T>
static PixelBufferDescriptor make(void const* buffer, size_t size,
backend::CompressedPixelDataType format, uint32_t imageSize, T&& functor,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, imageSize,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
}, new T(std::forward<T>(functor))
};
}
// --------------------------------------------------------------------------------------------
/**
* Computes the size in bytes needed to fit an image of given dimensions and format
*
@@ -210,8 +308,7 @@ public:
uint8_t alignment : 4;
};
} // namespace backend
} // namespace filament
} // namespace backend::filament
#if !defined(NDEBUG)
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PixelBufferDescriptor& b);

View File

@@ -19,8 +19,9 @@
#include <backend/DriverEnums.h>
namespace filament {
namespace backend {
namespace filament::backend {
class CallbackHandler;
// This lightweight POD allows us to bundle the state required to process an ACQUIRED stream.
// Since these types of external images need to be moved around and queued up, an encapsulation is
@@ -30,9 +31,9 @@ struct AcquiredImage {
void* image = nullptr;
backend::StreamCallback callback = nullptr;
void* userData = nullptr;
CallbackHandler* handler = nullptr;
};
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRIVATE_ACQUIREDIMAGE_H

View File

@@ -18,6 +18,7 @@
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
#include <backend/BufferDescriptor.h>
#include <backend/CallbackHandler.h>
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <backend/PipelineState.h>
@@ -63,7 +64,7 @@ public:
virtual ~Driver() noexcept;
// called from the main thread (NOT the render-thread) at various intervals, this
// is where the driver can free resources consumed by previous commands.
// is where the driver can execute user callbacks.
virtual void purge() noexcept = 0;
virtual ShaderModel getShaderModel() const noexcept = 0;

View File

@@ -280,7 +280,7 @@ DECL_DRIVER_API_N(destroySync, backend::SyncHandle, sh)
DECL_DRIVER_API_SYNCHRONOUS_0(void, terminate)
DECL_DRIVER_API_SYNCHRONOUS_N(backend::StreamHandle, createStreamNative, void*, stream)
DECL_DRIVER_API_SYNCHRONOUS_0(backend::StreamHandle, createStreamAcquired)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setAcquiredImage, backend::StreamHandle, stream, void*, image, backend::StreamCallback, cb, void*, userData)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setAcquiredImage, backend::StreamHandle, stream, void*, image, backend::CallbackHandler*, handler, backend::StreamCallback, cb, void*, userData)
DECL_DRIVER_API_SYNCHRONOUS_N(void, setStreamDimensions, backend::StreamHandle, stream, uint32_t, width, uint32_t, height)
DECL_DRIVER_API_SYNCHRONOUS_N(int64_t, getStreamTimestamp, backend::StreamHandle, stream)
DECL_DRIVER_API_SYNCHRONOUS_N(void, updateStreams, backend::DriverApi*, driver)
@@ -291,6 +291,7 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isTextureSwizzleSupported)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isTextureFormatMipmappable, backend::TextureFormat, format)
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isRenderTargetFormatSupported, backend::TextureFormat, format)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameBufferFetchMultiSampleSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isFrameTimeSupported)
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)

View File

@@ -43,18 +43,6 @@ public:
return env;
}
VirtualMachineEnv() noexcept : mVirtualMachine(sVirtualMachine) {
// We're not initializing the JVM here -- but we could -- because most of the time
// we don't need the jvm. Instead we do the initialization on first use. This means we could get
// a nasty slow down the very first time, but we'll live with it for now.
}
~VirtualMachineEnv() {
if (mVirtualMachine) {
mVirtualMachine->DetachCurrentThread();
}
}
inline JNIEnv* getEnvironment() noexcept {
assert_invariant(mVirtualMachine);
JNIEnv* env = mJniEnv;
@@ -67,6 +55,18 @@ public:
static void handleException(JNIEnv* env) noexcept;
private:
VirtualMachineEnv() noexcept : mVirtualMachine(sVirtualMachine) {
// We're not initializing the JVM here -- but we could -- because most of the time
// we don't need the jvm. Instead we do the initialization on first use. This means we could get
// a nasty slow down the very first time, but we'll live with it for now.
}
~VirtualMachineEnv() {
if (mVirtualMachine) {
mVirtualMachine->DetachCurrentThread();
}
}
JNIEnv* getEnvironmentSlow() noexcept;
static JavaVM* sVirtualMachine;
JNIEnv* mJniEnv = nullptr;

View File

@@ -0,0 +1,23 @@
/*
* Copyright (C) 2021 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.
*/
#include <backend/CallbackHandler.h>
namespace filament::backend {
CallbackHandler::~CallbackHandler() = default;
} // namespace filament::backend

View File

@@ -83,7 +83,13 @@ public:
dstComponentType* out = (dstComponentType*) dest;
for (size_t column = 0; column < width; ++column) {
for (size_t channel = 0; channel < minChannelCount; ++channel) {
out[channel] = in[inds[channel]] * dstMaxValue / srcMaxValue;
if constexpr (std::is_same_v<dstComponentType, srcComponentType>) {
out[channel] = in[inds[channel]];
} else {
// TODO: beware of overflows in the multiply
// TODO: probably not correct for _INTEGER src/dst
out[channel] = in[inds[channel]] * dstMaxValue / srcMaxValue;
}
}
for (size_t channel = srcChannelCount; channel < dstChannelCount; ++channel) {
out[channel] = dstMaxValue;
@@ -102,6 +108,12 @@ public:
bool flip) {
size_t dstChannelCount;
switch (dst->format) {
case PixelDataFormat::R_INTEGER: dstChannelCount = 1; break;
case PixelDataFormat::RG_INTEGER: dstChannelCount = 2; break;
case PixelDataFormat::RGB_INTEGER: dstChannelCount = 3; break;
case PixelDataFormat::RGBA_INTEGER: dstChannelCount = 4; break;
case PixelDataFormat::R: dstChannelCount = 1; break;
case PixelDataFormat::RG: dstChannelCount = 2; break;
case PixelDataFormat::RGB: dstChannelCount = 3; break;
case PixelDataFormat::RGBA: dstChannelCount = 4; break;
default: return false;

View File

@@ -39,35 +39,100 @@ namespace backend {
DriverBase::DriverBase(Dispatcher* dispatcher) noexcept
: mDispatcher(dispatcher) {
if constexpr (UTILS_HAS_THREADING) {
// This thread services user callbacks
mServiceThread = std::thread([this]() {
do {
auto& serviceThreadCondition = mServiceThreadCondition;
auto& serviceThreadCallbackQueue = mServiceThreadCallbackQueue;
// wait for some callbacks to dispatch
std::unique_lock<std::mutex> lock(mServiceThreadLock);
while (serviceThreadCallbackQueue.empty() && !mExitRequested) {
serviceThreadCondition.wait(lock);
}
if (mExitRequested) {
break;
}
// move the callbacks to a temporary vector
auto callbacks(std::move(serviceThreadCallbackQueue));
lock.unlock();
// and make sure to call them without our lock held
for (auto[handler, callback, user]: callbacks) {
handler->post(user, callback);
}
} while (true);
});
}
}
DriverBase::~DriverBase() noexcept {
if constexpr (UTILS_HAS_THREADING) {
// quit our service thread
std::unique_lock<std::mutex> lock(mServiceThreadLock);
mExitRequested = true;
mServiceThreadCondition.notify_one();
lock.unlock();
mServiceThread.join();
}
delete mDispatcher;
}
void DriverBase::purge() noexcept {
std::vector<BufferDescriptor> buffersToPurge;
std::vector<AcquiredImage> imagesToPurge;
std::unique_lock<std::mutex> lock(mPurgeLock);
std::swap(buffersToPurge, mBufferToPurge);
std::swap(imagesToPurge, mImagesToPurge);
lock.unlock(); // don't remove this, it ensures mBufferToPurge is destroyed without lock held
for (auto& image : imagesToPurge) {
image.callback(image.image, image.userData);
}
// When the BufferDescriptors go out of scope, their destructors invoke their callbacks.
// ------------------------------------------------------------------------------------------------
class DriverBase::CallbackDataDetails : public DriverBase::CallbackData {
UTILS_UNUSED DriverBase* mAllocator;
public:
explicit CallbackDataDetails(DriverBase* allocator) : mAllocator(allocator) {}
};
DriverBase::CallbackData* DriverBase::CallbackData::obtain(DriverBase* allocator) {
// todo: use a pool
return new CallbackDataDetails(allocator);
}
void DriverBase::CallbackData::release(CallbackData* data) {
// todo: use a pool
delete static_cast<CallbackDataDetails*>(data);
}
void DriverBase::scheduleCallback(CallbackHandler* handler, void* user, CallbackHandler::Callback callback) {
if (handler && UTILS_HAS_THREADING) {
std::lock_guard<std::mutex> lock(mServiceThreadLock);
mServiceThreadCallbackQueue.emplace_back(handler, callback, user);
mServiceThreadCondition.notify_one();
} else {
std::lock_guard<std::mutex> lock(mPurgeLock);
mCallbacks.emplace_back(user, callback);
}
}
void DriverBase::purge() noexcept {
decltype(mCallbacks) callbacks;
std::unique_lock<std::mutex> lock(mPurgeLock);
std::swap(callbacks, mCallbacks);
lock.unlock(); // don't remove this, it ensures callbacks are called without lock held
for (auto& item : callbacks) {
item.second(item.first);
}
}
// ------------------------------------------------------------------------------------------------
void DriverBase::scheduleDestroySlow(BufferDescriptor&& buffer) noexcept {
std::lock_guard<std::mutex> lock(mPurgeLock);
mBufferToPurge.push_back(std::move(buffer));
scheduleCallback(buffer.getHandler(), [buffer = std::move(buffer)]() {
// user callback is called when BufferDescriptor gets destroyed
});
}
// This is called from an async driver method so it's in the GL thread, but purge is called
// on the user thread. This is typically called 0 or 1 times per frame.
void DriverBase::scheduleRelease(AcquiredImage&& image) noexcept {
std::lock_guard<std::mutex> lock(mPurgeLock);
mImagesToPurge.push_back(std::move(image));
void DriverBase::scheduleRelease(AcquiredImage const& image) noexcept {
scheduleCallback(image.handler, [image]() {
image.callback(image.image, image.userData);
});
}
void DriverBase::debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept {

View File

@@ -23,20 +23,23 @@
#include <backend/Platform.h>
#include <backend/DriverEnums.h>
#include <backend/CallbackHandler.h>
#include "private/backend/AcquiredImage.h"
#include "private/backend/Driver.h"
#include "private/backend/SamplerGroup.h"
#include <array>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <thread>
#include <utility>
#include <vector>
#include <stdint.h>
namespace filament {
namespace backend {
namespace filament::backend {
class Dispatcher;
@@ -183,6 +186,38 @@ public:
protected:
Dispatcher* mDispatcher;
class CallbackDataDetails;
// Helpers...
struct CallbackData {
CallbackData(CallbackData const &) = delete;
CallbackData(CallbackData&&) = delete;
CallbackData& operator=(CallbackData const &) = delete;
CallbackData& operator=(CallbackData&&) = delete;
void* storage[8] = {};
static CallbackData* obtain(DriverBase* allocator);
static void release(CallbackData* data);
protected:
CallbackData() = default;
};
template<typename T>
void scheduleCallback(CallbackHandler* handler, T&& functor) {
CallbackData* data = CallbackData::obtain(this);
static_assert(sizeof(T) <= sizeof(data->storage), "functor too large");
new(data->storage) T(std::forward<T>(functor));
scheduleCallback(handler, data, (CallbackHandler::Callback)[](void* data) {
CallbackData* details = static_cast<CallbackData*>(data);
void* user = details->storage;
T& functor = *static_cast<T*>(user);
functor();
functor.~T();
CallbackData::release(details);
});
}
void scheduleCallback(CallbackHandler* handler, void* user, CallbackHandler::Callback callback);
inline void scheduleDestroy(BufferDescriptor&& buffer) noexcept {
if (buffer.hasCallback()) {
scheduleDestroySlow(std::move(buffer));
@@ -191,19 +226,23 @@ protected:
void scheduleDestroySlow(BufferDescriptor&& buffer) noexcept;
void scheduleRelease(AcquiredImage&& image) noexcept;
void scheduleRelease(AcquiredImage const& image) noexcept;
void debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept override;
void debugCommandEnd(CommandStream* cmds, bool synchronous, const char* methodName) noexcept override;
private:
std::mutex mPurgeLock;
std::vector<BufferDescriptor> mBufferToPurge;
std::vector<AcquiredImage> mImagesToPurge;
std::vector<std::pair<void*, CallbackHandler::Callback>> mCallbacks;
std::thread mServiceThread;
std::mutex mServiceThreadLock;
std::condition_variable mServiceThreadCondition;
std::vector<std::tuple<CallbackHandler*, CallbackHandler::Callback, void*>> mServiceThreadCallbackQueue;
bool mExitRequested = false;
};
} // namespace backend
} // namespace filament
} // namespace backend::filament
#endif // TNT_FILAMENT_DRIVER_DRIVERBASE_H

View File

@@ -22,44 +22,44 @@
#if defined(ANDROID)
#include <sys/system_properties.h>
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "opengl/PlatformEGLAndroid.h"
#include "opengl/platforms/PlatformEGLAndroid.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkAndroid.h"
#endif
#elif defined(IOS)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "opengl/PlatformCocoaTouchGL.h"
#include "opengl/platforms/PlatformCocoaTouchGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkCocoaTouch.h"
#endif
#elif defined(__APPLE__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/PlatformCocoaGL.h"
#include "opengl/platforms/PlatformCocoaGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkCocoa.h"
#endif
#elif defined(__linux__)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/PlatformGLX.h"
#include "opengl/platforms/PlatformGLX.h"
#endif
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkLinux.h"
#endif
#elif defined(WIN32)
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3) && !defined(FILAMENT_USE_SWIFTSHADER)
#include "opengl/PlatformWGL.h"
#include "opengl/platforms/PlatformWGL.h"
#endif
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
#include "vulkan/PlatformVkWindows.h"
#endif
#elif defined(__EMSCRIPTEN__)
#include "opengl/PlatformWebGL.h"
#include "opengl/platforms/PlatformWebGL.h"
#else
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
#include "opengl/PlatformDummyGL.h"
#include "opengl/platforms/PlatformDummyGL.h"
#endif
#endif

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
#include "VirtualMachineEnv.h"
#include "private/backend/VirtualMachineEnv.h"
#include <utils/debug.h>
@@ -44,7 +44,11 @@ void VirtualMachineEnv::handleException(JNIEnv* const env) noexcept {
UTILS_NOINLINE
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
#if defined(__ANDROID__)
mVirtualMachine->AttachCurrentThread(&mJniEnv, nullptr);
#else
mVirtualMachine->AttachCurrentThread(reinterpret_cast<void**>(&mJniEnv), nullptr);
#endif
assert_invariant(mJniEnv);
return mJniEnv;
}

View File

@@ -84,9 +84,12 @@ struct EGLExternalTexture : public ExternalTextureManagerAndroid::ExternalTextur
GraphicBufferWrapper* graphicBufferWrapper = nullptr;
};
ExternalTextureManagerAndroid& ExternalTextureManagerAndroid::get() noexcept {
static ExternalTextureManagerAndroid instance;
return instance;
ExternalTextureManagerAndroid& ExternalTextureManagerAndroid::create() noexcept {
return *(new ExternalTextureManagerAndroid{});
}
void ExternalTextureManagerAndroid::destroy(ExternalTextureManagerAndroid* pExternalTextureManager) noexcept {
delete pExternalTextureManager;
}
// called on gl thread
@@ -116,7 +119,7 @@ ExternalTextureManagerAndroid::~ExternalTextureManagerAndroid() noexcept {
}
// called on gl thread
backend::Platform::ExternalTexture* ExternalTextureManagerAndroid::create() noexcept {
backend::Platform::ExternalTexture* ExternalTextureManagerAndroid::createExternalTexture() noexcept {
#ifndef PLATFORM_HAS_HARDWAREBUFFER
if (!AHardwareBuffer_allocate) {
// initialize java stuff on-demand

View File

@@ -17,7 +17,7 @@
#ifndef TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
#define TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_TEXTURE_MANAGER_ANDROID_H
#include "android/VirtualMachineEnv.h"
#include "private/backend/VirtualMachineEnv.h"
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
@@ -31,6 +31,15 @@
namespace filament {
/*
* ExternalTextureManagerAndroid::ExternalTexture is basically a wrapper for AHardwareBuffer.
*
* This class doesn't rely on GL or EGL, and could be used for other Android platform if needed
* (e.g. Vulkan).
*
* ExternalTextureManagerAndroid handle allocation/destruction using either Java or the NDK,
* whichever is available.
*/
class ExternalTextureManagerAndroid {
public:
@@ -39,26 +48,27 @@ public:
AHardwareBuffer* hardwareBuffer = nullptr;
};
static ExternalTextureManagerAndroid& get() noexcept;
// must be called on backend thread
static ExternalTextureManagerAndroid& create() noexcept;
// called on gl thread
ExternalTextureManagerAndroid() noexcept;
// must be called on backend thread
static void destroy(ExternalTextureManagerAndroid* pExternalTextureManager) noexcept;
// not quite sure on which thread this is going to be called
~ExternalTextureManagerAndroid() noexcept;
// called on gl thread
backend::Platform::ExternalTexture* create() noexcept;
// must be called on backend thread (only because we don't synchronize
backend::Platform::ExternalTexture* createExternalTexture() noexcept;
// called on app thread
void reallocate(
backend::Platform::ExternalTexture* ets, uint32_t w, uint32_t h,
backend::TextureFormat format, uint64_t usage) noexcept;
// called on gl thread
// must be called on backend thread
void destroy(backend::Platform::ExternalTexture* ets) noexcept;
private:
ExternalTextureManagerAndroid() noexcept;
~ExternalTextureManagerAndroid() noexcept;
// called on app thread
void alloc(backend::Platform::ExternalTexture* ets,
uint32_t w, uint32_t h, backend::TextureFormat format, uint64_t usage) noexcept;

View File

@@ -64,16 +64,19 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept
initializeSupportedGpuFamilies(mContext);
utils::slog.d << "Supported GPU families: " << utils::io::endl;
utils::slog.v << "Supported GPU families: " << utils::io::endl;
if (mContext->highestSupportedGpuFamily.common > 0) {
utils::slog.d << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl;
utils::slog.v << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl;
}
if (mContext->highestSupportedGpuFamily.apple > 0) {
utils::slog.d << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl;
utils::slog.v << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl;
}
if (mContext->highestSupportedGpuFamily.mac > 0) {
utils::slog.d << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl;
utils::slog.v << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl;
}
utils::slog.v << "Features:" << utils::io::endl;
utils::slog.v << " readWriteTextureSupport: " <<
(bool) mContext->device.readWriteTextureSupport << utils::io::endl;
// In order to support texture swizzling, the GPU needs to support it and the system be running
// iOS 13+.
@@ -565,8 +568,8 @@ Handle<HwStream> MetalDriver::createStreamAcquired() {
return {};
}
void MetalDriver::setAcquiredImage(Handle<HwStream> sh, void* image, backend::StreamCallback cb,
void* userData) {
void MetalDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
}
void MetalDriver::setStreamDimensions(Handle<HwStream> stream, uint32_t width,
@@ -650,11 +653,14 @@ bool MetalDriver::isRenderTargetFormatSupported(TextureFormat format) {
}
bool MetalDriver::isFrameBufferFetchSupported() {
#if defined(IOS) && !defined(FILAMENT_IOS_SIMULATOR)
return true;
#else
return false;
#endif
// FrameBuffer fetch is achievable via "programmable blending" in Metal, and only supported on
// Apple GPUs with readWriteTextureSupport.
return mContext->highestSupportedGpuFamily.apple >= 1 &&
mContext->device.readWriteTextureSupport;
}
bool MetalDriver::isFrameBufferFetchMultiSampleSupported() {
return isFrameBufferFetchSupported();
}
bool MetalDriver::isFrameTimeSupported() {
@@ -973,23 +979,19 @@ void MetalDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y,
id<MTLTexture> srcTexture = color.getTexture();
size_t miplevel = color.level;
auto chooseMetalPixelFormat = [] (PixelDataFormat format, PixelDataType type) {
// TODO: Add support for UINT and INT
if (format == PixelDataFormat::RGBA && type == PixelDataType::UBYTE) {
return MTLPixelFormatRGBA8Unorm;
}
if (format == PixelDataFormat::RGBA && type == PixelDataType::FLOAT) {
return MTLPixelFormatRGBA32Float;
}
return MTLPixelFormatInvalid;
};
const MTLPixelFormat format = chooseMetalPixelFormat(data.format, data.type);
const MTLPixelFormat format = getMetalFormat(data.format, data.type);
ASSERT_PRECONDITION(format != MTLPixelFormatInvalid,
"The chosen combination of PixelDataFormat and PixelDataType is not supported for "
"readPixels.");
"The chosen combination of PixelDataFormat (%d) and PixelDataType (%d) is not supported for "
"readPixels.", (int) data.format, (int) data.type);
const bool formatConversionNecessary = srcTexture.pixelFormat != format;
// TODO: MetalBlitter does not currently support format conversions to integer types.
// The format and type must match the source pixel format exactly.
ASSERT_PRECONDITION(!formatConversionNecessary || !isMetalFormatInteger(format),
"readPixels does not support integer format conversions from MTLPixelFormat (%d) to (%d).",
(int) srcTexture.pixelFormat, (int) format);
MTLTextureDescriptor* textureDescriptor =
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
width:(srcTexture.width >> miplevel)

View File

@@ -222,6 +222,34 @@ inline MTLPixelFormat getMetalFormatLinear(MTLPixelFormat format) {
return format;
}
constexpr inline bool isMetalFormatInteger(MTLPixelFormat format) {
switch (format) {
case MTLPixelFormatR8Uint:
case MTLPixelFormatR8Sint:
case MTLPixelFormatR16Uint:
case MTLPixelFormatR16Sint:
case MTLPixelFormatRG8Uint:
case MTLPixelFormatRG8Sint:
case MTLPixelFormatR32Uint:
case MTLPixelFormatR32Sint:
case MTLPixelFormatRG16Uint:
case MTLPixelFormatRG16Sint:
case MTLPixelFormatRGBA8Uint:
case MTLPixelFormatRGBA8Sint:
case MTLPixelFormatRGB10A2Uint:
case MTLPixelFormatRG32Uint:
case MTLPixelFormatRG32Sint:
case MTLPixelFormatRGBA16Uint:
case MTLPixelFormatRGBA16Sint:
case MTLPixelFormatRGBA32Uint:
case MTLPixelFormatRGBA32Sint:
return true;
default:
return false;
}
}
constexpr inline MTLTextureType getMetalType(SamplerType target) {
switch (target) {
case SamplerType::SAMPLER_2D:

View File

@@ -352,8 +352,7 @@ MetalProgram::MetalProgram(id<MTLDevice> device, const Program& program) noexcep
length:source.size()
encoding:NSUTF8StringEncoding];
NSError* error = nil;
MTLCompileOptions* options = [MTLCompileOptions new];
options.languageVersion = MTLLanguageVersion1_1;
// When options is nil, Metal uses the most recent language version available.
id<MTLLibrary> library = [device newLibraryWithSource:objcSource
options:nil
error:&error];

View File

@@ -117,8 +117,8 @@ Handle<HwStream> NoopDriver::createStreamAcquired() {
return {};
}
void NoopDriver::setAcquiredImage(Handle<HwStream> sh, void* image, backend::StreamCallback cb,
void* userData) {
void NoopDriver::setAcquiredImage(Handle<HwStream> sh, void* image,
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
}
void NoopDriver::setStreamDimensions(Handle<HwStream> sh, uint32_t width, uint32_t height) {
@@ -160,6 +160,10 @@ bool NoopDriver::isFrameBufferFetchSupported() {
return false;
}
bool NoopDriver::isFrameBufferFetchMultiSampleSupported() {
return false; // TODO: add support for MS framebuffer_fetch
}
bool NoopDriver::isFrameTimeSupported() {
return true;
}

View File

@@ -35,9 +35,7 @@ OpenGLContext::OpenGLContext() noexcept {
UTILS_UNUSED char const* const version = (char const*) glGetString(GL_VERSION);
UTILS_UNUSED char const* const shader = (char const*) glGetString(GL_SHADING_LANGUAGE_VERSION);
#ifndef NDEBUG
slog.i << vendor << ", " << renderer << ", " << version << ", " << shader << io::endl;
#endif
slog.v << "[" << vendor << "], [" << renderer << "], [" << version << "], [" << shader << "]" << io::endl;
// OpenGL (ES) version
GLint major = 0;
@@ -77,12 +75,29 @@ OpenGLContext::OpenGLContext() noexcept {
// Figure out which driver bugs we need to workaround
if (strstr(renderer, "Adreno")) {
int maj, min, driverMajor, driverMinor;
int c = sscanf(version, "OpenGL ES %d.%d V@%d.%d", // NOLINT(cert-err34-c)
&maj, &min, &driverMajor, &driverMinor);
if (c == 4) {
// workarounds based on version here.
// notes:
// bugs.invalidate_end_only_if_invalidate_start
// - appeared at least in "OpenGL ES 3.2 V@0490.0 (GIT@85da404, I46ff5fc46f, 1606794520) (Date:11/30/20)"
// - wasn't present in "OpenGL ES 3.2 V@0490.0 (GIT@0905e9f, Ia11ce2d146, 1599072951) (Date:09/02/20)"
}
// On Adreno (As of 3/20) timer query seem to return the CPU time, not the GPU time.
bugs.dont_use_timer_query = true;
// Blits to texture arrays are failing
bugs.disable_sidecar_blit_into_texture_array = true;
// This bug doesn't happen anymore, but we don't know why. The standalone sample
// app that was written to show this problem still does. We have tested this on
// several V@0490.0 on several devices and the problem appears to have gone away.
// The working hypthesis is that some other state affects this behavior.
bugs.disable_sidecar_blit_into_texture_array = false;
// early exit condition is flattened in EASU code
bugs.split_easu = true;
bugs.invalidate_end_only_if_invalidate_start = true;
} else if (strstr(renderer, "Mali")) {
bugs.vao_doesnt_store_element_array_buffer_binding = true;
if (strstr(renderer, "Mali-T")) {
@@ -105,6 +120,14 @@ OpenGLContext::OpenGLContext() noexcept {
bugs.disable_invalidate_framebuffer = true;
}
slog.v << "Active workarounds: " << '\n';
for (auto [enabled, name, _] : mBugDatabase) {
if (enabled) {
slog.v << name << '\n';
}
}
flush(slog.v);
// now we can query getter and features
glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &gets.max_renderbuffer_size);
glGetIntegerv(GL_MAX_UNIFORM_BLOCK_SIZE, &gets.max_uniform_block_size);
@@ -119,16 +142,16 @@ OpenGLContext::OpenGLContext() noexcept {
assert_invariant(gets.max_draw_buffers >= 4); // minspec
#if 0
// this is useful for development, but too verbose even for debug builds
slog.i
<< "GL_MAX_DRAW_BUFFERS = " << gets.max_draw_buffers << '\n'
#ifndef NDEBUG
// this is useful for development
slog.v << "GL_MAX_DRAW_BUFFERS = " << gets.max_draw_buffers << '\n'
<< "GL_MAX_RENDERBUFFER_SIZE = " << gets.max_renderbuffer_size << '\n'
<< "GL_MAX_SAMPLES = " << gets.max_samples << '\n'
<< "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = " << gets.max_anisotropy << '\n'
<< "GL_MAX_UNIFORM_BLOCK_SIZE = " << gets.max_uniform_block_size << '\n'
<< "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = " << gets.uniform_buffer_offset_alignment << '\n'
<< io::endl;
;
flush(slog.v);
#endif
/*

View File

@@ -26,7 +26,9 @@
#include "GLUtils.h"
#include <array>
#include <set>
#include <utility>
namespace filament {
@@ -192,8 +194,48 @@ public:
// Some drivers incorrectly flatten the early exit condition in the EASU code, in which
// case we need an alternative algorithm
bool split_easu = false;
// As of Android R some qualcomm drivers invalidate buffers for the whole render pass
// even if glInvalidateFramebuffer() is called at the end of it.
bool invalidate_end_only_if_invalidate_start = false;
} bugs;
const std::array<std::tuple<bool const&, char const*, char const*>, sizeof(bugs)> mBugDatabase{{
{ bugs.disable_glFlush,
"disable_glFlush",
""},
{ bugs.vao_doesnt_store_element_array_buffer_binding,
"vao_doesnt_store_element_array_buffer_binding",
""},
{ bugs.disable_shared_context_draws,
"disable_shared_context_draws",
""},
{ bugs.texture_external_needs_rebind,
"texture_external_needs_rebind",
""},
{ bugs.disable_invalidate_framebuffer,
"disable_invalidate_framebuffer",
""},
{ bugs.texture_filter_anisotropic_broken_on_sampler,
"texture_filter_anisotropic_broken_on_sampler",
""},
{ bugs.disable_feedback_loops,
"disable_feedback_loops",
""},
{ bugs.dont_use_timer_query,
"dont_use_timer_query",
""},
{ bugs.disable_sidecar_blit_into_texture_array,
"disable_sidecar_blit_into_texture_array",
""},
{ bugs.split_easu,
"split_easu",
""},
{ bugs.invalidate_end_only_if_invalidate_start,
"invalidate_end_only_if_invalidate_start",
""},
}};
// state getters -- as needed.
GLuint getDrawFbo() const noexcept { return state.draw_fbo; }
vec4gli const& getViewport() const { return state.window.viewport; }

View File

@@ -1360,13 +1360,14 @@ Handle<HwStream> OpenGLDriver::createStreamAcquired() {
// called only once per frame. If the user pushes images to the same stream multiple times in a
// single frame, we emit a warning and honor only the final image, but still invoke all callbacks.
void OpenGLDriver::setAcquiredImage(Handle<HwStream> sh, void* hwbuffer,
backend::StreamCallback cb, void* userData) {
backend::CallbackHandler* handler, backend::StreamCallback cb, void* userData) {
GLStream* glstream = handle_cast<GLStream*>(sh);
if (glstream->user_thread.pending.image) {
scheduleRelease(std::move(glstream->user_thread.pending));
scheduleRelease(glstream->user_thread.pending);
slog.w << "Acquired image is set more than once per frame." << io::endl;
}
glstream->user_thread.pending = mPlatform.transformAcquiredImage({hwbuffer, cb, userData});
glstream->user_thread.pending = mPlatform.transformAcquiredImage({
hwbuffer, cb, userData, handler });
}
void OpenGLDriver::updateStreams(DriverApi* driver) {
@@ -1552,6 +1553,10 @@ bool OpenGLDriver::isFrameBufferFetchSupported() {
return gl.ext.EXT_shader_framebuffer_fetch;
}
bool OpenGLDriver::isFrameBufferFetchMultiSampleSupported() {
return isFrameBufferFetchSupported();
}
bool OpenGLDriver::isFrameTimeSupported() {
return mFrameTimeSupported;
}
@@ -2299,11 +2304,15 @@ void OpenGLDriver::endRenderPass(int) {
// glInvalidateFramebuffer appeared on GLES 3.0 and GL4.3, for simplicity we just
// ignore it on GL (rather than having to do a runtime check).
if (GLES30_HEADERS) {
auto effectiveDiscardFlags = discardFlags;
if (gl.bugs.invalidate_end_only_if_invalidate_start) {
effectiveDiscardFlags &= mRenderPassParams.flags.discardStart;
}
if (!gl.bugs.disable_invalidate_framebuffer) {
// we wouldn't have to bind the framebuffer if we had glInvalidateNamedFramebuffer()
gl.bindFramebuffer(GL_FRAMEBUFFER, rt->gl.fbo);
AttachmentArray attachments; // NOLINT
GLsizei attachmentCount = getAttachments(attachments, rt, discardFlags);
GLsizei attachmentCount = getAttachments(attachments, rt, effectiveDiscardFlags);
if (attachmentCount) {
glInvalidateFramebuffer(GL_FRAMEBUFFER, attachmentCount, attachments.data());
}
@@ -2750,7 +2759,7 @@ void OpenGLDriver::insertEventMarker(char const* string, uint32_t len) {
#endif
}
void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
#ifdef GL_EXT_debug_marker
auto& gl = mContext;
if (UTILS_LIKELY(gl.ext.EXT_debug_marker)) {
@@ -2834,6 +2843,7 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
glBufferData(GL_PIXEL_PACK_BUFFER, p.size, nullptr, GL_STATIC_DRAW);
glReadPixels(GLint(x), GLint(y), GLint(width), GLint(height), glFormat, glType, nullptr);
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
CHECK_GL_ERROR(utils::slog.e)
// we're forced to make a copy on the heap because otherwise it deletes std::function<> copy
// constructor.
@@ -2865,8 +2875,6 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
delete pUserBuffer;
CHECK_GL_ERROR(utils::slog.e)
});
CHECK_GL_ERROR(utils::slog.e)
}
void OpenGLDriver::whenGpuCommandsComplete(std::function<void()> fn) noexcept {

View File

@@ -17,7 +17,7 @@
#ifndef FILAMENT_DRIVER_OPENGL_COCOA_TOUCH_EXTERNAL_IMAGE
#define FILAMENT_DRIVER_OPENGL_COCOA_TOUCH_EXTERNAL_IMAGE
#include "gl_headers.h"
#include "../gl_headers.h"
#include <CoreVideo/CoreVideo.h>

View File

@@ -21,7 +21,7 @@
#include <OpenGLES/ES3/gl.h>
#include <OpenGLES/ES3/glext.h>
#include "GLUtils.h"
#include "../GLUtils.h"
#include <math/vec2.h>

View File

@@ -37,10 +37,12 @@ static void loadSymbol(T*& pfn, const char *symbol) noexcept {
pfn = (T*)dlsym(RTLD_DEFAULT, symbol);
}
ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::get() noexcept {
// declaring this thread local, will ensure it's destroyed with the calling thread
static thread_local ExternalStreamManagerAndroid instance;
return instance;
ExternalStreamManagerAndroid& ExternalStreamManagerAndroid::create() noexcept {
return *(new ExternalStreamManagerAndroid{});
}
void ExternalStreamManagerAndroid::destroy(ExternalStreamManagerAndroid* pExternalStreamManagerAndroid) noexcept {
delete pExternalStreamManagerAndroid;
}
ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
@@ -61,6 +63,8 @@ ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
}
}
ExternalStreamManagerAndroid::~ExternalStreamManagerAndroid() noexcept = default;
UTILS_NOINLINE
JNIEnv* ExternalStreamManagerAndroid::getEnvironmentSlow() noexcept {
JNIEnv * env = mVm.getEnvironment();

View File

@@ -17,7 +17,7 @@
#ifndef TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_STREAM_MANAGER_ANDROID_H
#define TNT_FILAMENT_DRIVER_ANDROID_EXTERNAL_STREAM_MANAGER_ANDROID_H
#include "android/VirtualMachineEnv.h"
#include "private/backend/VirtualMachineEnv.h"
#include <backend/Platform.h>
@@ -31,20 +31,37 @@ typedef struct ASurfaceTexture ASurfaceTexture;
namespace filament {
/*
* ExternalStreamManagerAndroid::Stream is basically a wrapper for SurfaceTexture.
*
* This class DOES DEPEND on having a GLES context, because that's how SurfaceTexture works.
*/
class ExternalStreamManagerAndroid {
public:
using Stream = backend::Platform::Stream;
ExternalStreamManagerAndroid() noexcept;
static ExternalStreamManagerAndroid& get() noexcept;
// must be called on GLES thread
static ExternalStreamManagerAndroid& create() noexcept;
// must be called on GLES thread
static void destroy(ExternalStreamManagerAndroid* pExternalStreamManagerAndroid) noexcept;
Stream* acquire(jobject surfaceTexture) noexcept;
void release(Stream* stream) noexcept;
// attach Stream to current GLES context
void attach(Stream* stream, intptr_t tname) noexcept;
// detach Stream to current GLES context
void detach(Stream* stream) noexcept;
// must be called on GLES context thread, updates the stream content
void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
private:
ExternalStreamManagerAndroid() noexcept;
~ExternalStreamManagerAndroid() noexcept;
VirtualMachineEnv& mVm;
JNIEnv* mJniEnv = nullptr;
@@ -63,17 +80,17 @@ private:
JNIEnv* getEnvironmentSlow() noexcept;
jmethodID mSurfaceTextureClass_updateTexImage;
jmethodID mSurfaceTextureClass_getTimestamp;
jmethodID mSurfaceTextureClass_attachToGLContext;
jmethodID mSurfaceTextureClass_detachFromGLContext;
jmethodID mSurfaceTextureClass_updateTexImage{};
jmethodID mSurfaceTextureClass_getTimestamp{};
jmethodID mSurfaceTextureClass_attachToGLContext{};
jmethodID mSurfaceTextureClass_detachFromGLContext{};
ASurfaceTexture* (*ASurfaceTexture_fromSurfaceTexture)(JNIEnv*, jobject);
void (*ASurfaceTexture_release)(ASurfaceTexture*);
int (*ASurfaceTexture_attachToGLContext)(ASurfaceTexture*, uint32_t);
int (*ASurfaceTexture_detachFromGLContext)(ASurfaceTexture*);
int (*ASurfaceTexture_updateTexImage)(ASurfaceTexture*);
int64_t (*ASurfaceTexture_getTimestamp)(ASurfaceTexture*); // available since api 28
ASurfaceTexture* (*ASurfaceTexture_fromSurfaceTexture)(JNIEnv*, jobject){};
void (*ASurfaceTexture_release)(ASurfaceTexture*){};
int (*ASurfaceTexture_attachToGLContext)(ASurfaceTexture*, uint32_t){};
int (*ASurfaceTexture_detachFromGLContext)(ASurfaceTexture*){};
int (*ASurfaceTexture_updateTexImage)(ASurfaceTexture*){};
int64_t (*ASurfaceTexture_getTimestamp)(ASurfaceTexture*){}; // available since api 28
};
} // namespace filament

View File

@@ -19,8 +19,8 @@
#include "PlatformCocoaGL.h"
#include "OpenGLDriverFactory.h"
#include "gl_headers.h"
#include "opengl/OpenGLDriverFactory.h"
#include "opengl/gl_headers.h"
#include <utils/compiler.h>
#include <utils/Panic.h>

View File

@@ -30,9 +30,9 @@
#include <utils/Panic.h>
#include "OpenGLDriverFactory.h"
#include "../OpenGLDriverFactory.h"
#include "OpenGLDriver.h"
#include "../OpenGLDriver.h"
#include "CocoaTouchExternalImage.h"
namespace filament {

View File

@@ -16,9 +16,9 @@
#include "PlatformEGL.h"
#include "OpenGLDriver.h"
#include "OpenGLContext.h"
#include "OpenGLDriverFactory.h"
#include "opengl/OpenGLDriver.h"
#include "opengl/OpenGLContext.h"
#include "opengl/OpenGLDriverFactory.h"
#include <EGL/egl.h>
#include <EGL/eglext.h>

View File

@@ -16,12 +16,12 @@
#include "PlatformEGLAndroid.h"
#include "OpenGLDriver.h"
#include "OpenGLContext.h"
#include "opengl/OpenGLDriver.h"
#include "opengl/OpenGLContext.h"
#include "android/ExternalTextureManagerAndroid.h"
#include "android/ExternalStreamManagerAndroid.h"
#include "android/VirtualMachineEnv.h"
#include "ExternalStreamManagerAndroid.h"
#include "private/backend/VirtualMachineEnv.h"
#include <android/api-level.h>
@@ -73,8 +73,8 @@ using EGLStream = Platform::Stream;
PlatformEGLAndroid::PlatformEGLAndroid() noexcept
: PlatformEGL(),
mExternalStreamManager(ExternalStreamManagerAndroid::get()),
mExternalTextureManager(ExternalTextureManagerAndroid::get()) {
mExternalStreamManager(ExternalStreamManagerAndroid::create()),
mExternalTextureManager(ExternalTextureManagerAndroid::create()) {
char scratch[PROP_VALUE_MAX + 1];
int length = __system_property_get("ro.build.version.release", scratch);
@@ -87,8 +87,17 @@ PlatformEGLAndroid::PlatformEGLAndroid() noexcept
}
}
backend::Driver* PlatformEGLAndroid::createDriver(void* sharedContext) noexcept {
backend::Driver* driver = PlatformEGL::createDriver(sharedContext);
PlatformEGLAndroid::~PlatformEGLAndroid() noexcept = default;
void PlatformEGLAndroid::terminate() noexcept {
ExternalStreamManagerAndroid::destroy(&mExternalStreamManager);
ExternalTextureManagerAndroid::destroy(&mExternalTextureManager);
PlatformEGL::terminate();
}
Driver* PlatformEGLAndroid::createDriver(void* sharedContext) noexcept {
Driver* driver = PlatformEGL::createDriver(sharedContext);
auto extensions = GLUtils::split(eglQueryString(mEGLDisplay, EGL_EXTENSIONS));
eglGetNativeClientBufferANDROID = (PFNEGLGETNATIVECLIENTBUFFERANDROIDPROC) eglGetProcAddress("eglGetNativeClientBufferANDROID");
@@ -146,12 +155,12 @@ void PlatformEGLAndroid::updateTexImage(Stream* stream, int64_t* timestamp) noex
}
Platform::ExternalTexture* PlatformEGLAndroid::createExternalTextureStorage() noexcept {
return mExternalTextureManager.create();
return mExternalTextureManager.createExternalTexture();
}
void PlatformEGLAndroid::reallocateExternalStorage(
Platform::ExternalTexture* externalTexture,
uint32_t w, uint32_t h, backend::TextureFormat format) noexcept {
uint32_t w, uint32_t h, TextureFormat format) noexcept {
if (externalTexture) {
if ((EGLImageKHR)externalTexture->image != EGL_NO_IMAGE_KHR) {
eglDestroyImageKHR(mEGLDisplay, (EGLImageKHR)externalTexture->image);
@@ -201,13 +210,9 @@ int PlatformEGLAndroid::getOSVersion() const noexcept {
return mOSVersion;
}
backend::AcquiredImage PlatformEGLAndroid::transformAcquiredImage(backend::AcquiredImage source) noexcept {
void* const hwbuffer = source.image;
const backend::StreamCallback userCallback = source.callback;
void* const userData = source.userData;
AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage source) noexcept {
// Convert the AHardwareBuffer to EGLImage.
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID((const AHardwareBuffer*) hwbuffer);
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID((const AHardwareBuffer*)source.image);
if (!clientBuffer) {
slog.e << "Unable to get EGLClientBuffer from AHardwareBuffer." << io::endl;
return {};
@@ -222,31 +227,22 @@ backend::AcquiredImage PlatformEGLAndroid::transformAcquiredImage(backend::Acqui
// Destroy the EGLImage before invoking the user's callback.
struct Closure {
void* image;
backend::StreamCallback callback;
void* userData;
Closure(AcquiredImage const& acquiredImage, EGLDisplay display)
: acquiredImage(acquiredImage), display(display) {}
AcquiredImage acquiredImage;
EGLDisplay display;
};
Closure* closure = new Closure();
closure->callback = userCallback;
closure->image = hwbuffer;
closure->userData = userData;
closure->display = mEGLDisplay;
Closure* closure = new Closure(source, mEGLDisplay);
auto patchedCallback = [](void* image, void* userdata) {
Closure* closure = (Closure*) userdata;
Closure* closure = (Closure*)userdata;
if (eglDestroyImageKHR(closure->display, (EGLImageKHR) image) == EGL_FALSE) {
slog.e << "eglDestroyImageKHR failed." << io::endl;
}
closure->callback(closure->image, closure->userData);
closure->acquiredImage.callback(closure->acquiredImage.image, closure->acquiredImage.userData);
delete closure;
};
return {eglImage, patchedCallback, closure};
}
// This must called when the library is loaded. We need this to get a reference to the global VM
void JNI_OnLoad(JavaVM* vm, void* reserved) {
::filament::VirtualMachineEnv::JNI_OnLoad(vm);
return { eglImage, patchedCallback, closure, source.handler };
}
} // namespace filament

View File

@@ -28,6 +28,9 @@ class PlatformEGLAndroid final : public PlatformEGL {
public:
PlatformEGLAndroid() noexcept;
~PlatformEGLAndroid() noexcept override;
void terminate() noexcept override;
backend::Driver* createDriver(void* sharedContext) noexcept final;

View File

@@ -23,7 +23,7 @@
#include <GL/glx.h>
#include <GL/glxext.h>
#include "OpenGLDriverFactory.h"
#include "../OpenGLDriverFactory.h"
#include <dlfcn.h>

View File

@@ -18,7 +18,7 @@
#include <Wingdi.h>
#include "OpenGLDriverFactory.h"
#include "../OpenGLDriverFactory.h"
#ifdef _MSC_VER
// this variable is checked in BlueGL.h (included from "gl_headers.h" right after this),
@@ -27,7 +27,7 @@
#define FILAMENT_PLATFORM_WGL
#endif
#include "gl_headers.h"
#include "../gl_headers.h"
#include "Windows.h"
#include <GL/gl.h>

View File

@@ -15,7 +15,7 @@
*/
#include "PlatformWebGL.h"
#include "OpenGLDriverFactory.h"
#include "../OpenGLDriverFactory.h"
namespace filament {

View File

@@ -38,30 +38,6 @@ struct BlitterUniforms {
float inverseSampleCount;
};
// Helper function for populating barrier fields based on the desired image layout.
// This logic is specific to blitting, please keep this private to VulkanBlitter.
static VulkanLayoutTransition transitionHelper(VulkanLayoutTransition transition) {
switch (transition.newLayout) {
case VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL:
case VK_IMAGE_LAYOUT_GENERAL:
transition.srcAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
transition.dstAccessMask = VK_ACCESS_SHADER_READ_BIT;
transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
transition.dstStage = VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
break;
case VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL:
case VK_IMAGE_LAYOUT_PRESENT_SRC_KHR:
default:
transition.srcAccessMask = VK_ACCESS_TRANSFER_READ_BIT;
transition.dstAccessMask = 0;
transition.srcStage = VK_PIPELINE_STAGE_TRANSFER_BIT;
transition.dstStage = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
break;
}
return transition;
}
void VulkanBlitter::blitColor(BlitArgs args) {
const VulkanAttachment src = args.srcTarget->getColor(mContext.currentSurface, args.targetIndex);
const VulkanAttachment dst = args.dstTarget->getColor(mContext.currentSurface, 0);
@@ -153,9 +129,15 @@ void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter,
const VkCommandBuffer cmdbuffer = mContext.commands->get().cmdbuffer;
VkImageLayout srcLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
if (src.texture) {
srcLayout = mContext.getTextureLayout(src.texture->usage);
}
transitionImageLayout(cmdbuffer, {
src.image,
VK_IMAGE_LAYOUT_UNDEFINED,
srcLayout,
VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
srcRange,
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT, 0,
@@ -180,21 +162,12 @@ void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter,
VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1, blitRegions, filter);
}
if (src.texture) {
transitionImageLayout(cmdbuffer, transitionHelper({
.image = src.image,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = mContext.getTextureLayout(src.texture->usage),
.subresources = srcRange
}));
} else if (!mContext.currentSurface->headlessQueue) {
transitionImageLayout(cmdbuffer, transitionHelper({
.image = src.image,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.newLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
.subresources = srcRange
}));
}
transitionImageLayout(cmdbuffer, blitterTransitionHelper({
.image = src.image,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
.newLayout = srcLayout,
.subresources = srcRange
}));
// Determine the desired texture layout for the destination while ensuring that the default
// render target is supported, which has no associated texture.
@@ -202,9 +175,9 @@ void VulkanBlitter::blitFast(VkImageAspectFlags aspect, VkFilter filter,
mContext.getTextureLayout(dst.texture->usage) :
mContext.currentSurface->getColor().layout;
transitionImageLayout(cmdbuffer, transitionHelper({
transitionImageLayout(cmdbuffer, blitterTransitionHelper({
.image = dst.image,
.oldLayout = VK_IMAGE_LAYOUT_UNDEFINED,
.oldLayout = VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,
.newLayout = desiredLayout,
.subresources = dstRange,
}));

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