Compare commits
402 Commits
bjd/debugg
...
v1.25.3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eedcd9f8cb | ||
|
|
ab252b210c | ||
|
|
1071b8ea90 | ||
|
|
a9c5bbf185 | ||
|
|
8dd4bff7a7 | ||
|
|
77c54446af | ||
|
|
4a0bc0af57 | ||
|
|
a171e75e70 | ||
|
|
f5ffa092fe | ||
|
|
8de5fdd551 | ||
|
|
ecca3abe98 | ||
|
|
8570e35224 | ||
|
|
84df9f9a03 | ||
|
|
5f93fb9613 | ||
|
|
75f77fdbdd | ||
|
|
7825d582c2 | ||
|
|
5deb0ba933 | ||
|
|
18e917aaf2 | ||
|
|
a165f3890a | ||
|
|
f88b6d9c97 | ||
|
|
db8ecd9952 | ||
|
|
b5ec06c2d2 | ||
|
|
dfbac8385e | ||
|
|
eaab737b2c | ||
|
|
45991cda0a | ||
|
|
09a016bb6f | ||
|
|
31607d355d | ||
|
|
a67d50b9e2 | ||
|
|
8d42f53c80 | ||
|
|
5e21a55bce | ||
|
|
85930ea2e8 | ||
|
|
4b3cde8b39 | ||
|
|
eedfa85355 | ||
|
|
bb54c6c807 | ||
|
|
c23f905858 | ||
|
|
8c7be0a1d0 | ||
|
|
878497b3d5 | ||
|
|
a155561769 | ||
|
|
8b86a0ed2e | ||
|
|
26f9a9b122 | ||
|
|
6e5f6978fb | ||
|
|
0d31d7b2de | ||
|
|
dd862b7e0a | ||
|
|
52065f2cbd | ||
|
|
77c02d5831 | ||
|
|
f7e4c8d16d | ||
|
|
b7410474ff | ||
|
|
384cc4ebf6 | ||
|
|
7c0643f122 | ||
|
|
58abae3067 | ||
|
|
4742693869 | ||
|
|
6c39e474ea | ||
|
|
5c8977c906 | ||
|
|
6b3cc2e2f3 | ||
|
|
76b2edd6ea | ||
|
|
8ebb37d011 | ||
|
|
3366db83ef | ||
|
|
5415254aac | ||
|
|
caacc61602 | ||
|
|
e902df19b2 | ||
|
|
40b372dda7 | ||
|
|
fd330a98aa | ||
|
|
90c23a7d5d | ||
|
|
5710304114 | ||
|
|
0f684820bc | ||
|
|
e1d2d6ade6 | ||
|
|
e0b6f2ca71 | ||
|
|
2a35ee279b | ||
|
|
5abf780360 | ||
|
|
181f158ea9 | ||
|
|
f4087fc81d | ||
|
|
82793f9b82 | ||
|
|
537576e84a | ||
|
|
375d1f55e3 | ||
|
|
597218963f | ||
|
|
0d29b3ddc8 | ||
|
|
e0e3b42623 | ||
|
|
0995ca6614 | ||
|
|
3d741fc8d4 | ||
|
|
c20772b458 | ||
|
|
4a6b659098 | ||
|
|
2b93f08ca5 | ||
|
|
fca62b8fff | ||
|
|
dee6d9de2c | ||
|
|
574e3e7521 | ||
|
|
29fdf82ac5 | ||
|
|
c8cf2a54e8 | ||
|
|
bfd32e67d4 | ||
|
|
95915367fa | ||
|
|
b769cfda62 | ||
|
|
40ac88dfed | ||
|
|
6d96082f07 | ||
|
|
21f913db1c | ||
|
|
699a578966 | ||
|
|
babbfa1394 | ||
|
|
73f0d58e10 | ||
|
|
9cb4b74bbd | ||
|
|
f2c8456971 | ||
|
|
e571600c30 | ||
|
|
e84c94d3eb | ||
|
|
e791d4818f | ||
|
|
cdadb43e50 | ||
|
|
edaff60fbf | ||
|
|
3f64e46557 | ||
|
|
32dab23bc6 | ||
|
|
362de7dd31 | ||
|
|
6b01fbb903 | ||
|
|
4934d9f7bc | ||
|
|
ed73955b00 | ||
|
|
3f1f2726c4 | ||
|
|
1a7bd7ea8d | ||
|
|
946ea43436 | ||
|
|
7f42385f5f | ||
|
|
8845ac2b75 | ||
|
|
da85001d4d | ||
|
|
8d15079937 | ||
|
|
adc542b5cd | ||
|
|
72feb044a3 | ||
|
|
c0ba260ddf | ||
|
|
2da215e8e7 | ||
|
|
4d0368b5f1 | ||
|
|
d11c78857d | ||
|
|
e829d90c4a | ||
|
|
a8006acd33 | ||
|
|
86ec502040 | ||
|
|
b19a73cc50 | ||
|
|
a99c695932 | ||
|
|
8cd720b53a | ||
|
|
04df79e58f | ||
|
|
a4b3717762 | ||
|
|
1035e442ee | ||
|
|
60d3638f15 | ||
|
|
3e7d3c9035 | ||
|
|
eb360be2ad | ||
|
|
485ac8704d | ||
|
|
dc74540423 | ||
|
|
96219c22db | ||
|
|
f3b7048775 | ||
|
|
aaed6fb376 | ||
|
|
35a5d3310f | ||
|
|
9da79a1d2d | ||
|
|
595b355d1b | ||
|
|
3a67d769f4 | ||
|
|
6fb536a937 | ||
|
|
bb460d78d8 | ||
|
|
838835a715 | ||
|
|
63acd53e23 | ||
|
|
fcd2d0457b | ||
|
|
58fc26461b | ||
|
|
fd82f6b04e | ||
|
|
cef3200533 | ||
|
|
634500c398 | ||
|
|
b3e294ac54 | ||
|
|
2bf7535ad0 | ||
|
|
3315f75de9 | ||
|
|
bbe7dbfa92 | ||
|
|
5697922a65 | ||
|
|
4da83df2b9 | ||
|
|
8f156d6588 | ||
|
|
cec0871c11 | ||
|
|
41a809368b | ||
|
|
ea53eb9290 | ||
|
|
05875057c9 | ||
|
|
44125926d1 | ||
|
|
60734349de | ||
|
|
fbfd5ec0ec | ||
|
|
a74a95cc65 | ||
|
|
bc0ea16ff0 | ||
|
|
b2dc8aa84c | ||
|
|
9987e8b6ab | ||
|
|
0d9bdcc008 | ||
|
|
b5c634045e | ||
|
|
1f05531d53 | ||
|
|
88f382f0e3 | ||
|
|
3e59925900 | ||
|
|
ea404f8d4f | ||
|
|
602a550d93 | ||
|
|
12abbe2d23 | ||
|
|
fb0ee97588 | ||
|
|
56ef48c9c3 | ||
|
|
47c3dd3dd1 | ||
|
|
c181648bfa | ||
|
|
0cf78b3abe | ||
|
|
22889a7ad9 | ||
|
|
a14451d0ac | ||
|
|
5dfdab10b7 | ||
|
|
d6f2e3b8e9 | ||
|
|
df30517743 | ||
|
|
8f80643c1a | ||
|
|
5aea9be2fb | ||
|
|
ad02e483d0 | ||
|
|
f463d53036 | ||
|
|
b8d4408524 | ||
|
|
fef70be848 | ||
|
|
bdb12d9b24 | ||
|
|
43ad283a83 | ||
|
|
2e4936afc4 | ||
|
|
891ffabd11 | ||
|
|
e2c19498b4 | ||
|
|
c32630b265 | ||
|
|
bf21e78d02 | ||
|
|
525d4e08a3 | ||
|
|
2e9bf6d694 | ||
|
|
e845f01d85 | ||
|
|
bef48be7b4 | ||
|
|
b54fdc9e6e | ||
|
|
cedbf2e30b | ||
|
|
592f8d1b0d | ||
|
|
29612a684e | ||
|
|
e6d5807399 | ||
|
|
fa2553251f | ||
|
|
7387718852 | ||
|
|
a503a6209a | ||
|
|
ce3e5f74e8 | ||
|
|
f37112358e | ||
|
|
f368b14621 | ||
|
|
6960b1148a | ||
|
|
3cc23aac25 | ||
|
|
11dc8740f2 | ||
|
|
4b797cff88 | ||
|
|
fe1c1736cd | ||
|
|
4058ef5f09 | ||
|
|
d25ca01624 | ||
|
|
d96f87dbbf | ||
|
|
8a2e31023f | ||
|
|
1ea8e171d9 | ||
|
|
e2be3dd0ac | ||
|
|
1c51164e7b | ||
|
|
f190f03530 | ||
|
|
055fc7cbc1 | ||
|
|
9073fc3dc3 | ||
|
|
2409dc9bc4 | ||
|
|
6586c8d70b | ||
|
|
ac0c94da69 | ||
|
|
d19d6a72b0 | ||
|
|
c81b5d98ef | ||
|
|
756866675f | ||
|
|
ebcd4925f7 | ||
|
|
13bed4fdf9 | ||
|
|
1dae5c6b6c | ||
|
|
8e6663e4b0 | ||
|
|
ba804444b8 | ||
|
|
58cfb85004 | ||
|
|
ab46481b45 | ||
|
|
4296782399 | ||
|
|
ef375a7103 | ||
|
|
fd258b7765 | ||
|
|
147de8d372 | ||
|
|
eb2a1928b6 | ||
|
|
35b033102f | ||
|
|
7bc65421a9 | ||
|
|
736514cf37 | ||
|
|
db0158dae8 | ||
|
|
e706695ed1 | ||
|
|
e8877ffe2d | ||
|
|
1fd5d9dae6 | ||
|
|
cd48089318 | ||
|
|
6379ab22c9 | ||
|
|
0bf02b75d5 | ||
|
|
c4259b5598 | ||
|
|
6b3c1179bc | ||
|
|
c1a0e61e8e | ||
|
|
fc06298ed4 | ||
|
|
4ca87b188c | ||
|
|
f1f60c3e0d | ||
|
|
76d21b56af | ||
|
|
0ab0e50a4f | ||
|
|
34f4c06a5c | ||
|
|
6de36f1e53 | ||
|
|
2a9a3b1ac2 | ||
|
|
84b73a3770 | ||
|
|
662a10e273 | ||
|
|
ecce02502e | ||
|
|
d17875aea1 | ||
|
|
b8897a68f9 | ||
|
|
84efd4871e | ||
|
|
85ea5a6b70 | ||
|
|
77891acb92 | ||
|
|
74fe102035 | ||
|
|
25cc554925 | ||
|
|
d787a521b5 | ||
|
|
46e52c71e1 | ||
|
|
1dad27a172 | ||
|
|
60d230b380 | ||
|
|
d7cb38e706 | ||
|
|
ce00cca6ee | ||
|
|
d627d57bad | ||
|
|
8ffc776f1c | ||
|
|
be032b52c1 | ||
|
|
4388e81e5f | ||
|
|
71a185d139 | ||
|
|
d2cf5985ac | ||
|
|
debcbb8e5c | ||
|
|
b9dd62c7d3 | ||
|
|
dc2b430f34 | ||
|
|
e5ef4e8868 | ||
|
|
c0d6cd3ac3 | ||
|
|
b63ab2dc19 | ||
|
|
5d8dad561c | ||
|
|
8933be1ae2 | ||
|
|
6b66b48b1d | ||
|
|
9c23eb6e33 | ||
|
|
baea54a3fc | ||
|
|
d9f800454c | ||
|
|
f9ee0de07a | ||
|
|
2786d0a9f7 | ||
|
|
491e8032e6 | ||
|
|
ef3f13f5d3 | ||
|
|
bcb5b2d790 | ||
|
|
02de3f2e2a | ||
|
|
0e7bb53c07 | ||
|
|
759109d478 | ||
|
|
54d5af6edf | ||
|
|
38fbe47ced | ||
|
|
f066c925ba | ||
|
|
994fdf4e1d | ||
|
|
50b50d65e3 | ||
|
|
0aaa985649 | ||
|
|
29564f8eae | ||
|
|
c15db68a5b | ||
|
|
3452fb3e56 | ||
|
|
35eb8e7be1 | ||
|
|
834b774128 | ||
|
|
5aa0eb9f9d | ||
|
|
d9a6e2e649 | ||
|
|
cb823b16a1 | ||
|
|
0bd41e877e | ||
|
|
ecc3e73967 | ||
|
|
464b4c24f9 | ||
|
|
32367516e8 | ||
|
|
1709a55606 | ||
|
|
58b4455979 | ||
|
|
ea1dede19c | ||
|
|
20ea3381fa | ||
|
|
7aa6fccd7c | ||
|
|
adbd54f4f8 | ||
|
|
9d54261f18 | ||
|
|
a97757c9ae | ||
|
|
7c79d9f89d | ||
|
|
bf0914f813 | ||
|
|
b96bc30fbd | ||
|
|
62b50eb8ba | ||
|
|
b4932e384a | ||
|
|
5e68dc5f8d | ||
|
|
f222f1b925 | ||
|
|
22e4a54782 | ||
|
|
1289922c5f | ||
|
|
2839c352b8 | ||
|
|
6a01cbc312 | ||
|
|
6193156556 | ||
|
|
fe23aa917d | ||
|
|
eb8a29a332 | ||
|
|
0626902530 | ||
|
|
042bfe2597 | ||
|
|
97133f3591 | ||
|
|
d06cc4390e | ||
|
|
6047d3235f | ||
|
|
2cda6e35bd | ||
|
|
8f8d51e17b | ||
|
|
6919e3b274 | ||
|
|
10bf944410 | ||
|
|
9a2f6fdb53 | ||
|
|
761977d385 | ||
|
|
21248f15b5 | ||
|
|
4f32817f6d | ||
|
|
cc9e05e711 | ||
|
|
419d68d4db | ||
|
|
8450232448 | ||
|
|
cc51726590 | ||
|
|
318e22af51 | ||
|
|
68ac87dc24 | ||
|
|
acb8f00075 | ||
|
|
06d9183aaa | ||
|
|
75af25419d | ||
|
|
f6b90d2a31 | ||
|
|
a3822f4af0 | ||
|
|
bcdad769ff | ||
|
|
be4fb4fdbb | ||
|
|
65394f6301 | ||
|
|
b0beee03bc | ||
|
|
fe1de41b8e | ||
|
|
a37b431e87 | ||
|
|
98107016b9 | ||
|
|
8bccfc2863 | ||
|
|
f54a0a3452 | ||
|
|
6778ab0624 | ||
|
|
269d636785 | ||
|
|
39862c91ce | ||
|
|
523f4026b4 | ||
|
|
a6bf162431 | ||
|
|
826e8d181c | ||
|
|
16dfadbba0 | ||
|
|
5cbb97551f | ||
|
|
defee767c3 | ||
|
|
9560318521 | ||
|
|
ef09feb048 | ||
|
|
39f323fe09 | ||
|
|
11b95304ea | ||
|
|
b7c30a7916 | ||
|
|
4cae48fc77 | ||
|
|
d1a93f0557 | ||
|
|
b93059fad7 |
20
.github/workflows/release.yml
vendored
20
.github/workflows/release.yml
vendored
@@ -39,8 +39,8 @@ jobs:
|
||||
run: |
|
||||
REF=${RELEASE_TAG:-${GITHUB_REF}}
|
||||
TAG=${REF##*/}
|
||||
echo "ref=${REF}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=ref::${REF}
|
||||
echo ::set-output name=tag::${TAG}
|
||||
- uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
@@ -69,8 +69,8 @@ jobs:
|
||||
run: |
|
||||
REF=${RELEASE_TAG:-${GITHUB_REF}}
|
||||
TAG=${REF##*/}
|
||||
echo "ref=${REF}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=ref::${REF}
|
||||
echo ::set-output name=tag::${TAG}
|
||||
- uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
@@ -97,8 +97,8 @@ jobs:
|
||||
run: |
|
||||
REF=${RELEASE_TAG:-${GITHUB_REF}}
|
||||
TAG=${REF##*/}
|
||||
echo "ref=${REF}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=ref::${REF}
|
||||
echo ::set-output name=tag::${TAG}
|
||||
- uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
@@ -143,8 +143,8 @@ jobs:
|
||||
run: |
|
||||
REF=${RELEASE_TAG:-${GITHUB_REF}}
|
||||
TAG=${REF##*/}
|
||||
echo "ref=${REF}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=ref::${REF}
|
||||
echo ::set-output name=tag::${TAG}
|
||||
- uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
ref: ${{ steps.git_ref.outputs.ref }}
|
||||
@@ -171,8 +171,8 @@ jobs:
|
||||
run: |
|
||||
REF=${RELEASE_TAG:-${GITHUB_REF}}
|
||||
TAG=${REF##*/}
|
||||
echo "ref=${REF}" >> $GITHUB_OUTPUT
|
||||
echo "tag=${TAG}" >> $GITHUB_OUTPUT
|
||||
echo ::set-output name=ref::${REF}
|
||||
echo ::set-output name=tag::${TAG}
|
||||
shell: bash
|
||||
- uses: actions/checkout@v2.0.0
|
||||
with:
|
||||
|
||||
12
BUILDING.md
12
BUILDING.md
@@ -15,7 +15,7 @@ To build Filament for Android you must also install the following:
|
||||
|
||||
- Android Studio Arctic Fox or more recent
|
||||
- Android SDK
|
||||
- Android NDK 25.1 or higher
|
||||
- Android NDK "side-by-side" 23.1 or higher
|
||||
|
||||
### Environment variables
|
||||
|
||||
@@ -352,7 +352,7 @@ same version that our continuous builds use.
|
||||
|
||||
```
|
||||
cd <your chosen parent folder for the emscripten SDK>
|
||||
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.15.zip > emsdk.zip
|
||||
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.9.zip > emsdk.zip
|
||||
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
|
||||
python ./emsdk.py install latest
|
||||
python ./emsdk.py activate latest
|
||||
@@ -368,11 +368,13 @@ export EMSDK=<your chosen home for the emscripten SDK>
|
||||
|
||||
The EMSDK variable is required so that the build script can find the Emscripten SDK. The build
|
||||
creates a `samples` folder that can be used as the root of a simple static web server. Note that you
|
||||
cannot open the HTML directly from the filesystem due to CORS. We recommend using the emrun tool
|
||||
to create a quick localhost server:
|
||||
cannot open the HTML directly from the filesystem due to CORS. One way to deal with this is to
|
||||
use Python to create a quick localhost server:
|
||||
|
||||
```
|
||||
emrun out/cmake-webgl-release/web/samples --no_browser --port 8000
|
||||
cd out/cmake-webgl-release/web/samples
|
||||
python3 -m http.server # Python 3
|
||||
python -m SimpleHTTPServer # Python 2.7
|
||||
```
|
||||
|
||||
You can then open http://localhost:8000/suzanne.html in your web browser.
|
||||
|
||||
@@ -35,16 +35,16 @@ set(FILAMENT_NDK_VERSION "" CACHE STRING
|
||||
"Android NDK version or version prefix to be used when building for Android."
|
||||
)
|
||||
|
||||
set(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB "3" CACHE STRING
|
||||
"Per render pass arena size. Must be roughly 1 MB larger than FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, default 3."
|
||||
set(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB "2" CACHE STRING
|
||||
"Per render pass arena size. Must be roughly 1 MB larger than FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB, default 2."
|
||||
)
|
||||
|
||||
set(FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB "2" CACHE STRING
|
||||
"Size of the high-level draw commands buffer. Rule of thumb, 1 MB less than FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB, default 2."
|
||||
set(FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB "1" CACHE STRING
|
||||
"Size of the high-level draw commands buffer. Rule of thumb, 1 MB less than FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB, default 1."
|
||||
)
|
||||
|
||||
set(FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB "2" CACHE STRING
|
||||
"Size of the command-stream buffer. As a rule of thumb use the same value as FILAMENT_PER_FRRAME_COMMANDS_SIZE_IN_MB, default 2."
|
||||
set(FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB "1" CACHE STRING
|
||||
"Size of the command-stream buffer. As a rule of thumb use the same value as FILAMENT_PER_FRRAME_COMMANDS_SIZE_IN_MB, default 1."
|
||||
)
|
||||
|
||||
set(FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB "4" CACHE STRING
|
||||
@@ -337,23 +337,19 @@ endif()
|
||||
# ==================================================================================================
|
||||
# Release compiler flags
|
||||
# ==================================================================================================
|
||||
if (NOT MSVC AND NOT IOS)
|
||||
# Omitting stack frame pointers prevents the generation of readable stack traces in crash reports on iOS
|
||||
if (NOT MSVC)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fomit-frame-pointer")
|
||||
|
||||
# These aren't compatible with -fembed-bitcode (and seem to have no effect on Apple platforms anyway)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
|
||||
if (NOT IOS)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -ffunction-sections -fdata-sections")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# On Android RELEASE builds, we disable exceptions and RTTI to save some space (about 75 KiB
|
||||
# saved by -fno-exception and 10 KiB saved by -fno-rtti).
|
||||
if (ANDROID OR IOS OR WEBGL)
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-rtti")
|
||||
|
||||
if (ANDROID OR WEBGL)
|
||||
# Omitting unwind info prevents the generation of readable stack traces in crash reports on iOS
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-unwind-tables -fno-asynchronous-unwind-tables")
|
||||
endif()
|
||||
set(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} -fno-exceptions -fno-unwind-tables -fno-asynchronous-unwind-tables -fno-rtti")
|
||||
endif()
|
||||
|
||||
# With WebGL, we disable RTTI even for debug builds because we pass emscripten::val back and forth
|
||||
@@ -363,10 +359,6 @@ if (WEBGL)
|
||||
set(CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG} -fno-rtti")
|
||||
endif()
|
||||
|
||||
if (WEBGL_PTHREADS)
|
||||
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -pthread")
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Debug compiler flags
|
||||
# ==================================================================================================
|
||||
@@ -409,8 +401,8 @@ endif()
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} ${GC_SECTIONS}")
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} ${GC_SECTIONS} ${B_SYMBOLIC_FUNCTIONS}")
|
||||
|
||||
if (WEBGL_PTHREADS)
|
||||
set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -pthread")
|
||||
if (WEBGL)
|
||||
set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -s USE_WEBGL2=1")
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
@@ -670,7 +662,7 @@ add_subdirectory(${EXTERNAL}/imgui/tnt)
|
||||
add_subdirectory(${EXTERNAL}/robin-map/tnt)
|
||||
add_subdirectory(${EXTERNAL}/smol-v/tnt)
|
||||
add_subdirectory(${EXTERNAL}/benchmark/tnt)
|
||||
add_subdirectory(${EXTERNAL}/meshoptimizer/tnt)
|
||||
add_subdirectory(${EXTERNAL}/meshoptimizer)
|
||||
add_subdirectory(${EXTERNAL}/cgltf/tnt)
|
||||
add_subdirectory(${EXTERNAL}/draco/tnt)
|
||||
add_subdirectory(${EXTERNAL}/jsmn/tnt)
|
||||
@@ -707,9 +699,7 @@ if (IS_HOST_PLATFORM)
|
||||
if (FILAMENT_SUPPORTS_OPENGL)
|
||||
add_subdirectory(${LIBRARIES}/bluegl)
|
||||
endif()
|
||||
if (NOT FILAMENT_SKIP_SDL2)
|
||||
add_subdirectory(${LIBRARIES}/filamentapp)
|
||||
endif()
|
||||
add_subdirectory(${LIBRARIES}/filamentapp)
|
||||
add_subdirectory(${LIBRARIES}/imageio)
|
||||
|
||||
add_subdirectory(${FILAMENT}/samples)
|
||||
|
||||
@@ -164,7 +164,8 @@ private:
|
||||
|
||||
### Strings
|
||||
|
||||
- Never use `std::string` in the Filament core renderer. Prefer `utils::CString` or `std::string_view`.
|
||||
- Never use `std::string` in the Filament core renderer. Prefer `utils::CString` or
|
||||
`utils::StaticString`.
|
||||
- When using `std::string` in tools, always include the `std::` qualifier to disambiguate it
|
||||
from other string types.
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.28.2'
|
||||
implementation 'com.google.android.filament:filament-android:1.25.3'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```
|
||||
pod 'Filament', '~> 1.28.2'
|
||||
pod 'Filament', '~> 1.25.3'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
@@ -179,7 +179,6 @@ steps:
|
||||
- [x] KHR_mesh_quantization
|
||||
- [x] KHR_texture_basisu
|
||||
- [x] KHR_texture_transform
|
||||
- [x] EXT_meshopt_compression
|
||||
|
||||
|
||||
## Rendering with Filament
|
||||
|
||||
@@ -5,100 +5,6 @@ A new header is inserted each time a *tag* is created.
|
||||
|
||||
## main branch
|
||||
|
||||
- gltfio: calculate primitive's AABB correctly.
|
||||
- gltfio: recompute bounding boxes with morph targets
|
||||
- engine: add missing getters on `MaterialInstance`
|
||||
- WebGL: add missing `ColorGrading` JS bindings
|
||||
- engine: improvements/cleanup of Shadow mapping code [⚠️ **Recompile Materials**]
|
||||
|
||||
## v1.28.3
|
||||
|
||||
- backend: add support for GGP platform
|
||||
- engine: primitives with `CullingMode::FRONT_AND_BACK` are now skipped.
|
||||
|
||||
## v1.28.2
|
||||
|
||||
- gltfio: support EXT_meshopt_compression
|
||||
- release packaging: fixed location of default IBL file
|
||||
|
||||
## v1.28.1
|
||||
|
||||
- gltfio: fix reloading crash in ubershader mode
|
||||
- Vulkan: improve performance in the readPixels path
|
||||
- engine: raise the spot shadows limit to 64, from 14.
|
||||
- engine: add experimental support for point light shadows.
|
||||
- gltfio: fix ubershader issues with assignment of dummy textures
|
||||
- gltfio: material instances and variants are now accessed via `FilamentInstance` [⚠️ **API Change**]
|
||||
- gltfio: the animator can now only be accessed via `FilamentInstance` [⚠️ **API Change**]
|
||||
- engine: fix "stable" shadows and make the default cascade splits logarithmic.
|
||||
- engine: Add new quality options to EVSM shadows + rendering fixes
|
||||
|
||||
## v1.28.0
|
||||
|
||||
- engine: LiSPSM is now a user settable option
|
||||
- engine: get the morph target buffer to the given primitive
|
||||
- Java: Fix TransformManager.getChildren()
|
||||
- Metal: newer devices are no longer limited to 16 samplers per Material.
|
||||
- gltfio: fix interpretation of occlusion strength
|
||||
- engine: minsdk is now 21 instead of 19. This allows the use of OpenGL ES 3.1
|
||||
- Vulkan: fix black screen regression
|
||||
|
||||
## v1.27.2
|
||||
|
||||
- gltfio: punctual lights are now duplicated when adding new asset instances
|
||||
- gltfio: FilamentInstance getAsset method now returns an immutable asset
|
||||
- gltfio: allow zero-instance assets
|
||||
- gltfio: fix regression with meshes that have no material
|
||||
- gltfio: fix regression with recomputeBoundingBoxes()
|
||||
- filamesh / matinfo: fix minor ASAN issues
|
||||
- engine: Added `Engine::resetBackendState()`, available only in WebGL builds
|
||||
|
||||
## v1.27.1
|
||||
|
||||
- Java: add methods for TransformManager.getChildCount(), TransformManager.getChildren() and Scene.hasEntity()
|
||||
- engine: Fix stencil buffer writes with OpenGL backend.
|
||||
- gltfio: add new virtual method to MaterialProvider that all plugins must implement
|
||||
- gltfio: add an assert for inconsistent sRGB flags among usages of a particular texture
|
||||
- engine: improve scissor documentation
|
||||
- backend: scissor is no longer clipped to the viewport (done on filament side)
|
||||
- samples: add debug overdraw visualization to gltf_viewer
|
||||
|
||||
## v1.27.0
|
||||
|
||||
- WebGL: reduce max instance count to work around Chrome issues [⚠️ **Recompile Materials**]
|
||||
- engine: rework material/shader sampler binding code [⚠️ **Recompile Materials**]
|
||||
- gltfio: move the API for `recomputeBoundingBoxes` [⚠️ **API Change**]
|
||||
- engine: add support for specialization constants [⚠️ **Recompile Materials**]
|
||||
- gltfio: fix spotlight regression
|
||||
- gltfio: clear the MaterialInstance cache when creating new instances
|
||||
|
||||
## v1.26.0
|
||||
|
||||
- engine: new feature level APIs, see `Engine::getSupportedFeatureLevel()`
|
||||
- engine: add new stencil API to `View` and stencil state APIs to `MaterialInstance` [**NEW API**].
|
||||
- engine: Fix guard bands and TAA with `vertexDomain:Device` [⚠️ **Recompile Materials**]
|
||||
- engine: `clipSpaceTransform` is now only available with `vertexDomain:Device` [⚠️ **API Change**]
|
||||
- gltfio: add unified `AssetLoader::createAsset()` method [⚠️ **API Change**]
|
||||
- gltfio: all assets are now "instanced" [⚠️ **API Change**]
|
||||
|
||||
## v1.25.6
|
||||
|
||||
- engine: Add `CONFIG_MINSPEC_UBO_SIZE` as a nicer way to allow exceeding the ES3.0 minspec.
|
||||
- gltfio: minor efficiency improvement for Android and WebGL builds.
|
||||
- gltfio: add support for concurrent texture downloading and decoding.
|
||||
|
||||
## v1.25.5
|
||||
|
||||
- WebGL: upgraded the JS bindings to work with emsdk 3.1.15
|
||||
- WebGL: added missing IBL builder to TypeScript annotations
|
||||
- engine: Fix incorrect precision restoration when computing accurate world translations
|
||||
- engine: make `MaterialInstance` public API friendly to `std::string_view` parameters
|
||||
- gltfio: add 'detach' methods to allow ownership transfer of entities and components
|
||||
|
||||
## v1.25.4
|
||||
|
||||
- backend: streamline texture upload APIs [⚠️ **API Change**]
|
||||
|
||||
## v1.25.3
|
||||
|
||||
- engine: Fix Adreno gpu crash introduced by gpu morph target change
|
||||
|
||||
@@ -29,12 +29,15 @@
|
||||
|
||||
// Publishing to Maven Central:
|
||||
// - Build and upload artifacts with ./gradlew publish
|
||||
// - Close and release staging repo on Nexus with ./gradlew closeAndReleaseStagingRepository
|
||||
// - Close and release staging repo on Nexus with ./gradlew closeAndReleaseRepository
|
||||
//
|
||||
// The following is needed in ~/gradle/gradle.properties:
|
||||
//
|
||||
// sonatypeUsername=nexus_user
|
||||
// sonatypePassword=nexus_password
|
||||
// SONATYPE_NEXUS_USERNAME=nexus_user
|
||||
// SONATYPE_NEXUS_PASSWORD=nexus_password
|
||||
//
|
||||
// nexusUsername=nexus_user
|
||||
// nexusPassword=nexus_password
|
||||
//
|
||||
// signing.keyId=pgp_key_id
|
||||
// signing.password=pgp_key_password
|
||||
@@ -44,7 +47,7 @@
|
||||
buildscript {
|
||||
def path = providers
|
||||
.gradleProperty("com.google.android.filament.dist-dir")
|
||||
.get()
|
||||
.forUseAtConfigurationTime().get()
|
||||
|
||||
def directory = objects.fileProperty().fileValue(new File(path)).getAsFile().get()
|
||||
def filamentPath = directory.absolutePath
|
||||
@@ -56,15 +59,18 @@ buildscript {
|
||||
// Warning: changing this property does not work well with incremental builds.
|
||||
def excludeVulkan = providers
|
||||
.gradleProperty("com.google.android.filament.exclude-vulkan")
|
||||
.forUseAtConfigurationTime()
|
||||
.isPresent()
|
||||
|
||||
def matdbg = providers
|
||||
.gradleProperty("com.google.android.filament.matdbg")
|
||||
.forUseAtConfigurationTime()
|
||||
.isPresent()
|
||||
|
||||
def abis = ["arm64-v8a", "armeabi-v7a", "x86_64", "x86"]
|
||||
def newAbis = providers
|
||||
.gradleProperty("com.google.android.filament.abis")
|
||||
.forUseAtConfigurationTime()
|
||||
.get()
|
||||
.split(',')
|
||||
if (!newAbis.contains("all")) {
|
||||
@@ -73,20 +79,18 @@ buildscript {
|
||||
|
||||
ext.versions = [
|
||||
'minSdk': 19,
|
||||
'targetSdk': 33,
|
||||
'compileSdk': 33,
|
||||
'kotlin': '1.7.10',
|
||||
'targetSdk': 31,
|
||||
'compileSdk': 31,
|
||||
'kotlin': '1.6.21',
|
||||
'kotlin_coroutines': '1.6.1',
|
||||
'buildTools': '33.0.0',
|
||||
'ndk': '25.1.8937393',
|
||||
'androidx_core': '1.9.0',
|
||||
'androidx_annotations': '1.3.0'
|
||||
'buildTools': '32.0.0',
|
||||
'ndk': '24.0.8215888'
|
||||
]
|
||||
|
||||
ext.deps = [
|
||||
'androidx': [
|
||||
'annotations': "androidx.annotation:annotation:${versions.androidx_annotations}",
|
||||
'core': "androidx.core:core:${versions.androidx_core}",
|
||||
'annotations': "androidx.annotation:annotation:1.3.0",
|
||||
'core': "androidx.core:core:1.7.0",
|
||||
],
|
||||
'kotlin': "org.jetbrains.kotlin:kotlin-stdlib-jdk8:${versions.kotlin}",
|
||||
'coroutines': [
|
||||
@@ -97,7 +101,7 @@ buildscript {
|
||||
|
||||
dependencies {
|
||||
// NOTE: See TODO in gradle.properties once we move to Gradle 7.4
|
||||
classpath 'com.android.tools.build:gradle:7.3.0'
|
||||
classpath 'com.android.tools.build:gradle:7.2.0'
|
||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:${versions.kotlin}"
|
||||
}
|
||||
|
||||
@@ -144,18 +148,14 @@ buildscript {
|
||||
}
|
||||
|
||||
plugins {
|
||||
id "io.github.gradle-nexus.publish-plugin" version "1.1.0"
|
||||
id 'io.codearte.nexus-staging' version '0.30.0'
|
||||
}
|
||||
|
||||
// See https://github.com/gradle-nexus/publish-plugin
|
||||
// Publish to https://oss.sonatype.org/ (not s01)
|
||||
nexusPublishing {
|
||||
// Nexus Staging configuration
|
||||
// See https://github.com/Codearte/gradle-nexus-staging-plugin/
|
||||
nexusStaging {
|
||||
packageGroup = 'com.google.android'
|
||||
repositories {
|
||||
sonatype {
|
||||
stagingProfileId = '9a75a224a4f17b'
|
||||
}
|
||||
}
|
||||
stagingProfileId = '9a75a224a4f17b'
|
||||
}
|
||||
|
||||
subprojects {
|
||||
|
||||
@@ -126,8 +126,8 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderUniform
|
||||
JNIEnv* env, jclass, jlong nativeBuilder, jint uniformType, jint precision, jstring name_) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
const char* name = env->GetStringUTFChars(name_, nullptr);
|
||||
builder->parameter(name, (MaterialBuilder::UniformType) uniformType,
|
||||
(MaterialBuilder::ParameterPrecision) precision);
|
||||
builder->parameter((MaterialBuilder::UniformType) uniformType,
|
||||
(MaterialBuilder::ParameterPrecision) precision, name);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderUniform
|
||||
jstring name_) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
const char* name = env->GetStringUTFChars(name_, nullptr);
|
||||
builder->parameter(name, (size_t) size, (MaterialBuilder::UniformType) uniformType,
|
||||
(MaterialBuilder::ParameterPrecision) precision);
|
||||
builder->parameter((MaterialBuilder::UniformType) uniformType, (size_t) size,
|
||||
(MaterialBuilder::ParameterPrecision) precision, name);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
@@ -148,8 +148,9 @@ Java_com_google_android_filament_filamat_MaterialBuilder_nMaterialBuilderSampler
|
||||
jint precision, jstring name_) {
|
||||
auto builder = (MaterialBuilder*) nativeBuilder;
|
||||
const char* name = env->GetStringUTFChars(name_, nullptr);
|
||||
builder->parameter(name, (MaterialBuilder::SamplerType) samplerType,
|
||||
(MaterialBuilder::SamplerFormat) format, (MaterialBuilder::ParameterPrecision) precision);
|
||||
builder->parameter((MaterialBuilder::SamplerType) samplerType,
|
||||
(MaterialBuilder::SamplerFormat) format, (MaterialBuilder::ParameterPrecision) precision,
|
||||
name);
|
||||
env->ReleaseStringUTFChars(name_, name);
|
||||
}
|
||||
|
||||
|
||||
@@ -328,24 +328,3 @@ Java_com_google_android_filament_Engine_nIsAutomaticInstancingEnabled(JNIEnv*, j
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jboolean)engine->isAutomaticInstancingEnabled();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Engine_nGetSupportedFeatureLevel(JNIEnv *, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jint)engine->getSupportedFeatureLevel();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Engine_nSetActiveFeatureLevel(JNIEnv *, jclass,
|
||||
jlong nativeEngine, jint ordinal) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jint)engine->setActiveFeatureLevel((Engine::FeatureLevel)ordinal);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Engine_nGetActiveFeatureLevel(JNIEnv *, jclass,
|
||||
jlong nativeEngine) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jint)engine->getActiveFeatureLevel();
|
||||
}
|
||||
@@ -76,10 +76,10 @@ extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env, jclass,
|
||||
jlong nativeBuilder, jint mapSize, jint cascades, jfloatArray splitPositions,
|
||||
jfloat constantBias, jfloat normalBias, jfloat shadowFar, jfloat shadowNearHint,
|
||||
jfloat shadowFarHint, jboolean stable, jboolean lispsm,
|
||||
jfloat shadowFarHint, jboolean stable,
|
||||
jfloat polygonOffsetConstant, jfloat polygonOffsetSlope,
|
||||
jboolean screenSpaceContactShadows, jint stepCount,
|
||||
jfloat maxShadowDistance, jint vsmMsaaSamples, jboolean elvsm, jfloat blurWidth, jfloat shadowBulbRadius) {
|
||||
jfloat maxShadowDistance, jint vsmMsaaSamples, jfloat blurWidth, jfloat shadowBulbRadius) {
|
||||
LightManager::Builder *builder = (LightManager::Builder *) nativeBuilder;
|
||||
LightManager::ShadowOptions shadowOptions {
|
||||
.mapSize = (uint32_t)mapSize,
|
||||
@@ -90,7 +90,6 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
|
||||
.shadowNearHint = shadowNearHint,
|
||||
.shadowFarHint = shadowFarHint,
|
||||
.stable = (bool)stable,
|
||||
.lispsm = (bool)lispsm,
|
||||
.polygonOffsetConstant = polygonOffsetConstant,
|
||||
.polygonOffsetSlope = polygonOffsetConstant,
|
||||
.screenSpaceContactShadows = (bool)screenSpaceContactShadows,
|
||||
@@ -98,7 +97,6 @@ Java_com_google_android_filament_LightManager_nBuilderShadowOptions(JNIEnv* env,
|
||||
.maxShadowDistance = maxShadowDistance,
|
||||
.vsm = {
|
||||
.msaaSamples = (uint8_t) vsmMsaaSamples,
|
||||
.elvsm = (bool)elvsm,
|
||||
.blurWidth = blurWidth
|
||||
},
|
||||
.shadowBulbRadius = shadowBulbRadius
|
||||
|
||||
@@ -341,14 +341,6 @@ Java_com_google_android_filament_MaterialInstance_nSetDepthWrite(JNIEnv*,
|
||||
instance->setDepthWrite(enable);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilWrite(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jboolean enable) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilWrite(enable);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetDepthCulling(JNIEnv*,
|
||||
@@ -357,70 +349,6 @@ Java_com_google_android_filament_MaterialInstance_nSetDepthCulling(JNIEnv*,
|
||||
instance->setDepthCulling(enable);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilCompareFunction(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jlong function, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilCompareFunction(
|
||||
static_cast<MaterialInstance::StencilCompareFunc>(function),
|
||||
static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilOpStencilFail(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jlong op, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilOpStencilFail(
|
||||
static_cast<MaterialInstance::StencilOperation>(op),
|
||||
static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilOpDepthFail(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jlong op, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilOpDepthFail(
|
||||
static_cast<MaterialInstance::StencilOperation>(op),
|
||||
static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilOpDepthStencilPass(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jlong op, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilOpDepthStencilPass(
|
||||
static_cast<MaterialInstance::StencilOperation>(op),
|
||||
static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilReferenceValue(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jint value, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilReferenceValue(value, static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilReadMask(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jint readMask, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilReadMask(readMask, static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nSetStencilWriteMask(JNIEnv*, jclass,
|
||||
jlong nativeMaterialInstance, jint writeMask, jlong face) {
|
||||
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
|
||||
instance->setStencilWriteMask(writeMask, static_cast<MaterialInstance::StencilFace>(face));
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jstring JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetName(JNIEnv* env, jclass,
|
||||
@@ -452,84 +380,3 @@ Java_com_google_android_filament_MaterialInstance_nDuplicate(JNIEnv* env, jclass
|
||||
}
|
||||
return (jlong)mi;
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetMaskThreshold(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetMaskThreshold()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->getMaskThreshold();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetSpecularAntiAliasingVariance(JNIEnv* env,
|
||||
jclass clazz, jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetSpecularAntiAliasingVariance()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->getSpecularAntiAliasingVariance();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jfloat JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetSpecularAntiAliasingThreshold(JNIEnv* env,
|
||||
jclass clazz, jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetSpecularAntiAliasingThreshold()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->getSpecularAntiAliasingThreshold();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsDoubleSided(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsDoubleSided()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isDoubleSided();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nGetCullingMode(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nGetCullingMode()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return (jint)instance->getCullingMode();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsColorWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsColorWriteEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isColorWriteEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsDepthWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsDepthWriteEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isDepthWriteEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsStencilWriteEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsStencilWriteEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isStencilWriteEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_MaterialInstance_nIsDepthCullingEnabled(JNIEnv* env, jclass clazz,
|
||||
jlong nativeMaterialInstance) {
|
||||
// TODO: implement nIsDepthCullingEnabled()
|
||||
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
|
||||
return instance->isDepthCullingEnabled();
|
||||
}
|
||||
|
||||
@@ -83,11 +83,3 @@ Java_com_google_android_filament_Scene_nGetLightCount(JNIEnv *env, jclass type,
|
||||
Scene* scene = (Scene*) nativeScene;
|
||||
return (jint) scene->getLightCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_Scene_nHasEntity(JNIEnv *env, jclass type, jlong nativeScene,
|
||||
jint entityId) {
|
||||
Scene* scene = (Scene*) nativeScene;
|
||||
Entity entity = Entity::import(entityId);
|
||||
return (jboolean) scene->hasEntity(entity);
|
||||
}
|
||||
|
||||
@@ -188,6 +188,69 @@ Java_com_google_android_filament_Texture_nGetInternalFormat(JNIEnv*, jclass,
|
||||
return (jint) texture->getFormat();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nSetImage(JNIEnv* env, jclass, jlong nativeTexture,
|
||||
jlong nativeEngine, jint level, jint xoffset, jint yoffset, jint width, jint height,
|
||||
jobject storage, jint remaining,
|
||||
jint left, jint top, jint type, jint alignment,
|
||||
jint stride, jint format,
|
||||
jobject handler, jobject runnable) {
|
||||
Texture* texture = (Texture*) nativeTexture;
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
|
||||
size_t sizeInBytes = getTextureDataSize(texture, (size_t) level, (Texture::Format) format,
|
||||
(Texture::Type) type, (size_t) stride, (size_t) height, (size_t) alignment);
|
||||
|
||||
AutoBuffer nioBuffer(env, storage, 0);
|
||||
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
|
||||
// BufferOverflowException
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buffer = nioBuffer.getData();
|
||||
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes, (backend::PixelDataFormat) format,
|
||||
(backend::PixelDataType) type, (uint8_t) alignment, (uint32_t) left, (uint32_t) top,
|
||||
(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));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nSetImageCompressed(JNIEnv *env, jclass,
|
||||
jlong nativeTexture, jlong nativeEngine, jint level, jint xoffset, jint yoffset,
|
||||
jint width, jint height, jobject storage, jint remaining,
|
||||
jint, jint, jint, jint, jint compressedSizeInBytes, jint compressedFormat,
|
||||
jobject handler, jobject runnable) {
|
||||
Texture *texture = (Texture *) nativeTexture;
|
||||
Engine *engine = (Engine *) nativeEngine;
|
||||
|
||||
size_t sizeInBytes = (size_t) compressedSizeInBytes;
|
||||
|
||||
AutoBuffer nioBuffer(env, storage, 0);
|
||||
if (sizeInBytes > (size_t(remaining) << nioBuffer.getShift())) {
|
||||
// BufferOverflowException
|
||||
return -1;
|
||||
}
|
||||
|
||||
void *buffer = nioBuffer.getData();
|
||||
auto *callback = JniBufferCallback::make(engine, env, handler, runnable, std::move(nioBuffer));
|
||||
|
||||
Texture::PixelBufferDescriptor desc(buffer, sizeInBytes,
|
||||
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
|
||||
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));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_Texture_nSetImage3D(JNIEnv* env, jclass, jlong nativeTexture,
|
||||
jlong nativeEngine, jint level,
|
||||
@@ -290,10 +353,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemap(JNIEnv *env, jclass,
|
||||
(uint32_t) stride,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -328,10 +388,7 @@ Java_com_google_android_filament_Texture_nSetImageCubemapCompressed(JNIEnv *env,
|
||||
(backend::CompressedPixelDataType) compressedFormat, (uint32_t) compressedSizeInBytes,
|
||||
callback->getHandler(), &JniBufferCallback::postToJavaAndDestroy, callback);
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
|
||||
texture->setImage(*engine, (size_t) level, std::move(desc), faceOffsets);
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -110,26 +110,6 @@ Java_com_google_android_filament_TransformManager_nGetParent(JNIEnv*, jclass,
|
||||
return tm->getParent((TransformManager::Instance) i).getId();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_TransformManager_nGetChildCount(JNIEnv*, jclass,
|
||||
jlong nativeTransformManager, jint i) {
|
||||
TransformManager* tm = (TransformManager*) nativeTransformManager;
|
||||
return tm->getChildCount((TransformManager::Instance) i);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_TransformManager_nGetChildren(JNIEnv* env,
|
||||
jclass, jlong nativeTransformManager, jint i,
|
||||
jintArray outEntities_, jint count) {
|
||||
TransformManager* tm = (TransformManager*) nativeTransformManager;
|
||||
jint* entities = env->GetIntArrayElements(outEntities_, nullptr);
|
||||
// This is very very gross, we just pretend Entity is just like an jint
|
||||
// (which it is), but still.
|
||||
tm->getChildren((TransformManager::Instance) i,
|
||||
reinterpret_cast<Entity *>(entities), (size_t) count);
|
||||
env->ReleaseIntArrayElements(outEntities_, entities, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_TransformManager_nSetTransform(JNIEnv* env,
|
||||
jclass, jlong nativeTransformManager, jint i,
|
||||
|
||||
@@ -149,13 +149,12 @@ Java_com_google_android_filament_View_nSetShadowType(JNIEnv*, jclass, jlong nati
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetVsmShadowOptions(JNIEnv*, jclass, jlong nativeView,
|
||||
jint anisotropy, jboolean mipmapping, jboolean highPrecision, jfloat minVarianceScale,
|
||||
jint anisotropy, jboolean mipmapping, jfloat minVarianceScale,
|
||||
jfloat lightBleedReduction) {
|
||||
View* view = (View*) nativeView;
|
||||
View::VsmShadowOptions options;
|
||||
options.anisotropy = (uint8_t)anisotropy;
|
||||
options.mipmapping = (bool)mipmapping;
|
||||
options.highPrecision = (bool)highPrecision;
|
||||
options.minVarianceScale = minVarianceScale;
|
||||
options.lightBleedReduction = lightBleedReduction;
|
||||
view->setVsmShadowOptions(options);
|
||||
@@ -463,21 +462,6 @@ Java_com_google_android_filament_View_nPick(JNIEnv* env, jclass,
|
||||
}, callback->getHandler());
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetStencilBufferEnabled(JNIEnv *, jclass, jlong nativeView,
|
||||
jboolean enabled) {
|
||||
View* view = (View*) nativeView;
|
||||
view->setStencilBufferEnabled(enabled);
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT jboolean JNICALL
|
||||
Java_com_google_android_filament_View_nIsStencilBufferEnabled(JNIEnv *, jclass, jlong nativeView) {
|
||||
View* view = (View*) nativeView;
|
||||
return view->isStencilBufferEnabled();
|
||||
}
|
||||
|
||||
extern "C"
|
||||
JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_View_nSetGuardBandOptions(JNIEnv *, jclass,
|
||||
|
||||
@@ -47,7 +47,7 @@ import com.google.android.filament.proguard.UsedByReflection;
|
||||
* <pre>
|
||||
* import com.google.android.filament.*
|
||||
*
|
||||
* Engine engine = Engine.create();
|
||||
* Engin engine = Engine.create();
|
||||
* SwapChain swapChain = engine.createSwapChain(nativeWindow);
|
||||
* Renderer renderer = engine.createRenderer();
|
||||
* Scene scene = engine.createScene();
|
||||
@@ -107,7 +107,6 @@ import com.google.android.filament.proguard.UsedByReflection;
|
||||
*/
|
||||
public class Engine {
|
||||
private static final Backend[] sBackendValues = Backend.values();
|
||||
private static final FeatureLevel[] sFeatureLevelValues = FeatureLevel.values();
|
||||
|
||||
private long mNativeObject;
|
||||
|
||||
@@ -142,18 +141,6 @@ public class Engine {
|
||||
NOOP,
|
||||
}
|
||||
|
||||
/**
|
||||
* Defines the backend's feature levels.
|
||||
*/
|
||||
public enum FeatureLevel {
|
||||
/** Reserved, don't use */
|
||||
FEATURE_LEVEL_0,
|
||||
/** OpenGL ES 3.0 features (default) */
|
||||
FEATURE_LEVEL_1,
|
||||
/** OpenGL ES 3.1 features + 31 textures units + cubemap arrays */
|
||||
FEATURE_LEVEL_2
|
||||
};
|
||||
|
||||
private Engine(long nativeEngine) {
|
||||
mNativeObject = nativeEngine;
|
||||
mTransformManager = new TransformManager(nGetTransformManager(nativeEngine));
|
||||
@@ -282,50 +269,6 @@ public class Engine {
|
||||
getTransformManager().setAccurateTranslationsEnabled(true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Query the feature level supported by the selected backend.
|
||||
*
|
||||
* A specific feature level needs to be set before the corresponding features can be used.
|
||||
*
|
||||
* @return FeatureLevel supported the selected backend.
|
||||
* @see #setActiveFeatureLevel
|
||||
*/
|
||||
@NonNull
|
||||
public FeatureLevel getSupportedFeatureLevel() {
|
||||
return sFeatureLevelValues[(int) nGetSupportedFeatureLevel(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Activate all features of a given feature level. By default FeatureLevel::FEATURE_LEVEL_1 is
|
||||
* active. The selected feature level must not be higher than the value returned by
|
||||
* getActiveFeatureLevel() and it's not possible lower the active feature level.
|
||||
*
|
||||
* @param featureLevel the feature level to activate. If featureLevel is lower than
|
||||
* getActiveFeatureLevel(), the current (higher) feature level is kept.
|
||||
* If featureLevel is higher than getSupportedFeatureLevel(), an exception
|
||||
* is thrown, or the program is terminated if exceptions are disabled.
|
||||
*
|
||||
* @return the active feature level.
|
||||
*
|
||||
* @see #getSupportedFeatureLevel
|
||||
* @see #getActiveFeatureLevel
|
||||
*/
|
||||
@NonNull
|
||||
public FeatureLevel setActiveFeatureLevel(@NonNull FeatureLevel featureLevel) {
|
||||
return sFeatureLevelValues[(int) nSetActiveFeatureLevel(getNativeObject(), featureLevel.ordinal())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the currently active feature level.
|
||||
* @return currently active feature level
|
||||
* @see #getSupportedFeatureLevel
|
||||
* @see #setActiveFeatureLevel
|
||||
*/
|
||||
@NonNull
|
||||
public FeatureLevel getActiveFeatureLevel() {
|
||||
return sFeatureLevelValues[(int) nGetActiveFeatureLevel(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables automatic instancing of render primitives. Instancing of render primitive
|
||||
* can greatly reduce CPU overhead but requires the instanced primitives to be identical
|
||||
@@ -346,7 +289,7 @@ public class Engine {
|
||||
|
||||
/**
|
||||
* @return true if automatic instancing is enabled, false otherwise.
|
||||
* @see #setAutomaticInstancingEnabled
|
||||
* @see setAutomaticInstancingEnabled
|
||||
*/
|
||||
public boolean isAutomaticInstancingEnabled() {
|
||||
return nIsAutomaticInstancingEnabled(getNativeObject());
|
||||
@@ -817,7 +760,4 @@ public class Engine {
|
||||
private static native long nGetEntityManager(long nativeEngine);
|
||||
private static native void nSetAutomaticInstancingEnabled(long nativeEngine, boolean enable);
|
||||
private static native boolean nIsAutomaticInstancingEnabled(long nativeEngine);
|
||||
private static native int nGetSupportedFeatureLevel(long nativeEngine);
|
||||
private static native int nSetActiveFeatureLevel(long nativeEngine, int ordinal);
|
||||
private static native int nGetActiveFeatureLevel(long nativeEngine);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ public class LightManager {
|
||||
*/
|
||||
@NonNull
|
||||
@Size(min = 3)
|
||||
public float[] cascadeSplitPositions = { 0.125f, 0.25f, 0.50f };
|
||||
public float[] cascadeSplitPositions = { 0.25f, 0.50f, 0.75f };
|
||||
|
||||
/** Constant bias in world units (e.g. meters) by which shadows are moved away from the
|
||||
* light. 1mm by default.
|
||||
@@ -280,25 +280,9 @@ public class LightManager {
|
||||
* Controls whether the shadow map should be optimized for resolution or stability.
|
||||
* When set to true, all resolution enhancing features that can affect stability are
|
||||
* disabling, resulting in significantly lower resolution shadows, albeit stable ones.
|
||||
*
|
||||
* Setting this flag to true always disables LiSPSM (see below).
|
||||
*/
|
||||
public boolean stable = false;
|
||||
|
||||
/**
|
||||
* LiSPSM, or light-space perspective shadow-mapping is a technique allowing to better
|
||||
* optimize the use of the shadow-map texture. When enabled the effective resolution of
|
||||
* shadows is greatly improved and yields result similar to using cascades without the
|
||||
* extra cost. LiSPSM comes with some drawbacks however, in particular it is incompatible
|
||||
* with blurring because it effectively affects the blur kernel size.
|
||||
*
|
||||
* Blurring is only an issue when using ShadowType.VSM with a large blur or with
|
||||
* ShadowType.PCSS however.
|
||||
*
|
||||
* If these blurring artifacts become problematic, this flag can be used to disable LiSPSM.
|
||||
*/
|
||||
public boolean lispsm = false;
|
||||
|
||||
/**
|
||||
* Constant bias in depth-resolution units by which shadows are moved away from the
|
||||
* light. The default value of 0.5 is used to round depth values up.
|
||||
@@ -362,15 +346,6 @@ public class LightManager {
|
||||
@IntRange(from = 1)
|
||||
public int vsmMsaaSamples = 1;
|
||||
|
||||
|
||||
/**
|
||||
* When elvsm is set to true, "Exponential Layered VSM without Layers" are used. It is
|
||||
* an improvement to the default EVSM which suffers important light leaks. Enabling
|
||||
* ELVSM for a single shadowmap doubles the memory usage of all shadow maps.
|
||||
* ELVSM is mostly useful when large blurs are used.
|
||||
*/
|
||||
public boolean elvsm = false;
|
||||
|
||||
/**
|
||||
* Blur width for the VSM blur. Zero do disable.
|
||||
* The maximum value is 125.
|
||||
@@ -495,6 +470,11 @@ public class LightManager {
|
||||
/**
|
||||
* Whether this Light casts shadows (disabled by default)
|
||||
*
|
||||
* <p>
|
||||
* <b>warning:</b>
|
||||
* {@link Type#POINT} lights cannot cast shadows.
|
||||
* </p>
|
||||
*
|
||||
* @param enable Enables or disables casting shadows from this Light.
|
||||
*
|
||||
* @return This Builder, for chaining calls.
|
||||
@@ -516,11 +496,11 @@ public class LightManager {
|
||||
nBuilderShadowOptions(mNativeBuilder,
|
||||
options.mapSize, options.shadowCascades, options.cascadeSplitPositions,
|
||||
options.constantBias, options.normalBias, options.shadowFar, options.shadowNearHint,
|
||||
options.shadowFarHint, options.stable, options.lispsm,
|
||||
options.shadowFarHint, options.stable,
|
||||
options.polygonOffsetConstant, options.polygonOffsetSlope,
|
||||
options.screenSpaceContactShadows,
|
||||
options.stepCount, options.maxShadowDistance, options.vsmMsaaSamples,
|
||||
options.elvsm, options.blurWidth, options.shadowBulbRadius);
|
||||
options.blurWidth, options.shadowBulbRadius);
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -1178,14 +1158,7 @@ public class LightManager {
|
||||
private static native void nDestroyBuilder(long nativeBuilder);
|
||||
private static native boolean nBuilderBuild(long nativeBuilder, long nativeEngine, int entity);
|
||||
private static native void nBuilderCastShadows(long nativeBuilder, boolean enable);
|
||||
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize,
|
||||
int cascades, float[] splitPositions,
|
||||
float constantBias, float normalBias,
|
||||
float shadowFar, float shadowNearHint, float shadowFarhint,
|
||||
boolean stable, boolean lispsm,
|
||||
float polygonOffsetConstant, float polygonOffsetSlope,
|
||||
boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance,
|
||||
int vsmMsaaSamples, boolean elvsm, float blurWidth, float shadowBulbRadius);
|
||||
private static native void nBuilderShadowOptions(long nativeBuilder, int mapSize, int cascades, float[] splitPositions, float constantBias, float normalBias, float shadowFar, float shadowNearHint, float shadowFarhint, boolean stable, float polygonOffsetConstant, float polygonOffsetSlope, boolean screenSpaceContactShadows, int stepCount, float maxShadowDistance, int vsmMsaaSamples, float blurWidth, float shadowBulbRadius);
|
||||
private static native void nBuilderCastLight(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderPosition(long nativeBuilder, float x, float y, float z);
|
||||
private static native void nBuilderDirection(long nativeBuilder, float x, float y, float z);
|
||||
|
||||
@@ -36,7 +36,6 @@ import java.util.Set;
|
||||
*
|
||||
* @see <a href="https://google.github.io/filament/Materials.html">Filament Materials Guide</a>
|
||||
*/
|
||||
@UsedByNative("AssetLoader.cpp")
|
||||
public class Material {
|
||||
static final class EnumCache {
|
||||
private EnumCache() { }
|
||||
|
||||
@@ -20,11 +20,7 @@ import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Size;
|
||||
|
||||
import com.google.android.filament.proguard.UsedByNative;
|
||||
|
||||
@UsedByNative("AssetLoader.cpp")
|
||||
public class MaterialInstance {
|
||||
private static final Material.CullingMode[] sCullingModeValues = Material.CullingMode.values();
|
||||
private Material mMaterial;
|
||||
private String mName;
|
||||
private long mNativeObject;
|
||||
@@ -53,54 +49,6 @@ public class MaterialInstance {
|
||||
MAT4
|
||||
}
|
||||
|
||||
/**
|
||||
* Operations that control how the stencil buffer is updated.
|
||||
*/
|
||||
public enum StencilOperation {
|
||||
/**
|
||||
* Keeps the current value.
|
||||
*/
|
||||
KEEP,
|
||||
/**
|
||||
* Sets the value to 0.
|
||||
*/
|
||||
ZERO,
|
||||
/**
|
||||
* Sets the value to the stencil reference value.
|
||||
*/
|
||||
REPLACE,
|
||||
/**
|
||||
* Increments the current value. Clamps to the maximum representable unsigned value.
|
||||
*/
|
||||
INCR_CLAMP,
|
||||
/**
|
||||
* Increments the current value. Wraps value to zero when incrementing the maximum
|
||||
* representable unsigned value.
|
||||
*/
|
||||
INCR_WRAP,
|
||||
/**
|
||||
* Decrements the current value. Clamps to 0.
|
||||
*/
|
||||
DECR_CLAMP,
|
||||
/**
|
||||
* Decrements the current value. Wraps value to the maximum representable unsigned value
|
||||
* when decrementing a value of zero.
|
||||
*/
|
||||
DECR_WRAP,
|
||||
/**
|
||||
* Bitwise inverts the current value.
|
||||
*/
|
||||
INVERT,
|
||||
}
|
||||
|
||||
public enum StencilFace {
|
||||
FRONT,
|
||||
BACK,
|
||||
FRONT_AND_BACK
|
||||
}
|
||||
// Converts the StencilFace enum ordinal to Filament's equivalent bit field.
|
||||
static final int[] sStencilFaceMapping = {0x1, 0x2, 0x3};
|
||||
|
||||
public MaterialInstance(Engine engine, long nativeMaterialInstance) {
|
||||
mNativeObject = nativeMaterialInstance;
|
||||
mNativeMaterial = nGetMaterial(mNativeObject);
|
||||
@@ -403,40 +351,19 @@ public class MaterialInstance {
|
||||
}
|
||||
|
||||
/**
|
||||
* Set-up a custom scissor rectangle; by default it is disabled.
|
||||
* Set up a custom scissor rectangle; by default this encompasses the View.
|
||||
*
|
||||
* <p>
|
||||
* The scissor rectangle gets clipped by the View's viewport, in other words, the scissor
|
||||
* cannot affect fragments outside of the View's Viewport.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Currently the scissor is not compatible with dynamic resolution and should always be
|
||||
* disabled when dynamic resolution is used.
|
||||
* </p>
|
||||
*
|
||||
* @param left left coordinate of the scissor box relative to the viewport
|
||||
* @param bottom bottom coordinate of the scissor box relative to the viewport
|
||||
* @param left left coordinate of the scissor box
|
||||
* @param bottom bottom coordinate of the scissor box
|
||||
* @param width width of the scissor box
|
||||
* @param height height of the scissor box
|
||||
*
|
||||
* @see #unsetScissor
|
||||
* @see View#setViewport
|
||||
* @see View#setDynamicResolutionOptions
|
||||
*/
|
||||
public void setScissor(@IntRange(from = 0) int left, @IntRange(from = 0) int bottom,
|
||||
@IntRange(from = 0) int width, @IntRange(from = 0) int height) {
|
||||
nSetScissor(getNativeObject(), left, bottom, width, height);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the scissor rectangle to its default disabled setting.
|
||||
* <p>
|
||||
* Currently the scissor is not compatible with dynamic resolution and should always be
|
||||
* disabled when dynamic resolution is used.
|
||||
* </p>
|
||||
* @see View#setDynamicResolutionOptions
|
||||
*/
|
||||
/** Returns the scissor rectangle to its default setting, which encompasses the View. */
|
||||
public void unsetScissor() {
|
||||
nUnsetScissor(getNativeObject());
|
||||
}
|
||||
@@ -474,14 +401,6 @@ public class MaterialInstance {
|
||||
nSetMaskThreshold(getNativeObject(), threshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the minimum alpha value a fragment must have to not be discarded when the blend
|
||||
* mode is MASKED
|
||||
*/
|
||||
public float getMaskThreshold() {
|
||||
return nGetMaskThreshold(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the screen space variance of the filter kernel used when applying specular
|
||||
* anti-aliasing. The default value is set to 0.15. The specified value should be between
|
||||
@@ -495,14 +414,6 @@ public class MaterialInstance {
|
||||
nSetSpecularAntiAliasingVariance(getNativeObject(), variance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the screen space variance of the filter kernel used when applying specular
|
||||
* anti-aliasing.
|
||||
*/
|
||||
public float getSpecularAntiAliasingVariance() {
|
||||
return nGetSpecularAntiAliasingVariance(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the clamping threshold used to suppress estimation errors when applying specular
|
||||
* anti-aliasing. The default value is set to 0.2. The specified value should be between 0
|
||||
@@ -516,14 +427,6 @@ public class MaterialInstance {
|
||||
nSetSpecularAntiAliasingThreshold(getNativeObject(), threshold);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the clamping threshold used to suppress estimation errors when applying specular
|
||||
* anti-aliasing.
|
||||
*/
|
||||
public float getSpecularAntiAliasingThreshold() {
|
||||
return nGetSpecularAntiAliasingThreshold(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or disables double-sided lighting if the parent Material has double-sided capability,
|
||||
* otherwise prints a warning. If double-sided lighting is enabled, backface culling is
|
||||
@@ -537,14 +440,6 @@ public class MaterialInstance {
|
||||
nSetDoubleSided(getNativeObject(), doubleSided);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether double-sided lighting is enabled when the parent Material has double-sided
|
||||
* capability.
|
||||
*/
|
||||
public boolean isDoubleSided() {
|
||||
return nIsDoubleSided(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default triangle culling state that was set on the material.
|
||||
*
|
||||
@@ -552,18 +447,10 @@ public class MaterialInstance {
|
||||
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
|
||||
* Rasterization: culling</a>
|
||||
*/
|
||||
public void setCullingMode(@NonNull Material.CullingMode mode) {
|
||||
public void setCullingMode(Material.CullingMode mode) {
|
||||
nSetCullingMode(getNativeObject(), mode.ordinal());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the face culling mode.
|
||||
*/
|
||||
@NonNull
|
||||
public Material.CullingMode getCullingMode() {
|
||||
return sCullingModeValues[nGetCullingMode(getNativeObject())];
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default color-buffer write state that was set on the material.
|
||||
*
|
||||
@@ -575,13 +462,6 @@ public class MaterialInstance {
|
||||
nSetColorWrite(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether color write is enabled.
|
||||
*/
|
||||
public boolean isColorWriteEnabled() {
|
||||
return nIsColorWriteEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default depth-buffer write state that was set on the material.
|
||||
*
|
||||
@@ -593,27 +473,6 @@ public class MaterialInstance {
|
||||
nSetDepthWrite(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether depth write is enabled.
|
||||
*/
|
||||
public boolean isDepthWriteEnabled() {
|
||||
return nIsDepthWriteEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables or Disable stencil writes
|
||||
*/
|
||||
public void setStencilWrite(boolean enable) {
|
||||
nSetStencilWrite(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether stencil write is enabled.
|
||||
*/
|
||||
public boolean isStencilWriteEnabled() {
|
||||
return nIsStencilWriteEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides the default depth testing state that was set on the material.
|
||||
*
|
||||
@@ -625,215 +484,6 @@ public class MaterialInstance {
|
||||
nSetDepthCulling(getNativeObject(), enable);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether depth culling is enabled.
|
||||
*/
|
||||
public boolean isDepthCullingEnabled() {
|
||||
return nIsDepthCullingEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil comparison function (default is {@link TextureSampler.CompareFunction#ALWAYS}).
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate stencil comparison functions; one for front-facing polygons,
|
||||
* and one for back-facing polygons. The face parameter determines the comparison function(s)
|
||||
* updated by this call.
|
||||
* </p>
|
||||
*
|
||||
* @param func the stencil comparison function
|
||||
* @param face the faces to update the comparison function for
|
||||
*/
|
||||
public void setStencilCompareFunction(TextureSampler.CompareFunction func, StencilFace face) {
|
||||
nSetStencilCompareFunction(getNativeObject(), func.ordinal(),
|
||||
sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil comparison function for both front and back-facing polygons.
|
||||
* @see #setStencilCompareFunction(TextureSampler.CompareFunction, StencilFace)
|
||||
*/
|
||||
public void setStencilCompareFunction(TextureSampler.CompareFunction func) {
|
||||
setStencilCompareFunction(func, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil fail operation (default is {@link StencilOperation#KEEP}).
|
||||
*
|
||||
* <p>
|
||||
* The stencil fail operation is performed to update values in the stencil buffer when the
|
||||
* stencil test fails.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate stencil fail operations; one for front-facing polygons, and one
|
||||
* for back-facing polygons. The face parameter determines the stencil fail operation(s) updated
|
||||
* by this call.
|
||||
* </p>
|
||||
*
|
||||
* @param op the stencil fail operation
|
||||
* @param face the faces to update the stencil fail operation for
|
||||
*/
|
||||
public void setStencilOpStencilFail(StencilOperation op, StencilFace face) {
|
||||
nSetStencilOpStencilFail(getNativeObject(), op.ordinal(),
|
||||
sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil fail operation for both front and back-facing polygons.
|
||||
* @see #setStencilOpStencilFail(StencilOperation, StencilFace)
|
||||
*/
|
||||
public void setStencilOpStencilFail(StencilOperation op) {
|
||||
setStencilOpStencilFail(op, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the depth fail operation (default is {@link StencilOperation#KEEP}).
|
||||
*
|
||||
* <p>
|
||||
* The depth fail operation is performed to update values in the stencil buffer when the depth
|
||||
* test fails.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate depth fail operations; one for front-facing polygons, and one
|
||||
* for back-facing polygons. The face parameter determines the depth fail operation(s) updated
|
||||
* by this call.
|
||||
* </p>
|
||||
*
|
||||
* @param op the depth fail operation
|
||||
* @param face the faces to update the depth fail operation for
|
||||
*/
|
||||
public void setStencilOpDepthFail(StencilOperation op, StencilFace face) {
|
||||
nSetStencilOpDepthFail(getNativeObject(), op.ordinal(),
|
||||
sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the depth fail operation for both front and back-facing polygons.
|
||||
* @see #setStencilOpDepthFail(StencilOperation, StencilFace)
|
||||
*/
|
||||
public void setStencilOpDepthFail(StencilOperation op) {
|
||||
setStencilOpDepthFail(op, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the depth-stencil pass operation (default is {@link StencilOperation#KEEP}).
|
||||
*
|
||||
* <p>
|
||||
* The depth-stencil pass operation is performed to update values in the stencil buffer when
|
||||
* both the stencil test and depth test pass.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate depth-stencil pass operations; one for front-facing polygons,
|
||||
* and one for back-facing polygons. The face parameter determines the depth-stencil pass
|
||||
* operation(s) updated by this call.
|
||||
* </p>
|
||||
*
|
||||
* @param op the depth-stencil pass operation
|
||||
* @param face the faces to update the depth-stencil operation for
|
||||
*/
|
||||
public void setStencilOpDepthStencilPass(StencilOperation op, StencilFace face) {
|
||||
nSetStencilOpDepthStencilPass(getNativeObject(), op.ordinal(),
|
||||
sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the depth-stencil pass operation for both front and back-facing polygons.
|
||||
* @see #setStencilOpDepthStencilPass(StencilOperation, StencilFace)
|
||||
*/
|
||||
public void setStencilOpDepthStencilPass(StencilOperation op) {
|
||||
setStencilOpDepthStencilPass(op, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil reference value (default is 0).
|
||||
*
|
||||
* <p>
|
||||
* The stencil reference value is the left-hand side for stencil comparison tests. It's also
|
||||
* used as the replacement stencil value when {@link StencilOperation} is
|
||||
* {@link StencilOperation#REPLACE}.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate stencil reference values; one for front-facing polygons, and
|
||||
* one for back-facing polygons. The face parameter determines the reference value(s) updated by
|
||||
* this call.
|
||||
* </p>
|
||||
*
|
||||
* @param value the stencil reference value (only the least significant 8 bits are used)
|
||||
* @param face the faces to update the reference value for
|
||||
*/
|
||||
public void setStencilReferenceValue(@IntRange(from = 0, to = 255) int value, StencilFace face) {
|
||||
nSetStencilReferenceValue(getNativeObject(), value, sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil reference value for both front and back-facing polygons.
|
||||
* @see #setStencilReferenceValue(int, StencilFace)
|
||||
*/
|
||||
public void setStencilReferenceValue(@IntRange(from = 0, to = 255) int value) {
|
||||
setStencilReferenceValue(value, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil read mask (default is 0xFF).
|
||||
*
|
||||
* <p>
|
||||
* The stencil read mask masks the bits of the values participating in the stencil comparison
|
||||
* test- both the value read from the stencil buffer and the reference value.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate stencil read masks; one for front-facing polygons, and one for
|
||||
* back-facing polygons. The face parameter determines the stencil read mask(s) updated by this
|
||||
* call.
|
||||
* </p>
|
||||
*
|
||||
* @param readMask the read mask (only the least significant 8 bits are used)
|
||||
* @param face the faces to update the read mask for
|
||||
*/
|
||||
public void setStencilReadMask(@IntRange(from = 0, to = 255) int readMask, StencilFace face) {
|
||||
nSetStencilReadMask(getNativeObject(), readMask, sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil read mask for both front and back-facing polygons.
|
||||
* @see #setStencilReadMask(int, StencilFace)
|
||||
*/
|
||||
public void setStencilReadMask(@IntRange(from = 0, to = 255) int readMask) {
|
||||
setStencilReadMask(readMask, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil write mask (default is 0xFF).
|
||||
*
|
||||
* <p>
|
||||
* The stencil write mask masks the bits in the stencil buffer updated by stencil operations.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* It's possible to set separate stencil write masks; one for front-facing polygons, and one for
|
||||
* back-facing polygons. The face parameter determines the stencil write mask(s) updated by this
|
||||
* call.
|
||||
* </p>
|
||||
*
|
||||
* @param writeMask the write mask (only the least significant 8 bits are used)
|
||||
* @param face the faces to update the read mask for
|
||||
*/
|
||||
public void setStencilWriteMask(@IntRange(from = 0, to = 255) int writeMask, StencilFace face) {
|
||||
nSetStencilWriteMask(getNativeObject(), writeMask, sStencilFaceMapping[face.ordinal()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the stencil write mask for both front and back-facing polygons.
|
||||
* @see #setStencilWriteMask(int, StencilFace)
|
||||
*/
|
||||
public void setStencilWriteMask(int writeMask) {
|
||||
setStencilWriteMask(writeMask, StencilFace.FRONT_AND_BACK);
|
||||
}
|
||||
|
||||
public long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Calling method on destroyed MaterialInstance");
|
||||
@@ -906,37 +556,10 @@ public class MaterialInstance {
|
||||
private static native void nSetCullingMode(long nativeMaterialInstance, long mode);
|
||||
private static native void nSetColorWrite(long nativeMaterialInstance, boolean enable);
|
||||
private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable);
|
||||
private static native void nSetStencilWrite(long nativeMaterialInstance, boolean enable);
|
||||
private static native void nSetDepthCulling(long nativeMaterialInstance, boolean enable);
|
||||
|
||||
private static native void nSetStencilCompareFunction(long nativeMaterialInstance,
|
||||
long function, long face);
|
||||
private static native void nSetStencilOpStencilFail(long nativeMaterialInstance, long op,
|
||||
long face);
|
||||
private static native void nSetStencilOpDepthFail(long nativeMaterialInstance, long op,
|
||||
long face);
|
||||
private static native void nSetStencilOpDepthStencilPass(long nativeMaterialInstance, long op,
|
||||
long face);
|
||||
private static native void nSetStencilReferenceValue(long nativeMaterialInstance, int value,
|
||||
long face);
|
||||
private static native void nSetStencilReadMask(long nativeMaterialInstance, int readMask,
|
||||
long face);
|
||||
private static native void nSetStencilWriteMask(long nativeMaterialInstance, int writeMask,
|
||||
long face);
|
||||
|
||||
private static native String nGetName(long nativeMaterialInstance);
|
||||
private static native long nGetMaterial(long nativeMaterialInstance);
|
||||
|
||||
private static native long nDuplicate(long otherNativeMaterialInstance, String name);
|
||||
|
||||
|
||||
private static native float nGetMaskThreshold(long nativeMaterialInstance);
|
||||
private static native float nGetSpecularAntiAliasingVariance(long nativeMaterialInstance);
|
||||
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterialInstance);
|
||||
private static native boolean nIsDoubleSided(long nativeMaterialInstance);
|
||||
private static native int nGetCullingMode(long nativeMaterialInstance);
|
||||
private static native boolean nIsColorWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
|
||||
private static native boolean nIsDepthCullingEnabled(long nativeMaterialInstance);
|
||||
}
|
||||
|
||||
@@ -163,15 +163,6 @@ public class Scene {
|
||||
return nGetLightCount(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the given entity is in the Scene.
|
||||
*
|
||||
* @return Whether the given entity is in the Scene.
|
||||
*/
|
||||
public boolean hasEntity(@Entity int entity) {
|
||||
return nHasEntity(getNativeObject(), entity);
|
||||
}
|
||||
|
||||
public long getNativeObject() {
|
||||
if (mNativeObject == 0) {
|
||||
throw new IllegalStateException("Calling method on destroyed Scene");
|
||||
@@ -191,5 +182,4 @@ public class Scene {
|
||||
private static native void nRemoveEntities(long nativeScene, int[] entities);
|
||||
private static native int nGetRenderableCount(long nativeScene);
|
||||
private static native int nGetLightCount(long nativeScene);
|
||||
private static native boolean nHasEntity(long nativeScene, int entity);
|
||||
}
|
||||
|
||||
@@ -29,6 +29,7 @@ import java.nio.ReadOnlyBufferException;
|
||||
* Stream supports three different configurations:
|
||||
*
|
||||
* <dl>
|
||||
* <dt>TEXTURE_ID</dt> <dd>takes an OpenGL texture ID and incurs a copy</dd>
|
||||
* <dt>ACQUIRED</dt> <dd>connects to an Android AHardwareBuffer</dd>
|
||||
* <dt>NATIVE</dt> <dd>connects to an Android SurfaceTexture</dd>
|
||||
* </dl>
|
||||
@@ -65,6 +66,12 @@ import java.nio.ReadOnlyBufferException;
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* The <b>TEXTURE_ID</b> configuration achieves synchronization automatically. In this mode,
|
||||
* Filament performs a copy on the main thread during beginFrame by blitting the external image into
|
||||
* an internal round-robin queue of images. This copy has a run-time cost.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* For <b>ACQUIRED</b> streams, there is no need to perform the copy because Filament explictly
|
||||
* acquires the stream, then releases it later via a callback function. This configuration is
|
||||
* especially useful when the Vulkan backend is enabled.
|
||||
@@ -111,7 +118,8 @@ public class Stream {
|
||||
* By default, Stream objects are {@link StreamType#ACQUIRED ACQUIRED} and must have external images pushed to them via
|
||||
* {@link #setAcquiredImage}.
|
||||
*
|
||||
* To create a {@link StreamType#NATIVE NATIVE} stream, call the <pre>stream</pre> method on the builder.
|
||||
* To create a {@link StreamType#NATIVE NATIVE} stream, call one of the <pre>stream</pre> methods
|
||||
* on the builder.
|
||||
*/
|
||||
public static class Builder {
|
||||
@SuppressWarnings({"FieldCanBeLocal", "UnusedDeclaration"}) // Keep to finalize native resources
|
||||
@@ -203,7 +211,7 @@ public class Stream {
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates whether this <code>Stream</code> is NATIVE or ACQUIRED.
|
||||
* Indicates whether this <code>Stream</code> is NATIVE, TEXTURE_ID, or ACQUIRED.
|
||||
*/
|
||||
public StreamType getStreamType() {
|
||||
return sStreamTypeValues[nGetStreamType(getNativeObject())];
|
||||
@@ -222,7 +230,7 @@ public class Stream {
|
||||
* also where the callback is invoked. This method can only be used for streams that were
|
||||
* constructed without calling the {@link Builder.stream} method.
|
||||
*
|
||||
* See {@link Stream} for more information about NATIVE and ACQUIRED configurations.
|
||||
* See {@link Stream} for more information about NATIVE, TEXTURE_ID, and ACQUIRED configurations.
|
||||
*
|
||||
* @param hwbuffer {@link android.hardware.HardwareBuffer HardwareBuffer} (requires API level 26)
|
||||
* @param handler {@link java.util.concurrent.Executor Executor} or {@link android.os.Handler Handler}.
|
||||
|
||||
@@ -884,7 +884,7 @@ public class Texture {
|
||||
// TODO: add a setImage() version that takes an android Bitmap
|
||||
|
||||
/**
|
||||
* <code>setImage</code> is used to modify the whole content of the texture from a CPU-buffer.
|
||||
* <code>setImage</code> is used to modify the whole content of the texure from a CPU-buffer.
|
||||
*
|
||||
* <p>This <code>Texture</code> instance must use {@link Sampler#SAMPLER_2D SAMPLER_2D} or
|
||||
* {@link Sampler#SAMPLER_EXTERNAL SAMPLER_EXTERNAL}. If the later is specified
|
||||
@@ -912,7 +912,7 @@ public class Texture {
|
||||
public void setImage(@NonNull Engine engine,
|
||||
@IntRange(from = 0) int level,
|
||||
@NonNull PixelBufferDescriptor buffer) {
|
||||
setImage(engine, level, 0, 0, 0, getWidth(level), getHeight(level), 1, buffer);
|
||||
setImage(engine, level, 0, 0, getWidth(level), getHeight(level), buffer);
|
||||
}
|
||||
|
||||
|
||||
@@ -947,15 +947,33 @@ public class Texture {
|
||||
@IntRange(from = 0) int xoffset, @IntRange(from = 0) int yoffset,
|
||||
@IntRange(from = 0) int width, @IntRange(from = 0) int height,
|
||||
@NonNull PixelBufferDescriptor buffer) {
|
||||
setImage(engine, level, xoffset, yoffset, 0, width, height, 1, buffer);
|
||||
int result;
|
||||
if (buffer.type == COMPRESSED) {
|
||||
result = nSetImageCompressed(getNativeObject(), engine.getNativeObject(), level,
|
||||
xoffset, yoffset, width, height,
|
||||
buffer.storage, buffer.storage.remaining(),
|
||||
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
|
||||
buffer.compressedSizeInBytes, buffer.compressedFormat.ordinal(),
|
||||
buffer.handler, buffer.callback);
|
||||
} else {
|
||||
result = nSetImage(getNativeObject(), engine.getNativeObject(), level,
|
||||
xoffset, yoffset, width, height,
|
||||
buffer.storage, buffer.storage.remaining(),
|
||||
buffer.left, buffer.top, buffer.type.ordinal(), buffer.alignment,
|
||||
buffer.stride, buffer.format.ordinal(),
|
||||
buffer.handler, buffer.callback);
|
||||
}
|
||||
if (result < 0) {
|
||||
throw new BufferOverflowException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* <code>setImage</code> is used to modify a sub-region of a 3D texture, 2D texture array or
|
||||
* cubemap from a CPU-buffer. Cubemaps are treated like a 2D array of six layers.
|
||||
* <code>setImage</code> is used to modify a sub-region of the 3D texture or 2D texture array
|
||||
* from a CPU-buffer.
|
||||
*
|
||||
* <p>This <code>Texture</code> instance must use {@link Sampler#SAMPLER_2D_ARRAY SAMPLER_2D_ARRAY},
|
||||
* {@link Sampler#SAMPLER_3D SAMPLER_3D} or {@link Sampler#SAMPLER_CUBEMAP SAMPLER_CUBEMAP}.</p>
|
||||
* <p>This <code>Texture</code> instance must use {@link Sampler#SAMPLER_2D_ARRAY SAMPLER_2D_ARRAY} or
|
||||
* {@link Sampler#SAMPLER_3D SAMPLER_3D}.</p>
|
||||
*
|
||||
* @param engine {@link Engine} this texture is associated to. Must be the
|
||||
* instance passed to {@link Builder#build Builder.build()}.
|
||||
@@ -1028,9 +1046,7 @@ public class Texture {
|
||||
*
|
||||
* @see Builder#sampler
|
||||
* @see PixelBufferDescriptor
|
||||
* @deprecated use {@link #setImage(Engine, int, int, int, int, int, int, int, PixelBufferDescriptor)}
|
||||
*/
|
||||
@Deprecated
|
||||
public void setImage(@NonNull Engine engine, @IntRange(from = 0) int level,
|
||||
@NonNull PixelBufferDescriptor buffer,
|
||||
@NonNull @Size(min = 6) int[] faceOffsetsInBytes) {
|
||||
@@ -1242,6 +1258,18 @@ public class Texture {
|
||||
private static native int nGetTarget(long nativeTexture);
|
||||
private static native int nGetInternalFormat(long nativeTexture);
|
||||
|
||||
private static native int nSetImage(long nativeTexture, long nativeEngine,
|
||||
int level, int xoffset, int yoffset, int width, int height,
|
||||
Buffer storage, int remaining, int left, int top, int type, int alignment,
|
||||
int stride, int format,
|
||||
Object handler, Runnable callback);
|
||||
|
||||
private static native int nSetImageCompressed(long nativeTexture, long nativeEngine,
|
||||
int level, int xoffset, int yoffset, int width, int height,
|
||||
Buffer storage, int remaining, int left, int top, int type, int alignment,
|
||||
int compressedSizeInBytes, int compressedFormat,
|
||||
Object handler, Runnable callback);
|
||||
|
||||
private static native int nSetImage3D(long nativeTexture, long nativeEngine,
|
||||
int level, int xoffset, int yoffset, int zoffset, int width, int height, int depth,
|
||||
Buffer storage, int remaining, int left, int top, int type, int alignment,
|
||||
|
||||
@@ -16,7 +16,6 @@
|
||||
|
||||
package com.google.android.filament;
|
||||
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Size;
|
||||
@@ -200,36 +199,6 @@ import androidx.annotation.Size;
|
||||
return nGetParent(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the number of children of an {@link EntityInstance}.
|
||||
*
|
||||
* @param i the {@link EntityInstance} of the transform component to query.
|
||||
* @return The number of children of the queried component.
|
||||
*/
|
||||
public int getChildCount(@EntityInstance int i) {
|
||||
return nGetChildCount(mNativeObject, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a list of children for a transform component.
|
||||
*
|
||||
* @param i the {@link EntityInstance} of the transform component to get the children
|
||||
* from.
|
||||
* @param outEntities array to receive the result sized to the maximum number of children to
|
||||
* retrieve. If <code>null</code> is given, a new suitable array sized to
|
||||
* {@link #getChildCount(int)} is allocated.
|
||||
* @return Array of retrieved children {@link Entity}.
|
||||
*/
|
||||
public @Entity @NonNull int[] getChildren(@EntityInstance int i, @Nullable int[] outEntities) {
|
||||
if (outEntities == null) {
|
||||
outEntities = new int[getChildCount(i)];
|
||||
}
|
||||
if (outEntities.length > 0) {
|
||||
nGetChildren(mNativeObject, i, outEntities, outEntities.length);
|
||||
}
|
||||
return outEntities;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a local transform of a transform component.
|
||||
* <p>This operation can be slow if the hierarchy of transform is too deep, and this
|
||||
@@ -391,8 +360,6 @@ import androidx.annotation.Size;
|
||||
private static native void nDestroy(long nativeTransformManager, int entity);
|
||||
private static native void nSetParent(long nativeTransformManager, int i, int newParent);
|
||||
private static native int nGetParent(long nativeTransformManager, int i);
|
||||
private static native int nGetChildCount(long nativeTransformManager, int i);
|
||||
private static native void nGetChildren(long nativeEntityManager, int i, int[] outEntities, int count);
|
||||
private static native void nSetTransform(long nativeTransformManager, int i, float[] localTransform);
|
||||
private static native void nSetTransformFp64(long nativeTransformManager, int i, double[] localTransform);
|
||||
private static native void nGetTransform(long nativeTransformManager, int i, float[] outLocalTransform);
|
||||
|
||||
@@ -793,7 +793,7 @@ public class View {
|
||||
public void setVsmShadowOptions(@NonNull VsmShadowOptions options) {
|
||||
mVsmShadowOptions = options;
|
||||
nSetVsmShadowOptions(getNativeObject(), options.anisotropy, options.mipmapping,
|
||||
options.highPrecision, options.minVarianceScale, options.lightBleedReduction);
|
||||
options.minVarianceScale, options.lightBleedReduction);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1011,45 +1011,6 @@ public class View {
|
||||
return mDepthOfFieldOptions;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enables use of the stencil buffer.
|
||||
*
|
||||
* <p>
|
||||
* The stencil buffer is an 8-bit, per-fragment unsigned integer stored alongside the depth
|
||||
* buffer. The stencil buffer is cleared at the beginning of a frame and discarded after the
|
||||
* color pass.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Each fragment's stencil value is set during rasterization by specifying stencil operations on
|
||||
* a {@link Material}. The stencil buffer can be used as a mask for later rendering by setting a
|
||||
* {@link Material}'s stencil comparison function and reference value. Fragments that don't pass
|
||||
* the stencil test are then discarded.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* Post-processing must be enabled in order to use the stencil buffer.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* A renderable's priority (see {@link RenderableManager#setPriority(int, int)}) is useful to
|
||||
* control the order in which primitives are drawn.
|
||||
* </p>
|
||||
*
|
||||
* @param enabled True to enable the stencil buffer, false disables it (default)
|
||||
*/
|
||||
public void setStencilBufferEnabled(boolean enabled) {
|
||||
nSetStencilBufferEnabled(getNativeObject(), enabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return true if the stencil buffer is enabled.
|
||||
* @see View#setStencilBufferEnabled(boolean)
|
||||
*/
|
||||
public boolean isStencilBufferEnabled() {
|
||||
return nIsStencilBufferEnabled(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* A class containing the result of a picking query
|
||||
*/
|
||||
@@ -1144,7 +1105,7 @@ public class View {
|
||||
private static native void nSetRenderQuality(long nativeView, int hdrColorBufferQuality);
|
||||
private static native void nSetDynamicLightingOptions(long nativeView, float zLightNear, float zLightFar);
|
||||
private static native void nSetShadowType(long nativeView, int type);
|
||||
private static native void nSetVsmShadowOptions(long nativeView, int anisotropy, boolean mipmapping, boolean highPrecision, float minVarianceScale, float lightBleedReduction);
|
||||
private static native void nSetVsmShadowOptions(long nativeView, int anisotropy, boolean mipmapping, float minVarianceScale, float lightBleedReduction);
|
||||
private static native void nSetSoftShadowOptions(long nativeView, float penumbraScale, float penumbraRatioScale);
|
||||
private static native void nSetColorGrading(long nativeView, long nativeColorGrading);
|
||||
private static native void nSetPostProcessingEnabled(long nativeView, boolean enabled);
|
||||
@@ -1170,8 +1131,6 @@ public class View {
|
||||
private static native void nSetGuardBandOptions(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);
|
||||
private static native void nSetStencilBufferEnabled(long nativeView, boolean enabled);
|
||||
private static native boolean nIsStencilBufferEnabled(long nativeView);
|
||||
|
||||
/**
|
||||
* List of available ambient occlusion techniques.
|
||||
@@ -1817,13 +1776,6 @@ public class View {
|
||||
* Whether to generate mipmaps for all VSM shadow maps.
|
||||
*/
|
||||
public boolean mipmapping = false;
|
||||
/**
|
||||
* Whether to use a 32-bits or 16-bits texture format for VSM shadow maps. 32-bits
|
||||
* precision is rarely needed, but it does reduces light leaks as well as "fading"
|
||||
* of the shadows in some situations. Setting highPrecision to true for a single
|
||||
* shadow map will double the memory usage of all shadow maps.
|
||||
*/
|
||||
public boolean highPrecision = false;
|
||||
/**
|
||||
* VSM minimum variance scale, must be positive.
|
||||
*/
|
||||
|
||||
@@ -70,8 +70,7 @@ Java_com_google_android_filament_utils_AutomationEngine_nStartBatchMode(JNIEnv*
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nTick(JNIEnv* env, jclass klass,
|
||||
jlong nativeAutomation, jlong nativeEngine,
|
||||
jlong view, jlongArray materials, jlong renderer, jfloat deltaTime) {
|
||||
jlong nativeAutomation, jlong view, jlongArray materials, jlong renderer, jfloat deltaTime) {
|
||||
using MaterialPointer = MaterialInstance*;
|
||||
jsize materialCount = 0;
|
||||
jlong* longMaterials = nullptr;
|
||||
@@ -91,8 +90,7 @@ Java_com_google_android_filament_utils_AutomationEngine_nTick(JNIEnv* env, jclas
|
||||
.materials = ptrMaterials,
|
||||
.materialCount = (size_t) materialCount,
|
||||
};
|
||||
Engine* engine = (Engine*)nativeEngine;
|
||||
automation->tick(engine, content, deltaTime);
|
||||
automation->tick(content, deltaTime);
|
||||
if (longMaterials) {
|
||||
env->ReleaseLongArrayElements(materials, longMaterials, 0);
|
||||
delete[] ptrMaterials;
|
||||
@@ -101,8 +99,7 @@ Java_com_google_android_filament_utils_AutomationEngine_nTick(JNIEnv* env, jclas
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_utils_AutomationEngine_nApplySettings(JNIEnv* env, jclass klass,
|
||||
jlong nativeAutomation, jlong nativeEngine,
|
||||
jstring json, jlong view, jlongArray materials, jlong nativeIbl,
|
||||
jlong nativeAutomation, jstring json, jlong view, jlongArray materials, jlong nativeIbl,
|
||||
jint sunlightEntity, jintArray assetLights, jlong nativeLm, jlong scene, jlong renderer) {
|
||||
using MaterialPointer = MaterialInstance*;
|
||||
|
||||
@@ -143,8 +140,8 @@ Java_com_google_android_filament_utils_AutomationEngine_nApplySettings(JNIEnv* e
|
||||
.assetLights = (Entity*) intLights,
|
||||
.assetLightCount = (size_t) lightCount,
|
||||
};
|
||||
Engine* engine = (Engine*)nativeEngine;
|
||||
automation->applySettings(engine, nativeJson, jsonLength, content);
|
||||
|
||||
automation->applySettings(nativeJson, jsonLength, content);
|
||||
env->ReleaseStringUTFChars(json, nativeJson);
|
||||
if (longMaterials) {
|
||||
env->ReleaseLongArrayElements(materials, longMaterials, 0);
|
||||
|
||||
@@ -156,11 +156,10 @@ public class AutomationEngine {
|
||||
* This is when settings get applied, screenshots are (optionally) exported, and the internal
|
||||
* test counter is potentially incremented.
|
||||
*
|
||||
* @param engine The filament Engine of interest.
|
||||
* @param content Contains the Filament View, Materials, and Renderer that get modified.
|
||||
* @param deltaTime The amount of time that has passed since the previous tick in seconds.
|
||||
*/
|
||||
public void tick(@NonNull Engine engine, @NonNull ViewerContent content, float deltaTime) {
|
||||
public void tick(@NonNull ViewerContent content, float deltaTime) {
|
||||
if (content.view == null || content.renderer == null) {
|
||||
throw new IllegalStateException("Must provide a View and Renderer");
|
||||
}
|
||||
@@ -173,7 +172,7 @@ public class AutomationEngine {
|
||||
}
|
||||
long nativeView = content.view.getNativeObject();
|
||||
long nativeRenderer = content.renderer.getNativeObject();
|
||||
nTick(mNativeObject, engine.getNativeObject(), nativeView, nativeMaterialInstances, nativeRenderer, deltaTime);
|
||||
nTick(mNativeObject, nativeView, nativeMaterialInstances, nativeRenderer, deltaTime);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -185,12 +184,10 @@ public class AutomationEngine {
|
||||
* This updates the stashed Settings object, then pushes those settings to the given
|
||||
* Filament objects. Clients can optionally call getColorGrading() after calling this method.
|
||||
*
|
||||
* @param engine Filament Engine to use.
|
||||
* @param settingsJson Contains the JSON string with a set of changes that need to be pushed.
|
||||
* @param content Contains a set of Filament objects that you want to mutate.
|
||||
*/
|
||||
public void applySettings(@NonNull Engine engine, @NonNull String settingsJson,
|
||||
@NonNull ViewerContent content) {
|
||||
public void applySettings(@NonNull String settingsJson, @NonNull ViewerContent content) {
|
||||
if (content.view == null || content.renderer == null) {
|
||||
throw new IllegalStateException("Must provide a View and Renderer");
|
||||
}
|
||||
@@ -209,8 +206,7 @@ public class AutomationEngine {
|
||||
long nativeLm = content.lightManager.getNativeObject();
|
||||
long nativeScene = content.scene.getNativeObject();
|
||||
long nativeRenderer = content.renderer.getNativeObject();
|
||||
nApplySettings(mNativeObject, engine.getNativeObject(),
|
||||
settingsJson, nativeView, nativeMaterialInstances,
|
||||
nApplySettings(mNativeObject, settingsJson, nativeView, nativeMaterialInstances,
|
||||
nativeIbl, content.sunlight, content.assetLights, nativeLm, nativeScene,
|
||||
nativeRenderer);
|
||||
}
|
||||
@@ -271,10 +267,9 @@ public class AutomationEngine {
|
||||
int minFrameCount, boolean verbose);
|
||||
private static native void nStartRunning(long nativeObject);
|
||||
private static native void nStartBatchMode(long nativeObject);
|
||||
private static native void nTick(long nativeObject, long nativeEngine,
|
||||
long view, long[] materials, long renderer, float deltaTime);
|
||||
private static native void nApplySettings(long nativeObject, long nativeEngine,
|
||||
String jsonSettings, long view,
|
||||
private static native void nTick(long nativeObject, long view, long[] materials, long renderer,
|
||||
float deltaTime);
|
||||
private static native void nApplySettings(long nativeObject, String jsonSettings, long view,
|
||||
long[] materials, long ibl, int sunlight, int[] assetLights, long lightManager,
|
||||
long scene, long renderer);
|
||||
private static native void nGetViewerOptions(long nativeObject, Object result);
|
||||
|
||||
@@ -73,6 +73,8 @@ class ModelViewer(
|
||||
get() = resourceLoader.asyncGetLoadProgress()
|
||||
|
||||
var normalizeSkinningWeights = true
|
||||
var recomputeBoundingBoxes = false
|
||||
var ignoreBindTransform = false
|
||||
|
||||
var cameraFocalLength = 28f
|
||||
set(value) {
|
||||
@@ -114,7 +116,7 @@ class ModelViewer(
|
||||
|
||||
materialProvider = UbershaderProvider(engine)
|
||||
assetLoader = AssetLoader(engine, materialProvider, EntityManager.get())
|
||||
resourceLoader = ResourceLoader(engine, normalizeSkinningWeights)
|
||||
resourceLoader = ResourceLoader(engine, normalizeSkinningWeights, recomputeBoundingBoxes, ignoreBindTransform)
|
||||
|
||||
// Always add a direct light source since it is required for shadowing.
|
||||
// We highly recommend adding an indirect light as well.
|
||||
@@ -176,10 +178,10 @@ class ModelViewer(
|
||||
*/
|
||||
fun loadModelGlb(buffer: Buffer) {
|
||||
destroyModel()
|
||||
asset = assetLoader.createAsset(buffer)
|
||||
asset = assetLoader.createAssetFromBinary(buffer)
|
||||
asset?.let { asset ->
|
||||
resourceLoader.asyncBeginLoad(asset)
|
||||
animator = asset.getInstance().animator
|
||||
animator = asset.animator
|
||||
asset.releaseSourceData()
|
||||
}
|
||||
}
|
||||
@@ -191,7 +193,7 @@ class ModelViewer(
|
||||
*/
|
||||
fun loadModelGltf(buffer: Buffer, callback: (String) -> Buffer?) {
|
||||
destroyModel()
|
||||
asset = assetLoader.createAsset(buffer)
|
||||
asset = assetLoader.createAssetFromJson(buffer)
|
||||
asset?.let { asset ->
|
||||
for (uri in asset.resourceUris) {
|
||||
val resourceBuffer = callback(uri)
|
||||
@@ -202,7 +204,7 @@ class ModelViewer(
|
||||
resourceLoader.addResourceData(uri, resourceBuffer)
|
||||
}
|
||||
resourceLoader.asyncBeginLoad(asset)
|
||||
animator = asset.getInstance().animator
|
||||
animator = asset.animator
|
||||
asset.releaseSourceData()
|
||||
}
|
||||
}
|
||||
@@ -214,7 +216,7 @@ class ModelViewer(
|
||||
*/
|
||||
fun loadModelGltfAsync(buffer: Buffer, callback: (String) -> Buffer) {
|
||||
destroyModel()
|
||||
asset = assetLoader.createAsset(buffer)
|
||||
asset = assetLoader.createAssetFromJson(buffer)
|
||||
fetchResourcesJob = CoroutineScope(Dispatchers.IO).launch {
|
||||
fetchResources(asset!!, callback)
|
||||
}
|
||||
@@ -310,8 +312,8 @@ class ModelViewer(
|
||||
|
||||
private fun addDetachListener(view: android.view.View) {
|
||||
view.addOnAttachStateChangeListener(object : android.view.View.OnAttachStateChangeListener {
|
||||
override fun onViewAttachedToWindow(v: android.view.View) {}
|
||||
override fun onViewDetachedFromWindow(v: android.view.View) {
|
||||
override fun onViewAttachedToWindow(v: android.view.View?) {}
|
||||
override fun onViewDetachedFromWindow(v: android.view.View?) {
|
||||
uiHelper.detach()
|
||||
|
||||
destroyModel()
|
||||
@@ -359,7 +361,7 @@ class ModelViewer(
|
||||
resourceLoader.addResourceData(uri, buffer)
|
||||
}
|
||||
resourceLoader.asyncBeginLoad(asset)
|
||||
animator = asset.getInstance().animator
|
||||
animator = asset.animator
|
||||
asset.releaseSourceData()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,10 +11,6 @@ add_library(dracodec STATIC IMPORTED)
|
||||
set_target_properties(dracodec PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libdracodec.a)
|
||||
|
||||
add_library(meshoptimizer STATIC IMPORTED)
|
||||
set_target_properties(meshoptimizer PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libmeshoptimizer.a)
|
||||
|
||||
add_library(ktxreader STATIC IMPORTED)
|
||||
set_target_properties(ktxreader PROPERTIES IMPORTED_LOCATION
|
||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libktxreader.a)
|
||||
@@ -80,7 +76,7 @@ set(GLTFIO_SRCS
|
||||
${GLTFIO_DIR}/src/UbershaderProvider.cpp
|
||||
${GLTFIO_DIR}/src/Wireframe.cpp
|
||||
${GLTFIO_DIR}/src/Wireframe.h
|
||||
${GLTFIO_DIR}/src/downcast.h
|
||||
${GLTFIO_DIR}/src/upcast.h
|
||||
|
||||
src/main/cpp/Animator.cpp
|
||||
src/main/cpp/AssetLoader.cpp
|
||||
@@ -103,7 +99,6 @@ set(GLTFIO_INCLUDE_DIRS
|
||||
../../libs/gltfio/include
|
||||
../../third_party/basisu/zstd
|
||||
../../third_party/cgltf
|
||||
../../third_party/meshoptimizer/src
|
||||
../../third_party/robin-map
|
||||
../../third_party/hat-trie
|
||||
../../third_party/stb
|
||||
@@ -116,7 +111,7 @@ target_include_directories(gltfio-jni PRIVATE ${GLTFIO_INCLUDE_DIRS})
|
||||
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.symbols)
|
||||
set_target_properties(gltfio-jni PROPERTIES LINK_DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/libgltfio-jni.map)
|
||||
target_link_libraries(gltfio-jni filament-jni utils uberzlib log stb ktxreader basis_transcoder zstd uberarchive)
|
||||
target_link_libraries(gltfio-jni dracodec meshoptimizer)
|
||||
target_link_libraries(gltfio-jni dracodec)
|
||||
target_compile_definitions(gltfio-jni PUBLIC GLTFIO_DRACO_SUPPORTED=1)
|
||||
target_include_directories(gltfio-jni PRIVATE ${DRACO_DIR}/src)
|
||||
target_include_directories(gltfio-jni PRIVATE ${DRACO_DIR}/tnt)
|
||||
|
||||
@@ -14,4 +14,5 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android" />
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.gltfio" />
|
||||
|
||||
@@ -42,7 +42,6 @@ class JavaMaterialProvider : public MaterialProvider {
|
||||
|
||||
jmethodID mMaterialKeyConstructor;
|
||||
jmethodID mCreateMaterialInstance;
|
||||
jmethodID mGetMaterial;
|
||||
jmethodID mGetMaterials;
|
||||
jmethodID mNeedsDummyData;
|
||||
jmethodID mDestroyMaterials;
|
||||
@@ -73,10 +72,6 @@ public:
|
||||
"(L" JAVA_MATERIAL_KEY ";[ILjava/lang/String;Ljava/lang/String;)Lcom/google/android/filament/MaterialInstance;");
|
||||
assert_invariant(mCreateMaterialInstance);
|
||||
|
||||
mGetMaterial = env->GetMethodID(providerClass, "getMaterial",
|
||||
"(L" JAVA_MATERIAL_KEY ";[ILjava/lang/String;)Lcom/google/android/filament/Material;");
|
||||
assert_invariant(mGetMaterial);
|
||||
|
||||
mGetMaterials = env->GetMethodID(providerClass, "getMaterials",
|
||||
"()[Lcom/google/android/filament/Material;");
|
||||
assert_invariant(mGetMaterials);
|
||||
@@ -108,7 +103,7 @@ public:
|
||||
jstring stringExtras = extras ? mEnv->NewStringUTF(extras) : nullptr;
|
||||
|
||||
// Allocate space for the output argument.
|
||||
jintArray uvMapArray = mEnv->NewIntArray(uvmap->size());
|
||||
jintArray uvMapArray = mEnv->NewIntArray(8);
|
||||
|
||||
// Call the Java-based material provider.
|
||||
jobject materialInstance = mEnv->CallObjectMethod(mJavaProvider, mCreateMaterialInstance,
|
||||
@@ -144,49 +139,6 @@ public:
|
||||
return (MaterialInstance*) mEnv->CallLongMethod(materialInstance, mMaterialInstanceGetNativeObject);
|
||||
}
|
||||
|
||||
Material* getMaterial(MaterialKey* config, UvMap* uvmap, const char* label) override {
|
||||
// Create a Java object for the material key and copy the native fields into it.
|
||||
jobject javaKey = mEnv->NewObject(mMaterialKeyClass, mMaterialKeyConstructor);
|
||||
|
||||
auto& helper = MaterialKeyHelper::get();
|
||||
helper.copy(mEnv, javaKey, *config);
|
||||
|
||||
// Convert the optional label into a Java string.
|
||||
jstring stringLabel = label ? mEnv->NewStringUTF(label) : nullptr;
|
||||
|
||||
// Allocate space for the output argument.
|
||||
jintArray uvMapArray = mEnv->NewIntArray(uvmap->size());
|
||||
|
||||
// Call the Java-based material provider.
|
||||
jobject material = mEnv->CallObjectMethod(mJavaProvider, mGetMaterial,
|
||||
javaKey, uvMapArray, stringLabel);
|
||||
|
||||
// Copy the UvMap results from the JVM array into the native array.
|
||||
if (uvmap) {
|
||||
jint* elements = mEnv->GetIntArrayElements(uvMapArray, nullptr);
|
||||
for (size_t i = 0; i < uvmap->size(); i++) {
|
||||
(*uvmap)[i] = (UvSet) elements[i];
|
||||
}
|
||||
mEnv->ReleaseIntArrayElements(uvMapArray, elements, JNI_ABORT);
|
||||
}
|
||||
|
||||
// The config parameter is an in-out parameter so we need to copy the results from Java.
|
||||
helper.copy(mEnv, *config, javaKey);
|
||||
|
||||
mEnv->DeleteLocalRef(javaKey);
|
||||
mEnv->DeleteLocalRef(uvMapArray);
|
||||
|
||||
if (stringLabel) {
|
||||
mEnv->DeleteLocalRef(stringLabel);
|
||||
}
|
||||
|
||||
if (material == nullptr) {
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
return (Material*) mEnv->CallLongMethod(material, mMaterialGetNativeObject);
|
||||
}
|
||||
|
||||
const Material* const* getMaterials() const noexcept override {
|
||||
jobjectArray javaMaterials = (jobjectArray) mEnv->CallObjectMethod(mJavaProvider, mGetMaterials);
|
||||
|
||||
@@ -255,11 +207,20 @@ Java_com_google_android_filament_gltfio_AssetLoader_nDestroyAssetLoader(JNIEnv*,
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nCreateAsset(JNIEnv* env, jclass,
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetFromBinary(JNIEnv* env, jclass,
|
||||
jlong nativeLoader, jobject javaBuffer, jint remaining) {
|
||||
AssetLoader* loader = (AssetLoader*) nativeLoader;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
return (jlong) loader->createAsset((const uint8_t *) buffer.getData(),
|
||||
return (jlong) loader->createAssetFromBinary((const uint8_t *) buffer.getData(),
|
||||
buffer.getSize());
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_AssetLoader_nCreateAssetFromJson(JNIEnv* env, jclass,
|
||||
jlong nativeLoader, jobject javaBuffer, jint remaining) {
|
||||
AssetLoader* loader = (AssetLoader*) nativeLoader;
|
||||
AutoBuffer buffer(env, javaBuffer, remaining);
|
||||
return (jlong) loader->createAssetFromJson((const uint8_t *) buffer.getData(),
|
||||
buffer.getSize());
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,27 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetCameraEntityCount(JNIE
|
||||
return asset->getCameraEntityCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMaterialInstanceCount(JNIEnv*, jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return asset->getMaterialInstanceCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMaterialInstances(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jlongArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
jsize count = std::min(available, (jsize) asset->getMaterialInstanceCount());
|
||||
jlong* dst = env->GetLongArrayElements(result, nullptr);
|
||||
const MaterialInstance * const* src = asset->getMaterialInstances();
|
||||
for (jsize i = 0; i < count; i++) {
|
||||
dst[i] = (jlong) src[i];
|
||||
}
|
||||
env->ReleaseLongArrayElements(result, dst, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetBoundingBox(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jfloatArray result) {
|
||||
@@ -207,11 +228,49 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetExtras(JNIEnv* env, jc
|
||||
return val ? env->NewStringUTF(val) : nullptr;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetInstance(JNIEnv* , jclass,
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinCount(JNIEnv* , jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return (jlong) asset->getInstance();
|
||||
return (jint) asset->getSkinCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetSkinNames(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jobjectArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
for (int i = 0; i < available; ++i) {
|
||||
const char* name = asset->getSkinNameAt(i);
|
||||
if (name) {
|
||||
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointCountAt(JNIEnv* , jclass,
|
||||
jlong nativeAsset, jint skinIndex) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return (jint) asset->getJointCountAt(skinIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetJointsAt(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jint skinIndex, jintArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
|
||||
std::copy_n(asset->getJointsAt(skinIndex),
|
||||
std::min(available, (jsize) asset->getJointCountAt(skinIndex)), entities);
|
||||
env->ReleaseIntArrayElements(result, (jint*) entities, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetAnimator(JNIEnv* , jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return (jlong) asset->getAnimator();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
@@ -251,9 +310,49 @@ Java_com_google_android_filament_gltfio_FilamentAsset_nGetMorphTargetNames(JNIEn
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMaterialVariantCount(JNIEnv*, jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
return (jint) asset->getMaterialVariantCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nGetMaterialVariantNames(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jobjectArray result) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
for (int i = 0; i < asset->getMaterialVariantCount(); ++i) {
|
||||
const char* name = asset->getMaterialVariantName(i);
|
||||
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nApplyMaterialVariant(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jint variantIndex) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
asset->applyMaterialVariant(variantIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nReleaseSourceData(JNIEnv* env, jclass,
|
||||
jlong nativeAsset) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
asset->releaseSourceData();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nAttachSkin(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jint skinIndex, jint targetEntity) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
Entity target = Entity::import(targetEntity);
|
||||
asset->attachSkin(skinIndex, target);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentAsset_nDetachSkin(JNIEnv* env, jclass,
|
||||
jlong nativeAsset, jint skinIndex, jint targetEntity) {
|
||||
FilamentAsset* asset = (FilamentAsset*) nativeAsset;
|
||||
Entity target = Entity::import(targetEntity);
|
||||
asset->detachSkin(skinIndex, target);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
|
||||
#include <algorithm>
|
||||
|
||||
using namespace filament;
|
||||
using namespace filament::gltfio;
|
||||
using namespace utils;
|
||||
|
||||
@@ -62,95 +61,3 @@ Java_com_google_android_filament_gltfio_FilamentInstance_nApplyMaterialVariant(J
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
instance->applyMaterialVariant(variantIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetMaterialVariantCount(JNIEnv*, jclass,
|
||||
jlong nativeInstance) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
return (jint) instance->getMaterialVariantCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetMaterialVariantNames(JNIEnv* env, jclass,
|
||||
jlong nativeInstance, jobjectArray result) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
for (int i = 0; i < instance->getMaterialVariantCount(); ++i) {
|
||||
const char* name = instance->getMaterialVariantName(i);
|
||||
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetMaterialInstanceCount(JNIEnv*, jclass,
|
||||
jlong nativeInstance) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
return instance->getMaterialInstanceCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetMaterialInstances(JNIEnv* env, jclass,
|
||||
jlong nativeInstance, jlongArray result) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
jsize count = std::min(available, (jsize) instance->getMaterialInstanceCount());
|
||||
jlong* dst = env->GetLongArrayElements(result, nullptr);
|
||||
const MaterialInstance * const* src = instance->getMaterialInstances();
|
||||
for (jsize i = 0; i < count; i++) {
|
||||
dst[i] = (jlong) src[i];
|
||||
}
|
||||
env->ReleaseLongArrayElements(result, dst, 0);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nAttachSkin(JNIEnv* env, jclass,
|
||||
jlong nativeInstance, jint skinIndex, jint targetEntity) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
Entity target = Entity::import(targetEntity);
|
||||
instance->attachSkin(skinIndex, target);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nDetachSkin(JNIEnv* env, jclass,
|
||||
jlong nativeInstance, jint skinIndex, jint targetEntity) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
Entity target = Entity::import(targetEntity);
|
||||
instance->detachSkin(skinIndex, target);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetSkinCount(JNIEnv* , jclass,
|
||||
jlong nativeInstance) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
return (jint) instance->getSkinCount();
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetSkinNames(JNIEnv* env, jclass,
|
||||
jlong nativeInstance, jobjectArray result) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
for (int i = 0; i < available; ++i) {
|
||||
const char* name = instance->getSkinNameAt(i);
|
||||
if (name) {
|
||||
env->SetObjectArrayElement(result, (jsize) i, env->NewStringUTF(name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT jint JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetJointCountAt(JNIEnv* , jclass,
|
||||
jlong nativeInstance, jint skinIndex) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
return (jint) instance->getJointCountAt(skinIndex);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_gltfio_FilamentInstance_nGetJointsAt(JNIEnv* env, jclass,
|
||||
jlong nativeInstance, jint skinIndex, jintArray result) {
|
||||
FilamentInstance* instance = (FilamentInstance*) nativeInstance;
|
||||
jsize available = env->GetArrayLength(result);
|
||||
Entity* entities = (Entity*) env->GetIntArrayElements(result, nullptr);
|
||||
std::copy_n(instance->getJointsAt(skinIndex),
|
||||
std::min(available, (jsize) instance->getJointCountAt(skinIndex)), entities);
|
||||
env->ReleaseIntArrayElements(result, (jint*) entities, 0);
|
||||
}
|
||||
|
||||
@@ -36,9 +36,11 @@ static void destroy(void*, size_t, void *userData) {
|
||||
|
||||
extern "C" JNIEXPORT jlong JNICALL
|
||||
Java_com_google_android_filament_gltfio_ResourceLoader_nCreateResourceLoader(JNIEnv*, jclass,
|
||||
jlong nativeEngine, jboolean normalizeSkinningWeights) {
|
||||
jlong nativeEngine, jboolean normalizeSkinningWeights, jboolean recomputeBoundingBoxes,
|
||||
jboolean ignoreBindTransform) {
|
||||
Engine* engine = (Engine*) nativeEngine;
|
||||
return (jlong) new ResourceLoader({ engine, {}, (bool) normalizeSkinningWeights});
|
||||
return (jlong) new ResourceLoader({ engine, {}, (bool) normalizeSkinningWeights,
|
||||
(bool) recomputeBoundingBoxes, (bool) ignoreBindTransform});
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
|
||||
@@ -49,46 +49,6 @@ Java_com_google_android_filament_gltfio_UbershaderProvider_nDestroyMaterials(JNI
|
||||
|
||||
extern "C" JNIEXPORT long JNICALL
|
||||
Java_com_google_android_filament_gltfio_UbershaderProvider_nCreateMaterialInstance(JNIEnv* env, jclass,
|
||||
jlong nativeProvider, jobject materialKey, jintArray uvmap, jstring label, jstring extras) {
|
||||
MaterialKey nativeKey = {};
|
||||
|
||||
auto& helper = MaterialKeyHelper::get();
|
||||
helper.copy(env, nativeKey, materialKey);
|
||||
|
||||
const char* nativeLabel = label ? env->GetStringUTFChars(label, nullptr) : nullptr;
|
||||
const char* nativeExtras = extras ? env->GetStringUTFChars(extras, nullptr) : nullptr;
|
||||
|
||||
UvMap nativeUvMap = {};
|
||||
auto provider = (MaterialProvider*) nativeProvider;
|
||||
MaterialInstance* instance = provider->createMaterialInstance(&nativeKey, &nativeUvMap,
|
||||
nativeLabel, nativeExtras);
|
||||
|
||||
// Copy the UvMap results from the native array into the JVM array.
|
||||
jint* elements = env->GetIntArrayElements(uvmap, nullptr);
|
||||
if (elements) {
|
||||
const size_t javaSize = env->GetArrayLength(uvmap);
|
||||
for (int i = 0, n = std::min(javaSize, nativeUvMap.size()); i < n; ++i) {
|
||||
elements[i] = nativeUvMap[i];
|
||||
}
|
||||
env->ReleaseIntArrayElements(uvmap, elements, 0);
|
||||
}
|
||||
|
||||
// The config parameter is an in-out parameter so we need to copy the results back to Java.
|
||||
helper.copy(env, materialKey, nativeKey);
|
||||
|
||||
if (label) {
|
||||
env->ReleaseStringUTFChars(label, nativeLabel);
|
||||
}
|
||||
|
||||
if (extras) {
|
||||
env->ReleaseStringUTFChars(extras, nativeExtras);
|
||||
}
|
||||
|
||||
return (long) instance;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT long JNICALL
|
||||
Java_com_google_android_filament_gltfio_UbershaderProvider_nGetMaterial(JNIEnv* env, jclass,
|
||||
jlong nativeProvider, jobject materialKey, jintArray uvmap, jstring label) {
|
||||
MaterialKey nativeKey = {};
|
||||
|
||||
@@ -96,10 +56,9 @@ Java_com_google_android_filament_gltfio_UbershaderProvider_nGetMaterial(JNIEnv*
|
||||
helper.copy(env, nativeKey, materialKey);
|
||||
|
||||
const char* nativeLabel = label ? env->GetStringUTFChars(label, nullptr) : nullptr;
|
||||
|
||||
UvMap nativeUvMap = {};
|
||||
auto provider = (MaterialProvider*) nativeProvider;
|
||||
Material* material = provider->getMaterial(&nativeKey, &nativeUvMap, nativeLabel);
|
||||
MaterialInstance* instance = provider->createMaterialInstance(&nativeKey, &nativeUvMap, nativeLabel);
|
||||
|
||||
// Copy the UvMap results from the native array into the JVM array.
|
||||
jint* elements = env->GetIntArrayElements(uvmap, nullptr);
|
||||
@@ -118,7 +77,7 @@ Java_com_google_android_filament_gltfio_UbershaderProvider_nGetMaterial(JNIEnv*
|
||||
env->ReleaseStringUTFChars(label, nativeLabel);
|
||||
}
|
||||
|
||||
return (long) material;
|
||||
return (long) instance;
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT int JNICALL
|
||||
|
||||
@@ -26,8 +26,8 @@ import java.nio.Buffer;
|
||||
|
||||
/**
|
||||
* Consumes a blob of glTF 2.0 content (either JSON or GLB) and produces a {@link FilamentAsset}
|
||||
* object, which is a bundle of Filament textures, vertex buffers, index buffers, etc. An asset is
|
||||
* composed of 1 or more FilamentInstance objects which contain entities and components.
|
||||
* object, which is a bundle of Filament entities, material instances, textures, vertex buffers,
|
||||
* and index buffers.
|
||||
*
|
||||
* <p>AssetLoader does not fetch external buffer data or create textures on its own. Clients can use
|
||||
* the provided {@link ResourceLoader} class for this, which obtains the URI list from the asset.
|
||||
@@ -51,7 +51,7 @@ import java.nio.Buffer;
|
||||
* filamentAsset = assets.open("models/lucy.gltf").use { input ->
|
||||
* val bytes = ByteArray(input.available())
|
||||
* input.read(bytes)
|
||||
* assetLoader.createAsset(ByteBuffer.wrap(bytes))!!
|
||||
* assetLoader.createAssetFromJson(ByteBuffer.wrap(bytes))!!
|
||||
* }
|
||||
*
|
||||
* val resourceLoader = ResourceLoader(engine)
|
||||
@@ -115,11 +115,20 @@ public class AssetLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link FilamentAsset} from the contents of a GLB or GLTF file.
|
||||
* Creates a {@link FilamentAsset} from the contents of a GLB file.
|
||||
*/
|
||||
@Nullable
|
||||
public FilamentAsset createAsset(@NonNull Buffer buffer) {
|
||||
long nativeAsset = nCreateAsset(mNativeObject, buffer, buffer.remaining());
|
||||
public FilamentAsset createAssetFromBinary(@NonNull Buffer buffer) {
|
||||
long nativeAsset = nCreateAssetFromBinary(mNativeObject, buffer, buffer.remaining());
|
||||
return nativeAsset != 0 ? new FilamentAsset(mEngine, nativeAsset) : null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a {@link FilamentAsset} from the contents of a GLTF file.
|
||||
*/
|
||||
@Nullable
|
||||
public FilamentAsset createAssetFromJson(@NonNull Buffer buffer) {
|
||||
long nativeAsset = nCreateAssetFromJson(mNativeObject, buffer, buffer.remaining());
|
||||
return nativeAsset != 0 ? new FilamentAsset(mEngine, nativeAsset) : null;
|
||||
}
|
||||
|
||||
@@ -149,7 +158,7 @@ public class AssetLoader {
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new instance to the asset.
|
||||
* Adds a new instance to an instanced asset.
|
||||
*
|
||||
* Use this with caution. It is more efficient to pre-allocate a max number of instances, and
|
||||
* gradually add them to the scene as needed. Instances can also be "recycled" by removing and
|
||||
@@ -160,6 +169,8 @@ public class AssetLoader {
|
||||
* create/destroy churn, as noted above.
|
||||
*
|
||||
* This cannot be called after FilamentAsset#releaseSourceData().
|
||||
* This cannot be called on a non-instanced asset.
|
||||
* Animation is not supported in new instances.
|
||||
* See also AssetLoader#createInstancedAsset().
|
||||
*/
|
||||
@Nullable
|
||||
@@ -191,7 +202,8 @@ public class AssetLoader {
|
||||
private static native long nCreateAssetLoader(long nativeEngine, Object provider,
|
||||
long nativeEntities);
|
||||
private static native void nDestroyAssetLoader(long nativeLoader);
|
||||
private static native long nCreateAsset(long nativeLoader, Buffer buffer, int remaining);
|
||||
private static native long nCreateAssetFromBinary(long nativeLoader, Buffer buffer, int remaining);
|
||||
private static native long nCreateAssetFromJson(long nativeLoader, Buffer buffer, int remaining);
|
||||
private static native long nCreateInstancedAsset(long nativeLoader, Buffer buffer, int remaining,
|
||||
long[] nativeInstances);
|
||||
private static native long nCreateInstance(long nativeLoader, long nativeAsset);
|
||||
|
||||
@@ -23,6 +23,7 @@ import androidx.annotation.Nullable;
|
||||
import com.google.android.filament.Box;
|
||||
import com.google.android.filament.Engine;
|
||||
import com.google.android.filament.Entity;
|
||||
import com.google.android.filament.MaterialInstance;
|
||||
|
||||
/**
|
||||
* Owns a bundle of Filament objects that have been created by <code>AssetLoader</code>.
|
||||
@@ -34,32 +35,25 @@ import com.google.android.filament.Entity;
|
||||
* <code>NameComponentManager</code>, <code>RenderableManager</code>, and others.</p>
|
||||
*
|
||||
* <p>In addition to the aforementioned entities, an asset has strong ownership over a list of
|
||||
* <code>VertexBuffer</code>, <code>IndexBuffer</code>, and <code>Texture</code>.</p>
|
||||
* <code>VertexBuffer</code>, <code>IndexBuffer</code>, <code>MaterialInstance</code>, and
|
||||
* <code>Texture</code>.</p>
|
||||
*
|
||||
* <p>Clients can use {@link ResourceLoader} to create textures, compute tangent quaternions, and
|
||||
* upload data into vertex buffers and index buffers.</p>
|
||||
*
|
||||
* @see ResourceLoader
|
||||
* @see FilamentInstance
|
||||
* @see Animator
|
||||
* @see AssetLoader
|
||||
*/
|
||||
public class FilamentAsset {
|
||||
private long mNativeObject;
|
||||
private FilamentInstance mPrimaryInstance;
|
||||
private Animator mAnimator;
|
||||
private Engine mEngine;
|
||||
|
||||
FilamentAsset(Engine engine, long nativeObject) {
|
||||
mEngine = engine;
|
||||
mNativeObject = nativeObject;
|
||||
}
|
||||
|
||||
public FilamentInstance getInstance() {
|
||||
if (mPrimaryInstance != null) {
|
||||
return mPrimaryInstance;
|
||||
}
|
||||
long nativeInstance = nGetInstance(getNativeObject());
|
||||
mPrimaryInstance = new FilamentInstance(this, nativeInstance);
|
||||
return mPrimaryInstance;
|
||||
mAnimator = null;
|
||||
}
|
||||
|
||||
long getNativeObject() {
|
||||
@@ -175,11 +169,19 @@ public class FilamentAsset {
|
||||
return result;
|
||||
}
|
||||
|
||||
public @NonNull MaterialInstance[] getMaterialInstances() {
|
||||
final int count = nGetMaterialInstanceCount(mNativeObject);
|
||||
MaterialInstance[] result = new MaterialInstance[count];
|
||||
long[] natives = new long[count];
|
||||
nGetMaterialInstances(mNativeObject, natives);
|
||||
for (int i = 0; i < count; i++) {
|
||||
result[i] = new MaterialInstance(mEngine, natives[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the bounding box computed from the supplied min / max values in glTF accessors.
|
||||
*
|
||||
* This does not return a bounding box over all FilamentInstance, it's just a straightforward
|
||||
* AAAB that can be determined at load time from the asset data.
|
||||
*/
|
||||
public @NonNull Box getBoundingBox() {
|
||||
float[] box = new float[6];
|
||||
@@ -204,6 +206,77 @@ public class FilamentAsset {
|
||||
return nGetExtras(mNativeObject, entity);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the <code>Animator</code> interface for this asset.
|
||||
*
|
||||
* <p>When calling this for the first time, this must be called after
|
||||
* {@link ResourceLoader#loadResources} or {@link ResourceLoader#asyncBeginLoad}. When the asset
|
||||
* is destroyed, its animator becomes invalid.</p>
|
||||
*/
|
||||
public @NonNull Animator getAnimator() {
|
||||
if (mAnimator != null) {
|
||||
return mAnimator;
|
||||
}
|
||||
long nativeAnimator = nGetAnimator(getNativeObject());
|
||||
if (nativeAnimator == 0) {
|
||||
throw new IllegalStateException("Unable to create animator");
|
||||
}
|
||||
mAnimator = new Animator(nativeAnimator);
|
||||
return mAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin count of this asset.
|
||||
*/
|
||||
public int getSkinCount() {
|
||||
return nGetSkinCount(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin name at skin index in this asset.
|
||||
*/
|
||||
public @NonNull String[] getSkinNames() {
|
||||
String[] result = new String[getSkinCount()];
|
||||
nGetSkinNames(getNativeObject(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the given skin to the given node, which must have an associated mesh with
|
||||
* BONE_INDICES and BONE_WEIGHTS attributes.
|
||||
*
|
||||
* This is a no-op if the given skin index or target is invalid.
|
||||
*/
|
||||
public void attachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
|
||||
nAttachSkin(getNativeObject(), skinIndex, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the given skin to the given node, which must have an associated mesh with
|
||||
* BONE_INDICES and BONE_WEIGHTS attributes.
|
||||
*
|
||||
* This is a no-op if the given skin index or target is invalid.
|
||||
*/
|
||||
public void detachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
|
||||
nDetachSkin(getNativeObject(), skinIndex, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the joint count at skin index in this asset.
|
||||
*/
|
||||
public int getJointCountAt(@IntRange(from = 0) int skinIndex) {
|
||||
return nGetJointCountAt(getNativeObject(), skinIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets joints at skin index in this asset.
|
||||
*/
|
||||
public @NonNull @Entity int[] getJointsAt(@IntRange(from = 0) int skinIndex) {
|
||||
int[] result = new int[getJointCountAt(skinIndex)];
|
||||
nGetJointsAt(getNativeObject(), skinIndex, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the names of all morph targets in the given entity.
|
||||
*/
|
||||
@@ -222,6 +295,31 @@ public class FilamentAsset {
|
||||
return uris;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of all material variants.
|
||||
*/
|
||||
public @NonNull String[] getMaterialVariantNames() {
|
||||
String[] names = new String[nGetMaterialVariantCount(mNativeObject)];
|
||||
nGetMaterialVariantNames(mNativeObject, names);
|
||||
return names;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given material variant to all primitives that it affects.
|
||||
*
|
||||
* This is efficient because it merely swaps around persistent MaterialInstances. If you change
|
||||
* a material parameter while a certain variant is active, the updated value will be remembered
|
||||
* after you re-apply that variant.
|
||||
*
|
||||
* If the asset is instanced, this affects all instances in the same way.
|
||||
* To set the variant on an individual instance, use FilamentInstance#applyMaterialVariant.
|
||||
*
|
||||
* Ignored if variantIndex is out of bounds.
|
||||
*/
|
||||
public void applyMaterialVariant(@IntRange(from = 0) int variantIndex) {
|
||||
nApplyMaterialVariant(getNativeObject(), variantIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Reclaims CPU-side memory for URI strings, binding lists, and raw animation data.
|
||||
*
|
||||
@@ -233,10 +331,8 @@ public class FilamentAsset {
|
||||
nReleaseSourceData(mNativeObject);
|
||||
}
|
||||
|
||||
public Engine getEngine() { return mEngine; }
|
||||
|
||||
void clearNativeObject() {
|
||||
mPrimaryInstance = null;
|
||||
if (mAnimator != null) mAnimator.clearNativeObject();
|
||||
mNativeObject = 0;
|
||||
}
|
||||
|
||||
@@ -260,17 +356,28 @@ public class FilamentAsset {
|
||||
private static native int nGetCameraEntityCount(long nativeAsset);
|
||||
private static native void nGetCameraEntities(long nativeAsset, int[] result);
|
||||
|
||||
private static native int nGetMaterialInstanceCount(long nativeAsset);
|
||||
private static native void nGetMaterialInstances(long nativeAsset, long[] nativeResults);
|
||||
|
||||
private static native int nGetMaterialVariantCount(long nativeAsset);
|
||||
private static native void nGetMaterialVariantNames(long nativeAsset, String[] result);
|
||||
|
||||
private static native int nGetMorphTargetCount(long nativeAsset, int entity);
|
||||
private static native void nGetMorphTargetNames(long nativeAsset, int entity, String[] result);
|
||||
|
||||
private static native void nAttachSkin(long nativeAsset, int skinIndex, int entity);
|
||||
private static native void nDetachSkin(long nativeAsset, int skinIndex, int entity);
|
||||
|
||||
private static native void nGetBoundingBox(long nativeAsset, float[] box);
|
||||
private static native String nGetName(long nativeAsset, int entity);
|
||||
private static native String nGetExtras(long nativeAsset, int entity);
|
||||
|
||||
private static native long nGetInstance(long nativeAsset);
|
||||
|
||||
private static native long nGetAnimator(long nativeAsset);
|
||||
private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
|
||||
private static native int nGetSkinCount(long nativeAsset);
|
||||
private static native void nGetSkinNames(long nativeAsset, String[] result);
|
||||
private static native int nGetJointCountAt(long nativeAsset, int skinIndex);
|
||||
private static native void nGetJointsAt(long nativeAsset, int skinIndex, int[] result);
|
||||
private static native int nGetResourceUriCount(long nativeAsset);
|
||||
private static native void nGetResourceUris(long nativeAsset, String[] result);
|
||||
|
||||
private static native void nReleaseSourceData(long nativeAsset);
|
||||
}
|
||||
|
||||
@@ -19,9 +19,7 @@ package com.google.android.filament.gltfio;
|
||||
import androidx.annotation.IntRange;
|
||||
import androidx.annotation.NonNull;
|
||||
|
||||
import com.google.android.filament.Engine;
|
||||
import com.google.android.filament.Entity;
|
||||
import com.google.android.filament.MaterialInstance;
|
||||
|
||||
/**
|
||||
* Provides access to a hierarchy of entities that have been instanced from a glTF asset.
|
||||
@@ -87,58 +85,6 @@ public class FilamentInstance {
|
||||
return mAnimator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin count of this instance.
|
||||
*/
|
||||
public int getSkinCount() {
|
||||
return nGetSkinCount(getNativeObject());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the skin name at skin index in this instance.
|
||||
*/
|
||||
public @NonNull String[] getSkinNames() {
|
||||
String[] result = new String[getSkinCount()];
|
||||
nGetSkinNames(getNativeObject(), result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the given skin to the given node, which must have an associated mesh with
|
||||
* BONE_INDICES and BONE_WEIGHTS attributes.
|
||||
*
|
||||
* This is a no-op if the given skin index or target is invalid.
|
||||
*/
|
||||
public void attachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
|
||||
nAttachSkin(getNativeObject(), skinIndex, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Attaches the given skin to the given node, which must have an associated mesh with
|
||||
* BONE_INDICES and BONE_WEIGHTS attributes.
|
||||
*
|
||||
* This is a no-op if the given skin index or target is invalid.
|
||||
*/
|
||||
public void detachSkin(@IntRange(from = 0) int skinIndex, @Entity int target) {
|
||||
nDetachSkin(getNativeObject(), skinIndex, target);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the joint count at skin index in this instance.
|
||||
*/
|
||||
public int getJointCountAt(@IntRange(from = 0) int skinIndex) {
|
||||
return nGetJointCountAt(getNativeObject(), skinIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets joints at skin index in this instance.
|
||||
*/
|
||||
public @NonNull @Entity int[] getJointsAt(@IntRange(from = 0) int skinIndex) {
|
||||
int[] result = new int[getJointCountAt(skinIndex)];
|
||||
nGetJointsAt(getNativeObject(), skinIndex, result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies the given material variant to all primitives in this instance.
|
||||
*
|
||||
@@ -148,43 +94,9 @@ public class FilamentInstance {
|
||||
nApplyMaterialVariant(mNativeObject, variantIndex);
|
||||
}
|
||||
|
||||
public @NonNull MaterialInstance[] getMaterialInstances() {
|
||||
final int count = nGetMaterialInstanceCount(mNativeObject);
|
||||
MaterialInstance[] result = new MaterialInstance[count];
|
||||
long[] natives = new long[count];
|
||||
nGetMaterialInstances(mNativeObject, natives);
|
||||
Engine engine = mAsset.getEngine();
|
||||
for (int i = 0; i < count; i++) {
|
||||
result[i] = new MaterialInstance(engine, natives[i]);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the names of all material variants.
|
||||
*/
|
||||
public @NonNull String[] getMaterialVariantNames() {
|
||||
String[] names = new String[nGetMaterialVariantCount(mNativeObject)];
|
||||
nGetMaterialVariantNames(mNativeObject, names);
|
||||
return names;
|
||||
}
|
||||
|
||||
private static native int nGetRoot(long nativeInstance);
|
||||
private static native int nGetEntityCount(long nativeInstance);
|
||||
private static native void nGetEntities(long nativeInstance, int[] result);
|
||||
private static native long nGetAnimator(long nativeInstance);
|
||||
|
||||
private static native int nGetMaterialInstanceCount(long nativeAsset);
|
||||
private static native void nGetMaterialInstances(long nativeAsset, long[] nativeResults);
|
||||
|
||||
private static native void nApplyMaterialVariant(long nativeInstance, int variantIndex);
|
||||
private static native int nGetMaterialVariantCount(long nativeAsset);
|
||||
private static native void nGetMaterialVariantNames(long nativeAsset, String[] result);
|
||||
|
||||
private static native void nGetJointsAt(long nativeInstance, int skinIndex, int[] result);
|
||||
private static native int nGetSkinCount(long nativeInstance);
|
||||
private static native void nGetSkinNames(long nativeInstance, String[] result);
|
||||
private static native int nGetJointCountAt(long nativeInstance, int skinIndex);
|
||||
private static native void nAttachSkin(long nativeInstance, int skinIndex, int entity);
|
||||
private static native void nDetachSkin(long nativeInstance, int skinIndex, int entity);
|
||||
private static native int nGetRoot(long nativeAsset);
|
||||
private static native int nGetEntityCount(long nativeAsset);
|
||||
private static native void nGetEntities(long nativeAsset, int[] result);
|
||||
private static native long nGetAnimator(long nativeAsset);
|
||||
private static native void nApplyMaterialVariant(long nativeAsset, int variantIndex);
|
||||
}
|
||||
|
||||
@@ -24,16 +24,12 @@ import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
import androidx.annotation.Size;
|
||||
|
||||
import com.google.android.filament.proguard.UsedByNative;
|
||||
|
||||
@UsedByNative("AssetLoader.cpp")
|
||||
public interface MaterialProvider {
|
||||
|
||||
/**
|
||||
* MaterialKey specifies the requirements for a requested glTF material.
|
||||
* The provider creates Filament materials that fulfill these requirements.
|
||||
*/
|
||||
@UsedByNative("MaterialKey.cpp")
|
||||
public static class MaterialKey {
|
||||
public boolean doubleSided;
|
||||
public boolean unlit;
|
||||
@@ -108,12 +104,6 @@ public interface MaterialProvider {
|
||||
public @Nullable MaterialInstance createMaterialInstance(MaterialKey config,
|
||||
@NonNull @Size(min = 8) int[] uvmap, @Nullable String label, @Nullable String extras);
|
||||
|
||||
/**
|
||||
* Creates or fetches a compiled Filament material corresponding to the given config.
|
||||
*/
|
||||
public @Nullable Material getMaterial(MaterialKey config, @NonNull @Size(min = 8) int[] uvmap,
|
||||
@Nullable String label);
|
||||
|
||||
/**
|
||||
* Creates and returns an array containing all cached materials.
|
||||
*/
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ResourceLoader {
|
||||
*/
|
||||
public ResourceLoader(@NonNull Engine engine) {
|
||||
long nativeEngine = engine.getNativeObject();
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, false);
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, false, false, false);
|
||||
mNativeStbProvider = nCreateStbProvider(nativeEngine);
|
||||
mNativeKtx2Provider = nCreateKtx2Provider(nativeEngine);
|
||||
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeStbProvider);
|
||||
@@ -60,12 +60,16 @@ public class ResourceLoader {
|
||||
*
|
||||
* @param engine the engine that gets passed to all builder methods
|
||||
* @param normalizeSkinningWeights scale non-conformant skinning weights so they sum to 1
|
||||
* @param recomputeBoundingBoxes use computed bounding boxes rather than the ones in the asset
|
||||
* @param ignoreBindTransform ignore skinned primitives bind transform when compute bounding boxes
|
||||
* @throws IllegalAccessException
|
||||
* @throws InvocationTargetException
|
||||
*/
|
||||
public ResourceLoader(@NonNull Engine engine, boolean normalizeSkinningWeights) {
|
||||
public ResourceLoader(@NonNull Engine engine, boolean normalizeSkinningWeights,
|
||||
boolean recomputeBoundingBoxes, boolean ignoreBindTransform) {
|
||||
long nativeEngine = engine.getNativeObject();
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, normalizeSkinningWeights);
|
||||
mNativeObject = nCreateResourceLoader(nativeEngine, normalizeSkinningWeights,
|
||||
recomputeBoundingBoxes, ignoreBindTransform);
|
||||
mNativeStbProvider = nCreateStbProvider(nativeEngine);
|
||||
mNativeKtx2Provider = nCreateKtx2Provider(nativeEngine);
|
||||
nAddTextureProvider(mNativeObject, "image/jpeg", mNativeStbProvider);
|
||||
@@ -177,7 +181,7 @@ public class ResourceLoader {
|
||||
}
|
||||
|
||||
private static native long nCreateResourceLoader(long nativeEngine,
|
||||
boolean normalizeSkinningWeights);
|
||||
boolean normalizeSkinningWeights, boolean recomputeBoundingBoxes, boolean ignoreBindTransform);
|
||||
private static native void nDestroyResourceLoader(long nativeLoader);
|
||||
private static native void nAddResourceData(long nativeLoader, String url, Buffer buffer,
|
||||
int remaining);
|
||||
|
||||
@@ -57,16 +57,10 @@ public class UbershaderProvider implements MaterialProvider {
|
||||
|
||||
public @Nullable MaterialInstance createMaterialInstance(MaterialKey config,
|
||||
@NonNull @Size(min = 8) int[] uvmap, @Nullable String label, @Nullable String extras) {
|
||||
long nativeMaterialInstance = nCreateMaterialInstance(mNativeObject, config, uvmap, label, extras);
|
||||
long nativeMaterialInstance = nCreateMaterialInstance(mNativeObject, config, uvmap, label);
|
||||
return nativeMaterialInstance == 0 ? null : new MaterialInstance(null, nativeMaterialInstance);
|
||||
}
|
||||
|
||||
public @Nullable Material getMaterial(MaterialKey config, @NonNull @Size(min = 8) int[] uvmap,
|
||||
@Nullable String label) {
|
||||
long nativeMaterial = nGetMaterial(mNativeObject, config, uvmap, label);
|
||||
return nativeMaterial == 0 ? null : new Material(nativeMaterial);
|
||||
}
|
||||
|
||||
public @NonNull Material[] getMaterials() {
|
||||
final int count = nGetMaterialCount(mNativeObject);
|
||||
Material[] result = new Material[count];
|
||||
@@ -102,8 +96,6 @@ public class UbershaderProvider implements MaterialProvider {
|
||||
private static native void nDestroyUbershaderProvider(long nativeProvider);
|
||||
private static native void nDestroyMaterials(long nativeProvider);
|
||||
private static native long nCreateMaterialInstance(long nativeProvider,
|
||||
MaterialKey config, int[] uvmap, String label, String extras);
|
||||
private static native long nGetMaterial(long nativeProvider,
|
||||
MaterialKey config, int[] uvmap, String label);
|
||||
private static native int nGetMaterialCount(long nativeProvider);
|
||||
private static native void nGetMaterials(long nativeProvider, long[] result);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.28.2
|
||||
VERSION_NAME=1.25.3
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
@@ -19,6 +19,10 @@ org.gradle.jvmargs=-Xmx1536m
|
||||
|
||||
android.useAndroidX=true
|
||||
|
||||
org.gradle.unsafe.configuration-cache=true
|
||||
# TODO: Remove this when we switch to Gradle 7.4
|
||||
org.gradle.unsafe.configuration-cache.max-problems=3
|
||||
|
||||
com.google.android.filament.tools-dir=../../../out/release/filament
|
||||
com.google.android.filament.dist-dir=../out/android-release/filament
|
||||
com.google.android.filament.abis=all
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#Wed Nov 17 10:40:18 PST 2021
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
14
android/proguard-rules.pro
vendored
14
android/proguard-rules.pro
vendored
@@ -14,17 +14,3 @@
|
||||
-keepclassmembers class * {
|
||||
@com.google.android.filament.proguard.UsedBy* *;
|
||||
}
|
||||
|
||||
# These classes is loaded via env->FindClass() from Utils.cpp
|
||||
# They are in the utils namespace and therefore not covered by previous rules.
|
||||
-keep class com.google.android.filament.utils.KTX1Loader
|
||||
-keep class com.google.android.filament.utils.HDRLoader
|
||||
|
||||
# These native JNI methods are loaded via env->RegisterNatives() from Utils.cpp
|
||||
-keepclassmembers class com.google.android.filament.utils.KTX1Loader {
|
||||
native <methods>;
|
||||
}
|
||||
-keepclassmembers class com.google.android.filament.utils.HDRLoader {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
|
||||
@@ -112,9 +112,9 @@ the Android SDK.
|
||||
|
||||
## Android Studio
|
||||
|
||||
You must use the latest stable release of Android Studio. To open the project, point Studio to the
|
||||
`android` folder. After opening the project and syncing to gradle, select the sample of your choice
|
||||
using the drop-down widget in the toolbar.
|
||||
You must use Android Studio 3.6 RC 1 or higher. To open the project, point Studio to the `android`
|
||||
folder. After opening the project and syncing to gradle, select the sample of your choice using the
|
||||
drop-down widget in the toolbar.
|
||||
|
||||
## Compiling
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.gltf">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
|
||||
@@ -353,7 +353,7 @@ class MainActivity : Activity() {
|
||||
fun loadSettings(message: RemoteServer.ReceivedMessage) {
|
||||
val json = StandardCharsets.UTF_8.decode(message.buffer).toString()
|
||||
viewerContent.assetLights = modelViewer.asset?.lightEntities
|
||||
automation.applySettings(modelViewer.engine, json, viewerContent)
|
||||
automation.applySettings(json, viewerContent)
|
||||
modelViewer.view.colorGrading = automation.getColorGrading(modelViewer.engine)
|
||||
modelViewer.cameraFocalLength = automation.viewerOptions.cameraFocalLength
|
||||
updateRootTransform()
|
||||
@@ -417,7 +417,7 @@ class MainActivity : Activity() {
|
||||
|
||||
// Just for testing purposes, this releases the current model and reloads the default model.
|
||||
inner class DoubleTapListener : GestureDetector.SimpleOnGestureListener() {
|
||||
override fun onDoubleTap(e: MotionEvent): Boolean {
|
||||
override fun onDoubleTap(e: MotionEvent?): Boolean {
|
||||
modelViewer.destroyModel()
|
||||
createDefaultRenderables()
|
||||
return super.onDoubleTap(e)
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.hellocam">
|
||||
|
||||
<uses-permission android:name="android.permission.CAMERA" />
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.hellotriangle">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.ibl">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.litcube">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.livewallpaper">
|
||||
|
||||
<uses-feature android:name="android.software.live_wallpaper" />
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.material_builder">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.multiview">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.pagecurl">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -16,7 +16,8 @@
|
||||
limitations under the License.
|
||||
-->
|
||||
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.streamtest">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.textureview">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.textured">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="com.google.android.filament.transparentrendering">
|
||||
|
||||
<application
|
||||
android:allowBackup="true"
|
||||
|
||||
11
build.sh
11
build.sh
@@ -44,8 +44,6 @@ function print_help {
|
||||
echo " Add iOS simulator support to the iOS build."
|
||||
echo " -t"
|
||||
echo " Enable SwiftShader support for Vulkan in desktop builds."
|
||||
echo " -e"
|
||||
echo " Enable EGL on Linux support for desktop builds."
|
||||
echo " -l"
|
||||
echo " Build arm64/x86_64 universal libraries."
|
||||
echo " For iOS, this builds universal binaries for devices and the simulator (implies -s)."
|
||||
@@ -157,8 +155,6 @@ VULKAN_ANDROID_GRADLE_OPTION=""
|
||||
|
||||
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=OFF"
|
||||
|
||||
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=OFF"
|
||||
|
||||
MATDBG_OPTION="-DFILAMENT_ENABLE_MATDBG=OFF"
|
||||
MATDBG_GRADLE_OPTION=""
|
||||
|
||||
@@ -219,7 +215,6 @@ function build_desktop_target {
|
||||
-DCMAKE_BUILD_TYPE="$1" \
|
||||
-DCMAKE_INSTALL_PREFIX="../${lc_target}/filament" \
|
||||
${SWIFTSHADER_OPTION} \
|
||||
${EGL_ON_LINUX_OPTION} \
|
||||
${MATDBG_OPTION} \
|
||||
${deployment_target} \
|
||||
${architectures} \
|
||||
@@ -740,7 +735,7 @@ function run_tests {
|
||||
|
||||
pushd "$(dirname "$0")" > /dev/null
|
||||
|
||||
while getopts ":hacCfijmp:q:uvslwtedk:" opt; do
|
||||
while getopts ":hacCfijmp:q:uvslwtdk:" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
@@ -847,10 +842,6 @@ while getopts ":hacCfijmp:q:uvslwtedk:" opt; do
|
||||
SWIFTSHADER_OPTION="-DFILAMENT_USE_SWIFTSHADER=ON"
|
||||
echo "SwiftShader support enabled."
|
||||
;;
|
||||
e)
|
||||
EGL_ON_LINUX_OPTION="-DFILAMENT_SUPPORTS_EGL_ON_LINUX=ON -DFILAMENT_SKIP_SDL2=ON -DFILAMENT_SKIP_SAMPLES=ON"
|
||||
echo "EGL on Linux support enabled; skipping SDL2."
|
||||
;;
|
||||
l)
|
||||
IOS_BUILD_SIMULATOR=true
|
||||
BUILD_UNIVERSAL_LIBRARIES=true
|
||||
|
||||
@@ -1 +1 @@
|
||||
25.1.8937393
|
||||
24.0.8215888
|
||||
@@ -1,99 +0,0 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
set -e
|
||||
|
||||
function print_help {
|
||||
local self_name=$(basename "$0")
|
||||
echo "This tool verifies that every Metal shader in the given Filament material file(s) successfully compiles."
|
||||
echo "Requires the matinfo tool and xcrun to be on the system PATH."
|
||||
echo ""
|
||||
echo "Usage:"
|
||||
echo " $self_name [options] [<material> ...]"
|
||||
echo ""
|
||||
echo "Options:"
|
||||
echo " -h"
|
||||
echo " Print this help message."
|
||||
echo " -w"
|
||||
echo " Pass the -w flag to the Metal compiler, to disable warnings."
|
||||
echo ""
|
||||
}
|
||||
|
||||
COMP_FLAGS=""
|
||||
while getopts ":hw" opt; do
|
||||
case ${opt} in
|
||||
h)
|
||||
print_help
|
||||
exit 1
|
||||
;;
|
||||
w)
|
||||
COMP_FLAGS="${COMP_FLAGS} -w"
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
if [[ "$#" == "0" ]]; then
|
||||
print_help
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure matinfo and xcrun are available.
|
||||
if [[ ! $(command -v matinfo) ]]; then
|
||||
echo "Error: matinfo not on PATH."
|
||||
exit 1
|
||||
fi
|
||||
if [[ ! $(command -v xcrun) ]]; then
|
||||
echo "Error: xcrun not on PATH."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
function check_material {
|
||||
local material="$1"
|
||||
|
||||
tmpdir="$(mktemp -d /tmp/check_metal_shaders.XXXXX)"
|
||||
|
||||
# First check that the material is valid.
|
||||
if [[ ! $(matinfo "${material}") ]]; then
|
||||
echo "Invalid material file: ${material}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "Checking that Metal shaders compile: ${material}"
|
||||
|
||||
set +e
|
||||
local i=0
|
||||
while true; do
|
||||
# The file must have a .metal extension.
|
||||
metalFile="${tmpdir}/${i}.metal"
|
||||
|
||||
# Extract shader i. matinfo will return a non-zero exit code if the shader doesn't exist,
|
||||
# which means we're finished with this material.
|
||||
matinfo --print-metal=${i} "${material}" > "${metalFile}" 2> /dev/null
|
||||
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
break
|
||||
fi
|
||||
|
||||
echo "Testing Metal shader ${i}"
|
||||
|
||||
# Attempt to compile the Metal shader.
|
||||
xcrun -sdk macosx metal ${COMP_FLAGS} -c "${metalFile}" -o /dev/null
|
||||
|
||||
if [[ "$?" -ne 0 ]]; then
|
||||
echo "Error compiling Metal shader: ${metalFile}"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
((i++))
|
||||
done
|
||||
set -e
|
||||
|
||||
rm -r "${tmpdir}"
|
||||
}
|
||||
|
||||
for material in "$@"
|
||||
do
|
||||
check_material "${material}"
|
||||
done
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
setuptools==58.0.4
|
||||
setuptools==40.6.2
|
||||
wheel==0.37.1
|
||||
certifi==2022.9.24
|
||||
cffi==1.15.1
|
||||
charset-normalizer==2.1.1
|
||||
certifi==2021.10.8
|
||||
cffi==1.15.0
|
||||
charset-normalizer==2.0.12
|
||||
Deprecated==1.2.13
|
||||
idna==3.4
|
||||
idna==3.3
|
||||
pycparser==2.21
|
||||
PyGithub==1.56
|
||||
PyJWT==2.6.0
|
||||
PyGithub==1.55
|
||||
PyJWT==2.4.0
|
||||
PyNaCl==1.5.0
|
||||
requests==2.28.1
|
||||
urllib3==1.26.12
|
||||
wrapt==1.14.1
|
||||
requests==2.27.1
|
||||
urllib3==1.26.9
|
||||
wrapt==1.14.0
|
||||
|
||||
@@ -17,7 +17,7 @@ export PATH="$PWD:$PATH"
|
||||
# npm install -g typescript
|
||||
|
||||
# Install emscripten.
|
||||
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.15.zip > emsdk.zip
|
||||
curl -L https://github.com/emscripten-core/emsdk/archive/refs/tags/3.1.9.zip > emsdk.zip
|
||||
unzip emsdk.zip ; mv emsdk-* emsdk ; cd emsdk
|
||||
./emsdk install latest
|
||||
./emsdk activate latest
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -1143,7 +1143,7 @@ Where $F(v,h)$ is the Fresnel term of the cloth specular BRDF in equation $\ref{
|
||||
Subsurface scattering is implemented using the wrapped diffuse lighting technique, in its energy conservative form:
|
||||
|
||||
$$\begin{equation}
|
||||
f_{d}(v,h) = \frac{c_{diff}}{\pi}(1 - F(v,h)) \left< \frac{\NoL + w}{(1 + w)^2} \right> \left< c_{subsurface} + \NoL \right>
|
||||
f_{d}(v,h) = \frac{c_{diff}}{\pi}(1 - F(v,h)) \left< \NoL + \frac{w}{(1 + w)^2} \right> \left< c_{subsurface} + \NoL \right>
|
||||
\end{equation}$$
|
||||
|
||||
Where $w$ is a value between 0 and 1 defining by how much the diffuse light should wrap around the terminator. To avoid introducing another parameter, we fix $w = 0.5$. Note that with wrap diffuse lighting, the diffuse term must not be multiplied by $\NoL$. The effect of this cheap
|
||||
@@ -1435,7 +1435,7 @@ The term $ \lambda(l) $ in equations $ \ref{spotAbsorber} $ and $ \ref{spotRefle
|
||||
$ \ref{spotAngleAtt} $ below.
|
||||
|
||||
$$\begin{equation}\label{spotAngleAtt}
|
||||
\lambda(l) = \frac{l \cdot spotDirection - cos\theta_{outer}}{cos\theta_{inner} - cos\theta_{outer}}
|
||||
\lambda(l) = \frac{l \times spotDirection - cos\theta_{outer}}{cos\theta_{inner} - cos\theta_{outer}}
|
||||
\end{equation}$$
|
||||
|
||||
#### Attenuation function
|
||||
@@ -3682,7 +3682,7 @@ However we only need the real bases:
|
||||
|
||||
$$\begin{align*}
|
||||
y^{m > 0}_l &= \sqrt{2} K^m_l cos(m \phi) P^m_l(cos \theta) \\
|
||||
y^{m < 0}_l &= \sqrt{2} K^m_l sin(|m| \phi) P^{|m|}_l(cos \theta) \\
|
||||
y^{m < 0}_l &= \sqrt{2} K^m_l sin(m \phi) P^{|m|}_l(cos \theta) \\
|
||||
y^0_l &= K^0_l P^0_l(cos \theta)
|
||||
\end{align*}$$
|
||||
|
||||
@@ -3716,18 +3716,19 @@ $l = 2$ | $y^{-2}_2$ $y^{-1}_2$ $y^0_2$ $y^1_2$ $y^2_2$
|
||||
It’s also fairly easy to compute the trigonometric terms recursively:
|
||||
|
||||
$$\begin{align*}
|
||||
C_m &\equiv cos(m \phi)sin(\theta)^m \\
|
||||
S_m &\equiv sin(m \phi)sin(\theta)^m \\
|
||||
C_m &\equiv cos(m \phi) \\
|
||||
S_m &\equiv sin(m \phi) \\
|
||||
\{ x, y, z \} &= \{ cos \phi sin \theta, sin \phi sin \theta, cos \theta \}
|
||||
\end{align*}$$
|
||||
|
||||
Using the angle sum trigonometric identities:
|
||||
|
||||
$$\begin{align*}
|
||||
cos(m \phi + \phi) &= cos(m \phi) cos(\phi) - sin(m \phi) sin(\phi) \Leftrightarrow C_{m + 1} = x C_m - y S_m \\
|
||||
sin(m \phi + \phi) &= sin(m \phi) cos(\phi) + cos(m \phi) sin(\phi) \Leftrightarrow S_{m + 1} = x S_m - y C_m
|
||||
cos(m \phi + \phi) &= cos(m \phi) cos(\phi) - sin(m \phi) sin(\phi) \Leftrightarrow C_{m + 1} = \frac{(x C_m - y S_m)}{sin(\theta)^{|m + 1|}} \\
|
||||
sin(m \phi + \phi) &= sin(m \phi) sin(\phi) + cos(m \phi) sin(\phi) \Leftrightarrow S_{m + 1} = \frac{(x S_m - y C_m)}{sin(\theta)^{|m + 1|}}
|
||||
\end{align*}$$
|
||||
|
||||
The equations above have an extra term $sin(\theta)^{-|m + 1|}$ but we can compensate for that in the $P^{|m|}_l(z)$ recursion by multiplying $P^l_l(z)$ by $sin(\theta)^{|m + 1|}$ which greatly simplifies the third equation in $\ref{shRecursions}$ because $P^l_l(cos \theta) sin(\theta)^{-l} = (-1)^l(2l - 1)!!$.
|
||||
|
||||
Listing [nonNormalizedSHBasis] shows the C++ code to compute the non-normalized SH basis $\frac{y^m_l(s)}{\sqrt{2} K^m_l}$:
|
||||
|
||||
|
||||
@@ -86,39 +86,36 @@ counter-increment: h6;margin-right:10px}
|
||||
<a href="#materialdefinitions/format/example" class="level3"><span class="tocNumber">4.1.2 </span>Example</a><br>
|
||||
<a href="#materialdefinitions/materialblock" class="level2"><span class="tocNumber">4.2 </span>Material block</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:name" class="level3"><span class="tocNumber">4.2.1 </span>General: name</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:featurelevel" class="level3"><span class="tocNumber">4.2.2 </span>General: featureLevel</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:shadingmodel" class="level3"><span class="tocNumber">4.2.3 </span>General: shadingModel</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:parameters" class="level3"><span class="tocNumber">4.2.4 </span>General: parameters</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:variantfilter" class="level3"><span class="tocNumber">4.2.5 </span>General: variantFilter</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:flipuv" class="level3"><span class="tocNumber">4.2.6 </span>General: flipUV</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:quality" class="level3"><span class="tocNumber">4.2.7 </span>General: quality</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:instanced" class="level3"><span class="tocNumber">4.2.8 </span>General: instanced</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:vertexdomaindevicejittered" class="level3"><span class="tocNumber">4.2.9 </span>General: vertexDomainDeviceJittered</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:requires" class="level3"><span class="tocNumber">4.2.10 </span>Vertex and attributes: requires</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:variables" class="level3"><span class="tocNumber">4.2.11 </span>Vertex and attributes: variables</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:vertexdomain" class="level3"><span class="tocNumber">4.2.12 </span>Vertex and attributes: vertexDomain</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:interpolation" class="level3"><span class="tocNumber">4.2.13 </span>Vertex and attributes: interpolation</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:blending" class="level3"><span class="tocNumber">4.2.14 </span>Blending and transparency: blending</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:postlightingblending" class="level3"><span class="tocNumber">4.2.15 </span>Blending and transparency: postLightingBlending</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:transparency" class="level3"><span class="tocNumber">4.2.16 </span>Blending and transparency: transparency</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:maskthreshold" class="level3"><span class="tocNumber">4.2.17 </span>Blending and transparency: maskThreshold</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:refractionmode" class="level3"><span class="tocNumber">4.2.18 </span>Blending and transparency: refractionMode</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:refractiontype" class="level3"><span class="tocNumber">4.2.19 </span>Blending and transparency: refractionType</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:culling" class="level3"><span class="tocNumber">4.2.20 </span>Rasterization: culling</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:colorwrite" class="level3"><span class="tocNumber">4.2.21 </span>Rasterization: colorWrite</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:depthwrite" class="level3"><span class="tocNumber">4.2.22 </span>Rasterization: depthWrite</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:depthculling" class="level3"><span class="tocNumber">4.2.23 </span>Rasterization: depthCulling</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:doublesided" class="level3"><span class="tocNumber">4.2.24 </span>Rasterization: doubleSided</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:reflections" class="level3"><span class="tocNumber">4.2.25 </span>Lighting: reflections</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" class="level3"><span class="tocNumber">4.2.26 </span>Lighting: shadowMultiplier</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:transparentshadow" class="level3"><span class="tocNumber">4.2.27 </span>Lighting: transparentShadow</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" class="level3"><span class="tocNumber">4.2.28 </span>Lighting: clearCoatIorChange</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" class="level3"><span class="tocNumber">4.2.29 </span>Lighting: multiBounceAmbientOcclusion</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" class="level3"><span class="tocNumber">4.2.30 </span>Lighting: specularAmbientOcclusion</a><br>
|
||||
<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" class="level3"><span class="tocNumber">4.2.31 </span>Anti-aliasing: specularAntiAliasing</a><br>
|
||||
<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" class="level3"><span class="tocNumber">4.2.32 </span>Anti-aliasing: specularAntiAliasingVariance</a><br>
|
||||
<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" class="level3"><span class="tocNumber">4.2.33 </span>Anti-aliasing: specularAntiAliasingThreshold</a><br>
|
||||
<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" class="level3"><span class="tocNumber">4.2.34 </span>Shading: customSurfaceShading</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:shadingmodel" class="level3"><span class="tocNumber">4.2.2 </span>General: shadingModel</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:parameters" class="level3"><span class="tocNumber">4.2.3 </span>General: parameters</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:variantfilter" class="level3"><span class="tocNumber">4.2.4 </span>General: variantFilter</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:flipuv" class="level3"><span class="tocNumber">4.2.5 </span>General: flipUV</a><br>
|
||||
<a href="#materialdefinitions/materialblock/general:quality" class="level3"><span class="tocNumber">4.2.6 </span>General: quality</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:requires" class="level3"><span class="tocNumber">4.2.7 </span>Vertex and attributes: requires</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:variables" class="level3"><span class="tocNumber">4.2.8 </span>Vertex and attributes: variables</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:vertexdomain" class="level3"><span class="tocNumber">4.2.9 </span>Vertex and attributes: vertexDomain</a><br>
|
||||
<a href="#materialdefinitions/materialblock/vertexandattributes:interpolation" class="level3"><span class="tocNumber">4.2.10 </span>Vertex and attributes: interpolation</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:blending" class="level3"><span class="tocNumber">4.2.11 </span>Blending and transparency: blending</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:postlightingblending" class="level3"><span class="tocNumber">4.2.12 </span>Blending and transparency: postLightingBlending</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:transparency" class="level3"><span class="tocNumber">4.2.13 </span>Blending and transparency: transparency</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:maskthreshold" class="level3"><span class="tocNumber">4.2.14 </span>Blending and transparency: maskThreshold</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:refractionmode" class="level3"><span class="tocNumber">4.2.15 </span>Blending and transparency: refractionMode</a><br>
|
||||
<a href="#materialdefinitions/materialblock/blendingandtransparency:refractiontype" class="level3"><span class="tocNumber">4.2.16 </span>Blending and transparency: refractionType</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:culling" class="level3"><span class="tocNumber">4.2.17 </span>Rasterization: culling</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:colorwrite" class="level3"><span class="tocNumber">4.2.18 </span>Rasterization: colorWrite</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:depthwrite" class="level3"><span class="tocNumber">4.2.19 </span>Rasterization: depthWrite</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:depthculling" class="level3"><span class="tocNumber">4.2.20 </span>Rasterization: depthCulling</a><br>
|
||||
<a href="#materialdefinitions/materialblock/rasterization:doublesided" class="level3"><span class="tocNumber">4.2.21 </span>Rasterization: doubleSided</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:reflections" class="level3"><span class="tocNumber">4.2.22 </span>Lighting: reflections</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:shadowmultiplier" class="level3"><span class="tocNumber">4.2.23 </span>Lighting: shadowMultiplier</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:transparentshadow" class="level3"><span class="tocNumber">4.2.24 </span>Lighting: transparentShadow</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:clearcoatiorchange" class="level3"><span class="tocNumber">4.2.25 </span>Lighting: clearCoatIorChange</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:multibounceambientocclusion" class="level3"><span class="tocNumber">4.2.26 </span>Lighting: multiBounceAmbientOcclusion</a><br>
|
||||
<a href="#materialdefinitions/materialblock/lighting:specularambientocclusion" class="level3"><span class="tocNumber">4.2.27 </span>Lighting: specularAmbientOcclusion</a><br>
|
||||
<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasing" class="level3"><span class="tocNumber">4.2.28 </span>Anti-aliasing: specularAntiAliasing</a><br>
|
||||
<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance" class="level3"><span class="tocNumber">4.2.29 </span>Anti-aliasing: specularAntiAliasingVariance</a><br>
|
||||
<a href="#materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold" class="level3"><span class="tocNumber">4.2.30 </span>Anti-aliasing: specularAntiAliasingThreshold</a><br>
|
||||
<a href="#materialdefinitions/materialblock/shading:customsurfaceshading" class="level3"><span class="tocNumber">4.2.31 </span>Shading: customSurfaceShading</a><br>
|
||||
<a href="#materialdefinitions/vertexblock" class="level2"><span class="tocNumber">4.3 </span>Vertex block</a><br>
|
||||
<a href="#materialdefinitions/vertexblock/materialvertexinputs" class="level3"><span class="tocNumber">4.3.1 </span>Material vertex inputs</a><br>
|
||||
<a href="#materialdefinitions/vertexblock/customvertexattributes" class="level3"><span class="tocNumber">4.3.2 </span>Custom vertex attributes</a><br>
|
||||
@@ -778,7 +775,7 @@ and with (right)</span></center></div></center>
|
||||
|
||||
The <code>bentNormal</code> property defines the average unoccluded direction at a point on the surface. It is
|
||||
used to improve the accuracy of indirect lighting. Bent normals can also improve the quality of
|
||||
specular ambient occlusion (see section <a href="#toc4.2.30">4.2.30</a> about
|
||||
specular ambient occlusion (see section <a href="#toc4.2.27">4.2.27</a> about
|
||||
<code>specularAmbientOcclusion</code>).
|
||||
|
||||
</p><p>
|
||||
@@ -893,7 +890,7 @@ light to bend further away from the initial path.
|
||||
<p></p><p>
|
||||
|
||||
The appearance of a refractive material will greatly depend on the <code>refractionType</code> and
|
||||
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.19">4.2.19</a> and section <a href="#toc4.2.18">4.2.18</a>
|
||||
<code>refractionMode</code> settings of the material. Refer to section <a href="#toc4.2.16">4.2.16</a> and section <a href="#toc4.2.15">4.2.15</a>
|
||||
for more information.
|
||||
|
||||
</p><p>
|
||||
@@ -1426,36 +1423,7 @@ non-shader data.
|
||||
<span class="line">material {</span>
|
||||
<span class="line"> name : <span class="hljs-string">"Wet pavement"</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:featurelevel"> </a><a class="target" name="materialdefinitions/materialblock/general:featurelevel"> </a><a class="target" name="toc4.2.2"> </a><h3>General: featureLevel</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><table><tbody><tr valign="top"><td><dt>Type</dt></td><td><dd><p> <code>number</code>
|
||||
|
||||
</p></dd></td></tr><tr valign="top"><td><dt>Value</dt></td><td><dd><p> An integer value, either 1, 2 or 3. Defaults to 1.
|
||||
|
||||
</p></dd></td></tr></tbody></table></dl><div class="table">
|
||||
<table class="table"><tbody><tr><th style="text-align:left"> Feature Level </th><th style="text-align:left"> Guaranteed features </th></tr>
|
||||
<tr><td style="text-align:left"> 1 </td><td style="text-align:left"> 9 textures per material </td></tr>
|
||||
<tr><td style="text-align:left"> 2 </td><td style="text-align:left"> 9 textures per material, cubemap arrays, ESSL 3.10 </td></tr>
|
||||
<tr><td style="text-align:left"> 3 </td><td style="text-align:left"> 12 textures per material, cubemap arrays, ESSL 3.10 </td></tr>
|
||||
</tbody></table><center><div class="tablecaption"><a class="target" name="table_featurelevels"> </a><b style="font-style:normal;">Table 13:</b> Feature levels</div></center></div>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
</p><dl><dt>Description</dt><dd><p> Sets the feature level of the material. Each feature level defines a set of features the
|
||||
material can use. If the material uses a feature not supported by the selected level, <code>matc</code>
|
||||
will generate an error during compilation. A given feature level is guaranteed to support
|
||||
all features of lower feature levels.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> featureLevel : <span class="hljs-number">2</span></span>
|
||||
<span class="line">}</span></code></pre><p>
|
||||
|
||||
</p><dl><table><tbody><tr valign="top"><td><dt>Bugs</dt></td><td><dd><p> <code>matc</code> doesn't verify that a material is not using features above its selected feature level.
|
||||
|
||||
</p></dd></td></tr></tbody></table></dl><p></p>
|
||||
<a class="target" name="general:shadingmodel"> </a><a class="target" name="materialdefinitions/materialblock/general:shadingmodel"> </a><a class="target" name="toc4.2.3"> </a><h3>General: shadingModel</h3>
|
||||
<a class="target" name="general:shadingmodel"> </a><a class="target" name="materialdefinitions/materialblock/general:shadingmodel"> </a><a class="target" name="toc4.2.2"> </a><h3>General: shadingModel</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1472,7 +1440,7 @@ non-shader data.
|
||||
<span class="line">material {</span>
|
||||
<span class="line"> shadingModel : <span class="hljs-string">"subsurface"</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:parameters"> </a><a class="target" name="materialdefinitions/materialblock/general:parameters"> </a><a class="target" name="toc4.2.4"> </a><h3>General: parameters</h3>
|
||||
<a class="target" name="general:parameters"> </a><a class="target" name="materialdefinitions/materialblock/general:parameters"> </a><a class="target" name="toc4.2.3"> </a><h3>General: parameters</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1482,7 +1450,7 @@ non-shader data.
|
||||
name must be a valid GLSL identifier. Entries also have an optional <code>precision</code>, which can be
|
||||
one of <code>default</code> (best precision for the platform, typically <code>high</code> on desktop, <code>medium</code> on
|
||||
mobile), <code>low</code>, <code>medium</code>, <code>high</code>. The type must be one of the types described in
|
||||
<a href="#table_materialparamstypes">table 14</a>.
|
||||
<a href="#table_materialparamstypes">table 13</a>.
|
||||
|
||||
</p></dd></dl><div class="table">
|
||||
<table class="table"><tbody><tr><th style="text-align:left"> Type </th><th style="text-align:left"> Description </th></tr>
|
||||
@@ -1505,10 +1473,9 @@ non-shader data.
|
||||
<tr><td style="text-align:left"> float3×3 </td><td style="text-align:left"> Matrix of 3×3 floats </td></tr>
|
||||
<tr><td style="text-align:left"> float4×4 </td><td style="text-align:left"> Matrix of 4×4 floats </td></tr>
|
||||
<tr><td style="text-align:left"> sampler2d </td><td style="text-align:left"> 2D texture </td></tr>
|
||||
<tr><td style="text-align:left"> sampler2dArray </td><td style="text-align:left"> Array of 2D textures </td></tr>
|
||||
<tr><td style="text-align:left"> samplerExternal </td><td style="text-align:left"> External texture (platform-specific) </td></tr>
|
||||
<tr><td style="text-align:left"> samplerCubemap </td><td style="text-align:left"> Cubemap texture </td></tr>
|
||||
</tbody></table><center><div class="tablecaption"><a class="target" name="table_materialparamstypes"> </a><b style="font-style:normal;">Table 14:</b> Material parameter types</div></center></div>
|
||||
</tbody></table><center><div class="tablecaption"><a class="target" name="table_materialparamstypes"> </a><b style="font-style:normal;">Table 13:</b> Material parameter types</div></center></div>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
@@ -1517,7 +1484,7 @@ non-shader data.
|
||||
|
||||
</p></dd><dt>Arrays</dt><dd><p> A parameter can define an array of values by appending <code>[size]</code> after the type name, where
|
||||
<code>size</code> is a positive integer. For instance: <code>float[9]</code> declares an array of nine <code>float</code>
|
||||
values. This syntax does not apply to samplers as arrays are treated as separate types.
|
||||
values. Arrays of samplers are <em class="underscore">not</em> supported at the moment.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Lists the parameters required by your material. These parameters can be set at runtime using
|
||||
Filament's material API. Accessing parameters from the shaders varies depending on the type of
|
||||
@@ -1564,7 +1531,7 @@ non-shader data.
|
||||
<span class="line"> material.reflectance = materialParams.metallicReflectance.y;</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:variantfilter"> </a><a class="target" name="materialdefinitions/materialblock/general:variantfilter"> </a><a class="target" name="toc4.2.5"> </a><h3>General: variantFilter</h3>
|
||||
<a class="target" name="general:variantfilter"> </a><a class="target" name="materialdefinitions/materialblock/general:variantfilter"> </a><a class="target" name="toc4.2.4"> </a><h3>General: variantFilter</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1606,7 +1573,7 @@ non-shader data.
|
||||
<span class="line"> blending : transparent,</span>
|
||||
<span class="line"> variantFilter : [ skinning ]</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:flipuv"> </a><a class="target" name="materialdefinitions/materialblock/general:flipuv"> </a><a class="target" name="toc4.2.6"> </a><h3>General: flipUV</h3>
|
||||
<a class="target" name="general:flipuv"> </a><a class="target" name="materialdefinitions/materialblock/general:flipuv"> </a><a class="target" name="toc4.2.5"> </a><h3>General: flipUV</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1621,7 +1588,7 @@ non-shader data.
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> flipUV : <span class="hljs-literal">false</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:quality"> </a><a class="target" name="materialdefinitions/materialblock/general:quality"> </a><a class="target" name="toc4.2.7"> </a><h3>General: quality</h3>
|
||||
<a class="target" name="general:quality"> </a><a class="target" name="materialdefinitions/materialblock/general:quality"> </a><a class="target" name="toc4.2.6"> </a><h3>General: quality</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1637,43 +1604,7 @@ non-shader data.
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> quality : default</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:instanced"> </a><a class="target" name="materialdefinitions/materialblock/general:instanced"> </a><a class="target" name="toc4.2.8"> </a><h3>General: instanced</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><dt>Type</dt><dd><p> <code>boolean</code>
|
||||
|
||||
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Allows a material to access the instance index (i.e.: <strong class="asterisk"><code>gl_InstanceIndex</code></strong>) of instanced
|
||||
primitives using <code>getInstanceIndex()</code> in the material's shader code. Never use
|
||||
<strong class="asterisk"><code>gl_InstanceIndex</code></strong> directly. This is typically used with
|
||||
<code>RenderableManager::Builder::instances()</code>. <code>getInstanceIndex()</code> is available in both the
|
||||
vertex and fragment shader.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> instanced : <span class="hljs-literal">true</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="general:vertexdomaindevicejittered"> </a><a class="target" name="materialdefinitions/materialblock/general:vertexdomaindevicejittered"> </a><a class="target" name="toc4.2.9"> </a><h3>General: vertexDomainDeviceJittered</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><dt>Type</dt><dd><p> <code>boolean</code>
|
||||
|
||||
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Only meaningful for <code>vertexDomain:Device</code> materials, this parameter specifies whether the
|
||||
filament clip-space transforms need to be applied or not, which affects TAA and guard bands.
|
||||
Generally it needs to be applied because by definition <code>vertexDomain:Device</code> materials
|
||||
vertices are not transformed and used <em class="asterisk">as is</em>.
|
||||
However, if the vertex shader uses for instance <code>getViewFromClipMatrix()</code> (or other
|
||||
matrices based on the projection), the clip-space transform is already applied.
|
||||
Setting this parameter incorrectly can prevent TAA or the guard bands to work correctly.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> vertexDomainDeviceJittered : <span class="hljs-literal">true</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="vertexandattributes:requires"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:requires"> </a><a class="target" name="toc4.2.10"> </a><h3>Vertex and attributes: requires</h3>
|
||||
<a class="target" name="vertexandattributes:requires"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:requires"> </a><a class="target" name="toc4.2.7"> </a><h3>Vertex and attributes: requires</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1708,7 +1639,7 @@ non-shader data.
|
||||
<span class="line"> material.baseColor.rgb *= getCustom0().rgb;</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="vertexandattributes:variables"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:variables"> </a><a class="target" name="toc4.2.11"> </a><h3>Vertex and attributes: variables</h3>
|
||||
<a class="target" name="vertexandattributes:variables"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:variables"> </a><a class="target" name="toc4.2.8"> </a><h3>Vertex and attributes: variables</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1755,7 +1686,7 @@ non-shader data.
|
||||
<span class="line"> material.eyeDirection.xyz = mulMat3x3Float3(getWorldFromViewMatrix(), u);</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="vertexandattributes:vertexdomain"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:vertexdomain"> </a><a class="target" name="toc4.2.12"> </a><h3>Vertex and attributes: vertexDomain</h3>
|
||||
<a class="target" name="vertexandattributes:vertexdomain"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:vertexdomain"> </a><a class="target" name="toc4.2.9"> </a><h3>Vertex and attributes: vertexDomain</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1784,7 +1715,7 @@ non-shader data.
|
||||
<p></p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> vertexDomain : device</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="vertexandattributes:interpolation"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:interpolation"> </a><a class="target" name="toc4.2.13"> </a><h3>Vertex and attributes: interpolation</h3>
|
||||
<a class="target" name="vertexandattributes:interpolation"> </a><a class="target" name="materialdefinitions/materialblock/vertexandattributes:interpolation"> </a><a class="target" name="toc4.2.10"> </a><h3>Vertex and attributes: interpolation</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1800,7 +1731,7 @@ non-shader data.
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> interpolation : flat</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="blendingandtransparency:blending"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blending"> </a><a class="target" name="toc4.2.14"> </a><h3>Blending and transparency: blending</h3>
|
||||
<a class="target" name="blendingandtransparency:blending"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:blending"> </a><a class="target" name="toc4.2.11"> </a><h3>Blending and transparency: blending</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1841,7 +1772,7 @@ non-shader data.
|
||||
<p></p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> blending : transparent</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="blendingandtransparency:postlightingblending"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:postlightingblending"> </a><a class="target" name="toc4.2.15"> </a><h3>Blending and transparency: postLightingBlending</h3>
|
||||
<a class="target" name="blendingandtransparency:postlightingblending"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:postlightingblending"> </a><a class="target" name="toc4.2.12"> </a><h3>Blending and transparency: postLightingBlending</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1871,7 +1802,7 @@ non-shader data.
|
||||
<p></p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> postLightingBlending : add</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="blendingandtransparency:transparency"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:transparency"> </a><a class="target" name="toc4.2.16"> </a><h3>Blending and transparency: transparency</h3>
|
||||
<a class="target" name="blendingandtransparency:transparency"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:transparency"> </a><a class="target" name="toc4.2.13"> </a><h3>Blending and transparency: transparency</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1918,7 +1849,7 @@ and correctly sorted</span></center></div></center>
|
||||
and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="blendingandtransparency:maskthreshold"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:maskthreshold"> </a><a class="target" name="toc4.2.17"> </a><h3>Blending and transparency: maskThreshold</h3>
|
||||
<a class="target" name="blendingandtransparency:maskthreshold"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:maskthreshold"> </a><a class="target" name="toc4.2.14"> </a><h3>Blending and transparency: maskThreshold</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1935,7 +1866,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
<span class="line"> blending : masked,</span>
|
||||
<span class="line"> maskThreshold : <span class="hljs-number">0.5</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="blendingandtransparency:refractionmode"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractionmode"> </a><a class="target" name="toc4.2.18"> </a><h3>Blending and transparency: refractionMode</h3>
|
||||
<a class="target" name="blendingandtransparency:refractionmode"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractionmode"> </a><a class="target" name="toc4.2.15"> </a><h3>Blending and transparency: refractionMode</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1956,7 +1887,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> refractionMode : cubemap,</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="blendingandtransparency:refractiontype"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractiontype"> </a><a class="target" name="toc4.2.19"> </a><h3>Blending and transparency: refractionType</h3>
|
||||
<a class="target" name="blendingandtransparency:refractiontype"> </a><a class="target" name="materialdefinitions/materialblock/blendingandtransparency:refractiontype"> </a><a class="target" name="toc4.2.16"> </a><h3>Blending and transparency: refractionType</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1975,7 +1906,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
<span class="line"> refractionMode : cubemap,</span>
|
||||
<span class="line"> refractionType : thin,</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="rasterization:culling"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:culling"> </a><a class="target" name="toc4.2.20"> </a><h3>Rasterization: culling</h3>
|
||||
<a class="target" name="rasterization:culling"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:culling"> </a><a class="target" name="toc4.2.17"> </a><h3>Rasterization: culling</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -1989,7 +1920,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
</p></dd></td></tr></tbody></table></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> culling : none</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="rasterization:colorwrite"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:colorwrite"> </a><a class="target" name="toc4.2.21"> </a><h3>Rasterization: colorWrite</h3>
|
||||
<a class="target" name="rasterization:colorwrite"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:colorwrite"> </a><a class="target" name="toc4.2.18"> </a><h3>Rasterization: colorWrite</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2002,7 +1933,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
</p></dd></td></tr></tbody></table></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> colorWrite : <span class="hljs-literal">false</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="rasterization:depthwrite"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:depthwrite"> </a><a class="target" name="toc4.2.22"> </a><h3>Rasterization: depthWrite</h3>
|
||||
<a class="target" name="rasterization:depthwrite"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:depthwrite"> </a><a class="target" name="toc4.2.19"> </a><h3>Rasterization: depthWrite</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2015,7 +1946,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
</p></dd></td></tr></tbody></table></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> depthWrite : <span class="hljs-literal">false</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="rasterization:depthculling"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:depthculling"> </a><a class="target" name="toc4.2.23"> </a><h3>Rasterization: depthCulling</h3>
|
||||
<a class="target" name="rasterization:depthculling"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:depthculling"> </a><a class="target" name="toc4.2.20"> </a><h3>Rasterization: depthCulling</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2029,49 +1960,7 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> depthCulling : <span class="hljs-literal">false</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="rasterization:doublesided"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:doublesided"> </a><a class="target" name="toc4.2.24"> </a><h3>Rasterization: doubleSided</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><dt>Type</dt><dd><p> <code>boolean</code>
|
||||
|
||||
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Enables two-sided rendering and its capability to be toggled at run time. When set to <code>true</code>,
|
||||
<code>culling</code> is automatically set to <code>none</code>; if the triangle is back-facing, the triangle's
|
||||
normal is flipped to become front-facing. When explicitly set to <code>false</code>, this allows the
|
||||
double-sidedness to be toggled at run time.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> name : <span class="hljs-string">"Double sided material"</span>,</span>
|
||||
<span class="line"> shadingModel : lit,</span>
|
||||
<span class="line"> doubleSided : <span class="hljs-literal">true</span></span>
|
||||
<span class="line">}</span>
|
||||
<span class="line"></span>
|
||||
<span class="line">fragment {</span>
|
||||
<span class="line"> void material(inout MaterialInputs material) {</span>
|
||||
<span class="line"> prepareMaterial(material);</span>
|
||||
<span class="line"> material.baseColor = materialParams.albedo;</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="lighting:reflections"> </a><a class="target" name="materialdefinitions/materialblock/lighting:reflections"> </a><a class="target" name="toc4.2.25"> </a><h3>Lighting: reflections</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><dt>Type</dt><dd><p> <code>string</code>
|
||||
|
||||
</p></dd><dt>Value</dt><dd><p> <code>default</code> or <code>screenspace</code>. Defaults to <code>default</code>.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Controls the source of specular reflections for this material. When this property is set to
|
||||
<code>default</code>, reflections only come image-based lights. When this property is set to
|
||||
<code>screenspace</code>, reflections come from the screen space's color buffer in addition to
|
||||
image-based lights.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> name : <span class="hljs-string">"Glossy metal"</span>,</span>
|
||||
<span class="line"> reflections : screenspace</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="lighting:shadowmultiplier"> </a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier"> </a><a class="target" name="toc4.2.26"> </a><h3>Lighting: shadowMultiplier</h3>
|
||||
<a class="target" name="rasterization:doublesided"> </a><a class="target" name="materialdefinitions/materialblock/rasterization:doublesided"> </a><a class="target" name="toc4.2.21"> </a><h3>Rasterization: doubleSided</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2098,7 +1987,51 @@ and sorting issues are minimized or eliminated</span></center></div></center>
|
||||
<span class="line"> material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="lighting:transparentshadow"> </a><a class="target" name="materialdefinitions/materialblock/lighting:transparentshadow"> </a><a class="target" name="toc4.2.27"> </a><h3>Lighting: transparentShadow</h3>
|
||||
<a class="target" name="lighting:reflections"> </a><a class="target" name="materialdefinitions/materialblock/lighting:reflections"> </a><a class="target" name="toc4.2.22"> </a><h3>Lighting: reflections</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><dt>Type</dt><dd><p> <code>string</code>
|
||||
|
||||
</p></dd><dt>Value</dt><dd><p> <code>default</code> or <code>screenspace</code>. Defaults to <code>default</code>.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Controls the source of specular reflections for this material. When this property is set to
|
||||
<code>default</code>, reflections only come image-based lights. When this property is set to
|
||||
<code>screenspace</code>, reflections come from the screen space's color buffer in addition to
|
||||
image-based lights.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> name : <span class="hljs-string">"Glossy metal"</span>,</span>
|
||||
<span class="line"> reflections : screenspace</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="lighting:shadowmultiplier"> </a><a class="target" name="materialdefinitions/materialblock/lighting:shadowmultiplier"> </a><a class="target" name="toc4.2.23"> </a><h3>Lighting: shadowMultiplier</h3>
|
||||
<p>
|
||||
|
||||
|
||||
</p><dl><dt>Type</dt><dd><p> <code>boolean</code>
|
||||
|
||||
</p></dd><dt>Value</dt><dd><p> <code>true</code> or <code>false</code>. Defaults to <code>false</code>.
|
||||
|
||||
</p></dd><dt>Description</dt><dd><p> Only available in the <code>unlit</code> shading model. If this property is enabled, the final color
|
||||
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
|
||||
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
|
||||
This is only supported with shadows from directional lights.
|
||||
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> name : <span class="hljs-string">"Invisible shadow plane"</span>,</span>
|
||||
<span class="line"> shadingModel : unlit,</span>
|
||||
<span class="line"> shadowMultiplier : <span class="hljs-literal">true</span>,</span>
|
||||
<span class="line"> blending : transparent</span>
|
||||
<span class="line">}</span>
|
||||
<span class="line"></span>
|
||||
<span class="line">fragment {</span>
|
||||
<span class="line"> void material(inout MaterialInputs material) {</span>
|
||||
<span class="line"> prepareMaterial(material);</span>
|
||||
<span class="line"> <span class="hljs-comment">// baseColor defines the color and opacity of the final shadow</span></span>
|
||||
<span class="line"> material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);</span>
|
||||
<span class="line"> }</span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="lighting:transparentshadow"> </a><a class="target" name="materialdefinitions/materialblock/lighting:transparentshadow"> </a><a class="target" name="toc4.2.24"> </a><h3>Lighting: transparentShadow</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2132,7 +2065,7 @@ radius of 4. Model <a href="https://sketchfab.com/3d-models/bottle-of-water-48fd
|
||||
by <a href="https://sketchfab.com/person-x">T-Art</a>.</span></center></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="lighting:clearcoatiorchange"> </a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange"> </a><a class="target" name="toc4.2.28"> </a><h3>Lighting: clearCoatIorChange</h3>
|
||||
<a class="target" name="lighting:clearcoatiorchange"> </a><a class="target" name="materialdefinitions/materialblock/lighting:clearcoatiorchange"> </a><a class="target" name="toc4.2.25"> </a><h3>Lighting: clearCoatIorChange</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2154,7 +2087,7 @@ with <code>clearCoatIorChange</code> enabled (left) and disabled
|
||||
(right).</span></center></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="lighting:multibounceambientocclusion"> </a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion"> </a><a class="target" name="toc4.2.29"> </a><h3>Lighting: multiBounceAmbientOcclusion</h3>
|
||||
<a class="target" name="lighting:multibounceambientocclusion"> </a><a class="target" name="materialdefinitions/materialblock/lighting:multibounceambientocclusion"> </a><a class="target" name="toc4.2.26"> </a><h3>Lighting: multiBounceAmbientOcclusion</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2183,7 +2116,7 @@ occclusion enabled (left) and disabled (right).</span></center></div></center>
|
||||
occclusion enabled and disabled.</span></center></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="lighting:specularambientocclusion"> </a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion"> </a><a class="target" name="toc4.2.30"> </a><h3>Lighting: specularAmbientOcclusion</h3>
|
||||
<a class="target" name="lighting:specularambientocclusion"> </a><a class="target" name="materialdefinitions/materialblock/lighting:specularambientocclusion"> </a><a class="target" name="toc4.2.27"> </a><h3>Lighting: specularAmbientOcclusion</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2209,7 +2142,7 @@ occclusion enabled and disabled.</span></center></div></center>
|
||||
particularly visible under the hose.</span></center></div></center>
|
||||
|
||||
<p></p>
|
||||
<a class="target" name="anti-aliasing:specularantialiasing"> </a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing"> </a><a class="target" name="toc4.2.31"> </a><h3>Anti-aliasing: specularAntiAliasing</h3>
|
||||
<a class="target" name="anti-aliasing:specularantialiasing"> </a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasing"> </a><a class="target" name="toc4.2.28"> </a><h3>Anti-aliasing: specularAntiAliasing</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2226,7 +2159,7 @@ particularly visible under the hose.</span></center></div></center>
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> specularAntiAliasing : <span class="hljs-literal">true</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="anti-aliasing:specularantialiasingvariance"> </a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance"> </a><a class="target" name="toc4.2.32"> </a><h3>Anti-aliasing: specularAntiAliasingVariance</h3>
|
||||
<a class="target" name="anti-aliasing:specularantialiasingvariance"> </a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingvariance"> </a><a class="target" name="toc4.2.29"> </a><h3>Anti-aliasing: specularAntiAliasingVariance</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2241,7 +2174,7 @@ particularly visible under the hose.</span></center></div></center>
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> specularAntiAliasingVariance : <span class="hljs-number">0.2</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="anti-aliasing:specularantialiasingthreshold"> </a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold"> </a><a class="target" name="toc4.2.33"> </a><h3>Anti-aliasing: specularAntiAliasingThreshold</h3>
|
||||
<a class="target" name="anti-aliasing:specularantialiasingthreshold"> </a><a class="target" name="materialdefinitions/materialblock/anti-aliasing:specularantialiasingthreshold"> </a><a class="target" name="toc4.2.30"> </a><h3>Anti-aliasing: specularAntiAliasingThreshold</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2255,7 +2188,7 @@ particularly visible under the hose.</span></center></div></center>
|
||||
</p></dd></dl><p></p><pre class="listing tilde"><code><span class="line">material {</span>
|
||||
<span class="line"> specularAntiAliasingThreshold : <span class="hljs-number">0.1</span></span>
|
||||
<span class="line">}</span></code></pre>
|
||||
<a class="target" name="shading:customsurfaceshading"> </a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading"> </a><a class="target" name="toc4.2.34"> </a><h3>Shading: customSurfaceShading</h3>
|
||||
<a class="target" name="shading:customsurfaceshading"> </a><a class="target" name="materialdefinitions/materialblock/shading:customsurfaceshading"> </a><a class="target" name="toc4.2.31"> </a><h3>Shading: customSurfaceShading</h3>
|
||||
<p>
|
||||
|
||||
|
||||
@@ -2319,7 +2252,7 @@ APIs listed in the <a href="#shaderpublicapis">Shader public APIs</a> section.
|
||||
<span class="line"> float3 worldNormal; <span class="hljs-comment">// only if the shading model is not unlit</span></span>
|
||||
<span class="line"> float4 worldPosition; <span class="hljs-comment">// always available (see note below about world-space)</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"> <span class="hljs-type">mat4</span> clipSpaceTransform; <span class="hljs-comment">// default: identity, transforms the clip-space position, only available for `vertexDomain:device`</span></span>
|
||||
<span class="line"> <span class="hljs-type">mat4</span> clipSpaceTransform; <span class="hljs-comment">// default: identity, transforms the clip-space position</span></span>
|
||||
<span class="line"></span>
|
||||
<span class="line"> <span class="hljs-comment">// variable* names are replaced with actual names</span></span>
|
||||
<span class="line"> float4 variable0; <span class="hljs-comment">// if 1 or more variables is defined</span></span>
|
||||
@@ -2814,7 +2747,7 @@ source material definition file.
|
||||
<p>
|
||||
|
||||
|
||||
The command line flags relevant to application development are described in <a href="#table_matcflags">table 15</a>.
|
||||
The command line flags relevant to application development are described in <a href="#table_matcflags">table 14</a>.
|
||||
</p><div class="table">
|
||||
<table class="table"><tbody><tr><th style="text-align:right"> Flag </th><th style="text-align:center"> Value </th><th style="text-align:left"> Usage </th></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">-o</strong>, <strong class="asterisk">—output</strong> </td><td style="text-align:center"> [path] </td><td style="text-align:left"> Specify the output file path </td></tr>
|
||||
@@ -2823,7 +2756,7 @@ The command line flags relevant to application development are described in <a h
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">-S</strong>, <strong class="asterisk">—optimize-size</strong> </td><td style="text-align:center"> N/A </td><td style="text-align:left"> Optimize compiled material for size instead of just performance </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">-r</strong>, <strong class="asterisk">—reflect</strong> </td><td style="text-align:center"> parameters </td><td style="text-align:left"> Outputs the specified metadata as JSON </td></tr>
|
||||
<tr><td style="text-align:right"> <strong class="asterisk">-v</strong>, <strong class="asterisk">—variant-filter</strong> </td><td style="text-align:center"> [variant] </td><td style="text-align:left"> Filters out the specified, comma-separated variants </td></tr>
|
||||
</tbody></table><center><div class="tablecaption"><a class="target" name="table_matcflags"> </a><b style="font-style:normal;">Table 15:</b> List of <code>matc</code> flags</div></center></div>
|
||||
</tbody></table><center><div class="tablecaption"><a class="target" name="table_matcflags"> </a><b style="font-style:normal;">Table 14:</b> List of <code>matc</code> flags</div></center></div>
|
||||
|
||||
<p></p><p>
|
||||
|
||||
|
||||
@@ -932,37 +932,6 @@ material {
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### General: featureLevel
|
||||
|
||||
Type
|
||||
: `number`
|
||||
|
||||
Value
|
||||
: An integer value, either 1, 2 or 3. Defaults to 1.
|
||||
|
||||
Feature Level | Guaranteed features
|
||||
:----------------------|:---------------------------------
|
||||
1 | 9 textures per material
|
||||
2 | 9 textures per material, cubemap arrays, ESSL 3.10
|
||||
3 | 12 textures per material, cubemap arrays, ESSL 3.10
|
||||
[Table [featureLevels]: Feature levels]
|
||||
|
||||
Description
|
||||
: Sets the feature level of the material. Each feature level defines a set of features the
|
||||
material can use. If the material uses a feature not supported by the selected level, `matc`
|
||||
will generate an error during compilation. A given feature level is guaranteed to support
|
||||
all features of lower feature levels.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
featureLevel : 2
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
Bugs
|
||||
: `matc` doesn't verify that a material is not using features above its selected feature level.
|
||||
|
||||
|
||||
### General: shadingModel
|
||||
|
||||
Type
|
||||
@@ -1017,7 +986,6 @@ uint4 | Vector of 4 unsigned integers
|
||||
float3x3 | Matrix of 3x3 floats
|
||||
float4x4 | Matrix of 4x4 floats
|
||||
sampler2d | 2D texture
|
||||
sampler2dArray | Array of 2D textures
|
||||
samplerExternal | External texture (platform-specific)
|
||||
samplerCubemap | Cubemap texture
|
||||
[Table [materialParamsTypes]: Material parameter types]
|
||||
@@ -1029,7 +997,7 @@ Samplers
|
||||
Arrays
|
||||
: A parameter can define an array of values by appending `[size]` after the type name, where
|
||||
`size` is a positive integer. For instance: `float[9]` declares an array of nine `float`
|
||||
values. This syntax does not apply to samplers as arrays are treated as separate types.
|
||||
values. Arrays of samplers are _not_ supported at the moment.
|
||||
|
||||
Description
|
||||
: Lists the parameters required by your material. These parameters can be set at runtime using
|
||||
@@ -1172,29 +1140,6 @@ material {
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### General: vertexDomainDeviceJittered
|
||||
|
||||
Type
|
||||
: `boolean`
|
||||
|
||||
Value
|
||||
: `true` or `false`. Defaults to `false`.
|
||||
|
||||
Description
|
||||
: Only meaningful for `vertexDomain:Device` materials, this parameter specifies whether the
|
||||
filament clip-space transforms need to be applied or not, which affects TAA and guard bands.
|
||||
Generally it needs to be applied because by definition `vertexDomain:Device` materials
|
||||
vertices are not transformed and used *as is*.
|
||||
However, if the vertex shader uses for instance `getViewFromClipMatrix()` (or other
|
||||
matrices based on the projection), the clip-space transform is already applied.
|
||||
Setting this parameter incorrectly can prevent TAA or the guard bands to work correctly.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
vertexDomainDeviceJittered : true
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
||||
### Vertex and attributes: requires
|
||||
|
||||
Type
|
||||
@@ -1582,22 +1527,24 @@ Value
|
||||
: `true` or `false`. Defaults to `false`.
|
||||
|
||||
Description
|
||||
: Enables two-sided rendering and its capability to be toggled at run time. When set to `true`,
|
||||
`culling` is automatically set to `none`; if the triangle is back-facing, the triangle's
|
||||
normal is flipped to become front-facing. When explicitly set to `false`, this allows the
|
||||
double-sidedness to be toggled at run time.
|
||||
: Only available in the `unlit` shading model. If this property is enabled, the final color
|
||||
computed by the material is multiplied by the shadowing factor (or visibility). This allows to
|
||||
create transparent shadow-receiving objects (for instance an invisible ground plane in AR).
|
||||
This is only supported with shadows from directional lights.
|
||||
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ JSON
|
||||
material {
|
||||
name : "Double sided material",
|
||||
shadingModel : lit,
|
||||
doubleSided : true
|
||||
name : "Invisible shadow plane",
|
||||
shadingModel : unlit,
|
||||
shadowMultiplier : true,
|
||||
blending : transparent
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
material.baseColor = materialParams.albedo;
|
||||
// baseColor defines the color and opacity of the final shadow
|
||||
material.baseColor = vec4(0.0, 0.0, 0.0, 0.7);
|
||||
}
|
||||
}
|
||||
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
@@ -1898,7 +1845,7 @@ struct MaterialVertexInputs {
|
||||
float3 worldNormal; // only if the shading model is not unlit
|
||||
float4 worldPosition; // always available (see note below about world-space)
|
||||
|
||||
mat4 clipSpaceTransform; // default: identity, transforms the clip-space position, only available for `vertexDomain:device`
|
||||
mat4 clipSpaceTransform; // default: identity, transforms the clip-space position
|
||||
|
||||
// variable* names are replaced with actual names
|
||||
float4 variable0; // if 1 or more variables is defined
|
||||
|
||||
@@ -43,7 +43,7 @@ filament-viewer::part(canvas) {
|
||||
</p>
|
||||
|
||||
</main>
|
||||
<script src="https://unpkg.com/filament@1.25.3/filament.js"></script>
|
||||
<script src="https://unpkg.com/filament@1.22.0/filament.js"></script>
|
||||
<script src="https://unpkg.com/gltumble"></script>
|
||||
<script src="filament-viewer.js" type="module"></script>
|
||||
</body>
|
||||
|
||||
@@ -48,7 +48,6 @@ set(PUBLIC_HDRS
|
||||
)
|
||||
|
||||
set(SRCS
|
||||
src/AtlasAllocator.cpp
|
||||
src/Box.cpp
|
||||
src/BufferObject.cpp
|
||||
src/Camera.cpp
|
||||
@@ -73,7 +72,6 @@ set(SRCS
|
||||
src/MaterialParser.cpp
|
||||
src/MorphTargetBuffer.cpp
|
||||
src/PerViewUniforms.cpp
|
||||
src/PerShadowMapUniforms.cpp
|
||||
src/PostProcessManager.cpp
|
||||
src/RenderPass.cpp
|
||||
src/RenderPrimitive.cpp
|
||||
@@ -147,7 +145,6 @@ set(PRIVATE_HDRS
|
||||
src/Intersections.h
|
||||
src/MaterialParser.h
|
||||
src/PerViewUniforms.h
|
||||
src/PerShadowMapUniforms.h
|
||||
src/PIDController.h
|
||||
src/PostProcessManager.h
|
||||
src/RendererUtils.h
|
||||
@@ -201,7 +198,7 @@ set(PRIVATE_HDRS
|
||||
src/materials/fsr/ffx_a.h
|
||||
src/materials/fsr/ffx_fsr1.h
|
||||
src/materials/fsr/ffx_fsr1_mobile.fs
|
||||
src/downcast.h
|
||||
src/upcast.h
|
||||
)
|
||||
|
||||
set(MATERIAL_SRCS
|
||||
@@ -526,9 +523,6 @@ add_library(${TARGET} STATIC ${PRIVATE_HDRS} ${PUBLIC_HDRS} ${SRCS} ${DATA_BINS}
|
||||
# specify where the public headers of this library are
|
||||
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
|
||||
|
||||
# add this subproject to the Filament folder
|
||||
set_target_properties(${TARGET} PROPERTIES FOLDER Filament)
|
||||
|
||||
# ==================================================================================================
|
||||
# Dependencies
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -11,14 +11,11 @@ set(GENERATION_ROOT ${CMAKE_CURRENT_BINARY_DIR})
|
||||
set(PUBLIC_HDRS
|
||||
include/backend/BufferDescriptor.h
|
||||
include/backend/CallbackHandler.h
|
||||
include/backend/DriverApiForward.h
|
||||
include/backend/DriverEnums.h
|
||||
include/backend/Handle.h
|
||||
include/backend/PipelineState.h
|
||||
include/backend/PixelBufferDescriptor.h
|
||||
include/backend/Platform.h
|
||||
include/backend/Program.h
|
||||
include/backend/SamplerDescriptor.h
|
||||
include/backend/TargetBufferInfo.h
|
||||
)
|
||||
|
||||
@@ -49,7 +46,9 @@ set(PRIVATE_HDRS
|
||||
include/private/backend/Driver.h
|
||||
include/private/backend/DriverApi.h
|
||||
include/private/backend/DriverAPI.inc
|
||||
include/private/backend/DriverApiForward.h
|
||||
include/private/backend/HandleAllocator.h
|
||||
include/private/backend/Program.h
|
||||
include/private/backend/SamplerGroup.h
|
||||
src/CommandStreamDispatcher.h
|
||||
src/DataReshaper.h
|
||||
@@ -104,6 +103,8 @@ if (FILAMENT_SUPPORTS_OPENGL AND NOT FILAMENT_USE_EXTERNAL_GLES3 AND NOT FILAMEN
|
||||
endif()
|
||||
elseif (WIN32)
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformWGL.cpp)
|
||||
else()
|
||||
list(APPEND SRCS src/opengl/platforms/PlatformDummyGL.cpp)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
@@ -222,9 +223,6 @@ add_library(${TARGET} STATIC ${PRIVATE_HDRS} ${PUBLIC_HDRS} ${SRCS})
|
||||
# specify where the public headers of this library are
|
||||
target_include_directories(${TARGET} PUBLIC ${PUBLIC_HDR_DIR})
|
||||
|
||||
# add this subproject to the Filament folder
|
||||
set_target_properties(${TARGET} PROPERTIES FOLDER Filament)
|
||||
|
||||
# ==================================================================================================
|
||||
# Expose a header-only target to minimize dependencies.
|
||||
# ==================================================================================================
|
||||
@@ -270,7 +268,6 @@ set(DUMMY_SRC "${VKSHADERS_DIR}/dummy.c")
|
||||
add_custom_command(OUTPUT ${DUMMY_SRC} COMMAND echo "//" > ${DUMMY_SRC})
|
||||
|
||||
add_library(vkshaders STATIC ${DUMMY_SRC} ${RESGEN_SOURCE})
|
||||
set_target_properties(vkshaders PROPERTIES FOLDER Filament/Generated)
|
||||
|
||||
# ==================================================================================================
|
||||
# Dependencies
|
||||
@@ -405,7 +402,6 @@ if (APPLE)
|
||||
backend
|
||||
getopt
|
||||
gtest
|
||||
filamat
|
||||
SPIRV
|
||||
spirv-cross-glsl)
|
||||
|
||||
@@ -438,8 +434,6 @@ if (APPLE)
|
||||
install(FILES "${BACKEND_TEST_COMBINED_OUTPUT}" DESTINATION lib/${DIST_DIR} RENAME ${BACKEND_TEST_LIB_NAME})
|
||||
install(FILES test/PlatformRunner.h DESTINATION include/backend_test)
|
||||
endif()
|
||||
|
||||
set_target_properties(backend_test PROPERTIES FOLDER Tests)
|
||||
endif()
|
||||
|
||||
if (APPLE AND NOT IOS)
|
||||
@@ -448,26 +442,5 @@ if (APPLE AND NOT IOS)
|
||||
# Because each test case is a separate file, the -force_load flag is necessary to prevent the
|
||||
# linker from removing "unused" symbols.
|
||||
target_link_libraries(backend_test_mac PRIVATE -force_load backend_test)
|
||||
set_target_properties(backend_test_mac PROPERTIES FOLDER Tests)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
# Compute tests
|
||||
|
||||
if (NOT IOS AND NOT WEBGL)
|
||||
|
||||
add_executable(compute_test
|
||||
test/ComputeTest.cpp
|
||||
test/Arguments.cpp
|
||||
test/test_ComputeBasic.cpp
|
||||
)
|
||||
|
||||
target_link_libraries(compute_test PRIVATE
|
||||
backend
|
||||
getopt
|
||||
gtest
|
||||
)
|
||||
|
||||
set_target_properties(compute_test PROPERTIES FOLDER Tests)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -48,37 +48,16 @@ static constexpr uint64_t SWAP_CHAIN_CONFIG_ENABLE_XCB = 0x4;
|
||||
static constexpr uint64_t SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = 0x8;
|
||||
|
||||
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_SAMPLER_COUNT = 62; // Maximum needed at feature level 3.
|
||||
static constexpr size_t MAX_VERTEX_SAMPLER_COUNT = 16; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_FRAGMENT_SAMPLER_COUNT = 16; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_SAMPLER_COUNT = 32; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t MAX_VERTEX_BUFFER_COUNT = 16; // Max number of bound buffer objects.
|
||||
static constexpr size_t MAX_SSBO_COUNT = 4; // This is guaranteed by OpenGL ES.
|
||||
|
||||
// Per feature level caps
|
||||
// Use (int)FeatureLevel to index this array
|
||||
static constexpr struct {
|
||||
const size_t MAX_VERTEX_SAMPLER_COUNT;
|
||||
const size_t MAX_FRAGMENT_SAMPLER_COUNT;
|
||||
} FEATURE_LEVEL_CAPS[4] = {
|
||||
{ 0, 0 }, // do not use
|
||||
{ 16, 16 }, // guaranteed by OpenGL ES, Vulkan and Metal
|
||||
{ 16, 16 }, // guaranteed by OpenGL ES, Vulkan and Metal
|
||||
{ 31, 31 }, // guaranteed by Metal
|
||||
};
|
||||
|
||||
static_assert(MAX_VERTEX_BUFFER_COUNT <= MAX_VERTEX_ATTRIBUTE_COUNT,
|
||||
"The number of buffer objects that can be attached to a VertexBuffer must be "
|
||||
"less than or equal to the maximum number of vertex attributes.");
|
||||
|
||||
static constexpr size_t CONFIG_UNIFORM_BINDING_COUNT = 10; // This is guaranteed by OpenGL ES.
|
||||
static constexpr size_t CONFIG_SAMPLER_BINDING_COUNT = 4; // This is guaranteed by OpenGL ES.
|
||||
|
||||
/**
|
||||
* Defines the backend's feature levels.
|
||||
*/
|
||||
enum class FeatureLevel : uint8_t {
|
||||
FEATURE_LEVEL_1 = 1, //!< OpenGL ES 3.0 features (default)
|
||||
FEATURE_LEVEL_2, //!< OpenGL ES 3.1 features + 16 textures units + cubemap arrays
|
||||
FEATURE_LEVEL_3 //!< OpenGL ES 3.1 features + 31 textures units + cubemap arrays
|
||||
};
|
||||
static constexpr size_t CONFIG_BINDING_COUNT = 12; // This is guaranteed by OpenGL ES.
|
||||
|
||||
/**
|
||||
* Selects which driver a particular Engine should use.
|
||||
@@ -198,18 +177,16 @@ static constexpr uint64_t FENCE_WAIT_FOR_EVER = uint64_t(-1);
|
||||
/**
|
||||
* Shader model.
|
||||
*
|
||||
* These enumerants are used across all backends and refer to a level of functionality and quality.
|
||||
*
|
||||
* For example, the OpenGL backend returns `MOBILE` if it supports OpenGL ES, or `DESKTOP` if it
|
||||
* supports Desktop OpenGL, this is later used to select the proper shader.
|
||||
*
|
||||
* Shader quality vs. performance is also affected by ShaderModel.
|
||||
* These enumerants are used across all backends and refer to a level of functionality, rather
|
||||
* than to an OpenGL specific shader model.
|
||||
*/
|
||||
enum class ShaderModel : uint8_t {
|
||||
MOBILE = 1, //!< Mobile level functionality
|
||||
DESKTOP = 2, //!< Desktop level functionality
|
||||
//! For testing
|
||||
UNKNOWN = 0,
|
||||
GL_ES_30 = 1, //!< Mobile level functionality
|
||||
GL_CORE_41 = 2, //!< Desktop level functionality
|
||||
};
|
||||
static constexpr size_t SHADER_MODEL_COUNT = 2;
|
||||
static constexpr size_t SHADER_MODEL_COUNT = 3;
|
||||
|
||||
/**
|
||||
* Primitive types
|
||||
@@ -220,7 +197,8 @@ enum class PrimitiveType : uint8_t {
|
||||
LINES = 1, //!< lines
|
||||
LINE_STRIP = 3, //!< line strip
|
||||
TRIANGLES = 4, //!< triangles
|
||||
TRIANGLE_STRIP = 5 //!< triangle strip
|
||||
TRIANGLE_STRIP = 5, //!< triangle strip
|
||||
NONE = 0xFF
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -257,12 +235,11 @@ enum class Precision : uint8_t {
|
||||
|
||||
//! Texture sampler type
|
||||
enum class SamplerType : uint8_t {
|
||||
SAMPLER_2D, //!< 2D texture
|
||||
SAMPLER_2D_ARRAY, //!< 2D array texture
|
||||
SAMPLER_CUBEMAP, //!< Cube map texture
|
||||
SAMPLER_EXTERNAL, //!< External texture
|
||||
SAMPLER_3D, //!< 3D texture
|
||||
SAMPLER_CUBEMAP_ARRAY, //!< Cube map array texture (feature level 2)
|
||||
SAMPLER_2D, //!< 2D texture
|
||||
SAMPLER_2D_ARRAY, //!< 2D array texture
|
||||
SAMPLER_CUBEMAP, //!< Cube map texture
|
||||
SAMPLER_EXTERNAL, //!< External texture
|
||||
SAMPLER_3D, //!< 3D texture
|
||||
};
|
||||
|
||||
//! Subpass type
|
||||
@@ -313,8 +290,7 @@ enum class ElementType : uint8_t {
|
||||
//! Buffer object binding type
|
||||
enum class BufferObjectBinding : uint8_t {
|
||||
VERTEX,
|
||||
UNIFORM,
|
||||
SHADER_STORAGE
|
||||
UNIFORM
|
||||
};
|
||||
|
||||
//! Face culling Mode
|
||||
@@ -651,10 +627,6 @@ static constexpr bool isS3TCSRGBCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::DXT1_SRGB && format <= TextureFormat::DXT5_SRGBA;
|
||||
}
|
||||
|
||||
static constexpr bool isASTCCompression(TextureFormat format) noexcept {
|
||||
return format >= TextureFormat::RGBA_ASTC_4x4 && format <= TextureFormat::SRGB8_ALPHA8_ASTC_12x12;
|
||||
}
|
||||
|
||||
//! Texture Cubemap Face
|
||||
enum class TextureCubemapFace : uint8_t {
|
||||
// don't change the enums values
|
||||
@@ -666,6 +638,54 @@ enum class TextureCubemapFace : uint8_t {
|
||||
NEGATIVE_Z = 5, //!< -z face
|
||||
};
|
||||
|
||||
inline constexpr int operator +(TextureCubemapFace rhs) noexcept {
|
||||
return int(rhs);
|
||||
}
|
||||
|
||||
//! Face offsets for all faces of a cubemap
|
||||
struct FaceOffsets {
|
||||
using size_type = size_t;
|
||||
union {
|
||||
struct {
|
||||
size_type px; //!< +x face offset in bytes
|
||||
size_type nx; //!< -x face offset in bytes
|
||||
size_type py; //!< +y face offset in bytes
|
||||
size_type ny; //!< -y face offset in bytes
|
||||
size_type pz; //!< +z face offset in bytes
|
||||
size_type nz; //!< -z face offset in bytes
|
||||
};
|
||||
size_type offsets[6];
|
||||
};
|
||||
size_type operator[](size_t n) const noexcept { return offsets[n]; }
|
||||
size_type& operator[](size_t n) { return offsets[n]; }
|
||||
FaceOffsets() noexcept = default;
|
||||
explicit FaceOffsets(size_type faceSize) noexcept {
|
||||
px = faceSize * 0;
|
||||
nx = faceSize * 1;
|
||||
py = faceSize * 2;
|
||||
ny = faceSize * 3;
|
||||
pz = faceSize * 4;
|
||||
nz = faceSize * 5;
|
||||
}
|
||||
FaceOffsets(const FaceOffsets& rhs) noexcept {
|
||||
px = rhs.px;
|
||||
nx = rhs.nx;
|
||||
py = rhs.py;
|
||||
ny = rhs.ny;
|
||||
pz = rhs.pz;
|
||||
nz = rhs.nz;
|
||||
}
|
||||
FaceOffsets& operator=(const FaceOffsets& rhs) noexcept {
|
||||
px = rhs.px;
|
||||
nx = rhs.nx;
|
||||
py = rhs.py;
|
||||
ny = rhs.ny;
|
||||
pz = rhs.pz;
|
||||
nz = rhs.nz;
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
//! Sampler Wrap mode
|
||||
enum class SamplerWrapMode : uint8_t {
|
||||
CLAMP_TO_EDGE, //!< clamp-to-edge. The edge of the texture extends to infinity.
|
||||
@@ -776,13 +796,6 @@ enum class StencilOperation : uint8_t {
|
||||
INVERT, //!< Bitwise inverts the current value.
|
||||
};
|
||||
|
||||
//! stencil faces
|
||||
enum class StencilFace : uint8_t {
|
||||
FRONT = 0x1, //!< Update stencil state for front-facing polygons.
|
||||
BACK = 0x2, //!< Update stencil state for back-facing polygons.
|
||||
FRONT_AND_BACK = FRONT | BACK, //!< Update stencil state for all polygons.
|
||||
};
|
||||
|
||||
//! Stream for external textures
|
||||
enum class StreamType {
|
||||
NATIVE, //!< Not synchronized but copy-free. Good for video.
|
||||
@@ -815,9 +828,11 @@ struct RasterState {
|
||||
using DepthFunc = backend::SamplerCompareFunc;
|
||||
using BlendEquation = backend::BlendEquation;
|
||||
using BlendFunction = backend::BlendFunction;
|
||||
using StencilFunction = backend::SamplerCompareFunc;
|
||||
using StencilOperation = backend::StencilOperation;
|
||||
|
||||
RasterState() noexcept { // NOLINT
|
||||
static_assert(sizeof(RasterState) == sizeof(uint32_t),
|
||||
static_assert(sizeof(RasterState) == sizeof(uint64_t),
|
||||
"RasterState size not what was intended");
|
||||
culling = CullingMode::BACK;
|
||||
blendEquationRGB = BlendEquation::ADD;
|
||||
@@ -826,6 +841,10 @@ struct RasterState {
|
||||
blendFunctionSrcAlpha = BlendFunction::ONE;
|
||||
blendFunctionDstRGB = BlendFunction::ZERO;
|
||||
blendFunctionDstAlpha = BlendFunction::ZERO;
|
||||
stencilFunc = StencilFunction::A;
|
||||
stencilOpStencilFail = StencilOperation::KEEP;
|
||||
stencilOpDepthFail = StencilOperation::KEEP;
|
||||
stencilOpDepthStencilPass = StencilOperation::KEEP;
|
||||
}
|
||||
|
||||
bool operator == (RasterState rhs) const noexcept { return u == rhs.u; }
|
||||
@@ -884,10 +903,26 @@ struct RasterState {
|
||||
//! whether front face winding direction must be inverted
|
||||
bool inverseFrontFaces : 1; // 31
|
||||
|
||||
//! Whether stencil-buffer writes are enabled
|
||||
bool stencilWrite : 1; // 32
|
||||
//! Stencil reference value
|
||||
uint8_t stencilRef : 8; // 40
|
||||
//! Stencil test function
|
||||
StencilFunction stencilFunc : 3; // 43
|
||||
//! Stencil operation when stencil test fails
|
||||
StencilOperation stencilOpStencilFail : 3; // 46
|
||||
//! padding, must be 0
|
||||
uint8_t padding : 1; // 32
|
||||
uint8_t padding0 : 2; // 48
|
||||
//! Stencil operation when stencil test passes but depth test fails
|
||||
StencilOperation stencilOpDepthFail : 3; // 51
|
||||
//! Stencil operation when both stencil and depth test pass
|
||||
StencilOperation stencilOpDepthStencilPass : 3; // 54
|
||||
//! padding, must be 0
|
||||
uint8_t padding1 : 2; // 56
|
||||
//! padding, must be 0
|
||||
uint8_t padding2 : 8; // 64
|
||||
};
|
||||
uint32_t u = 0;
|
||||
uint64_t u = 0;
|
||||
};
|
||||
};
|
||||
|
||||
@@ -896,31 +931,21 @@ struct RasterState {
|
||||
* \privatesection
|
||||
*/
|
||||
|
||||
enum class ShaderStage : uint8_t {
|
||||
enum ShaderType : uint8_t {
|
||||
VERTEX = 0,
|
||||
FRAGMENT = 1,
|
||||
COMPUTE = 2
|
||||
FRAGMENT = 1
|
||||
};
|
||||
|
||||
static constexpr size_t PIPELINE_STAGE_COUNT = 2;
|
||||
enum class ShaderStageFlags : uint8_t {
|
||||
NONE = 0,
|
||||
VERTEX = 0x1,
|
||||
FRAGMENT = 0x2,
|
||||
COMPUTE = 0x4,
|
||||
ALL_SHADER_STAGE_FLAGS = VERTEX | FRAGMENT | COMPUTE
|
||||
};
|
||||
|
||||
static inline constexpr bool hasShaderType(ShaderStageFlags flags, ShaderStage type) noexcept {
|
||||
switch (type) {
|
||||
case ShaderStage::VERTEX:
|
||||
return bool(uint8_t(flags) & uint8_t(ShaderStageFlags::VERTEX));
|
||||
case ShaderStage::FRAGMENT:
|
||||
return bool(uint8_t(flags) & uint8_t(ShaderStageFlags::FRAGMENT));
|
||||
case ShaderStage::COMPUTE:
|
||||
return bool(uint8_t(flags) & uint8_t(ShaderStageFlags::COMPUTE));
|
||||
struct ShaderStageFlags {
|
||||
bool vertex : 1;
|
||||
bool fragment : 1;
|
||||
bool hasShaderType(ShaderType type) const {
|
||||
return (vertex && type == ShaderType::VERTEX) ||
|
||||
(fragment && type == ShaderType::FRAGMENT);
|
||||
}
|
||||
}
|
||||
};
|
||||
static constexpr ShaderStageFlags ALL_SHADER_STAGE_FLAGS = { true, true };
|
||||
|
||||
/**
|
||||
* Selects which buffers to clear at the beginning of the render pass, as well as which buffers
|
||||
@@ -991,55 +1016,6 @@ struct PolygonOffset {
|
||||
float constant = 0; // units in GL-speak
|
||||
};
|
||||
|
||||
struct StencilState {
|
||||
using StencilFunction = SamplerCompareFunc;
|
||||
|
||||
struct StencilOperations {
|
||||
//! Stencil test function
|
||||
StencilFunction stencilFunc : 3; // 3
|
||||
|
||||
//! Stencil operation when stencil test fails
|
||||
StencilOperation stencilOpStencilFail : 3; // 6
|
||||
|
||||
uint8_t padding0 : 2; // 8
|
||||
|
||||
//! Stencil operation when stencil test passes but depth test fails
|
||||
StencilOperation stencilOpDepthFail : 3; // 11
|
||||
|
||||
//! Stencil operation when both stencil and depth test pass
|
||||
StencilOperation stencilOpDepthStencilPass : 3; // 14
|
||||
|
||||
uint8_t padding1 : 2; // 16
|
||||
|
||||
//! Reference value for stencil comparison tests and updates
|
||||
uint8_t ref; // 24
|
||||
|
||||
//! Masks the bits of the stencil values participating in the stencil comparison test.
|
||||
uint8_t readMask; // 32
|
||||
|
||||
//! Masks the bits of the stencil values updated by the stencil test.
|
||||
uint8_t writeMask; // 40
|
||||
};
|
||||
|
||||
//! Stencil operations for front-facing polygons
|
||||
StencilOperations front = {
|
||||
.stencilFunc = StencilFunction::A, .ref = 0, .readMask = 0xff, .writeMask = 0xff };
|
||||
|
||||
//! Stencil operations for back-facing polygons
|
||||
StencilOperations back = {
|
||||
.stencilFunc = StencilFunction::A, .ref = 0, .readMask = 0xff, .writeMask = 0xff };
|
||||
|
||||
//! Whether stencil-buffer writes are enabled
|
||||
bool stencilWrite = false;
|
||||
|
||||
uint8_t padding = 0;
|
||||
};
|
||||
|
||||
static_assert(sizeof(StencilState::StencilOperations) == 5u,
|
||||
"StencilOperations size not what was intended");
|
||||
|
||||
static_assert(sizeof(StencilState) == 12u,
|
||||
"StencilState size not what was intended");
|
||||
|
||||
using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
|
||||
|
||||
@@ -1057,18 +1033,11 @@ enum class Workaround : uint16_t {
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::ShaderStageFlags>
|
||||
: public std::true_type {};
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::TargetBufferFlags>
|
||||
: public std::true_type {};
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::TextureUsage>
|
||||
: public std::true_type {};
|
||||
template<> struct utils::EnableBitMaskOperators<filament::backend::StencilFace>
|
||||
: public std::true_type {};
|
||||
template<> struct utils::EnableIntegerOperators<filament::backend::TextureCubemapFace>
|
||||
: public std::true_type {};
|
||||
template<> struct utils::EnableIntegerOperators<filament::backend::FeatureLevel>
|
||||
: public std::true_type {};
|
||||
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::BufferUsage usage);
|
||||
@@ -1094,6 +1063,7 @@ utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::Textu
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::BufferObjectBinding binding);
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, filament::backend::TextureSwizzle swizzle);
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::AttributeArray& type);
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::FaceOffsets& type);
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::PolygonOffset& po);
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::RasterState& rs);
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const filament::backend::RenderPassParams& b);
|
||||
|
||||
@@ -31,7 +31,6 @@ namespace filament::backend {
|
||||
struct PipelineState {
|
||||
Handle<HwProgram> program;
|
||||
RasterState rasterState;
|
||||
StencilState stencilState;
|
||||
PolygonOffset polygonOffset;
|
||||
Viewport scissor{ 0, 0,
|
||||
(uint32_t)std::numeric_limits<int32_t>::max(),
|
||||
|
||||
@@ -280,7 +280,7 @@ public:
|
||||
}
|
||||
|
||||
size_t bpr = bpp * stride;
|
||||
size_t bprAligned = (bpr + (alignment - 1)) & (~alignment + 1);
|
||||
size_t bprAligned = (bpr + (alignment - 1)) & -alignment;
|
||||
return bprAligned * height;
|
||||
}
|
||||
|
||||
|
||||
@@ -21,16 +21,15 @@
|
||||
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
|
||||
#include <string_view>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
/**
|
||||
* Returns true if the shader string requests the Google-style line directive extension.
|
||||
*/
|
||||
bool requestsGoogleLineDirectivesExtension(std::string_view source) noexcept;
|
||||
bool requestsGoogleLineDirectivesExtension(const char* shader, size_t length) noexcept;
|
||||
|
||||
/**
|
||||
* Edit a GLSL shader string in-place so any Google-style line directives are turned into regular
|
||||
@@ -49,11 +48,6 @@ void removeGoogleLineDirectives(char* shader, size_t length) noexcept;
|
||||
*/
|
||||
size_t getFormatSize(TextureFormat format) noexcept;
|
||||
|
||||
/**
|
||||
* Returns the number of component (1 to 4) for the given format.
|
||||
*/
|
||||
size_t getFormatComponentCount(TextureFormat format) noexcept;
|
||||
|
||||
/**
|
||||
* For compressed texture formats, returns the number of horizontal texels per block. Otherwise
|
||||
* returns 0.
|
||||
@@ -71,6 +65,7 @@ size_t getBlockHeight(TextureFormat format) noexcept;
|
||||
*/
|
||||
bool reshape(const PixelBufferDescriptor& data, PixelBufferDescriptor& reshaped);
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_BACKENDUTILS_H
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
namespace filament::backend {
|
||||
#include <utils/compiler.h>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
class CircularBuffer {
|
||||
public:
|
||||
@@ -84,6 +85,7 @@ private:
|
||||
void* mHead = nullptr;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_CIRCULARBUFFER_H
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
|
||||
#include "private/backend/CircularBuffer.h"
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "private/backend/Program.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
#include "private/backend/Driver.h"
|
||||
|
||||
#include <backend/BufferDescriptor.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
#include <backend/Program.h>
|
||||
#include <backend/PixelBufferDescriptor.h>
|
||||
#include <backend/PresentCallable.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
@@ -36,11 +37,8 @@
|
||||
#include <cstddef>
|
||||
#include <functional>
|
||||
#include <tuple>
|
||||
#include <utility>
|
||||
|
||||
#ifndef NDEBUG
|
||||
#include <thread>
|
||||
#endif
|
||||
#include <utility>
|
||||
|
||||
#include <assert.h>
|
||||
#include <stddef.h>
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVER_H
|
||||
|
||||
#include <backend/DriverApiForward.h>
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/PipelineState.h>
|
||||
#include <backend/TargetBufferInfo.h>
|
||||
|
||||
#include "private/backend/DriverApiForward.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <functional>
|
||||
@@ -47,6 +48,7 @@ class BufferDescriptor;
|
||||
class CallbackHandler;
|
||||
class PixelBufferDescriptor;
|
||||
class Program;
|
||||
class SamplerGroup;
|
||||
|
||||
template<typename T>
|
||||
class ConcreteDispatcher;
|
||||
|
||||
@@ -158,9 +158,6 @@ DECL_DRIVER_API_0(flush)
|
||||
// flush and wait for the effects to be done
|
||||
DECL_DRIVER_API_0(finish)
|
||||
|
||||
// reset state tracking, if the driver does any state tracking (e.g. GL)
|
||||
DECL_DRIVER_API_0(resetState)
|
||||
|
||||
/*
|
||||
* Creating driver objects
|
||||
* -----------------------
|
||||
@@ -307,7 +304,6 @@ DECL_DRIVER_API_SYNCHRONOUS_N(void, cancelExternalImage, void*, image)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, getTimerQueryValue, backend::TimerQueryHandle, query, uint64_t*, elapsedTime)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(backend::SyncStatus, getSyncStatus, backend::SyncHandle, sh)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isWorkaroundNeeded, backend::Workaround, workaround)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(backend::FeatureLevel, getFeatureLevel)
|
||||
|
||||
/*
|
||||
* Updating driver objects
|
||||
@@ -339,7 +335,16 @@ DECL_DRIVER_API_N(resetBufferObject,
|
||||
|
||||
DECL_DRIVER_API_N(updateSamplerGroup,
|
||||
backend::SamplerGroupHandle, ubh,
|
||||
backend::BufferDescriptor&&, data)
|
||||
backend::SamplerGroup&&, samplerGroup)
|
||||
|
||||
DECL_DRIVER_API_N(update2DImage,
|
||||
backend::TextureHandle, th,
|
||||
uint32_t, level,
|
||||
uint32_t, xoffset,
|
||||
uint32_t, yoffset,
|
||||
uint32_t, width,
|
||||
uint32_t, height,
|
||||
backend::PixelBufferDescriptor&&, data)
|
||||
|
||||
DECL_DRIVER_API_N(setMinMaxLevels,
|
||||
backend::TextureHandle, th,
|
||||
@@ -357,6 +362,12 @@ DECL_DRIVER_API_N(update3DImage,
|
||||
uint32_t, depth,
|
||||
backend::PixelBufferDescriptor&&, data)
|
||||
|
||||
DECL_DRIVER_API_N(updateCubeImage,
|
||||
backend::TextureHandle, th,
|
||||
uint32_t, level,
|
||||
backend::PixelBufferDescriptor&&, data,
|
||||
backend::FaceOffsets, faceOffsets)
|
||||
|
||||
DECL_DRIVER_API_N(generateMipmaps,
|
||||
backend::TextureHandle, th)
|
||||
|
||||
@@ -409,17 +420,12 @@ DECL_DRIVER_API_N(bindUniformBuffer,
|
||||
uint32_t, index,
|
||||
backend::BufferObjectHandle, ubh)
|
||||
|
||||
DECL_DRIVER_API_N(bindBufferRange,
|
||||
BufferObjectBinding, bindingType,
|
||||
DECL_DRIVER_API_N(bindUniformBufferRange,
|
||||
uint32_t, index,
|
||||
backend::BufferObjectHandle, ubh,
|
||||
uint32_t, offset,
|
||||
uint32_t, size)
|
||||
|
||||
DECL_DRIVER_API_N(unbindBuffer,
|
||||
BufferObjectBinding, bindingType,
|
||||
uint32_t, index)
|
||||
|
||||
DECL_DRIVER_API_N(bindSamplers,
|
||||
uint32_t, index,
|
||||
backend::SamplerGroupHandle, sbh)
|
||||
@@ -452,12 +458,6 @@ DECL_DRIVER_API_N(readPixels,
|
||||
uint32_t, height,
|
||||
backend::PixelBufferDescriptor&&, data)
|
||||
|
||||
DECL_DRIVER_API_N(readBufferSubData,
|
||||
backend::BufferObjectHandle, src,
|
||||
uint32_t, offset,
|
||||
uint32_t, size,
|
||||
backend::BufferDescriptor&&, data)
|
||||
|
||||
/*
|
||||
* Rendering operations
|
||||
* --------------------
|
||||
@@ -476,11 +476,6 @@ DECL_DRIVER_API_N(draw,
|
||||
backend::RenderPrimitiveHandle, rph,
|
||||
uint32_t, instanceCount)
|
||||
|
||||
DECL_DRIVER_API_N(dispatchCompute,
|
||||
backend::ProgramHandle, program,
|
||||
math::uint3, workGroupCount)
|
||||
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
||||
#undef EXPAND
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPI_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPI_H
|
||||
|
||||
#include "backend/DriverApiForward.h"
|
||||
#include "private/backend/DriverApiForward.h"
|
||||
#include "private/backend/CommandStream.h"
|
||||
|
||||
#endif // TNT_FILAMENT_BACKEND_PRIVATE_DRIVERAPI_H
|
||||
|
||||
@@ -27,40 +27,39 @@
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <array>
|
||||
#include <variant>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class Program {
|
||||
public:
|
||||
|
||||
static constexpr size_t SHADER_TYPE_COUNT = 3;
|
||||
static constexpr size_t UNIFORM_BINDING_COUNT = CONFIG_UNIFORM_BINDING_COUNT;
|
||||
static constexpr size_t SAMPLER_BINDING_COUNT = CONFIG_SAMPLER_BINDING_COUNT;
|
||||
static constexpr size_t SHADER_TYPE_COUNT = 2;
|
||||
static constexpr size_t BINDING_COUNT = CONFIG_BINDING_COUNT;
|
||||
|
||||
enum class Shader : uint8_t {
|
||||
VERTEX = 0,
|
||||
FRAGMENT = 1
|
||||
};
|
||||
|
||||
struct Sampler {
|
||||
utils::CString name = {}; // name of the sampler in the shader
|
||||
uint32_t binding = 0; // binding point of the sampler in the shader
|
||||
uint16_t binding = 0; // binding point of the sampler in the shader
|
||||
bool strict = false; // if true, this sampler must always have a bound texture
|
||||
};
|
||||
|
||||
struct SamplerGroupData {
|
||||
utils::FixedCapacityVector<Sampler> samplers;
|
||||
ShaderStageFlags stageFlags = ShaderStageFlags::ALL_SHADER_STAGE_FLAGS;
|
||||
ShaderStageFlags stageFlags = ALL_SHADER_STAGE_FLAGS;
|
||||
};
|
||||
|
||||
using UniformBlockInfo = std::array<utils::CString, UNIFORM_BINDING_COUNT>;
|
||||
using SamplerGroupInfo = std::array<SamplerGroupData, SAMPLER_BINDING_COUNT>;
|
||||
using ShaderBlob = utils::FixedCapacityVector<uint8_t>;
|
||||
using ShaderSource = std::array<ShaderBlob, SHADER_TYPE_COUNT>;
|
||||
using SamplerGroupInfo = std::array<SamplerGroupData, BINDING_COUNT>;
|
||||
using UniformBlockInfo = std::array<utils::CString, BINDING_COUNT>;
|
||||
|
||||
Program() noexcept;
|
||||
|
||||
Program(const Program& rhs) = delete;
|
||||
Program& operator=(const Program& rhs) = delete;
|
||||
|
||||
Program(Program&& rhs) noexcept;
|
||||
Program& operator=(Program&& rhs) noexcept;
|
||||
|
||||
~Program() noexcept;
|
||||
|
||||
// sets the material name and variant for diagnostic purposes only
|
||||
@@ -70,13 +69,15 @@ public:
|
||||
// sets one of the program's shader (e.g. vertex, fragment)
|
||||
// string-based shaders are null terminated, consequently the size parameter must include the
|
||||
// null terminating character.
|
||||
Program& shader(ShaderStage shader, void const* data, size_t size);
|
||||
Program& shader(Shader shader, void const* data, size_t size) noexcept;
|
||||
|
||||
// sets the 'bindingPoint' uniform block's name for this program.
|
||||
//
|
||||
// Note: This is only needed for GLES3.0 backends, because the layout(binding=) syntax is
|
||||
// not permitted in glsl. The backend needs a way to associate a uniform block
|
||||
// to a binding point.
|
||||
Program& uniformBlockBindings(
|
||||
utils::FixedCapacityVector<std::pair<utils::CString, uint8_t>> const& uniformBlockBindings) noexcept;
|
||||
//
|
||||
Program& setUniformBlock(size_t bindingPoint, utils::CString uniformBlockName) noexcept;
|
||||
|
||||
// sets the 'bindingPoint' sampler group descriptor for this program.
|
||||
// 'samplers' can be destroyed after this call.
|
||||
@@ -85,33 +86,32 @@ public:
|
||||
Program& setSamplerGroup(size_t bindingPoint, ShaderStageFlags stageFlags,
|
||||
Sampler const* samplers, size_t count) noexcept;
|
||||
|
||||
struct SpecializationConstant {
|
||||
uint32_t id; // id set in glsl
|
||||
std::variant<int32_t, float, bool> value; // value and type
|
||||
};
|
||||
|
||||
Program& specializationConstants(
|
||||
utils::FixedCapacityVector<SpecializationConstant> specConstants) noexcept;
|
||||
// string-based shaders are null terminated, consequently the size parameter must include the
|
||||
// null terminating character.
|
||||
Program& withVertexShader(void const* data, size_t size) {
|
||||
return shader(Shader::VERTEX, data, size);
|
||||
}
|
||||
|
||||
// string-based shaders are null terminated, consequently the size parameter must include the
|
||||
// null terminating character.
|
||||
Program& withFragmentShader(void const* data, size_t size) {
|
||||
return shader(Shader::FRAGMENT, data, size);
|
||||
}
|
||||
|
||||
using ShaderBlob = utils::FixedCapacityVector<uint8_t>;
|
||||
using ShaderSource = std::array<ShaderBlob, SHADER_TYPE_COUNT>;
|
||||
ShaderSource const& getShadersSource() const noexcept { return mShadersSource; }
|
||||
ShaderSource& getShadersSource() noexcept { return mShadersSource; }
|
||||
|
||||
UniformBlockInfo const& getUniformBlockBindings() const noexcept { return mUniformBlocks; }
|
||||
UniformBlockInfo& getUniformBlockBindings() noexcept { return mUniformBlocks; }
|
||||
UniformBlockInfo const& getUniformBlockInfo() const noexcept { return mUniformBlocks; }
|
||||
UniformBlockInfo& getUniformBlockInfo() noexcept { return mUniformBlocks; }
|
||||
|
||||
SamplerGroupInfo const& getSamplerGroupInfo() const { return mSamplerGroups; }
|
||||
SamplerGroupInfo& getSamplerGroupInfo() { return mSamplerGroups; }
|
||||
|
||||
utils::CString const& getName() const noexcept { return mName; }
|
||||
utils::CString& getName() noexcept { return mName; }
|
||||
const utils::CString& getName() const noexcept { return mName; }
|
||||
|
||||
utils::FixedCapacityVector<SpecializationConstant> const& getSpecializationConstants() const noexcept {
|
||||
return mSpecializationConstants;
|
||||
}
|
||||
utils::FixedCapacityVector<SpecializationConstant>& getSpecializationConstants() noexcept {
|
||||
return mSpecializationConstants;
|
||||
}
|
||||
bool hasSamplers() const noexcept { return mHasSamplers; }
|
||||
|
||||
private:
|
||||
friend utils::io::ostream& operator<<(utils::io::ostream& out, const Program& builder);
|
||||
@@ -119,9 +119,9 @@ private:
|
||||
UniformBlockInfo mUniformBlocks = {};
|
||||
SamplerGroupInfo mSamplerGroups = {};
|
||||
ShaderSource mShadersSource;
|
||||
bool mHasSamplers = false;
|
||||
utils::CString mName;
|
||||
utils::Invocable<utils::io::ostream&(utils::io::ostream& out)> mLogger;
|
||||
utils::FixedCapacityVector<SpecializationConstant> mSpecializationConstants;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
@@ -17,77 +17,139 @@
|
||||
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
|
||||
#define TNT_FILAMENT_BACKEND_PRIVATE_SAMPLERGROUP_H
|
||||
|
||||
#include "backend/DriverApiForward.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/bitset.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
#include <backend/Handle.h>
|
||||
#include <backend/SamplerDescriptor.h>
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
namespace filament::backend {
|
||||
|
||||
class BufferDescriptor;
|
||||
|
||||
/*
|
||||
* FIXME: this should eventually be moved into Filament, outside of backend.
|
||||
* (but it is currently used by metal/vulkan backens)
|
||||
*/
|
||||
|
||||
class SamplerGroup {
|
||||
public:
|
||||
|
||||
using SamplerParams = backend::SamplerParams;
|
||||
|
||||
SamplerGroup() noexcept {} // NOLINT
|
||||
struct Sampler {
|
||||
Handle<HwTexture> t;
|
||||
SamplerParams s{};
|
||||
};
|
||||
|
||||
SamplerGroup() noexcept { } // NOLINT
|
||||
|
||||
// create a sampler group
|
||||
explicit SamplerGroup(size_t count) noexcept;
|
||||
|
||||
// can be copied. Sets dirty flag.
|
||||
// can be copied -- this preserves dirty bits
|
||||
SamplerGroup(const SamplerGroup& rhs) noexcept;
|
||||
SamplerGroup& operator=(const SamplerGroup& rhs) noexcept;
|
||||
|
||||
// and moved. Leaves rhs empty, keep diry flag on new SamplerGroup.
|
||||
SamplerGroup(SamplerGroup&& rhs) noexcept = default;
|
||||
SamplerGroup& operator=(SamplerGroup&& rhs) = default;
|
||||
// and moved -- this cleans rhs's dirty flags
|
||||
SamplerGroup(SamplerGroup&& rhs) noexcept;
|
||||
SamplerGroup& operator=(SamplerGroup&& rhs) noexcept;
|
||||
|
||||
// copy the rhs samplers into this group and sets the dirty flag
|
||||
SamplerGroup& setSamplers(SamplerGroup const& rhs) noexcept;
|
||||
|
||||
~SamplerGroup() noexcept = default;
|
||||
|
||||
BufferDescriptor toBufferDescriptor(DriverApi& driver) const noexcept;
|
||||
// Efficiently move a SamplerGroup to the command stream. Always use std::move() on the
|
||||
// returned value, as in the future this might return SamplerGroup by value.
|
||||
SamplerGroup& toCommandStream() const noexcept;
|
||||
|
||||
// pointer to the sampler group
|
||||
Sampler const* getSamplers() const noexcept { return mBuffer.data(); }
|
||||
|
||||
// sampler count
|
||||
size_t getSize() const noexcept { return mBuffer.size(); }
|
||||
|
||||
// return if any samplers has been changed
|
||||
bool isDirty() const noexcept {
|
||||
return mDirty;
|
||||
}
|
||||
bool isDirty() const noexcept { return mDirty.any(); }
|
||||
|
||||
// mark the whole group as clean (no modified uniforms)
|
||||
void clean() const noexcept { mDirty = false; }
|
||||
void clean() const noexcept { mDirty.reset(); }
|
||||
|
||||
// set sampler at given index
|
||||
void setSampler(size_t index, backend::SamplerDescriptor sampler) noexcept;
|
||||
void setSampler(size_t index, Sampler sampler) noexcept;
|
||||
|
||||
inline void clearSampler(size_t index) {
|
||||
setSampler(index, {});
|
||||
inline void setSampler(size_t index, Handle<HwTexture> t, SamplerParams s) {
|
||||
setSampler(index, { t, s });
|
||||
}
|
||||
|
||||
|
||||
// FIXME: This is now [[deprecated]]. Currently it is only used by the Vulkan/Metal backends.
|
||||
backend::SamplerDescriptor* data() noexcept { return mBuffer.data(); }
|
||||
inline void clearSampler(size_t index) {
|
||||
setSampler(index, {});
|
||||
}
|
||||
|
||||
private:
|
||||
#if !defined(NDEBUG)
|
||||
friend utils::io::ostream& operator<<(utils::io::ostream& out, const SamplerGroup& rhs);
|
||||
#endif
|
||||
|
||||
utils::FixedCapacityVector<backend::SamplerDescriptor> mBuffer;
|
||||
mutable bool mDirty = false;
|
||||
// This could probably be cleaned-up and moved to libutils
|
||||
template<class T, size_t N>
|
||||
class static_vector { //NOLINT
|
||||
typename std::aligned_storage<sizeof(T), alignof(T)>::type mData[N];
|
||||
uint32_t mSize = 0;
|
||||
public:
|
||||
static_vector() = default; //NOLINT
|
||||
|
||||
~static_vector() noexcept {
|
||||
for (auto& elem : *this) {
|
||||
elem.~T();
|
||||
}
|
||||
}
|
||||
|
||||
explicit static_vector(size_t count) noexcept : mSize(count) {
|
||||
assert_invariant(count < N);
|
||||
std::uninitialized_fill_n(begin(), count, T{});
|
||||
}
|
||||
|
||||
static_vector(static_vector const& rhs) noexcept : mSize(rhs.mSize) {
|
||||
std::uninitialized_copy(rhs.begin(), rhs.end(), begin());
|
||||
}
|
||||
|
||||
size_t size() const noexcept { return mSize; }
|
||||
|
||||
T* data() noexcept { return reinterpret_cast<T*>(&mData[0]); }
|
||||
|
||||
T const* data() const noexcept { return reinterpret_cast<T const*>(&mData[0]); }
|
||||
|
||||
static_vector& operator=(static_vector const& rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
const size_t n = std::min(mSize, rhs.mSize);
|
||||
std::copy_n(rhs.begin(), n, begin());
|
||||
for (size_t pos = n, c = mSize; pos < c; ++pos) {
|
||||
data()[pos].~T();
|
||||
}
|
||||
std::uninitialized_copy(rhs.begin() + n, rhs.end(), begin() + n);
|
||||
mSize = rhs.mSize;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
const T& operator[](size_t pos) const noexcept {
|
||||
assert_invariant(pos < mSize);
|
||||
return data()[pos];
|
||||
}
|
||||
|
||||
T& operator[](size_t pos) noexcept {
|
||||
assert_invariant(pos < mSize);
|
||||
return data()[pos];
|
||||
}
|
||||
|
||||
T* begin() { return data(); }
|
||||
T* end() { return data() + mSize; }
|
||||
T const* begin() const { return data(); }
|
||||
T const* end() const { return data() + mSize; }
|
||||
};
|
||||
|
||||
static_vector<Sampler, backend::MAX_SAMPLER_COUNT> mBuffer; // 128 bytes
|
||||
mutable utils::bitset32 mDirty;
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -22,10 +22,12 @@
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
bool requestsGoogleLineDirectivesExtension(std::string_view source) noexcept {
|
||||
return source.find("GL_GOOGLE_cpp_style_line_directive") != std::string_view::npos;
|
||||
bool requestsGoogleLineDirectivesExtension(const char* shader, size_t length) noexcept {
|
||||
std::string_view s(shader, length);
|
||||
return s.find("GL_GOOGLE_cpp_style_line_directive") != std::string_view::npos;
|
||||
}
|
||||
|
||||
void removeGoogleLineDirectives(char* shader, size_t length) noexcept {
|
||||
@@ -209,129 +211,6 @@ size_t getFormatSize(TextureFormat format) noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
size_t getFormatComponentCount(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::R8:
|
||||
case TextureFormat::R8_SNORM:
|
||||
case TextureFormat::R8UI:
|
||||
case TextureFormat::R8I:
|
||||
case TextureFormat::R16F:
|
||||
case TextureFormat::R16UI:
|
||||
case TextureFormat::R16I:
|
||||
case TextureFormat::R32F:
|
||||
case TextureFormat::R32I:
|
||||
case TextureFormat::R32UI:
|
||||
case TextureFormat::STENCIL8:
|
||||
case TextureFormat::DEPTH16:
|
||||
case TextureFormat::DEPTH24:
|
||||
case TextureFormat::DEPTH32F:
|
||||
return 1;
|
||||
|
||||
case TextureFormat::RG8:
|
||||
case TextureFormat::RG8_SNORM:
|
||||
case TextureFormat::RG8UI:
|
||||
case TextureFormat::RG8I:
|
||||
case TextureFormat::RG16F:
|
||||
case TextureFormat::RG16UI:
|
||||
case TextureFormat::RG16I:
|
||||
case TextureFormat::RG32F:
|
||||
case TextureFormat::RG32UI:
|
||||
case TextureFormat::RG32I:
|
||||
case TextureFormat::DEPTH24_STENCIL8:
|
||||
case TextureFormat::DEPTH32F_STENCIL8:
|
||||
return 2;
|
||||
|
||||
case TextureFormat::RGB565:
|
||||
case TextureFormat::RGB8:
|
||||
case TextureFormat::SRGB8:
|
||||
case TextureFormat::RGB8_SNORM:
|
||||
case TextureFormat::RGB8UI:
|
||||
case TextureFormat::RGB8I:
|
||||
case TextureFormat::R11F_G11F_B10F:
|
||||
case TextureFormat::RGB16F:
|
||||
case TextureFormat::RGB16UI:
|
||||
case TextureFormat::RGB16I:
|
||||
case TextureFormat::RGB32F:
|
||||
case TextureFormat::RGB32UI:
|
||||
case TextureFormat::RGB32I:
|
||||
return 3;
|
||||
|
||||
case TextureFormat::RGB5_A1:
|
||||
case TextureFormat::RGBA4:
|
||||
case TextureFormat::RGB9_E5:
|
||||
case TextureFormat::RGBA8:
|
||||
case TextureFormat::SRGB8_A8:
|
||||
case TextureFormat::RGBA8_SNORM:
|
||||
case TextureFormat::RGB10_A2:
|
||||
case TextureFormat::RGBA8UI:
|
||||
case TextureFormat::RGBA8I:
|
||||
case TextureFormat::RGBA16F:
|
||||
case TextureFormat::RGBA16UI:
|
||||
case TextureFormat::RGBA16I:
|
||||
case TextureFormat::RGBA32F:
|
||||
case TextureFormat::RGBA32UI:
|
||||
case TextureFormat::RGBA32I:
|
||||
return 4;
|
||||
|
||||
// Compressed formats ---------------------------------------------------------------------
|
||||
case TextureFormat::EAC_R11:
|
||||
case TextureFormat::EAC_R11_SIGNED:
|
||||
return 1;
|
||||
|
||||
case TextureFormat::EAC_RG11:
|
||||
case TextureFormat::EAC_RG11_SIGNED:
|
||||
return 2;
|
||||
|
||||
case TextureFormat::ETC2_RGB8:
|
||||
case TextureFormat::ETC2_SRGB8:
|
||||
case TextureFormat::DXT1_RGB:
|
||||
case TextureFormat::DXT1_SRGB:
|
||||
return 3;
|
||||
|
||||
case TextureFormat::ETC2_EAC_RGBA8:
|
||||
case TextureFormat::ETC2_EAC_SRGBA8:
|
||||
case TextureFormat::ETC2_RGB8_A1:
|
||||
case TextureFormat::ETC2_SRGB8_A1:
|
||||
case TextureFormat::DXT1_RGBA:
|
||||
case TextureFormat::DXT1_SRGBA:
|
||||
case TextureFormat::DXT3_RGBA:
|
||||
case TextureFormat::DXT3_SRGBA:
|
||||
case TextureFormat::DXT5_RGBA:
|
||||
case TextureFormat::DXT5_SRGBA:
|
||||
case TextureFormat::RGBA_ASTC_4x4:
|
||||
case TextureFormat::RGBA_ASTC_5x4:
|
||||
case TextureFormat::RGBA_ASTC_5x5:
|
||||
case TextureFormat::RGBA_ASTC_6x5:
|
||||
case TextureFormat::RGBA_ASTC_6x6:
|
||||
case TextureFormat::RGBA_ASTC_8x5:
|
||||
case TextureFormat::RGBA_ASTC_8x6:
|
||||
case TextureFormat::RGBA_ASTC_8x8:
|
||||
case TextureFormat::RGBA_ASTC_10x5:
|
||||
case TextureFormat::RGBA_ASTC_10x6:
|
||||
case TextureFormat::RGBA_ASTC_10x8:
|
||||
case TextureFormat::RGBA_ASTC_10x10:
|
||||
case TextureFormat::RGBA_ASTC_12x10:
|
||||
case TextureFormat::RGBA_ASTC_12x12:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10:
|
||||
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12:
|
||||
return 4;
|
||||
case TextureFormat::UNUSED:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
size_t getBlockWidth(TextureFormat format) noexcept {
|
||||
switch (format) {
|
||||
case TextureFormat::EAC_RG11:
|
||||
@@ -501,59 +380,60 @@ bool reshape(const PixelBufferDescriptor& data, PixelBufferDescriptor& reshaped)
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace backend::filament
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
namespace utils {
|
||||
|
||||
template<>
|
||||
CString to_string<filament::backend::TextureUsage>(filament::backend::TextureUsage value) noexcept {
|
||||
CString to_string<filament::backend::TextureUsage>(filament::backend::TextureUsage usage) noexcept {
|
||||
using namespace filament::backend;
|
||||
char string[7] = {'-', '-', '-', '-', '-', '-', 0};
|
||||
if (any(value & TextureUsage::UPLOADABLE)) {
|
||||
if (any(usage & TextureUsage::UPLOADABLE)) {
|
||||
string[0]='U';
|
||||
}
|
||||
if (any(value & TextureUsage::SAMPLEABLE)) {
|
||||
if (any(usage & TextureUsage::SAMPLEABLE)) {
|
||||
string[1]='S';
|
||||
}
|
||||
if (any(value & TextureUsage::COLOR_ATTACHMENT)) {
|
||||
if (any(usage & TextureUsage::COLOR_ATTACHMENT)) {
|
||||
string[2]='c';
|
||||
}
|
||||
if (any(value & TextureUsage::DEPTH_ATTACHMENT)) {
|
||||
if (any(usage & TextureUsage::DEPTH_ATTACHMENT)) {
|
||||
string[3]='d';
|
||||
}
|
||||
if (any(value & TextureUsage::STENCIL_ATTACHMENT)) {
|
||||
if (any(usage & TextureUsage::STENCIL_ATTACHMENT)) {
|
||||
string[4] = 's';
|
||||
}
|
||||
if (any(value & TextureUsage::SUBPASS_INPUT)) {
|
||||
if (any(usage & TextureUsage::SUBPASS_INPUT)) {
|
||||
string[5]='f';
|
||||
}
|
||||
return { string, 6 };
|
||||
return CString(string, 6);
|
||||
}
|
||||
|
||||
template<>
|
||||
CString to_string<filament::backend::TargetBufferFlags>(filament::backend::TargetBufferFlags value) noexcept {
|
||||
CString to_string<filament::backend::TargetBufferFlags>(filament::backend::TargetBufferFlags flags) noexcept {
|
||||
using namespace filament::backend;
|
||||
char string[7] = {'-', '-', '-', '-', '-', '-', 0};
|
||||
if (any(value & TargetBufferFlags::COLOR0)) {
|
||||
if (any(flags & TargetBufferFlags::COLOR0)) {
|
||||
string[0]='0';
|
||||
}
|
||||
if (any(value & TargetBufferFlags::COLOR1)) {
|
||||
if (any(flags & TargetBufferFlags::COLOR1)) {
|
||||
string[1]='1';
|
||||
}
|
||||
if (any(value & TargetBufferFlags::COLOR2)) {
|
||||
if (any(flags & TargetBufferFlags::COLOR2)) {
|
||||
string[2]='2';
|
||||
}
|
||||
if (any(value & TargetBufferFlags::COLOR3)) {
|
||||
if (any(flags & TargetBufferFlags::COLOR3)) {
|
||||
string[3]='3';
|
||||
}
|
||||
if (any(value & TargetBufferFlags::DEPTH)) {
|
||||
if (any(flags & TargetBufferFlags::DEPTH)) {
|
||||
string[4]='D';
|
||||
}
|
||||
if (any(value & TargetBufferFlags::STENCIL)) {
|
||||
if (any(flags & TargetBufferFlags::STENCIL)) {
|
||||
string[5]='S';
|
||||
}
|
||||
return { string, 6 };
|
||||
return CString(string, 6);
|
||||
}
|
||||
|
||||
} // namespace utils
|
||||
|
||||
@@ -59,21 +59,6 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
static void copyImage(uint8_t* UTILS_RESTRICT dest,
|
||||
const uint8_t* UTILS_RESTRICT src,
|
||||
size_t srcBytesPerRow, size_t /*srcChannelCount*/,
|
||||
size_t dstBytesPerRow, size_t /*dstChannelCount*/,
|
||||
size_t /*width*/, size_t height, bool /*swizzle*/) {
|
||||
if (srcBytesPerRow == dstBytesPerRow) {
|
||||
std::memcpy(dest, src, height * srcBytesPerRow);
|
||||
return;
|
||||
}
|
||||
const size_t minBytesPerRow = std::min(srcBytesPerRow, dstBytesPerRow);
|
||||
for (size_t i = 0; i < height; ++i, src += srcBytesPerRow, dest += dstBytesPerRow) {
|
||||
std::memcpy(dest, src, minBytesPerRow);
|
||||
}
|
||||
}
|
||||
|
||||
// Converts a n-channel image of UBYTE, INT, UINT, or FLOAT to a different type.
|
||||
template<typename dstComponentType, typename srcComponentType>
|
||||
static void reshapeImage(uint8_t* UTILS_RESTRICT dest, const uint8_t* UTILS_RESTRICT src,
|
||||
@@ -134,13 +119,7 @@ public:
|
||||
switch (dst->type) {
|
||||
case UBYTE:
|
||||
switch (srcType) {
|
||||
case UBYTE:
|
||||
reshaper = reshapeImage<uint8_t, uint8_t>;
|
||||
if (dst->format == PixelDataFormat::RGBA &&
|
||||
dstChannelCount == srcChannelCount && !swizzle) {
|
||||
reshaper = copyImage;
|
||||
}
|
||||
break;
|
||||
case UBYTE: reshaper = reshapeImage<uint8_t, uint8_t>; break;
|
||||
case FLOAT: reshaper = reshapeImage<uint8_t, float>; break;
|
||||
case INT: reshaper = reshapeImage<uint8_t, int32_t>; break;
|
||||
case UINT: reshaper = reshapeImage<uint8_t, uint32_t>; break;
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
|
||||
#include "private/backend/Dispatcher.h"
|
||||
#include "private/backend/Driver.h"
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
@@ -103,7 +104,10 @@ struct HwProgram : public HwBase {
|
||||
};
|
||||
|
||||
struct HwSamplerGroup : public HwBase {
|
||||
// NOTE: we have to use out-of-line allocation here because the size of a Handle<> is limited
|
||||
std::unique_ptr<SamplerGroup> sb; // FIXME: this shouldn't depend on filament::SamplerGroup
|
||||
HwSamplerGroup() noexcept = default;
|
||||
explicit HwSamplerGroup(size_t size) noexcept : sb(new SamplerGroup(size)) { }
|
||||
};
|
||||
|
||||
struct HwTexture : public HwBase {
|
||||
|
||||
@@ -42,9 +42,7 @@
|
||||
#include "vulkan/PlatformVkCocoa.h"
|
||||
#endif
|
||||
#elif defined(__linux__)
|
||||
#if defined(FILAMENT_SUPPORTS_GGP)
|
||||
#include "vulkan/PlatformVkLinuxGGP.h"
|
||||
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#if defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#if defined (FILAMENT_DRIVER_SUPPORTS_VULKAN)
|
||||
#include "vulkan/PlatformVkLinuxWayland.h"
|
||||
#endif
|
||||
@@ -69,6 +67,10 @@
|
||||
#endif
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
#include "opengl/platforms/PlatformWebGL.h"
|
||||
#else
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL) && !defined(FILAMENT_USE_EXTERNAL_GLES3)
|
||||
#include "opengl/platforms/PlatformDummyGL.h"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if defined (FILAMENT_SUPPORTS_METAL)
|
||||
@@ -79,7 +81,9 @@ filament::backend::DefaultPlatform* createDefaultMetalPlatform();
|
||||
|
||||
#include "noop/PlatformNoop.h"
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament {
|
||||
|
||||
namespace backend {
|
||||
|
||||
// this generates the vtable in this translation unit
|
||||
Platform::~Platform() noexcept = default;
|
||||
@@ -122,9 +126,7 @@ DefaultPlatform* DefaultPlatform::create(Backend* backend) noexcept {
|
||||
#elif defined(IOS)
|
||||
return new PlatformVkCocoaTouch();
|
||||
#elif defined(__linux__)
|
||||
#if defined(FILAMENT_SUPPORTS_GGP)
|
||||
return new PlatformVkLinuxGGP();
|
||||
#elif defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
#if defined(FILAMENT_SUPPORTS_WAYLAND)
|
||||
return new PlatformVkLinuxWayland();
|
||||
#elif defined(FILAMENT_SUPPORTS_X11)
|
||||
return new PlatformVkLinuxX11();
|
||||
@@ -150,7 +152,6 @@ DefaultPlatform* DefaultPlatform::create(Backend* backend) noexcept {
|
||||
assert_invariant(*backend == Backend::OPENGL);
|
||||
#if defined(FILAMENT_SUPPORTS_OPENGL)
|
||||
#if defined(FILAMENT_USE_EXTERNAL_GLES3) || defined(FILAMENT_USE_SWIFTSHADER)
|
||||
// Swiftshader OpenGLES support is deprecated and incomplete
|
||||
return nullptr;
|
||||
#elif defined(__ANDROID__)
|
||||
return new PlatformEGLAndroid();
|
||||
@@ -169,14 +170,14 @@ DefaultPlatform* DefaultPlatform::create(Backend* backend) noexcept {
|
||||
#elif defined(__EMSCRIPTEN__)
|
||||
return new PlatformWebGL();
|
||||
#else
|
||||
return nullptr;
|
||||
return new PlatformDummyGL();
|
||||
#endif
|
||||
#else
|
||||
return nullptr;
|
||||
#endif
|
||||
}
|
||||
|
||||
// destroys a Platform created by create()
|
||||
// destroys an Platform create by create()
|
||||
void DefaultPlatform::destroy(DefaultPlatform** platform) noexcept {
|
||||
delete *platform;
|
||||
*platform = nullptr;
|
||||
@@ -184,4 +185,5 @@ void DefaultPlatform::destroy(DefaultPlatform** platform) noexcept {
|
||||
|
||||
DefaultPlatform::~DefaultPlatform() noexcept = default;
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -14,49 +14,34 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "backend/Program.h"
|
||||
|
||||
namespace filament::backend {
|
||||
#include "private/backend/Program.h"
|
||||
|
||||
using namespace utils;
|
||||
|
||||
// We want these in the .cpp file, so they're not inlined (not worth it)
|
||||
Program::Program() noexcept { // NOLINT(modernize-use-equals-default)
|
||||
}
|
||||
namespace filament::backend {
|
||||
|
||||
// We want these in the .cpp file so they're not inlined (not worth it)
|
||||
Program::Program() noexcept {} // = default; does not work with msvc because of noexcept
|
||||
Program::Program(Program&& rhs) noexcept = default;
|
||||
|
||||
Program& Program::operator=(Program&& rhs) noexcept {
|
||||
mUniformBlocks.operator=(rhs.mUniformBlocks);
|
||||
mSamplerGroups.operator=(std::move(rhs.mSamplerGroups));
|
||||
mShadersSource.operator=(std::move(rhs.mShadersSource));
|
||||
mName.operator=(std::move(rhs.mName));
|
||||
mLogger.operator=(std::move(rhs.mLogger));
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::operator=(Program&& rhs) noexcept = default;
|
||||
Program::~Program() noexcept = default;
|
||||
|
||||
Program& Program::diagnostics(CString const& name,
|
||||
Invocable<io::ostream&(io::ostream&)>&& logger) {
|
||||
Program& Program::diagnostics(utils::CString const& name,
|
||||
utils::Invocable<io::ostream&(utils::io::ostream&)>&& logger) {
|
||||
mName = name;
|
||||
mLogger = std::move(logger);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::shader(ShaderStage shader, void const* data, size_t size) {
|
||||
Program& Program::shader(Program::Shader shader, void const* data, size_t size) noexcept {
|
||||
ShaderBlob blob(size);
|
||||
std::copy_n((const uint8_t *)data, size, blob.data());
|
||||
mShadersSource[size_t(shader)] = std::move(blob);
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::uniformBlockBindings(
|
||||
FixedCapacityVector<std::pair<utils::CString, uint8_t>> const& uniformBlockBindings) noexcept {
|
||||
for (auto const& item : uniformBlockBindings) {
|
||||
assert_invariant(item.second < UNIFORM_BINDING_COUNT);
|
||||
mUniformBlocks[item.second] = item.first;
|
||||
}
|
||||
Program& Program::setUniformBlock(size_t bindingPoint, utils::CString uniformBlockName) noexcept {
|
||||
mUniformBlocks[bindingPoint] = std::move(uniformBlockName);
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -68,12 +53,7 @@ Program& Program::setSamplerGroup(size_t bindingPoint, ShaderStageFlags stageFla
|
||||
samplerList.reserve(count);
|
||||
samplerList.resize(count);
|
||||
std::copy_n(samplers, count, samplerList.data());
|
||||
return *this;
|
||||
}
|
||||
|
||||
Program& Program::specializationConstants(
|
||||
FixedCapacityVector<SpecializationConstant> specConstants) noexcept {
|
||||
mSpecializationConstants = std::move(specConstants);
|
||||
mHasSamplers = true;
|
||||
return *this;
|
||||
}
|
||||
|
||||
@@ -84,5 +64,4 @@ io::ostream& operator<<(io::ostream& out, const Program& builder) {
|
||||
return out;
|
||||
}
|
||||
|
||||
|
||||
} // namespace filament::backend
|
||||
|
||||
@@ -16,53 +16,64 @@
|
||||
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
#include "private/backend/DriverApi.h"
|
||||
|
||||
#include "backend/BufferDescriptor.h"
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
// create a sampler buffer
|
||||
SamplerGroup::SamplerGroup(size_t count) noexcept
|
||||
: mBuffer(count) {
|
||||
}
|
||||
|
||||
SamplerGroup::SamplerGroup(const SamplerGroup& rhs) noexcept :
|
||||
mBuffer(rhs.mBuffer), mDirty(true) {
|
||||
SamplerGroup::SamplerGroup(const SamplerGroup& rhs) noexcept = default;
|
||||
|
||||
SamplerGroup::SamplerGroup(SamplerGroup&& rhs) noexcept
|
||||
: mBuffer(rhs.mBuffer), mDirty(rhs.mDirty) {
|
||||
rhs.clean();
|
||||
}
|
||||
|
||||
SamplerGroup& SamplerGroup::operator=(const SamplerGroup& rhs) noexcept {
|
||||
SamplerGroup& SamplerGroup::operator=(const SamplerGroup& rhs) noexcept = default;
|
||||
|
||||
SamplerGroup& SamplerGroup::operator=(SamplerGroup&& rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
mBuffer = rhs.mBuffer;
|
||||
mDirty = true;
|
||||
mDirty = rhs.mDirty;
|
||||
rhs.clean();
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SamplerGroup::setSampler(size_t index, SamplerDescriptor sampler) noexcept {
|
||||
if (UTILS_LIKELY(index < mBuffer.size())) {
|
||||
// We cannot compare two texture handles to determine if an update is needed. Texture
|
||||
// handles are (quickly) recycled and therefore can't be used for that purpose. e.g. if a
|
||||
// texture is destroyed, its handle could be reused quickly by another texture.
|
||||
// TODO: find a way to avoid marking dirty if the texture does not change.
|
||||
mBuffer[index] = sampler;
|
||||
mDirty = true;
|
||||
}
|
||||
SamplerGroup& SamplerGroup::toCommandStream() const noexcept {
|
||||
/*
|
||||
* This works because our move ctor preserves the data and cleans the dirty flags.
|
||||
* if we changed the implementation in the future to do a real move, we'd have to change
|
||||
* this method to return SamplerGroup by value, e.g.:
|
||||
* SamplerGroup copy(*this);
|
||||
* this->clean();
|
||||
* return copy;
|
||||
*/
|
||||
return const_cast<SamplerGroup&>(*this);
|
||||
}
|
||||
|
||||
BufferDescriptor SamplerGroup::toBufferDescriptor(DriverApi& driver) const noexcept {
|
||||
BufferDescriptor p;
|
||||
p.size = mBuffer.size() * sizeof(SamplerDescriptor);
|
||||
p.buffer = driver.allocate(p.size); // TODO: use out-of-line buffer if too large
|
||||
memcpy(p.buffer, static_cast<const void*>(mBuffer.data()), p.size); // inlined
|
||||
clean();
|
||||
return p;
|
||||
SamplerGroup& SamplerGroup::setSamplers(SamplerGroup const& rhs) noexcept {
|
||||
if (this != &rhs) {
|
||||
mBuffer = rhs.mBuffer;
|
||||
mDirty.setValue((1u << rhs.mBuffer.size()) - 1u);
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
void SamplerGroup::setSampler(size_t index, Sampler sampler) noexcept {
|
||||
if (UTILS_LIKELY(index < mBuffer.size())) {
|
||||
mBuffer[index] = sampler;
|
||||
mDirty.set(index);
|
||||
}
|
||||
}
|
||||
|
||||
#if !defined(NDEBUG)
|
||||
utils::io::ostream& operator<<(utils::io::ostream& out, const SamplerGroup& rhs) {
|
||||
return out << "SamplerGroup(size=" << rhs.getSize() << ")";
|
||||
return out << "SamplerGroup(data=" << rhs.getSamplers() << ", size=" << rhs.getSize() << ")";
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
@@ -91,14 +91,12 @@ blitterFrag(VertexOut in [[stage_in]],
|
||||
{
|
||||
FragmentOut out = {};
|
||||
|
||||
#if defined(BLIT_COLOR) || defined(BLIT_DEPTH)
|
||||
// These coordinates match the Vulkan vkCmdBlitImage spec:
|
||||
// https://www.khronos.org/registry/vulkan/specs/1.2-extensions/man/html/vkCmdBlitImage.html
|
||||
float2 uvbase = in.position.xy; // unnormalized coordinates at center of texel: (1.5, 2.5, etc)
|
||||
float2 uvoffset = uvbase - args->dstOffset;
|
||||
float2 uvscaled = uvoffset * args->scale;
|
||||
float2 uv = uvscaled + args->srcOffset;
|
||||
#endif
|
||||
|
||||
#ifdef BLIT_COLOR
|
||||
#ifdef MSAA_COLOR_SOURCE
|
||||
@@ -367,7 +365,7 @@ void MetalBlitter::blitDepthPlane(id<MTLCommandBuffer> cmdBuffer, bool blitColor
|
||||
[encoder setViewport:viewport];
|
||||
|
||||
DepthStencilState depthStencilState {
|
||||
.depthCompare = MTLCompareFunctionAlways,
|
||||
.compareFunction = MTLCompareFunctionAlways,
|
||||
.depthWriteEnabled = blitDepth
|
||||
};
|
||||
id<MTLDepthStencilState> depthStencil =
|
||||
|
||||
@@ -24,18 +24,13 @@
|
||||
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
#include <utility>
|
||||
#include <memory>
|
||||
|
||||
namespace filament::backend {
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
class MetalBuffer {
|
||||
public:
|
||||
|
||||
MetalBuffer(MetalContext& context, BufferObjectBinding bindingType, BufferUsage usage,
|
||||
size_t size, bool forceGpuBuffer = false);
|
||||
MetalBuffer(MetalContext& context, BufferUsage usage, size_t size, bool forceGpuBuffer = false);
|
||||
~MetalBuffer();
|
||||
|
||||
MetalBuffer(const MetalBuffer& rhs) = delete;
|
||||
@@ -57,153 +52,39 @@ public:
|
||||
* @return The MTLBuffer representing the current state of the buffer to bind, or nil if there
|
||||
* is no device allocation.
|
||||
*
|
||||
* For STREAM buffers, getGpuBufferStreamOffset() should be called to retrieve the correct
|
||||
* buffer offset.
|
||||
*
|
||||
*/
|
||||
id<MTLBuffer> getGpuBufferForDraw(id<MTLCommandBuffer> cmdBuffer) noexcept;
|
||||
|
||||
void* getCpuBuffer() const noexcept { return mCpuBuffer; }
|
||||
|
||||
enum Stage : uint8_t {
|
||||
VERTEX = 1u << 0u,
|
||||
FRAGMENT = 1u << 1u,
|
||||
COMPUTE = 1u << 2u
|
||||
enum Stage {
|
||||
VERTEX = 1,
|
||||
FRAGMENT = 2
|
||||
};
|
||||
|
||||
/**
|
||||
* Bind multiple buffers to pipeline stages.
|
||||
*
|
||||
* bindBuffers binds an array of buffers to the given stage(s) of a MTLCommandEncoders's
|
||||
* pipeline. The encoder must be either a MTLRenderCommandEncoder or a MTLComputeCommandEncoder.
|
||||
* For MTLRenderCommandEncoders, only the VERTEX and FRAGMENT stages may be specified.
|
||||
* For MTLComputeCommandEncoders, only the COMPUTE stage may be specified.
|
||||
* bindBuffers binds an array of buffers to the given stage(s) of a MTLRenderCommandEncoder's
|
||||
* pipeline.
|
||||
*/
|
||||
static void bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLCommandEncoder> encoder,
|
||||
static void bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLRenderCommandEncoder> encoder,
|
||||
size_t bufferStart, uint8_t stages, MetalBuffer* const* buffers, size_t const* offsets,
|
||||
size_t count);
|
||||
|
||||
private:
|
||||
|
||||
id<MTLBuffer> mBuffer = nil;
|
||||
BufferUsage mUsage;
|
||||
size_t mBufferSize = 0;
|
||||
const MetalBufferPoolEntry* mBufferPoolEntry = nullptr;
|
||||
void* mCpuBuffer = nullptr;
|
||||
MetalContext& mContext;
|
||||
};
|
||||
|
||||
template <typename TYPE>
|
||||
static inline TYPE align(TYPE p, size_t alignment) noexcept {
|
||||
// alignment must be a power-of-two
|
||||
assert(alignment && !(alignment & alignment-1));
|
||||
return (TYPE)((p + alignment - 1) & ~(alignment - 1));
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages a single id<MTLBuffer>, allowing sub-allocations in a "ring" fashion. Each slot in the
|
||||
* buffer has a fixed size. When a new allocation is made, previous allocations become available
|
||||
* when the current id<MTLCommandBuffer> has finished executing on the GPU.
|
||||
*
|
||||
* If there are no slots available when a new allocation is requested, MetalRingBuffer falls back to
|
||||
* allocating a new id<MTLBuffer> per allocation until a slot is freed.
|
||||
*
|
||||
* All methods must be called from the Metal backend thread.
|
||||
*/
|
||||
class MetalRingBuffer {
|
||||
public:
|
||||
// In practice, MetalRingBuffer is used for argument buffers, which are kept in the constant
|
||||
// address space. Constant buffers have specific alignment requirements when specifying an
|
||||
// offset.
|
||||
#if defined(IOS)
|
||||
#if TARGET_OS_SIMULATOR
|
||||
// The iOS simulator has differing alignment requirements.
|
||||
static constexpr auto METAL_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 256;
|
||||
#else
|
||||
static constexpr auto METAL_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 4;
|
||||
#endif // TARGET_OS_SIMULATOR
|
||||
#else
|
||||
static constexpr auto METAL_CONSTANT_BUFFER_OFFSET_ALIGNMENT = 32;
|
||||
#endif
|
||||
static inline auto computeSlotSize(MTLSizeAndAlign layout) {
|
||||
return align(align(layout.size, layout.align), METAL_CONSTANT_BUFFER_OFFSET_ALIGNMENT);
|
||||
}
|
||||
|
||||
MetalRingBuffer(id<MTLDevice> device, MTLResourceOptions options, MTLSizeAndAlign layout,
|
||||
NSUInteger slotCount)
|
||||
: mDevice(device),
|
||||
mAuxBuffer(nil),
|
||||
mBufferOptions(options),
|
||||
mSlotSizeBytes(computeSlotSize(layout)),
|
||||
mSlotCount(slotCount) {
|
||||
mBuffer = [device newBufferWithLength:mSlotSizeBytes * mSlotCount options:mBufferOptions];
|
||||
assert_invariant(mBuffer);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new allocation in the buffer.
|
||||
* @param cmdBuffer When this command buffer has finished executing on the GPU, the previous
|
||||
* ring buffer allocation will be freed.
|
||||
* @return the id<MTLBuffer> and offset for the new allocation
|
||||
*/
|
||||
std::pair<id<MTLBuffer>, NSUInteger> createNewAllocation(id<MTLCommandBuffer> cmdBuffer) {
|
||||
const auto occupiedSlots = mOccupiedSlots->load(std::memory_order_relaxed);
|
||||
assert_invariant(occupiedSlots <= mSlotCount);
|
||||
if (UTILS_UNLIKELY(occupiedSlots == mSlotCount)) {
|
||||
// We don't have any room left, so we fall back to creating a one-off aux buffer.
|
||||
// If we already have an aux buffer, it will get freed here, unless it has been retained
|
||||
// by a MTLCommandBuffer. In that case, it will be freed when the command buffer
|
||||
// finishes executing.
|
||||
mAuxBuffer = [mDevice newBufferWithLength:mSlotSizeBytes options:mBufferOptions];
|
||||
assert_invariant(mAuxBuffer);
|
||||
return {mAuxBuffer, 0};
|
||||
}
|
||||
mCurrentSlot = (mCurrentSlot + 1) % mSlotCount;
|
||||
mOccupiedSlots->fetch_add(1, std::memory_order_relaxed);
|
||||
|
||||
// Release the previous allocation.
|
||||
if (UTILS_UNLIKELY(mAuxBuffer)) {
|
||||
mAuxBuffer = nil;
|
||||
} else {
|
||||
// Capture the mOccupiedSlots var via a weak_ptr because the MetalRingBuffer could be
|
||||
// destructed before the block executes.
|
||||
std::weak_ptr<AtomicCounterType> slots = mOccupiedSlots;
|
||||
[cmdBuffer addCompletedHandler:^(id<MTLCommandBuffer> buffer) {
|
||||
if (auto s = slots.lock()) {
|
||||
s->fetch_sub(1, std::memory_order_relaxed);
|
||||
}
|
||||
}];
|
||||
}
|
||||
return getCurrentAllocation();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an allocation (buffer and offset) that is guaranteed not to be in use by the GPU.
|
||||
* @param cmdBuffer When this command buffer has finished executing on the GPU, the previous
|
||||
* ring buffer allocation will be freed.
|
||||
* @return the id<MTLBuffer> and offset for the current allocation
|
||||
*/
|
||||
std::pair<id<MTLBuffer>, NSUInteger> getCurrentAllocation() const {
|
||||
if (UTILS_UNLIKELY(mAuxBuffer)) {
|
||||
return { mAuxBuffer, 0 };
|
||||
}
|
||||
return { mBuffer, mCurrentSlot * mSlotSizeBytes };
|
||||
}
|
||||
|
||||
bool canAccomodateLayout(MTLSizeAndAlign layout) const {
|
||||
return mSlotSizeBytes >= computeSlotSize(layout);
|
||||
}
|
||||
|
||||
private:
|
||||
id<MTLDevice> mDevice;
|
||||
id<MTLBuffer> mBuffer;
|
||||
id<MTLBuffer> mAuxBuffer;
|
||||
|
||||
MTLResourceOptions mBufferOptions;
|
||||
|
||||
NSUInteger mSlotSizeBytes;
|
||||
NSUInteger mSlotCount;
|
||||
|
||||
NSUInteger mCurrentSlot = 0;
|
||||
using AtomicCounterType = std::atomic<NSUInteger>;
|
||||
std::shared_ptr<AtomicCounterType> mOccupiedSlots = std::make_shared<AtomicCounterType>(1);
|
||||
};
|
||||
|
||||
} // namespace filament::backend
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
#endif
|
||||
|
||||
@@ -16,32 +16,36 @@
|
||||
|
||||
#include "MetalBuffer.h"
|
||||
|
||||
#include "MetalContext.h"
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <array>
|
||||
|
||||
namespace filament {
|
||||
namespace backend {
|
||||
|
||||
MetalBuffer::MetalBuffer(MetalContext& context, BufferObjectBinding bindingType, BufferUsage usage,
|
||||
size_t size, bool forceGpuBuffer) : mBufferSize(size), mContext(context) {
|
||||
MetalBuffer::MetalBuffer(MetalContext& context, BufferUsage usage, size_t size, bool forceGpuBuffer)
|
||||
: mBufferSize(size), mContext(context) {
|
||||
// If the buffer is less than 4K in size and is updated frequently, we don't use an explicit
|
||||
// buffer. Instead, we use immediate command encoder methods like setVertexBytes:length:atIndex:.
|
||||
// This won't work for SSBOs, since they are read/write.
|
||||
if (size <= 4 * 1024 && bindingType != BufferObjectBinding::SHADER_STORAGE &&
|
||||
usage == BufferUsage::DYNAMIC && !forceGpuBuffer) {
|
||||
mBuffer = nil;
|
||||
mCpuBuffer = malloc(size);
|
||||
return;
|
||||
if (size <= 4 * 1024) {
|
||||
if (usage == BufferUsage::DYNAMIC && !forceGpuBuffer) {
|
||||
mBufferPoolEntry = nullptr;
|
||||
mCpuBuffer = malloc(size);
|
||||
}
|
||||
}
|
||||
|
||||
// Otherwise, we allocate a private GPU buffer.
|
||||
mBuffer = [context.device newBufferWithLength:size options:MTLResourceStorageModePrivate];
|
||||
ASSERT_POSTCONDITION(mBuffer, "Could not allocate Metal buffer of size %zu.", size);
|
||||
mUsage = usage;
|
||||
}
|
||||
|
||||
MetalBuffer::~MetalBuffer() {
|
||||
if (mCpuBuffer) {
|
||||
free(mCpuBuffer);
|
||||
}
|
||||
// This buffer is being destroyed. If we have a buffer pool entry, release it as it is no longer
|
||||
// needed.
|
||||
if (mBufferPoolEntry) {
|
||||
mContext.bufferPool->releaseBuffer(mBufferPoolEntry);
|
||||
}
|
||||
}
|
||||
|
||||
void MetalBuffer::copyIntoBuffer(void* src, size_t size, size_t byteOffset) {
|
||||
@@ -49,7 +53,7 @@ void MetalBuffer::copyIntoBuffer(void* src, size_t size, size_t byteOffset) {
|
||||
return;
|
||||
}
|
||||
ASSERT_PRECONDITION(size + byteOffset <= mBufferSize,
|
||||
"Attempting to copy %zu bytes into a buffer of size %zu at offset %zu",
|
||||
"Attempting to copy %d bytes into a buffer of size %d at offset %d",
|
||||
size, mBufferSize, byteOffset);
|
||||
|
||||
// Either copy into the Metal buffer or into our cpu buffer.
|
||||
@@ -58,26 +62,14 @@ void MetalBuffer::copyIntoBuffer(void* src, size_t size, size_t byteOffset) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Acquire a staging buffer to hold the contents of this update.
|
||||
MetalBufferPool* bufferPool = mContext.bufferPool;
|
||||
const MetalBufferPoolEntry* const staging = bufferPool->acquireBuffer(size);
|
||||
memcpy(staging->buffer.contents, src, size);
|
||||
// We're about to acquire a new buffer to hold the new contents. If we previously had obtained a
|
||||
// buffer we release it, decrementing its reference count, as we no longer needs it.
|
||||
if (mBufferPoolEntry) {
|
||||
mContext.bufferPool->releaseBuffer(mBufferPoolEntry);
|
||||
}
|
||||
|
||||
// The blit below requires that byteOffset be a multiple of 4.
|
||||
ASSERT_PRECONDITION(!(byteOffset & 0x3u), "byteOffset must be a multiple of 4");
|
||||
|
||||
// Encode a blit from the staging buffer into the private GPU buffer.
|
||||
id<MTLCommandBuffer> cmdBuffer = getPendingCommandBuffer(&mContext);
|
||||
id<MTLBlitCommandEncoder> blitEncoder = [cmdBuffer blitCommandEncoder];
|
||||
[blitEncoder copyFromBuffer:staging->buffer
|
||||
sourceOffset:0
|
||||
toBuffer:mBuffer
|
||||
destinationOffset:byteOffset
|
||||
size:size];
|
||||
[blitEncoder endEncoding];
|
||||
[cmdBuffer addCompletedHandler:^(id<MTLCommandBuffer> cb) {
|
||||
bufferPool->releaseBuffer(staging);
|
||||
}];
|
||||
mBufferPoolEntry = mContext.bufferPool->acquireBuffer(mBufferSize);
|
||||
memcpy(static_cast<uint8_t*>(mBufferPoolEntry->buffer.contents) + byteOffset, src, size);
|
||||
}
|
||||
|
||||
void MetalBuffer::copyIntoBufferUnsynchronized(void* src, size_t size, size_t byteOffset) {
|
||||
@@ -86,33 +78,36 @@ void MetalBuffer::copyIntoBufferUnsynchronized(void* src, size_t size, size_t by
|
||||
}
|
||||
|
||||
id<MTLBuffer> MetalBuffer::getGpuBufferForDraw(id<MTLCommandBuffer> cmdBuffer) noexcept {
|
||||
// If there's a CPU buffer, then we return nil here, as the CPU-side buffer will be bound
|
||||
// separately.
|
||||
if (mCpuBuffer) {
|
||||
return nil;
|
||||
if (!mBufferPoolEntry) {
|
||||
// If there's a CPU buffer, then we return nil here, as the CPU-side buffer will be bound
|
||||
// separately.
|
||||
if (mCpuBuffer) {
|
||||
return nil;
|
||||
}
|
||||
|
||||
// If there isn't a CPU buffer, it means no data has been loaded into this buffer yet. To
|
||||
// avoid an error, we'll allocate an empty buffer.
|
||||
mBufferPoolEntry = mContext.bufferPool->acquireBuffer(mBufferSize);
|
||||
}
|
||||
assert_invariant(mBuffer);
|
||||
return mBuffer;
|
||||
|
||||
// This buffer is being used in a draw call, so we retain it so it's not released back into the
|
||||
// buffer pool until the frame has finished.
|
||||
auto uniformDeleter = [bufferPool = mContext.bufferPool] (const void* resource) {
|
||||
bufferPool->releaseBuffer((const MetalBufferPoolEntry*) resource);
|
||||
};
|
||||
if (mContext.resourceTracker.trackResource((__bridge void*) cmdBuffer, mBufferPoolEntry,
|
||||
uniformDeleter)) {
|
||||
// We only want to retain the buffer once per command buffer- trackResource will return
|
||||
// true if this is the first time tracking this uniform for this command buffer.
|
||||
mContext.bufferPool->retainBuffer(mBufferPoolEntry);
|
||||
}
|
||||
|
||||
return mBufferPoolEntry->buffer;
|
||||
}
|
||||
|
||||
void MetalBuffer::bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLCommandEncoder> encoder,
|
||||
void MetalBuffer::bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLRenderCommandEncoder> encoder,
|
||||
size_t bufferStart, uint8_t stages, MetalBuffer* const* buffers, size_t const* offsets,
|
||||
size_t count) {
|
||||
// Ensure we were given the correct type of encoder:
|
||||
// either a MTLRenderCommandEncoder or a MTLComputeCommandEncoder.
|
||||
if (stages & MetalBuffer::Stage::VERTEX || stages & MetalBuffer::Stage::FRAGMENT) {
|
||||
assert_invariant([encoder respondsToSelector:@selector(setVertexBuffers:offsets:withRange:)]);
|
||||
assert_invariant([encoder respondsToSelector:@selector(setFragmentBuffers:offsets:withRange:)]);
|
||||
assert_invariant([encoder respondsToSelector:@selector(setVertexBytes:length:atIndex:)]);
|
||||
assert_invariant([encoder respondsToSelector:@selector(setFragmentBytes:length:atIndex:)]);
|
||||
assert_invariant(!(stages & MetalBuffer::Stage::COMPUTE));
|
||||
}
|
||||
if (stages & MetalBuffer::Stage::COMPUTE) {
|
||||
assert_invariant([encoder respondsToSelector:@selector(setBuffers:offsets:withRange:)]);
|
||||
assert_invariant([encoder respondsToSelector:@selector(setBytes:length:atIndex:)]);
|
||||
assert_invariant(!(stages & (MetalBuffer::Stage::FRAGMENT | MetalBuffer::Stage::VERTEX)));
|
||||
}
|
||||
|
||||
const NSRange bufferRange = NSMakeRange(bufferStart, count);
|
||||
|
||||
constexpr size_t MAX_BUFFERS = 16;
|
||||
@@ -137,19 +132,14 @@ void MetalBuffer::bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLCommandEncod
|
||||
}
|
||||
|
||||
if (stages & Stage::VERTEX) {
|
||||
[(id<MTLRenderCommandEncoder>) encoder setVertexBuffers:metalBuffers.data()
|
||||
offsets:metalOffsets.data()
|
||||
withRange:bufferRange];
|
||||
[encoder setVertexBuffers:metalBuffers.data()
|
||||
offsets:metalOffsets.data()
|
||||
withRange:bufferRange];
|
||||
}
|
||||
if (stages & Stage::FRAGMENT) {
|
||||
[(id<MTLRenderCommandEncoder>) encoder setFragmentBuffers:metalBuffers.data()
|
||||
offsets:metalOffsets.data()
|
||||
withRange:bufferRange];
|
||||
}
|
||||
if (stages & Stage::COMPUTE) {
|
||||
[(id<MTLComputeCommandEncoder>) encoder setBuffers:metalBuffers.data()
|
||||
offsets:metalOffsets.data()
|
||||
withRange:bufferRange];
|
||||
[encoder setFragmentBuffers:metalBuffers.data()
|
||||
offsets:metalOffsets.data()
|
||||
withRange:bufferRange];
|
||||
}
|
||||
|
||||
for (size_t b = 0; b < count; b++) {
|
||||
@@ -168,22 +158,14 @@ void MetalBuffer::bindBuffers(id<MTLCommandBuffer> cmdBuffer, id<MTLCommandEncod
|
||||
auto* bytes = static_cast<const uint8_t*>(cpuBuffer);
|
||||
|
||||
if (stages & Stage::VERTEX) {
|
||||
[(id<MTLRenderCommandEncoder>) encoder setVertexBytes:(bytes + offset)
|
||||
length:(buffer->getSize() - offset)
|
||||
atIndex:bufferIndex];
|
||||
[encoder setVertexBytes:(bytes + offset)
|
||||
length:(buffer->getSize() - offset)
|
||||
atIndex:bufferIndex];
|
||||
}
|
||||
if (stages & Stage::FRAGMENT) {
|
||||
[(id<MTLRenderCommandEncoder>) encoder setFragmentBytes:(bytes + offset)
|
||||
length:(buffer->getSize() - offset)
|
||||
atIndex:bufferIndex];
|
||||
}
|
||||
if (stages & Stage::COMPUTE) {
|
||||
// TODO: using setBytes means the data is read-only, which currently isn't enforced.
|
||||
// In practice this won't be an issue since MetalBuffer ensures all SSBOs are realized
|
||||
// through actual id<MTLBuffer> allocations.
|
||||
[(id<MTLComputeCommandEncoder>) encoder setBytes:(bytes + offset)
|
||||
length:(buffer->getSize() - offset)
|
||||
atIndex:bufferIndex];
|
||||
[encoder setFragmentBytes:(bytes + offset)
|
||||
length:(buffer->getSize() - offset)
|
||||
atIndex:bufferIndex];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,6 @@ MetalBufferPoolEntry const* MetalBufferPool::acquireBuffer(size_t numBytes) {
|
||||
// We were not able to find a sufficiently large stage, so create a new one.
|
||||
id<MTLBuffer> buffer = [mContext.device newBufferWithLength:numBytes
|
||||
options:MTLResourceStorageModeShared];
|
||||
ASSERT_POSTCONDITION(buffer, "Could not allocate Metal staging buffer of size %zu.", numBytes);
|
||||
MetalBufferPoolEntry* stage = new MetalBufferPoolEntry({
|
||||
.buffer = buffer,
|
||||
.capacity = numBytes,
|
||||
|
||||
@@ -25,7 +25,6 @@
|
||||
#include <QuartzCore/QuartzCore.h>
|
||||
|
||||
#include <array>
|
||||
#include <atomic>
|
||||
#include <stack>
|
||||
|
||||
#if defined(FILAMENT_METAL_PROFILING)
|
||||
@@ -42,12 +41,11 @@ class MetalDriver;
|
||||
class MetalBlitter;
|
||||
class MetalBufferPool;
|
||||
class MetalRenderTarget;
|
||||
class MetalSamplerGroup;
|
||||
class MetalSwapChain;
|
||||
class MetalTexture;
|
||||
class MetalTimerQueryInterface;
|
||||
struct MetalUniformBuffer;
|
||||
struct MetalIndexBuffer;
|
||||
struct MetalSamplerGroup;
|
||||
struct MetalVertexBuffer;
|
||||
|
||||
constexpr static uint8_t MAX_SAMPLE_COUNT = 8; // Metal devices support at most 8 MSAA samples
|
||||
@@ -60,12 +58,8 @@ struct MetalContext {
|
||||
id<MTLCommandBuffer> pendingCommandBuffer = nullptr;
|
||||
id<MTLRenderCommandEncoder> currentRenderPassEncoder = nullptr;
|
||||
|
||||
std::atomic<bool> memorylessLimitsReached = false;
|
||||
|
||||
// Supported features.
|
||||
bool supportsTextureSwizzling = false;
|
||||
bool supportsAutoDepthResolve = false;
|
||||
bool supportsMemorylessRenderTargets = false;
|
||||
uint8_t maxColorRenderTargets = 4;
|
||||
struct {
|
||||
uint8_t common;
|
||||
@@ -85,8 +79,7 @@ struct MetalContext {
|
||||
// State trackers.
|
||||
PipelineStateTracker pipelineState;
|
||||
DepthStencilStateTracker depthStencilState;
|
||||
std::array<BufferState, Program::UNIFORM_BINDING_COUNT> uniformState;
|
||||
std::array<BufferState, MAX_SSBO_COUNT> ssboState;
|
||||
UniformBufferState uniformState[VERTEX_BUFFER_START];
|
||||
CullModeStateTracker cullModeState;
|
||||
WindingStateTracker windingState;
|
||||
|
||||
@@ -94,18 +87,11 @@ struct MetalContext {
|
||||
DepthStencilStateCache depthStencilStateCache;
|
||||
PipelineStateCache pipelineStateCache;
|
||||
SamplerStateCache samplerStateCache;
|
||||
ArgumentEncoderCache argumentEncoderCache;
|
||||
|
||||
PolygonOffset currentPolygonOffset = {0.0f, 0.0f};
|
||||
MetalSamplerGroup* samplerBindings[SAMPLER_BINDING_COUNT] = {};
|
||||
|
||||
MetalSamplerGroup* samplerBindings[Program::SAMPLER_BINDING_COUNT] = {};
|
||||
|
||||
// Keeps track of sampler groups we've finalized for the current render pass.
|
||||
tsl::robin_set<MetalSamplerGroup*> finalizedSamplerGroups;
|
||||
|
||||
// Keeps track of all alive sampler groups, textures.
|
||||
// Keeps track of all alive sampler groups.
|
||||
tsl::robin_set<MetalSamplerGroup*> samplerGroups;
|
||||
tsl::robin_set<MetalTexture*> textures;
|
||||
|
||||
MetalBufferPool* bufferPool;
|
||||
|
||||
|
||||
@@ -103,15 +103,6 @@ id<MTLCommandBuffer> getPendingCommandBuffer(MetalContext* context) {
|
||||
// all frames and their completion handlers finish before context is deallocated.
|
||||
[context->pendingCommandBuffer addCompletedHandler:^(id <MTLCommandBuffer> buffer) {
|
||||
context->resourceTracker.clearResources((__bridge void*) buffer);
|
||||
|
||||
auto errorCode = (MTLCommandBufferError)buffer.error.code;
|
||||
if (@available(macOS 11.0, *)) {
|
||||
if (errorCode == MTLCommandBufferErrorMemoryless) {
|
||||
utils::slog.w << "Metal: memoryless geometry limit reached. "
|
||||
"Continuing with private storage mode." << utils::io::endl;
|
||||
context->memorylessLimitsReached = true;
|
||||
}
|
||||
}
|
||||
}];
|
||||
ASSERT_POSTCONDITION(context->pendingCommandBuffer, "Could not obtain command buffer.");
|
||||
return context->pendingCommandBuffer;
|
||||
|
||||
@@ -22,8 +22,6 @@
|
||||
|
||||
#include "private/backend/HandleAllocator.h"
|
||||
|
||||
#include <backend/SamplerDescriptor.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Log.h>
|
||||
#include <utils/debug.h>
|
||||
@@ -34,12 +32,10 @@ namespace backend {
|
||||
class MetalPlatform;
|
||||
|
||||
class MetalBuffer;
|
||||
class MetalSamplerGroup;
|
||||
class MetalTexture;
|
||||
struct MetalUniformBuffer;
|
||||
struct MetalContext;
|
||||
struct MetalProgram;
|
||||
struct BufferState;
|
||||
struct UniformBufferState;
|
||||
|
||||
#ifndef FILAMENT_METAL_HANDLE_ARENA_SIZE_IN_MB
|
||||
#define FILAMENT_METAL_HANDLE_ARENA_SIZE_IN_MB 8
|
||||
@@ -128,9 +124,10 @@ private:
|
||||
inline void setRenderPrimitiveRange(Handle<HwRenderPrimitive> rph, PrimitiveType pt,
|
||||
uint32_t offset, uint32_t minIndex, uint32_t maxIndex, uint32_t count);
|
||||
|
||||
void finalizeSamplerGroup(MetalSamplerGroup* sg);
|
||||
void enumerateBoundBuffers(BufferObjectBinding bindingType,
|
||||
const std::function<void(const BufferState&, MetalBuffer*, uint32_t)>& f);
|
||||
void enumerateSamplerGroups(const MetalProgram* program, ShaderType shaderType,
|
||||
const std::function<void(const SamplerGroup::Sampler*, size_t)>& f);
|
||||
void enumerateBoundUniformBuffers(const std::function<void(const UniformBufferState&,
|
||||
MetalBuffer*, uint32_t)>& f);
|
||||
|
||||
};
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -52,19 +52,6 @@ constexpr inline MTLCompareFunction getMetalCompareFunction(RasterState::DepthFu
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline MTLStencilOperation getMetalStencilOperation(StencilOperation op) {
|
||||
switch (op) {
|
||||
case StencilOperation::KEEP: return MTLStencilOperationKeep;
|
||||
case StencilOperation::ZERO: return MTLStencilOperationZero;
|
||||
case StencilOperation::REPLACE: return MTLStencilOperationReplace;
|
||||
case StencilOperation::INCR: return MTLStencilOperationIncrementClamp;
|
||||
case StencilOperation::INCR_WRAP: return MTLStencilOperationIncrementWrap;
|
||||
case StencilOperation::DECR: return MTLStencilOperationDecrementClamp;
|
||||
case StencilOperation::DECR_WRAP: return MTLStencilOperationDecrementWrap;
|
||||
case StencilOperation::INVERT: return MTLStencilOperationInvert;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline MTLIndexType getIndexType(size_t elementSize) noexcept {
|
||||
if (elementSize == 2) {
|
||||
return MTLIndexTypeUInt16;
|
||||
@@ -262,22 +249,6 @@ constexpr inline bool isMetalFormatInteger(MTLPixelFormat format) {
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline bool isMetalFormatStencil(MTLPixelFormat format) {
|
||||
switch (format) {
|
||||
case MTLPixelFormatStencil8:
|
||||
case MTLPixelFormatDepth32Float_Stencil8:
|
||||
case MTLPixelFormatX32_Stencil8:
|
||||
#if !defined(IOS)
|
||||
case MTLPixelFormatDepth24Unorm_Stencil8:
|
||||
case MTLPixelFormatX24_Stencil8:
|
||||
#endif
|
||||
return true;
|
||||
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
constexpr inline MTLTextureType getMetalType(SamplerType target) {
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
@@ -289,8 +260,6 @@ constexpr inline MTLTextureType getMetalType(SamplerType target) {
|
||||
return MTLTextureTypeCube;
|
||||
case SamplerType::SAMPLER_3D:
|
||||
return MTLTextureType3D;
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
return MTLTextureTypeCubeArray;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -337,6 +306,8 @@ constexpr inline MTLPrimitiveType getMetalPrimitiveType(PrimitiveType type) noex
|
||||
case PrimitiveType::LINE_STRIP: return MTLPrimitiveTypeLineStrip;
|
||||
case PrimitiveType::TRIANGLES: return MTLPrimitiveTypeTriangle;
|
||||
case PrimitiveType::TRIANGLE_STRIP: return MTLPrimitiveTypeTriangleStrip;
|
||||
case PrimitiveType::NONE:
|
||||
ASSERT_POSTCONDITION(false, "NONE is not a valid primitive type.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -29,14 +29,10 @@
|
||||
#include "MetalExternalImage.h"
|
||||
#include "MetalState.h" // for MetalState::VertexDescription
|
||||
|
||||
#include "private/backend/SamplerGroup.h"
|
||||
|
||||
#include <utils/bitset.h>
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
#include <utils/Panic.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
|
||||
#include <atomic>
|
||||
#include <condition_variable>
|
||||
#include <memory>
|
||||
@@ -118,18 +114,15 @@ private:
|
||||
|
||||
class MetalBufferObject : public HwBufferObject {
|
||||
public:
|
||||
MetalBufferObject(MetalContext& context, BufferObjectBinding bindingType, BufferUsage usage,
|
||||
uint32_t byteCount);
|
||||
MetalBufferObject(MetalContext& context, BufferUsage usage, uint32_t byteCount);
|
||||
|
||||
void updateBuffer(void* data, size_t size, uint32_t byteOffset);
|
||||
void updateBufferUnsynchronized(void* data, size_t size, uint32_t byteOffset);
|
||||
MetalBuffer* getBuffer() { return &buffer; }
|
||||
|
||||
// Tracks which uniform/ssbo buffers this buffer object is bound into.
|
||||
static_assert(Program::UNIFORM_BINDING_COUNT <= 32);
|
||||
static_assert(MAX_SSBO_COUNT <= 32);
|
||||
// Tracks which uniform buffers this buffer object is bound into.
|
||||
static_assert(Program::BINDING_COUNT <= 32);
|
||||
utils::bitset32 boundUniformBuffers;
|
||||
utils::bitset32 boundSsbos;
|
||||
|
||||
private:
|
||||
MetalBuffer buffer;
|
||||
@@ -166,9 +159,14 @@ struct MetalProgram : public HwProgram {
|
||||
|
||||
id<MTLFunction> vertexFunction;
|
||||
id<MTLFunction> fragmentFunction;
|
||||
id<MTLFunction> computeFunction;
|
||||
|
||||
Program::SamplerGroupInfo samplerGroupInfo;
|
||||
struct SamplerBlockInfo {
|
||||
uint8_t samplerGroup = UINT8_MAX;
|
||||
uint8_t sampler = UINT8_MAX;
|
||||
};
|
||||
|
||||
std::array<SamplerBlockInfo, MAX_VERTEX_SAMPLER_COUNT> vertexSamplerBlockInfo;
|
||||
std::array<SamplerBlockInfo, MAX_FRAGMENT_SAMPLER_COUNT> fragmentSamplerBlockInfo;
|
||||
|
||||
bool isValid = false;
|
||||
};
|
||||
@@ -186,8 +184,7 @@ struct PixelBufferShape {
|
||||
MTLSize size, uint32_t byteOffset);
|
||||
};
|
||||
|
||||
class MetalTexture : public HwTexture {
|
||||
public:
|
||||
struct MetalTexture : public HwTexture {
|
||||
MetalTexture(MetalContext& context, SamplerType target, uint8_t levels, TextureFormat format,
|
||||
uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage,
|
||||
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a)
|
||||
@@ -200,144 +197,39 @@ public:
|
||||
|
||||
~MetalTexture();
|
||||
|
||||
// Returns an id<MTLTexture> suitable for reading in a shader, taking into account swizzle and
|
||||
// LOD clamping.
|
||||
id<MTLTexture> getMtlTextureForRead() noexcept;
|
||||
|
||||
// Returns the id<MTLTexture> for attaching to a render pass.
|
||||
id<MTLTexture> getMtlTextureForWrite() noexcept {
|
||||
return texture;
|
||||
}
|
||||
|
||||
void loadImage(uint32_t level, MTLRegion region, PixelBufferDescriptor& p) noexcept;
|
||||
void generateMipmaps() noexcept;
|
||||
|
||||
// A texture starts out with none of its mip levels (also referred to as LODs) available for
|
||||
// reading. 3 actions update the range of LODs available:
|
||||
// - calling loadImage
|
||||
// - calling generateMipmaps
|
||||
// - using the texture as a render target attachment
|
||||
// The range of available mips can only increase, never decrease.
|
||||
// A texture's available mips are consistent throughout a render pass.
|
||||
void loadCubeImage(const FaceOffsets& faceOffsets, int miplevel, PixelBufferDescriptor& p);
|
||||
void loadSlice(uint32_t level, MTLRegion region, uint32_t byteOffset, uint32_t slice,
|
||||
PixelBufferDescriptor& data) noexcept;
|
||||
void loadWithCopyBuffer(uint32_t level, uint32_t slice, MTLRegion region, PixelBufferDescriptor& data,
|
||||
const PixelBufferShape& shape);
|
||||
void loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region, PixelBufferDescriptor& data,
|
||||
const PixelBufferShape& shape);
|
||||
void updateLodRange(uint32_t level);
|
||||
void updateLodRange(uint32_t minLevel, uint32_t maxLevel);
|
||||
|
||||
// Returns true if the texture has all of its mip levels accessible for reading.
|
||||
// For any MetalTexture, once this is true, will always return true.
|
||||
// The value returned will remain consistent for an entire render pass.
|
||||
bool allLodsValid() const {
|
||||
return minLod == 0 && maxLod == levels - 1;
|
||||
}
|
||||
|
||||
static MTLPixelFormat decidePixelFormat(MetalContext* context, TextureFormat format);
|
||||
|
||||
MetalContext& context;
|
||||
MetalExternalImage externalImage;
|
||||
id<MTLTexture> texture = nil;
|
||||
|
||||
// A "sidecar" texture used to implement automatic MSAA resolve.
|
||||
// This is created by MetalRenderTarget and stored here so it can be used with multiple
|
||||
// render targets.
|
||||
id<MTLTexture> msaaSidecar = nil;
|
||||
|
||||
MTLPixelFormat devicePixelFormat;
|
||||
|
||||
private:
|
||||
void loadSlice(uint32_t level, MTLRegion region, uint32_t byteOffset, uint32_t slice,
|
||||
PixelBufferDescriptor const& data) noexcept;
|
||||
void loadWithCopyBuffer(uint32_t level, uint32_t slice, MTLRegion region, PixelBufferDescriptor const& data,
|
||||
const PixelBufferShape& shape);
|
||||
void loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region, PixelBufferDescriptor const& data,
|
||||
const PixelBufferShape& shape);
|
||||
|
||||
id<MTLTexture> texture = nil;
|
||||
|
||||
// If non-nil, a swizzled texture view to use instead of "texture".
|
||||
// Filament swizzling only affects texture reads, so this should not be used when the texture is
|
||||
// bound as a render target attachment.
|
||||
id<MTLTexture> swizzledTextureView = nil;
|
||||
id<MTLTexture> lodTextureView = nil;
|
||||
|
||||
MTLPixelFormat devicePixelFormat;
|
||||
uint32_t minLod = UINT_MAX;
|
||||
uint32_t maxLod = 0;
|
||||
};
|
||||
|
||||
class MetalSamplerGroup : public HwSamplerGroup {
|
||||
public:
|
||||
explicit MetalSamplerGroup(size_t size) noexcept
|
||||
: size(size),
|
||||
textureHandles(size, Handle<HwTexture>()),
|
||||
textures(size, nil),
|
||||
samplers(size, nil) {}
|
||||
|
||||
inline void setTextureHandle(size_t index, Handle<HwTexture> th) {
|
||||
assert_invariant(!finalized);
|
||||
textureHandles[index] = th;
|
||||
}
|
||||
|
||||
#ifndef NDEBUG
|
||||
// This method is only used for debugging, to ensure all texture handles are alive.
|
||||
const auto& getTextureHandles() const {
|
||||
return textureHandles;
|
||||
}
|
||||
#endif
|
||||
|
||||
// Encode a MTLTexture into this SamplerGroup at the given index.
|
||||
inline void setFinalizedTexture(size_t index, id<MTLTexture> t) {
|
||||
assert_invariant(!finalized);
|
||||
textures[index] = t;
|
||||
}
|
||||
|
||||
// Encode a MTLSamplerState into this SamplerGroup at the given index.
|
||||
inline void setFinalizedSampler(size_t index, id<MTLSamplerState> s) {
|
||||
assert_invariant(!finalized);
|
||||
samplers[index] = s;
|
||||
}
|
||||
|
||||
// A SamplerGroup is "finalized" when all of its textures have been set and is ready for use in
|
||||
// a draw call.
|
||||
// Once a SamplerGroup is finalized, it must be reset or mutated to be written into again.
|
||||
void finalize();
|
||||
bool isFinalized() const noexcept { return finalized; }
|
||||
|
||||
// Both of these methods "unfinalize" a SamplerGroup, allowing it to be updated via calls to
|
||||
// setFinalizedTexture or setFinalizedSampler. The difference is that when reset is called, all
|
||||
// the samplers/textures must be rebound. The MTLArgumentEncoder must be specified, in case
|
||||
// the texture types have changed.
|
||||
// Mutate re-encodes the current set of samplers/textures into the new argument
|
||||
// buffer.
|
||||
void reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEncoder> e, id<MTLDevice> device);
|
||||
void mutate(id<MTLCommandBuffer> cmdBuffer);
|
||||
|
||||
id<MTLBuffer> getArgumentBuffer() const {
|
||||
assert_invariant(finalized);
|
||||
return argBuffer->getCurrentAllocation().first;
|
||||
}
|
||||
|
||||
NSUInteger getArgumentBufferOffset() const {
|
||||
return argBuffer->getCurrentAllocation().second;
|
||||
}
|
||||
|
||||
inline std::pair<Handle<HwTexture>, id<MTLTexture>> getFinalizedTexture(size_t index) {
|
||||
return {textureHandles[index], textures[index]};
|
||||
}
|
||||
|
||||
// Calls the Metal useResource:usage:stages: method for all the textures in this SamplerGroup.
|
||||
void useResources(id<MTLRenderCommandEncoder> renderPassEncoder);
|
||||
|
||||
size_t size;
|
||||
|
||||
public:
|
||||
|
||||
// These vectors are kept in sync with one another.
|
||||
utils::FixedCapacityVector<Handle<HwTexture>> textureHandles;
|
||||
utils::FixedCapacityVector<id<MTLTexture>> textures;
|
||||
utils::FixedCapacityVector<id<MTLSamplerState>> samplers;
|
||||
|
||||
id<MTLArgumentEncoder> encoder;
|
||||
|
||||
std::unique_ptr<MetalRingBuffer> argBuffer = nullptr;
|
||||
|
||||
bool finalized = false;
|
||||
struct MetalSamplerGroup : public HwSamplerGroup {
|
||||
explicit MetalSamplerGroup(size_t size) : HwSamplerGroup(size) {}
|
||||
};
|
||||
|
||||
class MetalRenderTarget : public HwRenderTarget {
|
||||
@@ -351,7 +243,7 @@ public:
|
||||
Attachment() = default;
|
||||
Attachment(MetalTexture* metalTexture, uint8_t level = 0, uint16_t layer = 0) :
|
||||
level(level), layer(layer),
|
||||
texture(metalTexture->getMtlTextureForWrite()),
|
||||
texture(metalTexture->texture),
|
||||
metalTexture(metalTexture) { }
|
||||
|
||||
id<MTLTexture> getTexture() const {
|
||||
@@ -386,28 +278,14 @@ public:
|
||||
};
|
||||
|
||||
MetalRenderTarget(MetalContext* context, uint32_t width, uint32_t height, uint8_t samples,
|
||||
Attachment colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
|
||||
Attachment depthAttachment, Attachment stencilAttachment);
|
||||
Attachment colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT], Attachment depthAttachment);
|
||||
explicit MetalRenderTarget(MetalContext* context)
|
||||
: HwRenderTarget(0, 0), context(context), defaultRenderTarget(true) {}
|
||||
|
||||
void setUpRenderPassAttachments(MTLRenderPassDescriptor* descriptor, const RenderPassParams& params);
|
||||
|
||||
MTLViewport getViewportFromClientViewport(
|
||||
Viewport rect, float depthRangeNear, float depthRangeFar) {
|
||||
const int32_t height = int32_t(getAttachmentSize().y);
|
||||
assert_invariant(height > 0);
|
||||
|
||||
// Metal's viewport coordinates have (0, 0) at the top-left, but Filament's have (0, 0) at
|
||||
// bottom-left.
|
||||
return {double(rect.left),
|
||||
double(height - rect.bottom - int32_t(rect.height)),
|
||||
double(rect.width), double(rect.height),
|
||||
double(depthRangeNear), double(depthRangeFar)};
|
||||
}
|
||||
|
||||
MTLRegion getRegionFromClientRect(Viewport rect) {
|
||||
const uint32_t height = getAttachmentSize().y;
|
||||
const uint32_t height = getAttachmentHeight();
|
||||
assert_invariant(height > 0);
|
||||
|
||||
// Convert the Filament rect into Metal texture coordinates, taking into account Metal's
|
||||
@@ -419,21 +297,21 @@ public:
|
||||
rect.width, rect.height);
|
||||
}
|
||||
|
||||
math::uint2 getAttachmentSize() noexcept;
|
||||
|
||||
bool isDefaultRenderTarget() const { return defaultRenderTarget; }
|
||||
uint8_t getSamples() const { return samples; }
|
||||
|
||||
Attachment getDrawColorAttachment(size_t index);
|
||||
Attachment getReadColorAttachment(size_t index);
|
||||
Attachment getDepthAttachment();
|
||||
Attachment getStencilAttachment();
|
||||
|
||||
private:
|
||||
|
||||
static MTLLoadAction getLoadAction(const RenderPassParams& params, TargetBufferFlags buffer);
|
||||
static MTLStoreAction getStoreAction(const RenderPassParams& params, TargetBufferFlags buffer);
|
||||
id<MTLTexture> createMultisampledTexture(MTLPixelFormat format, uint32_t width, uint32_t height, uint8_t samples) const;
|
||||
static id<MTLTexture> createMultisampledTexture(id<MTLDevice> device, MTLPixelFormat format,
|
||||
uint32_t width, uint32_t height, uint8_t samples);
|
||||
|
||||
uint32_t getAttachmentHeight() noexcept;
|
||||
|
||||
MetalContext* context;
|
||||
bool defaultRenderTarget = false;
|
||||
@@ -441,8 +319,7 @@ private:
|
||||
|
||||
Attachment color[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = {};
|
||||
Attachment depth = {};
|
||||
Attachment stencil = {};
|
||||
math::uint2 attachmentSize = {};
|
||||
uint32_t attachmentHeight = 0;
|
||||
};
|
||||
|
||||
// MetalFence is used to implement both Fences and Syncs.
|
||||
|
||||
@@ -22,15 +22,13 @@
|
||||
|
||||
#include <filament/SwapChain.h>
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include "private/backend/BackendUtils.h"
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <utils/Panic.h>
|
||||
#include <utils/trap.h>
|
||||
#include <utils/debug.h>
|
||||
|
||||
#include <math/vec2.h>
|
||||
#include <math/scalar.h>
|
||||
|
||||
#include <math.h>
|
||||
@@ -271,9 +269,8 @@ void MetalSwapChain::scheduleFrameCompletedCallback() {
|
||||
}];
|
||||
}
|
||||
|
||||
MetalBufferObject::MetalBufferObject(MetalContext& context, BufferObjectBinding bindingType,
|
||||
BufferUsage usage, uint32_t byteCount)
|
||||
: HwBufferObject(byteCount), buffer(context, bindingType, usage, byteCount) {}
|
||||
MetalBufferObject::MetalBufferObject(MetalContext& context, BufferUsage usage, uint32_t byteCount)
|
||||
: HwBufferObject(byteCount), buffer(context, usage, byteCount) {}
|
||||
|
||||
void MetalBufferObject::updateBuffer(void* data, size_t size, uint32_t byteOffset) {
|
||||
buffer.copyIntoBuffer(data, size, byteOffset);
|
||||
@@ -289,7 +286,7 @@ MetalVertexBuffer::MetalVertexBuffer(MetalContext& context, uint8_t bufferCount,
|
||||
|
||||
MetalIndexBuffer::MetalIndexBuffer(MetalContext& context, BufferUsage usage, uint8_t elementSize,
|
||||
uint32_t indexCount) : HwIndexBuffer(elementSize, indexCount),
|
||||
buffer(context, BufferObjectBinding::VERTEX, usage, elementSize * indexCount, true) { }
|
||||
buffer(context, usage, elementSize * indexCount, true) { }
|
||||
|
||||
void MetalRenderPrimitive::setBuffers(MetalVertexBuffer* vertexBuffer, MetalIndexBuffer*
|
||||
indexBuffer) {
|
||||
@@ -300,8 +297,9 @@ void MetalRenderPrimitive::setBuffers(MetalVertexBuffer* vertexBuffer, MetalInde
|
||||
|
||||
vertexDescription = {};
|
||||
|
||||
// Each attribute gets its own vertex buffer, starting at logical buffer 1.
|
||||
uint32_t bufferIndex = 1;
|
||||
// Each attribute gets its own vertex buffer.
|
||||
|
||||
uint32_t bufferIndex = 0;
|
||||
for (uint32_t attributeIndex = 0; attributeIndex < attributeCount; attributeIndex++) {
|
||||
const auto& attribute = vertexBuffer->attributes[attributeIndex];
|
||||
if (attribute.buffer == Attribute::BUFFER_UNUSED) {
|
||||
@@ -313,10 +311,10 @@ void MetalRenderPrimitive::setBuffers(MetalVertexBuffer* vertexBuffer, MetalInde
|
||||
// shader to read from missing vertex attributes.
|
||||
vertexDescription.attributes[attributeIndex] = {
|
||||
.format = format,
|
||||
.buffer = ZERO_VERTEX_BUFFER_LOGICAL_INDEX,
|
||||
.buffer = ZERO_VERTEX_BUFFER,
|
||||
.offset = 0
|
||||
};
|
||||
vertexDescription.layouts[ZERO_VERTEX_BUFFER_LOGICAL_INDEX] = {
|
||||
vertexDescription.layouts[ZERO_VERTEX_BUFFER] = {
|
||||
.step = MTLVertexStepFunctionConstant,
|
||||
.stride = 16
|
||||
};
|
||||
@@ -340,12 +338,12 @@ void MetalRenderPrimitive::setBuffers(MetalVertexBuffer* vertexBuffer, MetalInde
|
||||
|
||||
MetalProgram::MetalProgram(id<MTLDevice> device, const Program& program) noexcept
|
||||
: HwProgram(program.getName()), vertexFunction(nil), fragmentFunction(nil),
|
||||
computeFunction(nil), isValid(false) {
|
||||
isValid(false) {
|
||||
|
||||
using MetalFunctionPtr = __strong id<MTLFunction>*;
|
||||
|
||||
static_assert(Program::SHADER_TYPE_COUNT == 3, "Only vertex, fragment, and/or compute shaders expected.");
|
||||
MetalFunctionPtr shaderFunctions[3] = { &vertexFunction, &fragmentFunction, &computeFunction };
|
||||
static_assert(Program::SHADER_TYPE_COUNT == 2, "Only vertex and fragment shaders expected.");
|
||||
MetalFunctionPtr shaderFunctions[2] = { &vertexFunction, &fragmentFunction };
|
||||
|
||||
const auto& sources = program.getShadersSource();
|
||||
for (size_t i = 0; i < Program::SHADER_TYPE_COUNT; i++) {
|
||||
@@ -376,37 +374,51 @@ MetalProgram::MetalProgram(id<MTLDevice> device, const Program& program) noexcep
|
||||
return;
|
||||
}
|
||||
|
||||
MTLFunctionConstantValues* constants = [MTLFunctionConstantValues new];
|
||||
auto const& specializationConstants = program.getSpecializationConstants();
|
||||
for (auto const& sc : specializationConstants) {
|
||||
const std::array<MTLDataType, 3> types{
|
||||
MTLDataTypeInt, MTLDataTypeFloat, MTLDataTypeBool };
|
||||
std::visit([&sc, constants, type = types[sc.value.index()]](auto&& arg) {
|
||||
[constants setConstantValue:&arg
|
||||
type:type
|
||||
atIndex:sc.id];
|
||||
}, sc.value);
|
||||
}
|
||||
|
||||
id<MTLFunction> function = [library newFunctionWithName:@"main0"
|
||||
constantValues:constants
|
||||
error:&error];
|
||||
assert_invariant(function);
|
||||
*shaderFunctions[i] = function;
|
||||
*shaderFunctions[i] = [library newFunctionWithName:@"main0"];
|
||||
}
|
||||
|
||||
UTILS_UNUSED_IN_RELEASE const bool isRasterizationProgram =
|
||||
vertexFunction != nil && fragmentFunction != nil;
|
||||
UTILS_UNUSED_IN_RELEASE const bool isComputeProgram = computeFunction != nil;
|
||||
// The program must be either a rasterization program XOR a compute program.
|
||||
assert_invariant(isRasterizationProgram != isComputeProgram);
|
||||
|
||||
// All stages of the program have compiled successfully, this is a valid program.
|
||||
isValid = true;
|
||||
|
||||
// Save this program's SamplerGroupInfo, it's used during draw calls to bind sampler groups to
|
||||
// the appropriate stage(s).
|
||||
samplerGroupInfo = program.getSamplerGroupInfo();
|
||||
// This calculates Metal resource binding indices. Filament's sampler bindings range from 0-31
|
||||
// across both vertex and fragment stages. However, Metal binding indices must be < 16, with a
|
||||
// separate binding "namespace" for each stage. So, we recompute binding indices for each shader
|
||||
// stage. This logic should match updateResourceBinding in GLSLPostProcessor.cpp
|
||||
// This is an example how binding indices each of shader stages is generated from sampler's
|
||||
// bindings. Below is sampler's bindings.
|
||||
// 0 shadowMap { fragment }
|
||||
// 1 structure { fragment }
|
||||
// 2 targets { vertex }
|
||||
// 3 color { vertex | fragment }
|
||||
// 4 depth { vertex | fragment }
|
||||
// Below is generated vertex sampler binding indices.
|
||||
// 0 targets
|
||||
// 1 color
|
||||
// 2 depth
|
||||
// Below is generated fragment sampler binding indices.
|
||||
// 0 shadowMap
|
||||
// 1 structure
|
||||
// 2 color
|
||||
// 3 depth
|
||||
auto& samplerGroupInfo = program.getSamplerGroupInfo();
|
||||
for (size_t shaderType = 0; shaderType != PIPELINE_STAGE_COUNT; ++shaderType) {
|
||||
size_t bindingIdx = 0;
|
||||
auto& samplerBlockInfo = (shaderType == ShaderType::VERTEX) ? vertexSamplerBlockInfo
|
||||
: fragmentSamplerBlockInfo;
|
||||
for (size_t samplerGroupIdx = 0; samplerGroupIdx != SAMPLER_GROUP_COUNT; ++samplerGroupIdx) {
|
||||
auto& groupData = samplerGroupInfo[samplerGroupIdx];
|
||||
auto stageFlags = groupData.stageFlags;
|
||||
if (!stageFlags.hasShaderType(static_cast<ShaderType>(shaderType))) {
|
||||
continue;
|
||||
}
|
||||
auto& samplers = groupData.samplers;
|
||||
for (size_t samplerIdx = 0, c = samplers.size(); samplerIdx != c; ++samplerIdx) {
|
||||
samplerBlockInfo[bindingIdx].samplerGroup = samplerGroupIdx;
|
||||
samplerBlockInfo[bindingIdx].sampler = samplerIdx;
|
||||
++bindingIdx;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t levels,
|
||||
@@ -421,27 +433,36 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le
|
||||
|
||||
const BOOL mipmapped = levels > 1;
|
||||
const BOOL multisampled = samples > 1;
|
||||
const BOOL textureArray = target == SamplerType::SAMPLER_2D_ARRAY;
|
||||
|
||||
#if defined(IOS)
|
||||
const BOOL textureArray = target == SamplerType::SAMPLER_2D_ARRAY;
|
||||
ASSERT_PRECONDITION(!textureArray || !multisampled,
|
||||
"iOS does not support multisampled texture arrays.");
|
||||
#endif
|
||||
|
||||
const auto get2DTextureType = [](SamplerType target, bool isMultisampled) {
|
||||
if (!isMultisampled) {
|
||||
return getMetalType(target);
|
||||
const auto get2DTextureType = [](bool isArray, bool isMultisampled) {
|
||||
uint8_t value = 0;
|
||||
if (isMultisampled) {
|
||||
value |= 0b10u;
|
||||
}
|
||||
switch (target) {
|
||||
case SamplerType::SAMPLER_2D:
|
||||
return MTLTextureType2DMultisample;
|
||||
#if !defined(IOS)
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
return MTLTextureType2DMultisampleArray;
|
||||
#endif
|
||||
if (isArray) {
|
||||
value |= 0b01u;
|
||||
}
|
||||
switch (value) {
|
||||
default:
|
||||
case 0b00:
|
||||
return MTLTextureType2D;
|
||||
case 0b01:
|
||||
return MTLTextureType2DArray;
|
||||
case 0b10:
|
||||
return MTLTextureType2DMultisample;
|
||||
case 0b11:
|
||||
#if !defined(IOS)
|
||||
return MTLTextureType2DMultisampleArray;
|
||||
#else
|
||||
// should not get here
|
||||
return getMetalType(target);
|
||||
return MTLTextureType2DArray;
|
||||
#endif
|
||||
}
|
||||
};
|
||||
|
||||
@@ -451,7 +472,7 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le
|
||||
case SamplerType::SAMPLER_2D_ARRAY:
|
||||
descriptor = [MTLTextureDescriptor new];
|
||||
descriptor.pixelFormat = devicePixelFormat;
|
||||
descriptor.textureType = get2DTextureType(target, multisampled);
|
||||
descriptor.textureType = get2DTextureType(textureArray, multisampled);
|
||||
descriptor.width = width;
|
||||
descriptor.height = height;
|
||||
descriptor.arrayLength = depth;
|
||||
@@ -463,13 +484,11 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le
|
||||
ASSERT_POSTCONDITION(texture != nil, "Could not create Metal texture. Out of memory?");
|
||||
break;
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
ASSERT_POSTCONDITION(!multisampled, "Multisampled cubemap faces not supported.");
|
||||
ASSERT_POSTCONDITION(width == height, "Cubemap faces must be square.");
|
||||
descriptor = [MTLTextureDescriptor textureCubeDescriptorWithPixelFormat:devicePixelFormat
|
||||
size:width
|
||||
mipmapped:mipmapped];
|
||||
descriptor.arrayLength = depth;
|
||||
descriptor.mipmapLevelCount = levels;
|
||||
descriptor.usage = getMetalTextureUsage(usage);
|
||||
descriptor.storageMode = MTLStorageModePrivate;
|
||||
@@ -521,33 +540,14 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le
|
||||
: HwTexture(target, levels, samples, width, height, depth, format, usage), context(context),
|
||||
externalImage(context) {
|
||||
texture = metalTexture;
|
||||
updateLodRange(0, levels - 1);
|
||||
minLod = 0;
|
||||
maxLod = levels - 1;
|
||||
}
|
||||
|
||||
MetalTexture::~MetalTexture() {
|
||||
externalImage.set(nullptr);
|
||||
}
|
||||
|
||||
id<MTLTexture> MetalTexture::getMtlTextureForRead() noexcept {
|
||||
if (lodTextureView) {
|
||||
return lodTextureView;
|
||||
}
|
||||
// The texture's swizzle remains constant throughout its lifetime, however its LOD range can
|
||||
// change. We'll cache the LOD view, and set lodTextureView to nil if minLod or maxLod is
|
||||
// updated.
|
||||
id<MTLTexture> t = swizzledTextureView ? swizzledTextureView : texture;
|
||||
if (!t) {
|
||||
return nil;
|
||||
}
|
||||
if (UTILS_UNLIKELY(minLod > maxLod)) {
|
||||
// If the texture does not have any available LODs, provide a view of only level 0.
|
||||
// Filament should prevent this from ever occurring.
|
||||
lodTextureView = createTextureViewWithLodRange(t, 0, 0);
|
||||
return lodTextureView;
|
||||
}
|
||||
lodTextureView = createTextureViewWithLodRange(t, minLod, maxLod);
|
||||
return lodTextureView;
|
||||
}
|
||||
|
||||
MTLPixelFormat MetalTexture::decidePixelFormat(MetalContext* context, TextureFormat format) {
|
||||
const MTLPixelFormat metalFormat = getMetalFormat(context, format);
|
||||
@@ -641,8 +641,6 @@ void MetalTexture::loadImage(uint32_t level, MTLRegion region, PixelBufferDescri
|
||||
break;
|
||||
}
|
||||
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
case SamplerType::SAMPLER_CUBEMAP_ARRAY:
|
||||
case SamplerType::SAMPLER_2D_ARRAY: {
|
||||
// Metal uses 'slice' (not z offset) to index into individual layers of a texture array.
|
||||
const uint32_t slice = region.origin.z;
|
||||
@@ -661,6 +659,7 @@ void MetalTexture::loadImage(uint32_t level, MTLRegion region, PixelBufferDescri
|
||||
break;
|
||||
}
|
||||
|
||||
case SamplerType::SAMPLER_CUBEMAP:
|
||||
case SamplerType::SAMPLER_EXTERNAL: {
|
||||
assert_invariant(false);
|
||||
}
|
||||
@@ -669,15 +668,26 @@ void MetalTexture::loadImage(uint32_t level, MTLRegion region, PixelBufferDescri
|
||||
updateLodRange(level);
|
||||
}
|
||||
|
||||
void MetalTexture::generateMipmaps() noexcept {
|
||||
id <MTLBlitCommandEncoder> blitEncoder = [getPendingCommandBuffer(&context) blitCommandEncoder];
|
||||
[blitEncoder generateMipmapsForTexture:texture];
|
||||
[blitEncoder endEncoding];
|
||||
updateLodRange(0, texture.mipmapLevelCount - 1);
|
||||
void MetalTexture::loadCubeImage(const FaceOffsets& faceOffsets, int miplevel,
|
||||
PixelBufferDescriptor& p) {
|
||||
PixelBufferDescriptor* data = &p;
|
||||
PixelBufferDescriptor reshapedData;
|
||||
if(reshape(p, reshapedData)) {
|
||||
data = &reshapedData;
|
||||
}
|
||||
|
||||
const NSUInteger faceWidth = width >> miplevel;
|
||||
|
||||
for (NSUInteger slice = 0; slice < 6; slice++) {
|
||||
FaceOffsets::size_type faceOffset = faceOffsets.offsets[slice];
|
||||
loadSlice(miplevel, MTLRegionMake2D(0, 0, faceWidth, faceWidth), faceOffset, slice, *data);
|
||||
}
|
||||
|
||||
updateLodRange((uint32_t) miplevel);
|
||||
}
|
||||
|
||||
void MetalTexture::loadSlice(uint32_t level, MTLRegion region, uint32_t byteOffset, uint32_t slice,
|
||||
PixelBufferDescriptor const& data) noexcept {
|
||||
PixelBufferDescriptor& data) noexcept {
|
||||
const PixelBufferShape shape = PixelBufferShape::compute(data, format, region.size, byteOffset);
|
||||
|
||||
ASSERT_PRECONDITION(data.size >= shape.totalBytes,
|
||||
@@ -712,7 +722,7 @@ void MetalTexture::loadSlice(uint32_t level, MTLRegion region, uint32_t byteOffs
|
||||
}
|
||||
|
||||
void MetalTexture::loadWithCopyBuffer(uint32_t level, uint32_t slice, MTLRegion region,
|
||||
PixelBufferDescriptor const& data, const PixelBufferShape& shape) {
|
||||
PixelBufferDescriptor& data, const PixelBufferShape& shape) {
|
||||
const size_t stagingBufferSize = shape.totalBytes;
|
||||
auto entry = context.bufferPool->acquireBuffer(stagingBufferSize);
|
||||
memcpy(entry->buffer.contents,
|
||||
@@ -740,7 +750,7 @@ void MetalTexture::loadWithCopyBuffer(uint32_t level, uint32_t slice, MTLRegion
|
||||
}
|
||||
|
||||
void MetalTexture::loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region,
|
||||
PixelBufferDescriptor const& data, const PixelBufferShape& shape) {
|
||||
PixelBufferDescriptor& data, const PixelBufferShape& shape) {
|
||||
MTLPixelFormat stagingPixelFormat = getMetalFormat(data.format, data.type);
|
||||
MTLTextureDescriptor* descriptor = [MTLTextureDescriptor new];
|
||||
descriptor.textureType = region.size.depth == 1 ? MTLTextureType2D : MTLTextureType3D;
|
||||
@@ -796,103 +806,15 @@ void MetalTexture::loadWithBlit(uint32_t level, uint32_t slice, MTLRegion region
|
||||
}
|
||||
|
||||
void MetalTexture::updateLodRange(uint32_t level) {
|
||||
assert_invariant(!isInRenderPass(&context));
|
||||
minLod = std::min(minLod, level);
|
||||
maxLod = std::max(maxLod, level);
|
||||
lodTextureView = nil;
|
||||
}
|
||||
|
||||
void MetalTexture::updateLodRange(uint32_t min, uint32_t max) {
|
||||
assert_invariant(!isInRenderPass(&context));
|
||||
assert_invariant(min <= max);
|
||||
minLod = std::min(minLod, min);
|
||||
maxLod = std::max(maxLod, max);
|
||||
lodTextureView = nil;
|
||||
}
|
||||
|
||||
void MetalSamplerGroup::finalize() {
|
||||
assert_invariant(encoder);
|
||||
// TODO: we should be able to encode textures and samplers inside setFinalizedTexture and
|
||||
// setFinalizedSampler as they become available, but Metal doesn't seem to like this; the arg
|
||||
// buffer gets encoded incorrectly. This warrants more investigation.
|
||||
|
||||
auto [buffer, offset] = argBuffer->getCurrentAllocation();
|
||||
[encoder setArgumentBuffer:buffer offset:offset];
|
||||
|
||||
// Encode all textures and samplers.
|
||||
for (size_t s = 0; s < size; s++) {
|
||||
[encoder setTexture:textures[s] atIndex:(s * 2 + 0)];
|
||||
[encoder setSamplerState:samplers[s] atIndex:(s * 2 + 1)];
|
||||
}
|
||||
|
||||
finalized = true;
|
||||
}
|
||||
|
||||
void MetalSamplerGroup::reset(id<MTLCommandBuffer> cmdBuffer, id<MTLArgumentEncoder> e,
|
||||
id<MTLDevice> device) {
|
||||
encoder = e;
|
||||
|
||||
// The number of slots in the ring buffer we use to manage argument buffer allocations.
|
||||
// This number was chosen to avoid running out of slots and having to allocate a "fallback"
|
||||
// buffer when SamplerGroups are updated multiple times a frame. This value can reduced after
|
||||
// auditing Filament's calls to updateSamplerGroup, which should be as few times as possible.
|
||||
// For example, the bloom downsample pass should be refactored to maintain two separate
|
||||
// MaterialInstances instead of "ping ponging" between two texture bindings, which causes a
|
||||
// single SamplerGroup to be updated many times a frame.
|
||||
static constexpr auto METAL_ARGUMENT_BUFFER_SLOTS = 32;
|
||||
|
||||
MTLSizeAndAlign argBufferLayout;
|
||||
argBufferLayout.size = encoder.encodedLength;
|
||||
argBufferLayout.align = encoder.alignment;
|
||||
// Chances are, even though the MTLArgumentEncoder might change, the required size and alignment
|
||||
// probably won't. So we can re-use the previous ring buffer.
|
||||
if (UTILS_UNLIKELY(!argBuffer || !argBuffer->canAccomodateLayout(argBufferLayout))) {
|
||||
argBuffer = std::make_unique<MetalRingBuffer>(device, MTLResourceStorageModeShared,
|
||||
argBufferLayout, METAL_ARGUMENT_BUFFER_SLOTS);
|
||||
} else {
|
||||
argBuffer->createNewAllocation(cmdBuffer);
|
||||
}
|
||||
|
||||
// Clear all textures and samplers.
|
||||
assert_invariant(textureHandles.size() == textures.size());
|
||||
assert_invariant(textures.size() == samplers.size());
|
||||
for (size_t s = 0; s < textureHandles.size(); s++) {
|
||||
textureHandles[s] = {};
|
||||
textures[s] = nil;
|
||||
samplers[s] = nil;
|
||||
}
|
||||
|
||||
finalized = false;
|
||||
}
|
||||
|
||||
void MetalSamplerGroup::mutate(id<MTLCommandBuffer> cmdBuffer) {
|
||||
assert_invariant(finalized); // only makes sense to mutate if this sampler group is finalized
|
||||
assert_invariant(argBuffer);
|
||||
argBuffer->createNewAllocation(cmdBuffer);
|
||||
finalized = false;
|
||||
}
|
||||
|
||||
void MetalSamplerGroup::useResources(id<MTLRenderCommandEncoder> renderPassEncoder) {
|
||||
assert_invariant(finalized);
|
||||
if (@available(iOS 13, *)) {
|
||||
// TODO: pass only the appropriate stages to useResources.
|
||||
[renderPassEncoder useResources:textures.data()
|
||||
count:textures.size()
|
||||
usage:MTLResourceUsageRead | MTLResourceUsageSample
|
||||
stages:MTLRenderStageFragment | MTLRenderStageVertex];
|
||||
} else {
|
||||
[renderPassEncoder useResources:textures.data()
|
||||
count:textures.size()
|
||||
usage:MTLResourceUsageRead | MTLResourceUsageSample];
|
||||
}
|
||||
}
|
||||
|
||||
MetalRenderTarget::MetalRenderTarget(MetalContext* context, uint32_t width, uint32_t height,
|
||||
uint8_t samples, Attachment colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT],
|
||||
Attachment depthAttachment, Attachment stencilAttachment) :
|
||||
uint8_t samples, Attachment colorAttachments[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT], Attachment depthAttachment) :
|
||||
HwRenderTarget(width, height), context(context), samples(samples) {
|
||||
math::uint2 tmin = {std::numeric_limits<uint32_t>::max()};
|
||||
UTILS_UNUSED_IN_RELEASE math::uint2 tmax = {0};
|
||||
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmin = {std::numeric_limits<size_t>::max()};
|
||||
UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmax = {0};
|
||||
UTILS_UNUSED_IN_RELEASE size_t attachmentCount = 0;
|
||||
|
||||
for (size_t i = 0; i < MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT; i++) {
|
||||
@@ -917,7 +839,7 @@ MetalRenderTarget::MetalRenderTarget(MetalContext* context, uint32_t width, uint
|
||||
if (samples > 1 && color[i].getSampleCount() == 1) {
|
||||
auto& sidecar = color[i].metalTexture->msaaSidecar;
|
||||
if (!sidecar) {
|
||||
sidecar = createMultisampledTexture(color[i].getPixelFormat(),
|
||||
sidecar = createMultisampledTexture(context->device, color[i].getPixelFormat(),
|
||||
color[i].metalTexture->width, color[i].metalTexture->height, samples);
|
||||
}
|
||||
}
|
||||
@@ -942,37 +864,12 @@ MetalRenderTarget::MetalRenderTarget(MetalContext* context, uint32_t width, uint
|
||||
if (samples > 1 && depth.getSampleCount() == 1) {
|
||||
auto& sidecar = depth.metalTexture->msaaSidecar;
|
||||
if (!sidecar) {
|
||||
sidecar = createMultisampledTexture(depth.getPixelFormat(),
|
||||
sidecar = createMultisampledTexture(context->device, depth.getPixelFormat(),
|
||||
depth.metalTexture->width, depth.metalTexture->height, samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (stencilAttachment) {
|
||||
stencil = stencilAttachment;
|
||||
|
||||
ASSERT_PRECONDITION(stencil.getSampleCount() <= samples,
|
||||
"MetalRenderTarget was initialized with a MSAA STENCIL texture, but sample count is %d.",
|
||||
samples);
|
||||
|
||||
auto t = stencil.metalTexture;
|
||||
const auto twidth = std::max(1u, t->width >> stencil.level);
|
||||
const auto theight = std::max(1u, t->height >> stencil.level);
|
||||
tmin = { math::min(tmin.x, twidth), math::min(tmin.y, theight) };
|
||||
tmax = { math::max(tmax.x, twidth), math::max(tmax.y, theight) };
|
||||
attachmentCount++;
|
||||
|
||||
// If we were given a single-sampled texture but the samples parameter is > 1, we create
|
||||
// a multisampled sidecar texture and do a resolve automatically.
|
||||
if (samples > 1 && stencil.getSampleCount() == 1) {
|
||||
auto& sidecar = stencil.metalTexture->msaaSidecar;
|
||||
if (!sidecar) {
|
||||
sidecar = createMultisampledTexture(stencil.getPixelFormat(),
|
||||
stencil.metalTexture->width, stencil.metalTexture->height, samples);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Verify that all attachments have the same non-zero dimensions.
|
||||
assert_invariant(attachmentCount > 0);
|
||||
assert_invariant(tmin == tmax);
|
||||
@@ -981,9 +878,9 @@ MetalRenderTarget::MetalRenderTarget(MetalContext* context, uint32_t width, uint
|
||||
// The render target dimensions must be less than or equal to the attachment size.
|
||||
assert_invariant(width <= tmin.x && height <= tmin.y);
|
||||
|
||||
// Store the width/height of all attachments. We'll use this when converting from Filament's
|
||||
// Store the height of all attachments. We'll use this when converting from Filament's
|
||||
// coordinate system to Metal's.
|
||||
attachmentSize = tmin;
|
||||
attachmentHeight = tmin.y;
|
||||
}
|
||||
|
||||
void MetalRenderTarget::setUpRenderPassAttachments(MTLRenderPassDescriptor* descriptor,
|
||||
@@ -1030,17 +927,15 @@ void MetalRenderTarget::setUpRenderPassAttachments(MTLRenderPassDescriptor* desc
|
||||
}
|
||||
|
||||
Attachment depthAttachment = getDepthAttachment();
|
||||
if (depthAttachment) {
|
||||
descriptor.depthAttachment.texture = depthAttachment.getTexture();
|
||||
descriptor.depthAttachment.level = depthAttachment.level;
|
||||
descriptor.depthAttachment.slice = depthAttachment.layer;
|
||||
descriptor.depthAttachment.loadAction = getLoadAction(params, TargetBufferFlags::DEPTH);
|
||||
descriptor.depthAttachment.storeAction = getStoreAction(params, TargetBufferFlags::DEPTH);
|
||||
descriptor.depthAttachment.clearDepth = params.clearDepth;
|
||||
}
|
||||
descriptor.depthAttachment.texture = depthAttachment.getTexture();
|
||||
descriptor.depthAttachment.level = depthAttachment.level;
|
||||
descriptor.depthAttachment.slice = depthAttachment.layer;
|
||||
descriptor.depthAttachment.loadAction = getLoadAction(params, TargetBufferFlags::DEPTH);
|
||||
descriptor.depthAttachment.storeAction = getStoreAction(params, TargetBufferFlags::DEPTH);
|
||||
descriptor.depthAttachment.clearDepth = params.clearDepth;
|
||||
|
||||
const bool depthAutomaticResolve = samples > 1 && depthAttachment.getSampleCount() == 1;
|
||||
if (depthAutomaticResolve) {
|
||||
const bool automaticResolve = samples > 1 && depthAttachment.getSampleCount() == 1;
|
||||
if (automaticResolve) {
|
||||
// We're rendering into our temporary MSAA texture and doing an automatic resolve.
|
||||
// We should not be attempting to load anything into the MSAA texture.
|
||||
assert_invariant(descriptor.depthAttachment.loadAction != MTLLoadActionLoad);
|
||||
@@ -1054,49 +949,12 @@ void MetalRenderTarget::setUpRenderPassAttachments(MTLRenderPassDescriptor* desc
|
||||
descriptor.depthAttachment.slice = 0;
|
||||
const bool discard = any(discardFlags & TargetBufferFlags::DEPTH);
|
||||
if (!discard) {
|
||||
assert_invariant(context->supportsAutoDepthResolve);
|
||||
descriptor.depthAttachment.resolveTexture = depthAttachment.getTexture();
|
||||
descriptor.depthAttachment.resolveLevel = depthAttachment.level;
|
||||
descriptor.depthAttachment.resolveSlice = depthAttachment.layer;
|
||||
descriptor.depthAttachment.storeAction = MTLStoreActionMultisampleResolve;
|
||||
}
|
||||
}
|
||||
|
||||
Attachment stencilAttachment = getStencilAttachment();
|
||||
if (stencilAttachment) {
|
||||
descriptor.stencilAttachment.texture = stencilAttachment.getTexture();
|
||||
descriptor.stencilAttachment.level = stencilAttachment.level;
|
||||
descriptor.stencilAttachment.slice = stencilAttachment.layer;
|
||||
descriptor.stencilAttachment.loadAction = getLoadAction(params, TargetBufferFlags::STENCIL);
|
||||
descriptor.stencilAttachment.storeAction = getStoreAction(params, TargetBufferFlags::STENCIL);
|
||||
descriptor.stencilAttachment.clearStencil = params.clearStencil;
|
||||
}
|
||||
|
||||
const bool stencilAutomaticResolve = samples > 1 && stencilAttachment.getSampleCount() == 1;
|
||||
if (stencilAutomaticResolve) {
|
||||
// We're rendering into our temporary MSAA texture and doing an automatic resolve.
|
||||
// We should not be attempting to load anything into the MSAA texture.
|
||||
assert_invariant(descriptor.stencilAttachment.loadAction != MTLLoadActionLoad);
|
||||
assert_invariant(!defaultRenderTarget);
|
||||
|
||||
id<MTLTexture> sidecar = stencilAttachment.getMSAASidecarTexture();
|
||||
assert_invariant(sidecar);
|
||||
|
||||
descriptor.stencilAttachment.texture = sidecar;
|
||||
descriptor.stencilAttachment.level = 0;
|
||||
descriptor.stencilAttachment.slice = 0;
|
||||
const bool discard = any(discardFlags & TargetBufferFlags::STENCIL);
|
||||
if (!discard) {
|
||||
assert_invariant(context->supportsAutoDepthResolve);
|
||||
descriptor.stencilAttachment.resolveTexture = stencilAttachment.getTexture();
|
||||
descriptor.stencilAttachment.resolveLevel = stencilAttachment.level;
|
||||
descriptor.stencilAttachment.resolveSlice = stencilAttachment.layer;
|
||||
descriptor.stencilAttachment.storeAction = MTLStoreActionMultisampleResolve;
|
||||
if (@available(iOS 12.0, *)) {
|
||||
descriptor.stencilAttachment.stencilResolveFilter = MTLMultisampleStencilResolveFilterSample0;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MetalRenderTarget::Attachment MetalRenderTarget::getDrawColorAttachment(size_t index) {
|
||||
@@ -1127,14 +985,6 @@ MetalRenderTarget::Attachment MetalRenderTarget::getDepthAttachment() {
|
||||
return result;
|
||||
}
|
||||
|
||||
MetalRenderTarget::Attachment MetalRenderTarget::getStencilAttachment() {
|
||||
Attachment result = stencil;
|
||||
if (defaultRenderTarget) {
|
||||
// TODO: do we want the default SwapChain to have a default stencil buffer?
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
MTLLoadAction MetalRenderTarget::getLoadAction(const RenderPassParams& params,
|
||||
TargetBufferFlags buffer) {
|
||||
const auto clearFlags = (TargetBufferFlags) params.flags.clear;
|
||||
@@ -1156,8 +1006,8 @@ MTLStoreAction MetalRenderTarget::getStoreAction(const RenderPassParams& params,
|
||||
return MTLStoreActionStore;
|
||||
}
|
||||
|
||||
id<MTLTexture> MetalRenderTarget::createMultisampledTexture(MTLPixelFormat format,
|
||||
uint32_t width, uint32_t height, uint8_t samples) const {
|
||||
id<MTLTexture> MetalRenderTarget::createMultisampledTexture(id<MTLDevice> device,
|
||||
MTLPixelFormat format, uint32_t width, uint32_t height, uint8_t samples) {
|
||||
MTLTextureDescriptor* descriptor =
|
||||
[MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format
|
||||
width:width
|
||||
@@ -1168,25 +1018,18 @@ id<MTLTexture> MetalRenderTarget::createMultisampledTexture(MTLPixelFormat forma
|
||||
descriptor.usage = MTLTextureUsageRenderTarget;
|
||||
descriptor.resourceOptions = MTLResourceStorageModePrivate;
|
||||
|
||||
if (context->supportsMemorylessRenderTargets) {
|
||||
if (@available(macOS 11.0, *)) {
|
||||
descriptor.resourceOptions = MTLResourceStorageModeMemoryless;
|
||||
}
|
||||
}
|
||||
|
||||
return [context->device newTextureWithDescriptor:descriptor];
|
||||
return [device newTextureWithDescriptor:descriptor];
|
||||
}
|
||||
|
||||
math::uint2 MetalRenderTarget::getAttachmentSize() noexcept {
|
||||
uint32_t MetalRenderTarget::getAttachmentHeight() noexcept {
|
||||
if (defaultRenderTarget) {
|
||||
// The default render target always has a color attachment.
|
||||
auto colorAttachment = getDrawColorAttachment(0);
|
||||
assert_invariant(colorAttachment);
|
||||
id<MTLTexture> t = colorAttachment.getTexture();
|
||||
return {t.width, t.height};
|
||||
return colorAttachment.getTexture().height;
|
||||
}
|
||||
assert_invariant(attachmentSize.x > 0 && attachmentSize.y > 0);
|
||||
return attachmentSize;
|
||||
assert_invariant(attachmentHeight > 0);
|
||||
return attachmentHeight;
|
||||
}
|
||||
|
||||
MetalFence::MetalFence(MetalContext& context) : context(context), value(context.signalId++) { }
|
||||
|
||||
@@ -20,12 +20,10 @@
|
||||
#include <Metal/Metal.h>
|
||||
|
||||
#include "private/backend/Driver.h"
|
||||
#include "backend/Program.h"
|
||||
#include "private/backend/Program.h"
|
||||
|
||||
#include <backend/DriverEnums.h>
|
||||
|
||||
#include <utils/FixedCapacityVector.h>
|
||||
|
||||
#include <memory>
|
||||
#include <tsl/robin_map.h>
|
||||
#include <utils/Hash.h>
|
||||
@@ -37,42 +35,17 @@ inline bool operator==(const SamplerParams& lhs, const SamplerParams& rhs) {
|
||||
return lhs.u == rhs.u;
|
||||
}
|
||||
|
||||
// Rasterization Bindings
|
||||
// ----------------------
|
||||
// Bindings Buffer name Count
|
||||
// ------------------------------------------------------
|
||||
// 0 Zero buffer (placeholder vertex buffer) 1
|
||||
// 1-16 Filament vertex buffers 16 limited by MAX_VERTEX_BUFFER_COUNT
|
||||
// 17-26 Uniform buffers 10 Program::UNIFORM_BINDING_COUNT
|
||||
// 27-30 Sampler groups (argument buffers) 4 Program::SAMPLER_BINDING_COUNT
|
||||
//
|
||||
// Total 31
|
||||
static constexpr uint32_t SAMPLER_GROUP_COUNT = Program::BINDING_COUNT;
|
||||
static constexpr uint32_t SAMPLER_BINDING_COUNT = MAX_SAMPLER_COUNT;
|
||||
static constexpr uint32_t VERTEX_BUFFER_START = Program::BINDING_COUNT;
|
||||
|
||||
// Compute Bindings
|
||||
// ----------------------
|
||||
// Bindings Buffer name Count
|
||||
// ------------------------------------------------------
|
||||
// 0-3 SSBO buffers 4 MAX_SSBO_COUNT
|
||||
// 17-26 Uniform buffers 10 Program::UNIFORM_BINDING_COUNT
|
||||
// 27-30 Sampler groups (argument buffers) 4 Program::SAMPLER_BINDING_COUNT
|
||||
//
|
||||
// Total 18
|
||||
// The "zero" buffer is a small buffer for missing attributes that resides in the vertex slot
|
||||
// immediately following any user-provided vertex buffers.
|
||||
static constexpr uint32_t ZERO_VERTEX_BUFFER = MAX_VERTEX_BUFFER_COUNT;
|
||||
|
||||
// The total number of vertex buffer "slots" that the Metal backend can bind.
|
||||
// + 1 to account for the zero buffer, a placeholder buffer used internally by the Metal backend.
|
||||
// MAX_VERTEX_BUFFER_COUNT represents the max number of vertex buffers Filament can bind.
|
||||
static constexpr uint32_t LOGICAL_VERTEX_BUFFER_COUNT = MAX_VERTEX_BUFFER_COUNT + 1;
|
||||
|
||||
// The "zero" buffer is a small buffer for missing attributes.
|
||||
static constexpr uint32_t ZERO_VERTEX_BUFFER_LOGICAL_INDEX = 0u;
|
||||
static constexpr uint32_t ZERO_VERTEX_BUFFER_BINDING = 0u;
|
||||
|
||||
static constexpr uint32_t USER_VERTEX_BUFFER_BINDING_START = 1u;
|
||||
|
||||
// These constants must match the equivalent in CodeGenerator.h.
|
||||
static constexpr uint32_t UNIFORM_BUFFER_BINDING_START = 17u;
|
||||
static constexpr uint32_t SSBO_BINDING_START = 0u;
|
||||
static constexpr uint32_t SAMPLER_GROUP_BINDING_START = 27u;
|
||||
// + 1 to account for the zero buffer.
|
||||
static constexpr uint32_t VERTEX_BUFFER_COUNT = MAX_VERTEX_BUFFER_COUNT + 1;
|
||||
|
||||
// Forward declarations necessary here, definitions at end of file.
|
||||
inline bool operator==(const MTLViewport& lhs, const MTLViewport& rhs);
|
||||
@@ -85,7 +58,7 @@ inline bool operator!=(const MTLViewport& lhs, const MTLViewport& rhs);
|
||||
struct VertexDescription {
|
||||
struct Attribute {
|
||||
MTLVertexFormat format; // 8 bytes
|
||||
uint32_t buffer; // 4 bytes a logical vertex buffer index
|
||||
uint32_t buffer; // 4 bytes
|
||||
uint32_t offset; // 4 bytes
|
||||
};
|
||||
struct Layout {
|
||||
@@ -93,8 +66,7 @@ struct VertexDescription {
|
||||
uint64_t stride; // 8 bytes
|
||||
};
|
||||
Attribute attributes[MAX_VERTEX_ATTRIBUTE_COUNT] = {}; // 256 bytes
|
||||
// layouts[n] represents the layout of the vertex buffer at logical index n
|
||||
Layout layouts[LOGICAL_VERTEX_BUFFER_COUNT] = {}; // 272 bytes
|
||||
Layout layouts[VERTEX_BUFFER_COUNT] = {}; // 272 bytes
|
||||
|
||||
bool operator==(const VertexDescription& rhs) const noexcept {
|
||||
bool result = true;
|
||||
@@ -154,11 +126,9 @@ static_assert(sizeof(BlendState) == 56, "BlendState is unexpected size.");
|
||||
// StateCache caches Metal state objects using StateType as a key.
|
||||
// MetalType is the corresponding Metal API type.
|
||||
// StateCreator is a functor that creates a new state of type MetalType.
|
||||
// HashFn is a functor that hashes StateType.
|
||||
template<typename StateType,
|
||||
typename MetalType,
|
||||
typename StateCreator,
|
||||
typename HashFn = utils::hash::MurmurHashFn<StateType>>
|
||||
typename StateCreator>
|
||||
class StateCache {
|
||||
|
||||
public:
|
||||
@@ -171,8 +141,6 @@ public:
|
||||
void setDevice(id<MTLDevice> device) noexcept { mDevice = device; }
|
||||
|
||||
MetalType getOrCreateState(const StateType& state) noexcept {
|
||||
assert_invariant(mDevice);
|
||||
|
||||
// Check if a valid state already exists in the cache.
|
||||
auto iter = mStateCache.find(state);
|
||||
if (UTILS_LIKELY(iter != mStateCache.end())) {
|
||||
@@ -182,7 +150,6 @@ public:
|
||||
|
||||
// If we reach this point, we couldn't find one in the cache; create a new one.
|
||||
const auto& metalObject = creator(mDevice, state);
|
||||
assert_invariant(metalObject);
|
||||
|
||||
mStateCache.emplace(std::make_pair(
|
||||
state,
|
||||
@@ -197,6 +164,7 @@ private:
|
||||
StateCreator creator;
|
||||
id<MTLDevice> mDevice = nil;
|
||||
|
||||
using HashFn = utils::hash::MurmurHashFn<StateType>;
|
||||
tsl::robin_map<StateType, MetalType, HashFn> mStateCache;
|
||||
|
||||
};
|
||||
@@ -247,7 +215,6 @@ struct MetalPipelineState {
|
||||
VertexDescription vertexDescription; // 528 bytes
|
||||
MTLPixelFormat colorAttachmentPixelFormat[MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT] = { MTLPixelFormatInvalid }; // 64 bytes
|
||||
MTLPixelFormat depthAttachmentPixelFormat = MTLPixelFormatInvalid; // 8 bytes
|
||||
MTLPixelFormat stencilAttachmentPixelFormat = MTLPixelFormatInvalid; // 8 bytes
|
||||
NSUInteger sampleCount = 1; // 8 bytes
|
||||
BlendState blendState; // 56 bytes
|
||||
bool colorWrite = true; // 1 byte
|
||||
@@ -261,7 +228,6 @@ struct MetalPipelineState {
|
||||
std::equal(this->colorAttachmentPixelFormat, this->colorAttachmentPixelFormat + MRT::MAX_SUPPORTED_RENDER_TARGET_COUNT,
|
||||
rhs.colorAttachmentPixelFormat) &&
|
||||
this->depthAttachmentPixelFormat == rhs.depthAttachmentPixelFormat &&
|
||||
this->stencilAttachmentPixelFormat == rhs.stencilAttachmentPixelFormat &&
|
||||
this->sampleCount == rhs.sampleCount &&
|
||||
this->blendState == rhs.blendState &&
|
||||
this->colorWrite == rhs.colorWrite
|
||||
@@ -275,7 +241,7 @@ struct MetalPipelineState {
|
||||
|
||||
// This assert checks that the struct is the size we expect without any "hidden" padding bytes
|
||||
// inserted by the compiler.
|
||||
static_assert(sizeof(MetalPipelineState) == 696, "MetalPipelineState unexpected size.");
|
||||
static_assert(sizeof(MetalPipelineState) == 688, "MetalPipelineState unexpected size.");
|
||||
|
||||
struct PipelineStateCreator {
|
||||
id<MTLRenderPipelineState> operator()(id<MTLDevice> device, const MetalPipelineState& state)
|
||||
@@ -290,39 +256,13 @@ using PipelineStateCache = StateCache<MetalPipelineState, id<MTLRenderPipelineSt
|
||||
// Depth-stencil State
|
||||
|
||||
struct DepthStencilState {
|
||||
struct StencilDescriptor {
|
||||
MTLCompareFunction stencilCompare = MTLCompareFunctionAlways; // 8 bytes
|
||||
MTLStencilOperation stencilOperationStencilFail = MTLStencilOperationKeep; // 8 bytes
|
||||
MTLStencilOperation stencilOperationDepthFail = MTLStencilOperationKeep; // 8 bytes
|
||||
MTLStencilOperation stencilOperationDepthStencilPass = MTLStencilOperationKeep; // 8 bytes
|
||||
uint32_t readMask = 0xFFFF; // 4 bytes
|
||||
uint32_t writeMask = 0xFFFF; // 4 bytes
|
||||
MTLCompareFunction compareFunction = MTLCompareFunctionAlways; // 8 bytes
|
||||
bool depthWriteEnabled = false; // 1 byte
|
||||
char padding[7] = { 0 }; // 7 bytes
|
||||
|
||||
bool operator==(const StencilDescriptor& rhs) const {
|
||||
return stencilCompare == rhs.stencilCompare &&
|
||||
stencilOperationStencilFail == rhs.stencilOperationStencilFail &&
|
||||
stencilOperationDepthFail == rhs.stencilOperationDepthFail &&
|
||||
stencilOperationDepthStencilPass == rhs.stencilOperationDepthStencilPass &&
|
||||
readMask == rhs.readMask &&
|
||||
writeMask == rhs.writeMask;
|
||||
}
|
||||
|
||||
bool operator!=(const StencilDescriptor& rhs) const {
|
||||
return !(rhs == *this);
|
||||
}
|
||||
} front, back;
|
||||
|
||||
MTLCompareFunction depthCompare = MTLCompareFunctionAlways; // 8 bytes
|
||||
bool depthWriteEnabled = false; // 1 byte
|
||||
bool stencilWriteEnabled = false; // 1 byte
|
||||
uint8_t padding[6] = { 0 }; // 6 bytes
|
||||
|
||||
bool operator==(const DepthStencilState& rhs) const {
|
||||
return depthCompare == rhs.depthCompare &&
|
||||
depthWriteEnabled == rhs.depthWriteEnabled &&
|
||||
front == rhs.front &&
|
||||
back == rhs.back &&
|
||||
stencilWriteEnabled == rhs.stencilWriteEnabled;
|
||||
bool operator==(const DepthStencilState& rhs) const noexcept {
|
||||
return this->compareFunction == rhs.compareFunction &&
|
||||
this->depthWriteEnabled == rhs.depthWriteEnabled;
|
||||
}
|
||||
|
||||
bool operator!=(const DepthStencilState& rhs) const noexcept {
|
||||
@@ -332,7 +272,7 @@ struct DepthStencilState {
|
||||
|
||||
// This assert checks that the struct is the size we expect without any "hidden" padding bytes
|
||||
// inserted by the compiler.
|
||||
static_assert(sizeof(DepthStencilState) == 96, "DepthStencilState unexpected size.");
|
||||
static_assert(sizeof(DepthStencilState) == 16, "DepthStencilState unexpected size.");
|
||||
|
||||
struct DepthStateCreator {
|
||||
id<MTLDepthStencilState> operator()(id<MTLDevice> device, const DepthStencilState& state)
|
||||
@@ -348,19 +288,38 @@ using DepthStencilStateCache = StateCache<DepthStencilState, id<MTLDepthStencilS
|
||||
|
||||
class MetalBufferObject;
|
||||
|
||||
struct BufferState {
|
||||
struct UniformBufferState {
|
||||
MetalBufferObject* buffer = nullptr; // 8 bytes
|
||||
uint32_t offset = 0; // 4 bytes
|
||||
bool bound = false; // 1 byte
|
||||
char padding[3] = { 0 }; // 3 bytes
|
||||
|
||||
bool operator==(const UniformBufferState& rhs) const noexcept {
|
||||
return this->bound == rhs.bound &&
|
||||
this->buffer == rhs.buffer &&
|
||||
this->offset == rhs.offset;
|
||||
}
|
||||
|
||||
bool operator!=(const UniformBufferState& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(UniformBufferState) == 16, "UniformBufferState unexpected size.");
|
||||
|
||||
using UniformBufferStateTracker = StateTracker<UniformBufferState>;
|
||||
|
||||
// Sampler states
|
||||
|
||||
struct SamplerState {
|
||||
SamplerParams samplerParams;
|
||||
uint32_t minLod = 0;
|
||||
uint32_t maxLod = UINT_MAX;
|
||||
|
||||
bool operator==(const SamplerState& rhs) const noexcept {
|
||||
return this->samplerParams == rhs.samplerParams;
|
||||
return this->samplerParams == rhs.samplerParams &&
|
||||
this->minLod == rhs.minLod &&
|
||||
this->maxLod == rhs.maxLod;
|
||||
}
|
||||
|
||||
bool operator!=(const SamplerState& rhs) const noexcept {
|
||||
@@ -368,7 +327,7 @@ struct SamplerState {
|
||||
}
|
||||
};
|
||||
|
||||
static_assert(sizeof(SamplerState) == 4, "SamplerState unexpected size.");
|
||||
static_assert(sizeof(SamplerState) == 12, "SamplerState unexpected size.");
|
||||
|
||||
struct SamplerStateCreator {
|
||||
id<MTLSamplerState> operator()(id<MTLDevice> device, const SamplerState& state) noexcept;
|
||||
@@ -381,38 +340,6 @@ using SamplerStateCache = StateCache<SamplerState, id<MTLSamplerState>, SamplerS
|
||||
using CullModeStateTracker = StateTracker<MTLCullMode>;
|
||||
using WindingStateTracker = StateTracker<MTLWinding>;
|
||||
|
||||
// Argument encoder
|
||||
|
||||
struct ArgumentEncoderState {
|
||||
utils::FixedCapacityVector<MTLTextureType> textureTypes;
|
||||
|
||||
explicit ArgumentEncoderState(utils::FixedCapacityVector<MTLTextureType>&& types)
|
||||
: textureTypes(std::move(types)) {}
|
||||
|
||||
bool operator==(const ArgumentEncoderState& rhs) const noexcept {
|
||||
return std::equal(textureTypes.begin(), textureTypes.end(), rhs.textureTypes.begin(),
|
||||
rhs.textureTypes.end());
|
||||
}
|
||||
|
||||
bool operator!=(const ArgumentEncoderState& rhs) const noexcept {
|
||||
return !operator==(rhs);
|
||||
}
|
||||
};
|
||||
|
||||
struct ArgumentEncoderHasher {
|
||||
uint32_t operator()(const ArgumentEncoderState& key) const noexcept {
|
||||
return utils::hash::murmur3((const uint32_t*)key.textureTypes.data(),
|
||||
sizeof(MTLTextureType) * key.textureTypes.size() / 4, 0);
|
||||
}
|
||||
};
|
||||
|
||||
struct ArgumentEncoderCreator {
|
||||
id<MTLArgumentEncoder> operator()(id<MTLDevice> device, const ArgumentEncoderState& state) noexcept;
|
||||
};
|
||||
|
||||
using ArgumentEncoderCache = StateCache<ArgumentEncoderState, id<MTLArgumentEncoder>,
|
||||
ArgumentEncoderCreator, ArgumentEncoderHasher>;
|
||||
|
||||
} // namespace backend
|
||||
} // namespace filament
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user