Compare commits
117
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c7da1c0ad5 | ||
|
|
04ff88fab2 | ||
|
|
7d242341f2 | ||
|
|
e625c7024c | ||
|
|
192a61a06b | ||
|
|
6a93e3a765 | ||
|
|
e1fb1391f9 | ||
|
|
a3922ac3a9 | ||
|
|
5f1112d85e | ||
|
|
09545690bf | ||
|
|
3ce752c47b | ||
|
|
1f9f3ddb91 | ||
|
|
8e94688fbf | ||
|
|
438ee40f40 | ||
|
|
7f22d733d7 | ||
|
|
77d77f0a5c | ||
|
|
0aabd3dd6a | ||
|
|
72a54b30f9 | ||
|
|
00b2ab7ac4 | ||
|
|
39e15d67fc | ||
|
|
921dbddad9 | ||
|
|
6406d4602c | ||
|
|
880cd66166 | ||
|
|
f27ff203cf | ||
|
|
3ea8e529cc | ||
|
|
572dd233d7 | ||
|
|
c19070e477 | ||
|
|
64328b7388 | ||
|
|
1414fdcd38 | ||
|
|
e607a035ae | ||
|
|
0496e089c1 | ||
|
|
b310e3d24a | ||
|
|
b359d77669 | ||
|
|
e57a4061cc | ||
|
|
53f82e6b71 | ||
|
|
e88bba5940 | ||
|
|
0b83454d08 | ||
|
|
1ef0d36f79 | ||
|
|
e350737d1e | ||
|
|
cb203b13de | ||
|
|
92a0d7bfc3 | ||
|
|
c1a7ed2799 | ||
|
|
692301bdf1 | ||
|
|
05b87b3c42 | ||
|
|
9825297e70 | ||
|
|
6a59c887de | ||
|
|
33b4b46220 | ||
|
|
06170a25f7 | ||
|
|
418dad883d | ||
|
|
447661efed | ||
|
|
bd61ab691c | ||
|
|
2a04cee97f | ||
|
|
5ae7760752 | ||
|
|
56b8bf5b4b | ||
|
|
6af38fa47f | ||
|
|
0c01799c50 | ||
|
|
e2519e0eed | ||
|
|
6178ae0459 | ||
|
|
8a1a0b0fd2 | ||
|
|
a7c3cf4173 | ||
|
|
57b68eeba3 | ||
|
|
ad8c9ce4e0 | ||
|
|
7dc0f2cc86 | ||
|
|
37110799ef | ||
|
|
88a06ec8e7 | ||
|
|
38705d6226 | ||
|
|
d325bb43cf | ||
|
|
0c52d3c9bf | ||
|
|
770176a1e3 | ||
|
|
672603f9b4 | ||
|
|
0ecf6c46e2 | ||
|
|
8b87a54c1a | ||
|
|
cd1d3e8749 | ||
|
|
e88072cec0 | ||
|
|
1d2e165d99 | ||
|
|
cfc4ac5511 | ||
|
|
73a03d7af0 | ||
|
|
56dc348cc8 | ||
|
|
1b46ddd8b6 | ||
|
|
a68aaa114e | ||
|
|
3da7dabb2a | ||
|
|
1e2311da3d | ||
|
|
a38c55c82d | ||
|
|
cd22478e4f | ||
|
|
60036c75fe | ||
|
|
044f2aeb7c | ||
|
|
c73d11858e | ||
|
|
23b67be41a | ||
|
|
7d53baad5c | ||
|
|
1ae33a23fe | ||
|
|
351d9287af | ||
|
|
e7e5004946 | ||
|
|
b9be9b4f2d | ||
|
|
ce88a56579 | ||
|
|
689e769f9a | ||
|
|
2f0a8b19b5 | ||
|
|
1bed68afb7 | ||
|
|
130e02da5c | ||
|
|
8e06a68446 | ||
|
|
656b50b304 | ||
|
|
880db4ec43 | ||
|
|
2ce294720d | ||
|
|
eb07decb4b | ||
|
|
47930edf70 | ||
|
|
05b89905d8 | ||
|
|
3e0df36c1c | ||
|
|
c9ce384f14 | ||
|
|
6a6bdd5be7 | ||
|
|
d56ade924e | ||
|
|
fe561e3e27 | ||
|
|
1d98e350e4 | ||
|
|
d34e018acb | ||
|
|
169c8d57ff | ||
|
|
a1e0cfa33c | ||
|
|
6d44db3ca0 | ||
|
|
a261429d06 | ||
|
|
69d0de3c6d |
+1
-1
@@ -57,7 +57,7 @@ SpaceBeforeInheritanceColon: true
|
|||||||
SpaceBeforeParens: ControlStatements
|
SpaceBeforeParens: ControlStatements
|
||||||
SpaceBeforeRangeBasedForLoopColon: false
|
SpaceBeforeRangeBasedForLoopColon: false
|
||||||
SpaceInEmptyParentheses: false
|
SpaceInEmptyParentheses: false
|
||||||
SpacesBeforeTrailingComments: 0
|
SpacesBeforeTrailingComments: 1
|
||||||
SpacesInAngles: false
|
SpacesInAngles: false
|
||||||
SpacesInCStyleCastParentheses: false
|
SpacesInCStyleCastParentheses: false
|
||||||
SpacesInContainerLiterals: false
|
SpacesInContainerLiterals: false
|
||||||
|
|||||||
@@ -0,0 +1,45 @@
|
|||||||
|
name: 'Get commit message'
|
||||||
|
outputs:
|
||||||
|
msg:
|
||||||
|
value: ${{ steps.action_output.outputs.msg }}
|
||||||
|
runs:
|
||||||
|
using: "composite"
|
||||||
|
steps:
|
||||||
|
- name: Find commit message (on push)
|
||||||
|
if: github.event_name == 'push'
|
||||||
|
shell: bash
|
||||||
|
run: |
|
||||||
|
AUTHOR_NAME="${{ github.event.head_commit.author.name }}"
|
||||||
|
AUTHOR_EMAIL="${{ github.event.head_commit.author.email }}"
|
||||||
|
TSTAMP="${{ github.event.head_commit.timestamp }}"
|
||||||
|
echo "commit ${{ github.event.head_commit.id }}" >> /tmp/commit_msg.txt
|
||||||
|
echo "Author: ${AUTHOR_NAME}<${AUTHOR_EMAIL}>" >> /tmp/commit_msg.txt
|
||||||
|
echo "Date: ${TSTAMP}" >> /tmp/commit_msg.txt
|
||||||
|
echo "" >> /tmp/commit_msg.txt
|
||||||
|
echo "${{ github.event.head_commit.message }}" >> /tmp/commit_msg.txt
|
||||||
|
- name: Find commit message (PR)
|
||||||
|
shell: bash
|
||||||
|
id: checkout_code
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
run: |
|
||||||
|
echo "+++++ head commit message +++++"
|
||||||
|
echo "$(git log -1 --no-merges)"
|
||||||
|
echo "+++++++++++++++++++++++++++++++"
|
||||||
|
echo "hash=$(git rev-parse HEAD)" >> "$GITHUB_OUTPUT"
|
||||||
|
git checkout ${{ github.event.pull_request.head.sha }}
|
||||||
|
echo "$(git log -1 --no-merges)" >> /tmp/commit_msg.txt
|
||||||
|
- shell: bash
|
||||||
|
id: action_output
|
||||||
|
run: |
|
||||||
|
DELIMITER="EOF_FILE_CONTENT_$(date +%s)" # Using timestamp to make it more unique
|
||||||
|
echo "msg<<$DELIMITER" >> "$GITHUB_OUTPUT"
|
||||||
|
cat /tmp/commit_msg.txt >> "$GITHUB_OUTPUT"
|
||||||
|
echo "$DELIMITER" >> "$GITHUB_OUTPUT"
|
||||||
|
echo "----- got commit message ---"
|
||||||
|
cat /tmp/commit_msg.txt
|
||||||
|
echo "----------------------------"
|
||||||
|
- name: Cleanup Find commit message (PR)
|
||||||
|
shell: bash
|
||||||
|
if: github.event_name == 'pull_request'
|
||||||
|
run: |
|
||||||
|
git checkout ${{ steps.checkout_code.outputs.hash }}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
name: 'Post-submit tasks'
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- main
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
update-renderdiff-goldens:
|
||||||
|
name: update-renderdiff-goldens
|
||||||
|
runs-on: 'ubuntu-24.04-4core'
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v4.1.6
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: ./.github/actions/linux-prereq
|
||||||
|
- id: get_commit_msg
|
||||||
|
uses: ./.github/actions/get-commit-msg
|
||||||
|
- name: Prerequisites
|
||||||
|
run: pip install tifffile numpy
|
||||||
|
- name: Run update script
|
||||||
|
env:
|
||||||
|
GH_TOKEN: ${{ secrets.FILAMENTBOT_TOKEN }}
|
||||||
|
run: |
|
||||||
|
GOLDEN_BRANCH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | python3 test/renderdiff/src/commit_msg.py)
|
||||||
|
COMMIT_HASH=$(echo "${{ steps.get_commit_msg.outputs.msg }}" | head -n 1 | tr -d 'commit ')
|
||||||
|
if [[ "${GOLDEN_BRANCH}" != "main" ]]; then
|
||||||
|
git config --global user.email "filament.bot@gmail.com"
|
||||||
|
git config --global user.name "Filament Bot"
|
||||||
|
git config --global credential.helper cache
|
||||||
|
echo "branch==${GOLDEN_BRANCH}"
|
||||||
|
echo "hash==${COMMIT_HASH}"
|
||||||
|
python3 test/renderdiff/src/update_golden.py --branch=${GOLDEN_BRANCH} \
|
||||||
|
--merge-to-main --filament-tag=${COMMIT_HASH} --golden-repo-token=${GH_TOKEN}
|
||||||
|
fi
|
||||||
@@ -3,10 +3,10 @@ name: Presubmit
|
|||||||
on:
|
on:
|
||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
pull_request:
|
pull_request:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
build-desktop-mac:
|
build-desktop-mac:
|
||||||
@@ -41,8 +41,7 @@ jobs:
|
|||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
name: build-windows
|
name: build-windows
|
||||||
runs-on: win-2019-16core
|
runs-on: windows-2022-32core
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.6
|
- uses: actions/checkout@v4.1.6
|
||||||
with:
|
with:
|
||||||
@@ -110,9 +109,9 @@ jobs:
|
|||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: Check for manual edits to /docs
|
- name: Check for manual edits to /docs
|
||||||
run: |
|
run: |
|
||||||
echo "${{ github.event.pull_request.head.sha }} -- ${{ github.event.pull_request.head.sha }}"
|
echo "${{ github.event.pull_request.head.sha }} -- ${{ github.event.pull_request.head.sha }}"
|
||||||
# disable for now
|
# disable for now
|
||||||
# bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }}
|
# bash docs_src/build/presubmit_check.sh ${{ github.event.pull_request.head.sha }}
|
||||||
|
|
||||||
test-renderdiff:
|
test-renderdiff:
|
||||||
name: test-renderdiff
|
name: test-renderdiff
|
||||||
@@ -121,20 +120,21 @@ jobs:
|
|||||||
- uses: actions/checkout@v4.1.6
|
- uses: actions/checkout@v4.1.6
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- id: get_commit_msg
|
||||||
|
uses: ./.github/actions/get-commit-msg
|
||||||
- uses: ./.github/actions/mac-prereq
|
- uses: ./.github/actions/mac-prereq
|
||||||
- name: Cache Mesa and deps
|
- name: Cache Mesa and deps
|
||||||
id: mesa-cache
|
|
||||||
uses: actions/cache@v4
|
uses: actions/cache@v4
|
||||||
with:
|
with:
|
||||||
path: mesa
|
path: mesa
|
||||||
key: ${{ runner.os }}-mesa-deps-2-${{ vars.MESA_VERSION }}
|
key: ${{ runner.os }}-mesa-deps-2-${{ vars.MESA_VERSION }}
|
||||||
- name: Prerequisites
|
- name: Prerequisites
|
||||||
id: prereqs
|
|
||||||
run: |
|
run: |
|
||||||
bash build/common/get-mesa.sh
|
bash build/common/get-mesa.sh
|
||||||
pip install tifffile numpy
|
pip install tifffile numpy
|
||||||
- name: Run Test
|
- name: Run Test
|
||||||
run: bash test/renderdiff/test.sh
|
run: |
|
||||||
|
echo "${{ steps.get_commit_msg.outputs.msg }}" | bash test/renderdiff/test.sh
|
||||||
- uses: actions/upload-artifact@v4
|
- uses: actions/upload-artifact@v4
|
||||||
with:
|
with:
|
||||||
name: presubmit-renderdiff-result
|
name: presubmit-renderdiff-result
|
||||||
|
|||||||
@@ -226,7 +226,7 @@ jobs:
|
|||||||
|
|
||||||
build-windows:
|
build-windows:
|
||||||
name: build-windows
|
name: build-windows
|
||||||
runs-on: windows-2019-32core
|
runs-on: windows-2022-32core
|
||||||
if: github.event_name == 'release' || github.event.inputs.platform == 'windows'
|
if: github.event_name == 'release' || github.event.inputs.platform == 'windows'
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ on:
|
|||||||
jobs:
|
jobs:
|
||||||
build-windows:
|
build-windows:
|
||||||
name: build-windows
|
name: build-windows
|
||||||
runs-on: windows-2019-32core
|
runs-on: windows-2022-32core
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4.1.6
|
- uses: actions/checkout@v4.1.6
|
||||||
|
|||||||
@@ -97,6 +97,10 @@ Make sure you've installed the following dependencies:
|
|||||||
- `libxcomposite-dev` (`libXcomposite-devel` on Fedora)
|
- `libxcomposite-dev` (`libXcomposite-devel` on Fedora)
|
||||||
- `libxxf86vm-dev` (`libXxf86vm-devel` on Fedora)
|
- `libxxf86vm-dev` (`libXxf86vm-devel` on Fedora)
|
||||||
|
|
||||||
|
```shell
|
||||||
|
sudo apt install clang-14 libglu1-mesa-dev libc++-14-dev libc++abi-14-dev ninja-build libxi-dev libxcomposite-dev libxxf86vm-dev -y
|
||||||
|
```
|
||||||
|
|
||||||
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
|
After dependencies have been installed, we highly recommend using the [easy build](#easy-build)
|
||||||
script.
|
script.
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,12 @@ option(FILAMENT_SUPPORTS_OSMESA "Enable OSMesa (headless GL context) for Filamen
|
|||||||
|
|
||||||
option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
|
option(FILAMENT_ENABLE_FGVIEWER "Enable the frame graph viewer" OFF)
|
||||||
|
|
||||||
|
option(FILAMENT_USE_ABSEIL_LOGGING "Use Abseil to log, may increase binary size" OFF)
|
||||||
|
|
||||||
|
# This is to disable GTAO for the short-term while we investigate a way to better manage size increases.
|
||||||
|
# On the regular filament build (where size is of less concern), we enable GTAO by default.
|
||||||
|
option(FILAMENT_DISABLE_GTAO "Disable GTAO" OFF)
|
||||||
|
|
||||||
set(FILAMENT_NDK_VERSION "" CACHE STRING
|
set(FILAMENT_NDK_VERSION "" CACHE STRING
|
||||||
"Android NDK version or version prefix to be used when building for Android."
|
"Android NDK version or version prefix to be used when building for Android."
|
||||||
)
|
)
|
||||||
@@ -587,6 +593,10 @@ if (CMAKE_BUILD_TYPE STREQUAL "Debug" AND NOT FILAMENT_BACKEND_DEBUG_FLAG STREQU
|
|||||||
unset(FILAMENT_BACKEND_DEBUG_FLAG)
|
unset(FILAMENT_BACKEND_DEBUG_FLAG)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (FILAMENT_USE_ABSEIL_LOGGING)
|
||||||
|
add_definitions(-DFILAMENT_USE_ABSEIL_LOGGING)
|
||||||
|
endif()
|
||||||
|
|
||||||
# ==================================================================================================
|
# ==================================================================================================
|
||||||
# Material compilation flags
|
# Material compilation flags
|
||||||
# ==================================================================================================
|
# ==================================================================================================
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
# Filament Release Notes log
|
# Filament Release Notes log
|
||||||
|
|
||||||
**If you are merging a PR into main**: please add the release note below, under the *Release notes
|
**If you are merging a PR into main**: please add the release note below, under the *Release notes
|
||||||
for next branch cut* header.
|
We are chaning the way Vulkan buffers are handled. We need to switch over to a managed (or view-based) model where the data stored inside the object is a proxy to a Vulkan object that can dynamically be swapped around.
|
||||||
|
|
||||||
**If you are cherry-picking a commit into an rc/ branch**: add the release note under the
|
**If you are cherry-picking a commit into an rc/ branch**: add the release note under the
|
||||||
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
|
||||||
|
|
||||||
## Release notes for next branch cut
|
## Release notes for next branch cut
|
||||||
@@ -31,7 +31,7 @@ repositories {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
implementation 'com.google.android.filament:filament-android:1.60.1'
|
implementation 'com.google.android.filament:filament-android:1.61.1'
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
@@ -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:
|
iOS projects can use CocoaPods to install the latest release:
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
pod 'Filament', '~> 1.60.1'
|
pod 'Filament', '~> 1.61.1'
|
||||||
```
|
```
|
||||||
|
|
||||||
## Documentation
|
## Documentation
|
||||||
|
|||||||
@@ -7,6 +7,13 @@ A new header is inserted each time a *tag* is created.
|
|||||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||||
|
|
||||||
|
## v1.61.2
|
||||||
|
|
||||||
|
- samples: samples now have a CLI to select backend api
|
||||||
|
|
||||||
|
## v1.61.1
|
||||||
|
|
||||||
|
|
||||||
## v1.61.0
|
## v1.61.0
|
||||||
|
|
||||||
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]
|
- materials: sampler now export their type in the material binary [⚠️ **New Material Version**]
|
||||||
|
|||||||
@@ -59,6 +59,10 @@ add_library(smol-v STATIC IMPORTED)
|
|||||||
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
|
set_target_properties(smol-v PROPERTIES IMPORTED_LOCATION
|
||||||
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
|
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libsmol-v.a)
|
||||||
|
|
||||||
|
add_library(abseil STATIC IMPORTED)
|
||||||
|
set_target_properties(abseil PROPERTIES IMPORTED_LOCATION
|
||||||
|
${FILAMENT_DIR}/lib/${ANDROID_ABI}/libabseil.a)
|
||||||
|
|
||||||
if (FILAMENT_ENABLE_FGVIEWER)
|
if (FILAMENT_ENABLE_FGVIEWER)
|
||||||
add_library(fgviewer STATIC IMPORTED)
|
add_library(fgviewer STATIC IMPORTED)
|
||||||
set_target_properties(fgviewer PROPERTIES IMPORTED_LOCATION
|
set_target_properties(fgviewer PROPERTIES IMPORTED_LOCATION
|
||||||
@@ -128,6 +132,7 @@ target_link_libraries(filament-jni
|
|||||||
PRIVATE jnigraphics
|
PRIVATE jnigraphics
|
||||||
PRIVATE utils
|
PRIVATE utils
|
||||||
PRIVATE perfetto
|
PRIVATE perfetto
|
||||||
|
PRIVATE abseil
|
||||||
|
|
||||||
# libgeometry is PUBLIC because gltfio uses it.
|
# libgeometry is PUBLIC because gltfio uses it.
|
||||||
PUBLIC geometry
|
PUBLIC geometry
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
GROUP=com.google.android.filament
|
GROUP=com.google.android.filament
|
||||||
VERSION_NAME=1.60.1
|
VERSION_NAME=1.61.1
|
||||||
|
|
||||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||||
|
|
||||||
|
|||||||
@@ -41,6 +41,8 @@ for cmd in "${NEEDED_PYTHON_DEPS[@]}"; do
|
|||||||
done
|
done
|
||||||
deactivate
|
deactivate
|
||||||
|
|
||||||
|
LOCAL_PKG_CONFIG_PATH=
|
||||||
|
|
||||||
# Install system deps
|
# Install system deps
|
||||||
if [[ "$OS_NAME" == "Linux" ]]; then
|
if [[ "$OS_NAME" == "Linux" ]]; then
|
||||||
if [[ "$GITHUB_WORKFLOW" ]]; then
|
if [[ "$GITHUB_WORKFLOW" ]]; then
|
||||||
@@ -82,6 +84,9 @@ elif [[ "$OS_NAME" == "Darwin" ]]; then
|
|||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=true brew install autoconf automake libx11 libxext libxrandr llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
|
HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=true brew install autoconf automake libx11 libxext libxrandr llvm@${LLVM_VERSION} ninja meson pkg-config libxshmfence
|
||||||
|
|
||||||
|
# For reasons unknown, this is necessary for pkg-config to find homebrew's packages
|
||||||
|
LOCAL_PKG_CONFIG_PATH="/opt/homebrew/lib/pkgconfig:$PKG_CONFIG_PATH"
|
||||||
fi # [[ "$OS_NAME" == x ]]
|
fi # [[ "$OS_NAME" == x ]]
|
||||||
|
|
||||||
LOCAL_LDFLAGS=${LDFLAGS}
|
LOCAL_LDFLAGS=${LDFLAGS}
|
||||||
@@ -134,9 +139,11 @@ fi
|
|||||||
# -Dgallium-drivers=swrast => builds GL software rasterizer
|
# -Dgallium-drivers=swrast => builds GL software rasterizer
|
||||||
# -Dvulkan-drivers=swrast => builds VK software rasterizer
|
# -Dvulkan-drivers=swrast => builds VK software rasterizer
|
||||||
# -Dgallium-drivers=llvmpipe is needed for GL >= 4.1 pipe-screen (see src/gallium/auxiliary/target-helpers/inline_sw_helper.h)
|
# -Dgallium-drivers=llvmpipe is needed for GL >= 4.1 pipe-screen (see src/gallium/auxiliary/target-helpers/inline_sw_helper.h)
|
||||||
CXX=${LOCAL_CXX} CC=${LOCAL_CC} PATH=${LOCAL_PATH} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
|
PKG_CONFIG_PATH=${LOCAL_PKG_CONFIG_PATH} PATH=${LOCAL_PATH} \
|
||||||
|
CXX=${LOCAL_CXX} CC=${LOCAL_CC} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
|
||||||
meson setup --wipe builddir/ -Dprefix="${MESA_DIR}/out" -Dglx=xlib -Dosmesa=true -Dgallium-drivers=llvmpipe,swrast -Dvulkan-drivers=swrast
|
meson setup --wipe builddir/ -Dprefix="${MESA_DIR}/out" -Dglx=xlib -Dosmesa=true -Dgallium-drivers=llvmpipe,swrast -Dvulkan-drivers=swrast
|
||||||
CXX=${LOCAL_CXX} CC=${LOCAL_CC} PATH=${LOCAL_PATH} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
|
PKG_CONFIG_PATH=${LOCAL_PKG_CONFIG_PATH} PATH=${LOCAL_PATH} \
|
||||||
|
CXX=${LOCAL_CXX} CC=${LOCAL_CC} LDFLAGS=${LOCAL_LDFLAGS} CPPFLAGS=${LOCAL_CPPFLAGS} \
|
||||||
meson install -C builddir/
|
meson install -C builddir/
|
||||||
|
|
||||||
# Disable python venv
|
# Disable python venv
|
||||||
|
|||||||
+7
-6
@@ -204,9 +204,10 @@
|
|||||||
"license": "Apache-2.0"
|
"license": "Apache-2.0"
|
||||||
},
|
},
|
||||||
"node_modules/brace-expansion": {
|
"node_modules/brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
|
"license": "MIT",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
@@ -409,9 +410,9 @@
|
|||||||
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="
|
"integrity": "sha512-Nik3Sc0ncrMK4UUdXQmAnRtzmNQTAAXmXIopizwZ1W1t8QmfJj+zL4OA2I7XPTPW5z5TDqv4hRo/JzouDJnX3A=="
|
||||||
},
|
},
|
||||||
"brace-expansion": {
|
"brace-expansion": {
|
||||||
"version": "1.1.11",
|
"version": "1.1.12",
|
||||||
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
|
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
|
||||||
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
|
"integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"balanced-match": "^1.0.0",
|
"balanced-match": "^1.0.0",
|
||||||
"concat-map": "0.0.1"
|
"concat-map": "0.0.1"
|
||||||
|
|||||||
@@ -47,7 +47,11 @@ if "%RUNNING_LOCALLY%" == "1" (
|
|||||||
set "PATH=%PATH%;C:\Program Files\7-Zip"
|
set "PATH=%PATH%;C:\Program Files\7-Zip"
|
||||||
)
|
)
|
||||||
|
|
||||||
call "C:\Program Files (x86)\Microsoft Visual Studio\2019\%VISUAL_STUDIO_VERSION%\VC\Auxiliary\Build\vcvars64.bat"
|
:: Outdated windows-2019 pattern
|
||||||
|
:: call "C:\Program Files (x86)\Microsoft Visual Studio\2019\%VISUAL_STUDIO_VERSION%\VC\Auxiliary\Build\vcvars64.bat"
|
||||||
|
|
||||||
|
call "C:\Program Files\Microsoft Visual Studio\2022\%VISUAL_STUDIO_VERSION%\VC\Auxiliary\Build\vcvars64.bat"
|
||||||
|
echo Passed vcvars64.bat
|
||||||
if errorlevel 1 exit /b %errorlevel%
|
if errorlevel 1 exit /b %errorlevel%
|
||||||
|
|
||||||
msbuild /version
|
msbuild /version
|
||||||
@@ -107,7 +111,7 @@ cd out\cmake-%variant%
|
|||||||
if errorlevel 1 exit /b %errorlevel%
|
if errorlevel 1 exit /b %errorlevel%
|
||||||
|
|
||||||
cmake ..\.. ^
|
cmake ..\.. ^
|
||||||
-G "Visual Studio 16 2019" ^
|
-G "Visual Studio 17 2022" ^
|
||||||
-A x64 ^
|
-A x64 ^
|
||||||
%flag% ^
|
%flag% ^
|
||||||
-DCMAKE_INSTALL_PREFIX=..\%variant% ^
|
-DCMAKE_INSTALL_PREFIX=..\%variant% ^
|
||||||
|
|||||||
+37
-22
@@ -262,11 +262,16 @@ set(MATERIAL_SRCS
|
|||||||
src/materials/ssao/mipmapDepth.mat
|
src/materials/ssao/mipmapDepth.mat
|
||||||
src/materials/ssao/sao.mat
|
src/materials/ssao/sao.mat
|
||||||
src/materials/ssao/saoBentNormals.mat
|
src/materials/ssao/saoBentNormals.mat
|
||||||
src/materials/ssao/gtao.mat
|
|
||||||
src/materials/ssao/gtaoBentNormals.mat
|
|
||||||
src/materials/vsmMipmap.mat
|
src/materials/vsmMipmap.mat
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if (NOT FILAMENT_DISABLE_GTAO)
|
||||||
|
list(APPEND MATERIAL_SRCS
|
||||||
|
src/materials/ssao/gtao.mat
|
||||||
|
src/materials/ssao/gtaoBentNormals.mat
|
||||||
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
set(MATERIAL_FL0_SRCS
|
set(MATERIAL_FL0_SRCS
|
||||||
src/materials/defaultMaterial.mat
|
src/materials/defaultMaterial.mat
|
||||||
src/materials/skybox.mat
|
src/materials/skybox.mat
|
||||||
@@ -316,6 +321,10 @@ if (FILAMENT_FORCE_PROFILING_MODE)
|
|||||||
add_definitions(-DFILAMENT_FORCE_PROFILING_MODE)
|
add_definitions(-DFILAMENT_FORCE_PROFILING_MODE)
|
||||||
endif()
|
endif()
|
||||||
|
|
||||||
|
if (FILAMENT_DISABLE_GTAO)
|
||||||
|
add_definitions(-DFILAMENT_DISABLE_GTAO)
|
||||||
|
endif()
|
||||||
|
|
||||||
# ==================================================================================================
|
# ==================================================================================================
|
||||||
# Definitions
|
# Definitions
|
||||||
# ==================================================================================================
|
# ==================================================================================================
|
||||||
@@ -463,27 +472,29 @@ add_custom_command(
|
|||||||
APPEND
|
APPEND
|
||||||
)
|
)
|
||||||
|
|
||||||
add_custom_command(
|
if (NOT FILAMENT_DISABLE_GTAO)
|
||||||
OUTPUT "${MATERIAL_DIR}/gtao.filamat"
|
add_custom_command(
|
||||||
DEPENDS src/materials/ssao/ssaoUtils.fs
|
OUTPUT "${MATERIAL_DIR}/gtao.filamat"
|
||||||
DEPENDS src/materials/ssao/ssct.fs
|
DEPENDS src/materials/ssao/ssaoUtils.fs
|
||||||
DEPENDS src/materials/utils/depthUtils.fs
|
DEPENDS src/materials/ssao/ssct.fs
|
||||||
DEPENDS src/materials/utils/geometry.fs
|
DEPENDS src/materials/utils/depthUtils.fs
|
||||||
DEPENDS src/materials/ssao/gtaoImpl.fs
|
DEPENDS src/materials/utils/geometry.fs
|
||||||
DEPENDS src/materials/ssao/ssctImpl.fs
|
DEPENDS src/materials/ssao/gtaoImpl.fs
|
||||||
APPEND
|
DEPENDS src/materials/ssao/ssctImpl.fs
|
||||||
)
|
APPEND
|
||||||
|
)
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${MATERIAL_DIR}/gtaoBentNormals.filamat"
|
OUTPUT "${MATERIAL_DIR}/gtaoBentNormals.filamat"
|
||||||
DEPENDS src/materials/ssao/ssaoUtils.fs
|
DEPENDS src/materials/ssao/ssaoUtils.fs
|
||||||
DEPENDS src/materials/ssao/ssct.fs
|
DEPENDS src/materials/ssao/ssct.fs
|
||||||
DEPENDS src/materials/utils/depthUtils.fs
|
DEPENDS src/materials/utils/depthUtils.fs
|
||||||
DEPENDS src/materials/utils/geometry.fs
|
DEPENDS src/materials/utils/geometry.fs
|
||||||
DEPENDS src/materials/ssao/gtaoImpl.fs
|
DEPENDS src/materials/ssao/gtaoImpl.fs
|
||||||
DEPENDS src/materials/ssao/ssctImpl.fs
|
DEPENDS src/materials/ssao/ssctImpl.fs
|
||||||
APPEND
|
APPEND
|
||||||
)
|
)
|
||||||
|
endif()
|
||||||
|
|
||||||
add_custom_command(
|
add_custom_command(
|
||||||
OUTPUT "${MATERIAL_DIR}/bilateralBlur.filamat"
|
OUTPUT "${MATERIAL_DIR}/bilateralBlur.filamat"
|
||||||
@@ -590,6 +601,10 @@ target_link_libraries(${TARGET} PUBLIC filaflat)
|
|||||||
target_link_libraries(${TARGET} PUBLIC filabridge)
|
target_link_libraries(${TARGET} PUBLIC filabridge)
|
||||||
target_link_libraries(${TARGET} PUBLIC ibl-lite)
|
target_link_libraries(${TARGET} PUBLIC ibl-lite)
|
||||||
|
|
||||||
|
if (FILAMENT_USE_ABSEIL_LOGGING)
|
||||||
|
target_link_libraries(${TARGET} PUBLIC absl::log)
|
||||||
|
endif()
|
||||||
|
|
||||||
if (FILAMENT_ENABLE_FGVIEWER)
|
if (FILAMENT_ENABLE_FGVIEWER)
|
||||||
target_link_libraries(${TARGET} PUBLIC fgviewer)
|
target_link_libraries(${TARGET} PUBLIC fgviewer)
|
||||||
add_definitions(-DFILAMENT_ENABLE_FGVIEWER=1)
|
add_definitions(-DFILAMENT_ENABLE_FGVIEWER=1)
|
||||||
|
|||||||
+5
-4
@@ -92,7 +92,7 @@ Copy your platform's Makefile below into a `Makefile` inside the same directory.
|
|||||||
### Linux
|
### Linux
|
||||||
|
|
||||||
```make
|
```make
|
||||||
FILAMENT_LIBS=-lfilament -lbackend -lbluegl -lbluevk -lfilabridge -lfilaflat -lutils -lgeometry -lsmol-v -lvkshaders -libl
|
FILAMENT_LIBS=-lfilament -lbackend -lbluegl -lbluevk -lfilabridge -lfilaflat -lutils -lgeometry -lsmol-v -lvkshaders -libl -labseil
|
||||||
CC=clang++
|
CC=clang++
|
||||||
|
|
||||||
main: main.o
|
main: main.o
|
||||||
@@ -110,12 +110,13 @@ clean:
|
|||||||
### macOS
|
### macOS
|
||||||
|
|
||||||
```make
|
```make
|
||||||
FILAMENT_LIBS=-lfilament -lbackend -lbluegl -lbluevk -lfilabridge -lfilaflat -lutils -lgeometry -lsmol-v -lvkshaders -libl
|
FILAMENT_LIBS=-lfilament -lbackend -lbluegl -lbluevk -lfilabridge -lfilaflat -lutils -lgeometry -lsmol-v -lvkshaders -libl -labseil
|
||||||
FRAMEWORKS=-framework Cocoa -framework Metal -framework CoreVideo
|
FRAMEWORKS=-framework Cocoa -framework Metal -framework CoreVideo
|
||||||
CC=clang++
|
CC=clang++
|
||||||
|
ARCH ?= $(shell uname -m)
|
||||||
|
|
||||||
main: main.o
|
main: main.o
|
||||||
$(CC) -Llib/x86_64/ main.o $(FILAMENT_LIBS) $(FRAMEWORKS) -o main
|
$(CC) -Llib/$(ARCH)/ main.o $(FILAMENT_LIBS) $(FRAMEWORKS) -o main
|
||||||
|
|
||||||
main.o: main.cpp
|
main.o: main.cpp
|
||||||
$(CC) -Iinclude/ -std=c++17 -c main.cpp
|
$(CC) -Iinclude/ -std=c++17 -c main.cpp
|
||||||
@@ -139,7 +140,7 @@ used to change the run-time library version.
|
|||||||
|
|
||||||
```make
|
```make
|
||||||
FILAMENT_LIBS=filament.lib backend.lib bluegl.lib bluevk.lib filabridge.lib filaflat.lib \
|
FILAMENT_LIBS=filament.lib backend.lib bluegl.lib bluevk.lib filabridge.lib filaflat.lib \
|
||||||
utils.lib geometry.lib smol-v.lib ibl.lib vkshaders.lib
|
utils.lib geometry.lib smol-v.lib ibl.lib vkshaders.lib abseil.lib
|
||||||
CC=cl.exe
|
CC=cl.exe
|
||||||
|
|
||||||
main.exe: main.obj
|
main.exe: main.obj
|
||||||
|
|||||||
@@ -180,8 +180,11 @@ if (FILAMENT_SUPPORTS_VULKAN)
|
|||||||
src/vulkan/VulkanAsyncHandles.h
|
src/vulkan/VulkanAsyncHandles.h
|
||||||
src/vulkan/VulkanBlitter.cpp
|
src/vulkan/VulkanBlitter.cpp
|
||||||
src/vulkan/VulkanBlitter.h
|
src/vulkan/VulkanBlitter.h
|
||||||
src/vulkan/VulkanBuffer.cpp
|
|
||||||
src/vulkan/VulkanBuffer.h
|
src/vulkan/VulkanBuffer.h
|
||||||
|
src/vulkan/VulkanBufferCache.h
|
||||||
|
src/vulkan/VulkanBufferCache.cpp
|
||||||
|
src/vulkan/VulkanBufferProxy.h
|
||||||
|
src/vulkan/VulkanBufferProxy.cpp
|
||||||
src/vulkan/VulkanCommands.cpp
|
src/vulkan/VulkanCommands.cpp
|
||||||
src/vulkan/VulkanCommands.h
|
src/vulkan/VulkanCommands.h
|
||||||
src/vulkan/VulkanConstants.h
|
src/vulkan/VulkanConstants.h
|
||||||
@@ -254,16 +257,38 @@ if (FILAMENT_SUPPORTS_WEBGPU)
|
|||||||
list(APPEND SRCS
|
list(APPEND SRCS
|
||||||
include/backend/platforms/WebGPUPlatform.h
|
include/backend/platforms/WebGPUPlatform.h
|
||||||
src/webgpu/platform/WebGPUPlatform.cpp
|
src/webgpu/platform/WebGPUPlatform.cpp
|
||||||
|
src/webgpu/SpdMipmapGenerator/SpdMipmapGenerator.cpp
|
||||||
|
src/webgpu/WebGPUBufferBase.cpp
|
||||||
|
src/webgpu/WebGPUBufferBase.h
|
||||||
|
src/webgpu/WebGPUBufferObject.cpp
|
||||||
|
src/webgpu/WebGPUBufferObject.h
|
||||||
src/webgpu/WebGPUConstants.h
|
src/webgpu/WebGPUConstants.h
|
||||||
|
src/webgpu/WebGPUDescriptorSet.cpp
|
||||||
|
src/webgpu/WebGPUDescriptorSet.h
|
||||||
|
src/webgpu/WebGPUDescriptorSetLayout.cpp
|
||||||
|
src/webgpu/WebGPUDescriptorSetLayout.h
|
||||||
src/webgpu/WebGPUDriver.cpp
|
src/webgpu/WebGPUDriver.cpp
|
||||||
src/webgpu/WebGPUDriver.h
|
src/webgpu/WebGPUDriver.h
|
||||||
src/webgpu/WebGPUHandles.cpp
|
src/webgpu/WebGPUIndexBuffer.cpp
|
||||||
src/webgpu/WebGPUHandles.h
|
src/webgpu/WebGPUIndexBuffer.h
|
||||||
src/webgpu/WebGPUPipelineCreation.cpp
|
src/webgpu/WebGPUPipelineCreation.cpp
|
||||||
src/webgpu/WebGPUPipelineCreation.h
|
src/webgpu/WebGPUPipelineCreation.h
|
||||||
|
src/webgpu/WebGPUProgram.cpp
|
||||||
|
src/webgpu/WebGPUProgram.h
|
||||||
|
src/webgpu/WebGPURenderPrimitive.h
|
||||||
|
src/webgpu/WebGPURenderTarget.cpp
|
||||||
|
src/webgpu/WebGPURenderTarget.h
|
||||||
|
src/webgpu/WebGPUStrings.h
|
||||||
src/webgpu/WebGPUSwapChain.cpp
|
src/webgpu/WebGPUSwapChain.cpp
|
||||||
src/webgpu/WebGPUSwapChain.h
|
src/webgpu/WebGPUSwapChain.h
|
||||||
src/webgpu/WGPUProgram.cpp
|
src/webgpu/WebGPUTexture.cpp
|
||||||
|
src/webgpu/WebGPUTexture.h
|
||||||
|
src/webgpu/WebGPUTimerQuery.cpp
|
||||||
|
src/webgpu/WebGPUTimerQuery.h
|
||||||
|
src/webgpu/WebGPUVertexBuffer.cpp
|
||||||
|
src/webgpu/WebGPUVertexBuffer.h
|
||||||
|
src/webgpu/WebGPUVertexBufferInfo.cpp
|
||||||
|
src/webgpu/WebGPUVertexBufferInfo.h
|
||||||
)
|
)
|
||||||
if (WIN32)
|
if (WIN32)
|
||||||
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformWindows.cpp)
|
list(APPEND SRCS src/webgpu/platform/WebGPUPlatformWindows.cpp)
|
||||||
@@ -381,6 +406,10 @@ endif()
|
|||||||
target_link_libraries(${TARGET} PUBLIC math)
|
target_link_libraries(${TARGET} PUBLIC math)
|
||||||
target_link_libraries(${TARGET} PUBLIC utils)
|
target_link_libraries(${TARGET} PUBLIC utils)
|
||||||
|
|
||||||
|
if (FILAMENT_USE_ABSEIL_LOGGING)
|
||||||
|
target_link_libraries(${TARGET} PRIVATE absl::log)
|
||||||
|
endif()
|
||||||
|
|
||||||
# Android, iOS, and WebGL do not use bluegl.
|
# Android, iOS, and WebGL do not use bluegl.
|
||||||
if(FILAMENT_SUPPORTS_OPENGL AND NOT IOS AND NOT ANDROID AND NOT WEBGL)
|
if(FILAMENT_SUPPORTS_OPENGL AND NOT IOS AND NOT ANDROID AND NOT WEBGL)
|
||||||
target_link_libraries(${TARGET} PRIVATE bluegl)
|
target_link_libraries(${TARGET} PRIVATE bluegl)
|
||||||
|
|||||||
@@ -495,18 +495,12 @@ struct DescriptorSetLayoutBinding {
|
|||||||
DescriptorFlags flags = DescriptorFlags::NONE;
|
DescriptorFlags flags = DescriptorFlags::NONE;
|
||||||
uint16_t count = 0;
|
uint16_t count = 0;
|
||||||
|
|
||||||
// TODO: uncomment when needed. Note that this class is used as hash key. We need to ensure
|
|
||||||
// no uninitialized padding bytes.
|
|
||||||
// uint8_t externalSamplerDataIndex = EXTERNAL_SAMPLER_DATA_INDEX_UNUSED;
|
|
||||||
|
|
||||||
friend bool operator==(DescriptorSetLayoutBinding const& lhs,
|
friend bool operator==(DescriptorSetLayoutBinding const& lhs,
|
||||||
DescriptorSetLayoutBinding const& rhs) noexcept {
|
DescriptorSetLayoutBinding const& rhs) noexcept {
|
||||||
return lhs.type == rhs.type &&
|
return lhs.type == rhs.type &&
|
||||||
lhs.flags == rhs.flags &&
|
lhs.flags == rhs.flags &&
|
||||||
lhs.count == rhs.count &&
|
lhs.count == rhs.count &&
|
||||||
lhs.stageFlags == rhs.stageFlags;
|
lhs.stageFlags == rhs.stageFlags;
|
||||||
// lhs.stageFlags == rhs.stageFlags &&
|
|
||||||
// lhs.externalSamplerDataIndex == rhs.externalSamplerDataIndex;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -1254,26 +1248,6 @@ enum class SamplerCompareFunc : uint8_t {
|
|||||||
N //!< Never. The depth / stencil test always fails.
|
N //!< Never. The depth / stencil test always fails.
|
||||||
};
|
};
|
||||||
|
|
||||||
//! this API is copied from (and only applies to) the Vulkan spec.
|
|
||||||
//! These specify YUV to RGB conversions.
|
|
||||||
enum class SamplerYcbcrModelConversion : uint8_t {
|
|
||||||
RGB_IDENTITY = 0,
|
|
||||||
YCBCR_IDENTITY = 1,
|
|
||||||
YCBCR_709 = 2,
|
|
||||||
YCBCR_601 = 3,
|
|
||||||
YCBCR_2020 = 4,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class SamplerYcbcrRange : uint8_t {
|
|
||||||
ITU_FULL = 0,
|
|
||||||
ITU_NARROW = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
enum class ChromaLocation : uint8_t {
|
|
||||||
COSITED_EVEN = 0,
|
|
||||||
MIDPOINT = 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
//! Sampler parameters
|
//! Sampler parameters
|
||||||
struct SamplerParams { // NOLINT
|
struct SamplerParams { // NOLINT
|
||||||
SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST)
|
SamplerMagFilter filterMag : 1; //!< magnification filter (NEAREST)
|
||||||
@@ -1342,94 +1316,9 @@ static_assert(sizeof(SamplerParams) == 4);
|
|||||||
static_assert(sizeof(SamplerParams) <= sizeof(uint64_t),
|
static_assert(sizeof(SamplerParams) <= sizeof(uint64_t),
|
||||||
"SamplerParams must be no more than 64 bits");
|
"SamplerParams must be no more than 64 bits");
|
||||||
|
|
||||||
//! Sampler parameters
|
|
||||||
struct SamplerYcbcrConversion {// NOLINT
|
|
||||||
SamplerYcbcrModelConversion ycbcrModel : 4;
|
|
||||||
TextureSwizzle r : 4;
|
|
||||||
TextureSwizzle g : 4;
|
|
||||||
TextureSwizzle b : 4;
|
|
||||||
TextureSwizzle a : 4;
|
|
||||||
SamplerYcbcrRange ycbcrRange : 1;
|
|
||||||
ChromaLocation xChromaOffset : 1;
|
|
||||||
ChromaLocation yChromaOffset : 1;
|
|
||||||
SamplerMagFilter chromaFilter : 1;
|
|
||||||
uint8_t padding;
|
|
||||||
|
|
||||||
struct Hasher {
|
|
||||||
size_t operator()(const SamplerYcbcrConversion p) const noexcept {
|
|
||||||
// we don't use std::hash<> here, so we don't have to include <functional>
|
|
||||||
return *reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&p));
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct EqualTo {
|
|
||||||
bool operator()(SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs) const noexcept {
|
|
||||||
assert_invariant(lhs.padding == 0);
|
|
||||||
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
|
|
||||||
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
|
|
||||||
return *pLhs == *pRhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
struct LessThan {
|
|
||||||
bool operator()(SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs) const noexcept {
|
|
||||||
assert_invariant(lhs.padding == 0);
|
|
||||||
auto* pLhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&lhs));
|
|
||||||
auto* pRhs = reinterpret_cast<uint32_t const*>(reinterpret_cast<char const*>(&rhs));
|
|
||||||
return *pLhs < *pRhs;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
private:
|
|
||||||
friend bool operator == (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
|
||||||
noexcept {
|
|
||||||
return SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
|
|
||||||
}
|
|
||||||
friend bool operator != (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
|
||||||
noexcept {
|
|
||||||
return !SamplerYcbcrConversion::EqualTo{}(lhs, rhs);
|
|
||||||
}
|
|
||||||
friend bool operator < (SamplerYcbcrConversion lhs, SamplerYcbcrConversion rhs)
|
|
||||||
noexcept {
|
|
||||||
return SamplerYcbcrConversion::LessThan{}(lhs, rhs);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
static_assert(sizeof(SamplerYcbcrConversion) == 4);
|
|
||||||
|
|
||||||
static_assert(sizeof(SamplerYcbcrConversion) <= sizeof(uint64_t),
|
|
||||||
"SamplerYcbcrConversion must be no more than 64 bits");
|
|
||||||
|
|
||||||
struct ExternalSamplerDatum {
|
|
||||||
ExternalSamplerDatum(SamplerYcbcrConversion ycbcr, SamplerParams spm, uint32_t extFmt)
|
|
||||||
: YcbcrConversion(ycbcr),
|
|
||||||
samplerParams(spm),
|
|
||||||
externalFormat(extFmt) {}
|
|
||||||
bool operator==(ExternalSamplerDatum const& rhs) const {
|
|
||||||
return (YcbcrConversion == rhs.YcbcrConversion && samplerParams == rhs.samplerParams &&
|
|
||||||
externalFormat == rhs.externalFormat);
|
|
||||||
}
|
|
||||||
struct EqualTo {
|
|
||||||
bool operator()(const ExternalSamplerDatum& lhs,
|
|
||||||
const ExternalSamplerDatum& rhs) const noexcept {
|
|
||||||
return (lhs.YcbcrConversion == rhs.YcbcrConversion &&
|
|
||||||
lhs.samplerParams == rhs.samplerParams &&
|
|
||||||
lhs.externalFormat == rhs.externalFormat);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
SamplerYcbcrConversion YcbcrConversion;
|
|
||||||
SamplerParams samplerParams;
|
|
||||||
uint32_t externalFormat;
|
|
||||||
};
|
|
||||||
// No implicit padding allowed due to it being a hash key.
|
|
||||||
static_assert(sizeof(ExternalSamplerDatum) == 12);
|
|
||||||
|
|
||||||
struct DescriptorSetLayout {
|
struct DescriptorSetLayout {
|
||||||
std::variant<utils::StaticString, utils::CString, std::monostate> label;
|
std::variant<utils::StaticString, utils::CString, std::monostate> label;
|
||||||
utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings;
|
utils::FixedCapacityVector<DescriptorSetLayoutBinding> bindings;
|
||||||
|
|
||||||
// TODO: uncomment when needed
|
|
||||||
// utils::FixedCapacityVector<ExternalSamplerDatum> externalSamplerData;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
//! blending equation function
|
//! blending equation function
|
||||||
|
|||||||
@@ -149,6 +149,13 @@ public:
|
|||||||
* - PlatformEGLAndroid
|
* - PlatformEGLAndroid
|
||||||
*/
|
*/
|
||||||
bool assertNativeWindowIsValid = false;
|
bool assertNativeWindowIsValid = false;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The action to take if a Drawable cannot be acquired. If true, the
|
||||||
|
* frame is aborted instead of panic. This is only supported for:
|
||||||
|
* - PlatformMetal
|
||||||
|
*/
|
||||||
|
bool metalDisablePanicOnDrawableFailure = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
Platform() noexcept;
|
Platform() noexcept;
|
||||||
|
|||||||
@@ -199,7 +199,7 @@ public:
|
|||||||
*/
|
*/
|
||||||
virtual bool makeCurrent(ContextType type,
|
virtual bool makeCurrent(ContextType type,
|
||||||
SwapChain* UTILS_NONNULL drawSwapChain,
|
SwapChain* UTILS_NONNULL drawSwapChain,
|
||||||
SwapChain* UTILS_NONNULL readSwapChain) noexcept = 0;
|
SwapChain* UTILS_NONNULL readSwapChain) = 0;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the driver to make the OpenGL context active on the calling thread and bind
|
* Called by the driver to make the OpenGL context active on the calling thread and bind
|
||||||
@@ -219,7 +219,7 @@ public:
|
|||||||
SwapChain* UTILS_NONNULL drawSwapChain,
|
SwapChain* UTILS_NONNULL drawSwapChain,
|
||||||
SwapChain* UTILS_NONNULL readSwapChain,
|
SwapChain* UTILS_NONNULL readSwapChain,
|
||||||
utils::Invocable<void()> preContextChange,
|
utils::Invocable<void()> preContextChange,
|
||||||
utils::Invocable<void(size_t index)> postContextChange) noexcept;
|
utils::Invocable<void(size_t index)> postContextChange);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Called by the backend just before calling commit()
|
* Called by the backend just before calling commit()
|
||||||
|
|||||||
@@ -58,7 +58,7 @@ protected:
|
|||||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) override;
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||||
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
void destroyExternalImageTexture(ExternalTexture* texture) noexcept override;
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ public:
|
|||||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) override;
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
|
|
||||||
ExternalTexture* createExternalImageTexture() noexcept override;
|
ExternalTexture* createExternalImageTexture() noexcept override;
|
||||||
|
|||||||
@@ -109,11 +109,11 @@ protected:
|
|||||||
|
|
||||||
bool makeCurrent(ContextType type,
|
bool makeCurrent(ContextType type,
|
||||||
SwapChain* drawSwapChain,
|
SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept override;
|
SwapChain* readSwapChain) override;
|
||||||
|
|
||||||
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
|
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
|
||||||
utils::Invocable<void()> preContextChange,
|
utils::Invocable<void()> preContextChange,
|
||||||
utils::Invocable<void(size_t index)> postContextChange) noexcept override;
|
utils::Invocable<void(size_t index)> postContextChange) override;
|
||||||
|
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
|
|
||||||
@@ -128,7 +128,7 @@ protected:
|
|||||||
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
bool setExternalImage(ExternalImageHandleRef externalImage, ExternalTexture* texture) noexcept override;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Logs glGetError() to slog.e
|
* Logs glGetError() to LOG(ERROR)
|
||||||
* @param name a string giving some context on the error. Typically __func__.
|
* @param name a string giving some context on the error. Typically __func__.
|
||||||
*/
|
*/
|
||||||
static void logEglError(const char* name) noexcept;
|
static void logEglError(const char* name) noexcept;
|
||||||
@@ -148,12 +148,12 @@ protected:
|
|||||||
EGLContext getContextForType(ContextType type) const noexcept;
|
EGLContext getContextForType(ContextType type) const noexcept;
|
||||||
|
|
||||||
// makes the draw and read surface current without changing the current context
|
// makes the draw and read surface current without changing the current context
|
||||||
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept {
|
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) {
|
||||||
return egl.makeCurrent(drawSurface, readSurface);
|
return egl.makeCurrent(drawSurface, readSurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
// makes context current and set draw and read surfaces to EGL_NO_SURFACE
|
// makes context current and set draw and read surfaces to EGL_NO_SURFACE
|
||||||
EGLBoolean makeCurrent(EGLContext context) noexcept {
|
EGLBoolean makeCurrent(EGLContext context) {
|
||||||
return egl.makeCurrent(context, mEGLDummySurface, mEGLDummySurface);
|
return egl.makeCurrent(context, mEGLDummySurface, mEGLDummySurface);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,9 +211,9 @@ private:
|
|||||||
public:
|
public:
|
||||||
explicit EGL(EGLDisplay& dpy) : mEGLDisplay(dpy) {}
|
explicit EGL(EGLDisplay& dpy) : mEGLDisplay(dpy) {}
|
||||||
EGLBoolean makeCurrent(EGLContext context,
|
EGLBoolean makeCurrent(EGLContext context,
|
||||||
EGLSurface drawSurface, EGLSurface readSurface) noexcept;
|
EGLSurface drawSurface, EGLSurface readSurface);
|
||||||
|
|
||||||
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept {
|
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) {
|
||||||
return makeCurrent(mCurrentContext, drawSurface, readSurface);
|
return makeCurrent(mCurrentContext, drawSurface, readSurface);
|
||||||
}
|
}
|
||||||
} egl{ mEGLDisplay };
|
} egl{ mEGLDisplay };
|
||||||
|
|||||||
@@ -127,7 +127,7 @@ protected:
|
|||||||
protected:
|
protected:
|
||||||
bool makeCurrent(ContextType type,
|
bool makeCurrent(ContextType type,
|
||||||
SwapChain* drawSwapChain,
|
SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept override;
|
SwapChain* readSwapChain) override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
struct InitializeJvmForPerformanceManagerIfNeeded {
|
struct InitializeJvmForPerformanceManagerIfNeeded {
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ protected:
|
|||||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) override;
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -56,7 +56,7 @@ protected:
|
|||||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept override;
|
SwapChain* readSwapChain) override;
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|||||||
@@ -53,7 +53,7 @@ protected:
|
|||||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) override;
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ protected:
|
|||||||
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
|
||||||
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
|
||||||
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
void destroySwapChain(SwapChain* swapChain) noexcept override;
|
||||||
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
|
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) override;
|
||||||
void commit(SwapChain* swapChain) noexcept override;
|
void commit(SwapChain* swapChain) noexcept override;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include <webgpu/webgpu_cpp.h>
|
#include <webgpu/webgpu_cpp.h>
|
||||||
|
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <vector>
|
||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
@@ -56,6 +57,10 @@ protected:
|
|||||||
const Platform::DriverConfig& driverConfig) noexcept override;
|
const Platform::DriverConfig& driverConfig) noexcept override;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
// returns adapter request option variations applicable for the particular
|
||||||
|
// platform
|
||||||
|
[[nodiscard]] static std::vector<wgpu::RequestAdapterOptions> getAdapterOptions();
|
||||||
|
|
||||||
// we may consider having the driver own this in the future
|
// we may consider having the driver own this in the future
|
||||||
wgpu::Instance mInstance;
|
wgpu::Instance mInstance;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -72,7 +72,7 @@ public:
|
|||||||
Range getBuffer() noexcept;
|
Range getBuffer() noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void* alloc(size_t size) noexcept;
|
void* alloc(size_t size);
|
||||||
void dealloc() noexcept;
|
void dealloc() noexcept;
|
||||||
|
|
||||||
// pointer to the beginning of the circular buffer (constant)
|
// pointer to the beginning of the circular buffer (constant)
|
||||||
|
|||||||
@@ -76,7 +76,7 @@ public:
|
|||||||
|
|
||||||
// all commands buffers (Slices) written to this point are returned by waitForCommand(). This
|
// all commands buffers (Slices) written to this point are returned by waitForCommand(). This
|
||||||
// call blocks until the CircularBuffer has at least mRequiredSize bytes available.
|
// call blocks until the CircularBuffer has at least mRequiredSize bytes available.
|
||||||
void flush() noexcept;
|
void flush();
|
||||||
|
|
||||||
// returns from waitForCommands() immediately.
|
// returns from waitForCommands() immediately.
|
||||||
void requestExit();
|
void requestExit();
|
||||||
|
|||||||
@@ -39,7 +39,7 @@
|
|||||||
#define FILAMENT_DEBUG_COMMANDS_NONE 0x0
|
#define FILAMENT_DEBUG_COMMANDS_NONE 0x0
|
||||||
// Command debugging enabled. No logging by default.
|
// Command debugging enabled. No logging by default.
|
||||||
#define FILAMENT_DEBUG_COMMANDS_ENABLE 0x1
|
#define FILAMENT_DEBUG_COMMANDS_ENABLE 0x1
|
||||||
// Command debugging enabled. Every command logged to slog.d
|
// Command debugging enabled. Every command logged to DLOG(INFO)
|
||||||
#define FILAMENT_DEBUG_COMMANDS_LOG 0x2
|
#define FILAMENT_DEBUG_COMMANDS_LOG 0x2
|
||||||
// Command debugging enabled. Every command logged to systrace
|
// Command debugging enabled. Every command logged to systrace
|
||||||
#define FILAMENT_DEBUG_COMMANDS_SYSTRACE 0x4
|
#define FILAMENT_DEBUG_COMMANDS_SYSTRACE 0x4
|
||||||
|
|||||||
@@ -27,13 +27,13 @@ namespace filament {
|
|||||||
class VirtualMachineEnv {
|
class VirtualMachineEnv {
|
||||||
public:
|
public:
|
||||||
// must be called before VirtualMachineEnv::get() from a thread that is attached to the JavaVM
|
// must be called before VirtualMachineEnv::get() from a thread that is attached to the JavaVM
|
||||||
static jint JNI_OnLoad(JavaVM* vm) noexcept;
|
static jint JNI_OnLoad(JavaVM* vm);
|
||||||
|
|
||||||
// must be called on backend thread
|
// must be called on backend thread
|
||||||
static VirtualMachineEnv& get() noexcept;
|
static VirtualMachineEnv& get() noexcept;
|
||||||
|
|
||||||
// can be called from any thread that already has a JniEnv
|
// can be called from any thread that already has a JniEnv
|
||||||
static JNIEnv* getThreadEnvironment() noexcept;
|
static JNIEnv* getThreadEnvironment();
|
||||||
|
|
||||||
// must be called from the backend thread
|
// must be called from the backend thread
|
||||||
JNIEnv* getEnvironment() noexcept {
|
JNIEnv* getEnvironment() noexcept {
|
||||||
@@ -49,7 +49,7 @@ public:
|
|||||||
private:
|
private:
|
||||||
explicit VirtualMachineEnv(JavaVM* vm) noexcept;
|
explicit VirtualMachineEnv(JavaVM* vm) noexcept;
|
||||||
~VirtualMachineEnv() noexcept;
|
~VirtualMachineEnv() noexcept;
|
||||||
JNIEnv* getEnvironmentSlow() noexcept;
|
JNIEnv* getEnvironmentSlow();
|
||||||
|
|
||||||
static utils::Mutex sLock;
|
static utils::Mutex sLock;
|
||||||
static JavaVM* sVirtualMachine;
|
static JavaVM* sVirtualMachine;
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include "private/backend/CircularBuffer.h"
|
#include "private/backend/CircularBuffer.h"
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/architecture.h>
|
#include <utils/architecture.h>
|
||||||
#include <utils/ashmem.h>
|
#include <utils/ashmem.h>
|
||||||
@@ -65,7 +65,7 @@ CircularBuffer::~CircularBuffer() noexcept {
|
|||||||
// to each others and a special case in circularize()
|
// to each others and a special case in circularize()
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
void* CircularBuffer::alloc(size_t size) noexcept {
|
void* CircularBuffer::alloc(size_t size) {
|
||||||
#if HAS_MMAP
|
#if HAS_MMAP
|
||||||
void* data = nullptr;
|
void* data = nullptr;
|
||||||
void* vaddr = MAP_FAILED;
|
void* vaddr = MAP_FAILED;
|
||||||
@@ -127,7 +127,7 @@ void* CircularBuffer::alloc(size_t size) noexcept {
|
|||||||
"couldn't allocate " << (size * 2 / 1024) <<
|
"couldn't allocate " << (size * 2 / 1024) <<
|
||||||
" KiB of virtual address space for the command buffer";
|
" KiB of virtual address space for the command buffer";
|
||||||
|
|
||||||
slog.w << "Using 'soft' CircularBuffer (" << (size * 2 / 1024) << " KiB)" << io::endl;
|
LOG(WARNING) << "Using 'soft' CircularBuffer (" << (size * 2 / 1024) << " KiB)";
|
||||||
|
|
||||||
// guard page at the end
|
// guard page at the end
|
||||||
void* guard = (void*)(uintptr_t(data) + size * 2);
|
void* guard = (void*)(uintptr_t(data) + size * 2);
|
||||||
|
|||||||
@@ -20,12 +20,12 @@
|
|||||||
|
|
||||||
#include <private/utils/Tracing.h>
|
#include <private/utils/Tracing.h>
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/Mutex.h>
|
#include <utils/Mutex.h>
|
||||||
#include <utils/ostream.h>
|
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
@@ -53,18 +53,18 @@ CommandBufferQueue::~CommandBufferQueue() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferQueue::requestExit() {
|
void CommandBufferQueue::requestExit() {
|
||||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
std::lock_guard const lock(mLock);
|
||||||
mExitRequested = EXIT_REQUESTED;
|
mExitRequested = EXIT_REQUESTED;
|
||||||
mCondition.notify_one();
|
mCondition.notify_one();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferQueue::isPaused() const noexcept {
|
bool CommandBufferQueue::isPaused() const noexcept {
|
||||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
std::lock_guard const lock(mLock);
|
||||||
return mPaused;
|
return mPaused;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CommandBufferQueue::setPaused(bool paused) {
|
void CommandBufferQueue::setPaused(bool paused) {
|
||||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
std::lock_guard const lock(mLock);
|
||||||
if (paused) {
|
if (paused) {
|
||||||
mPaused = true;
|
mPaused = true;
|
||||||
} else {
|
} else {
|
||||||
@@ -74,12 +74,12 @@ void CommandBufferQueue::setPaused(bool paused) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool CommandBufferQueue::isExitRequested() const {
|
bool CommandBufferQueue::isExitRequested() const {
|
||||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
std::lock_guard const lock(mLock);
|
||||||
return (bool)mExitRequested;
|
return bool(mExitRequested);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void CommandBufferQueue::flush() noexcept {
|
void CommandBufferQueue::flush() {
|
||||||
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
FILAMENT_TRACING_CALL(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||||
|
|
||||||
CircularBuffer& circularBuffer = mCircularBuffer;
|
CircularBuffer& circularBuffer = mCircularBuffer;
|
||||||
@@ -103,7 +103,7 @@ void CommandBufferQueue::flush() noexcept {
|
|||||||
static_cast<char const*>(begin), static_cast<char const*>(end));
|
static_cast<char const*>(begin), static_cast<char const*>(end));
|
||||||
|
|
||||||
|
|
||||||
std::unique_lock<utils::Mutex> lock(mLock);
|
std::unique_lock lock(mLock);
|
||||||
|
|
||||||
// circular buffer is too small, we corrupted the stream
|
// circular buffer is too small, we corrupted the stream
|
||||||
FILAMENT_CHECK_POSTCONDITION(used <= mFreeSpace) <<
|
FILAMENT_CHECK_POSTCONDITION(used <= mFreeSpace) <<
|
||||||
@@ -121,11 +121,10 @@ void CommandBufferQueue::flush() noexcept {
|
|||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
size_t const totalUsed = circularBuffer.size() - mFreeSpace;
|
size_t const totalUsed = circularBuffer.size() - mFreeSpace;
|
||||||
slog.d << "CommandStream used too much space (will block): "
|
DLOG(INFO) << "CommandStream used too much space (will block): "
|
||||||
<< "needed space " << requiredSize << " out of " << mFreeSpace
|
<< "needed space " << requiredSize << " out of " << mFreeSpace
|
||||||
<< ", totalUsed=" << totalUsed << ", current=" << used
|
<< ", totalUsed=" << totalUsed << ", current=" << used
|
||||||
<< ", queue size=" << mCommandBuffersToExecute.size() << " buffers"
|
<< ", queue size=" << mCommandBuffersToExecute.size() << " buffers";
|
||||||
<< io::endl;
|
|
||||||
|
|
||||||
mHighWatermark = std::max(mHighWatermark, totalUsed);
|
mHighWatermark = std::max(mHighWatermark, totalUsed);
|
||||||
#endif
|
#endif
|
||||||
@@ -147,7 +146,7 @@ std::vector<CommandBufferQueue::Range> CommandBufferQueue::waitForCommands() con
|
|||||||
if (!UTILS_HAS_THREADING) {
|
if (!UTILS_HAS_THREADING) {
|
||||||
return std::move(mCommandBuffersToExecute);
|
return std::move(mCommandBuffersToExecute);
|
||||||
}
|
}
|
||||||
std::unique_lock<utils::Mutex> lock(mLock);
|
std::unique_lock lock(mLock);
|
||||||
while ((mCommandBuffersToExecute.empty() || mPaused) && !mExitRequested) {
|
while ((mCommandBuffersToExecute.empty() || mPaused) && !mExitRequested) {
|
||||||
mCondition.wait(lock);
|
mCondition.wait(lock);
|
||||||
}
|
}
|
||||||
@@ -157,7 +156,7 @@ std::vector<CommandBufferQueue::Range> CommandBufferQueue::waitForCommands() con
|
|||||||
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Range const& buffer) {
|
void CommandBufferQueue::releaseBuffer(CommandBufferQueue::Range const& buffer) {
|
||||||
size_t const used = std::distance(
|
size_t const used = std::distance(
|
||||||
static_cast<char const*>(buffer.begin), static_cast<char const*>(buffer.end));
|
static_cast<char const*>(buffer.begin), static_cast<char const*>(buffer.end));
|
||||||
std::lock_guard<utils::Mutex> const lock(mLock);
|
std::lock_guard const lock(mLock);
|
||||||
mFreeSpace += used;
|
mFreeSpace += used;
|
||||||
mCondition.notify_one();
|
mCondition.notify_one();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -22,10 +22,13 @@
|
|||||||
#include <utils/CallStack.h>
|
#include <utils/CallStack.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <private/utils/Tracing.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/ostream.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Profiler.h>
|
#include <utils/Profiler.h>
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
#include <utils/ostream.h>
|
||||||
|
#include <utils/sstream.h>
|
||||||
|
|
||||||
#include <cstddef>
|
#include <cstddef>
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -129,9 +132,10 @@ void CommandType<void (Driver::*)(ARGS...)>::Command<METHOD>::log(std::index_seq
|
|||||||
#if DEBUG_COMMAND_STREAM
|
#if DEBUG_COMMAND_STREAM
|
||||||
static_assert(UTILS_HAS_RTTI, "DEBUG_COMMAND_STREAM can only be used with RTTI");
|
static_assert(UTILS_HAS_RTTI, "DEBUG_COMMAND_STREAM can only be used with RTTI");
|
||||||
std::string command = utils::CallStack::demangleTypeName(typeid(Command).name()).c_str();
|
std::string command = utils::CallStack::demangleTypeName(typeid(Command).name()).c_str();
|
||||||
slog.d << extractMethodName(command) << " : size=" << sizeof(Command) << "\n\t";
|
DLOG(INFO) << extractMethodName(command) << " : size=" << sizeof(Command);
|
||||||
printParameterPack(slog.d, std::get<I>(mArgs)...);
|
utils::io::sstream parameterPack;
|
||||||
slog.d << io::endl;
|
printParameterPack(parameterPack, std::get<I>(mArgs)...);
|
||||||
|
DLOG(INFO) << "\t" << parameterPack.c_str();
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -25,9 +25,9 @@
|
|||||||
|
|
||||||
#include <private/utils/Tracing.h>
|
#include <private/utils/Tracing.h>
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#include <math/half.h>
|
#include <math/half.h>
|
||||||
@@ -149,7 +149,7 @@ void DriverBase::scheduleRelease(AcquiredImage const& image) noexcept {
|
|||||||
void DriverBase::debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept {
|
void DriverBase::debugCommandBegin(CommandStream* cmds, bool synchronous, const char* methodName) noexcept {
|
||||||
if constexpr (bool(FILAMENT_DEBUG_COMMANDS > FILAMENT_DEBUG_COMMANDS_NONE)) {
|
if constexpr (bool(FILAMENT_DEBUG_COMMANDS > FILAMENT_DEBUG_COMMANDS_NONE)) {
|
||||||
if constexpr (bool(FILAMENT_DEBUG_COMMANDS & FILAMENT_DEBUG_COMMANDS_LOG)) {
|
if constexpr (bool(FILAMENT_DEBUG_COMMANDS & FILAMENT_DEBUG_COMMANDS_LOG)) {
|
||||||
utils::slog.d << methodName << utils::io::endl;
|
DLOG(INFO) << methodName;
|
||||||
}
|
}
|
||||||
if constexpr (bool(FILAMENT_DEBUG_COMMANDS & FILAMENT_DEBUG_COMMANDS_SYSTRACE)) {
|
if constexpr (bool(FILAMENT_DEBUG_COMMANDS & FILAMENT_DEBUG_COMMANDS_SYSTRACE)) {
|
||||||
FILAMENT_TRACING_CONTEXT(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
FILAMENT_TRACING_CONTEXT(FILAMENT_TRACING_CATEGORY_FILAMENT);
|
||||||
|
|||||||
@@ -20,7 +20,7 @@
|
|||||||
|
|
||||||
#include <utils/Allocator.h>
|
#include <utils/Allocator.h>
|
||||||
#include <utils/CString.h>
|
#include <utils/CString.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
@@ -57,8 +57,8 @@ HandleAllocator<P0, P1, P2>::Allocator::Allocator(AreaPolicy::HeapArea const& ar
|
|||||||
size_t const maxHeapSize = std::min(area.size(), HANDLE_INDEX_MASK * getAlignment());
|
size_t const maxHeapSize = std::min(area.size(), HANDLE_INDEX_MASK * getAlignment());
|
||||||
|
|
||||||
if (UTILS_UNLIKELY(maxHeapSize != area.size())) {
|
if (UTILS_UNLIKELY(maxHeapSize != area.size())) {
|
||||||
slog.w << "HandleAllocator heap size reduced to "
|
LOG(WARNING) << "HandleAllocator heap size reduced to " << maxHeapSize << " from "
|
||||||
<< maxHeapSize << " from " << area.size() << io::endl;
|
<< area.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
// make sure we start with a clean arena. This is needed to ensure that all blocks start
|
// make sure we start with a clean arena. This is needed to ensure that all blocks start
|
||||||
|
|||||||
@@ -50,7 +50,7 @@ JavaVM* VirtualMachineEnv::getVirtualMachine() {
|
|||||||
*/
|
*/
|
||||||
UTILS_PUBLIC
|
UTILS_PUBLIC
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
jint VirtualMachineEnv::JNI_OnLoad(JavaVM* vm) noexcept {
|
jint VirtualMachineEnv::JNI_OnLoad(JavaVM* vm) {
|
||||||
std::lock_guard const lock(sLock);
|
std::lock_guard const lock(sLock);
|
||||||
if (sVirtualMachine) {
|
if (sVirtualMachine) {
|
||||||
// It doesn't make sense for JNI_OnLoad() to be called more than once
|
// It doesn't make sense for JNI_OnLoad() to be called more than once
|
||||||
@@ -77,7 +77,7 @@ VirtualMachineEnv& VirtualMachineEnv::get() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
JNIEnv* VirtualMachineEnv::getThreadEnvironment() noexcept {
|
JNIEnv* VirtualMachineEnv::getThreadEnvironment() {
|
||||||
JavaVM* const vm = getVirtualMachine();
|
JavaVM* const vm = getVirtualMachine();
|
||||||
JNIEnv* env = nullptr;
|
JNIEnv* env = nullptr;
|
||||||
jint const result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
jint const result = vm->GetEnv(reinterpret_cast<void**>(&env), JNI_VERSION_1_6);
|
||||||
@@ -101,7 +101,7 @@ VirtualMachineEnv::~VirtualMachineEnv() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() noexcept {
|
JNIEnv* VirtualMachineEnv::getEnvironmentSlow() {
|
||||||
FILAMENT_CHECK_PRECONDITION(mVirtualMachine)
|
FILAMENT_CHECK_PRECONDITION(mVirtualMachine)
|
||||||
<< "JNI_OnLoad() has not been called";
|
<< "JNI_OnLoad() has not been called";
|
||||||
|
|
||||||
|
|||||||
@@ -19,8 +19,8 @@
|
|||||||
#include "MetalContext.h"
|
#include "MetalContext.h"
|
||||||
#include "MetalUtils.h"
|
#include "MetalUtils.h"
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
@@ -323,7 +323,7 @@ id<MTLFunction> MetalBlitter::compileFragmentFunction(BlitFunctionKey key) const
|
|||||||
if (!library || !function) {
|
if (!library || !function) {
|
||||||
if (error) {
|
if (error) {
|
||||||
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
utils::slog.e << description << utils::io::endl;
|
LOG(ERROR) << description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FILAMENT_CHECK_POSTCONDITION(library && function)
|
FILAMENT_CHECK_POSTCONDITION(library && function)
|
||||||
@@ -349,7 +349,7 @@ id<MTLFunction> MetalBlitter::getBlitVertexFunction() {
|
|||||||
if (!library || !function) {
|
if (!library || !function) {
|
||||||
if (error) {
|
if (error) {
|
||||||
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
utils::slog.e << description << utils::io::endl;
|
LOG(ERROR) << description;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
FILAMENT_CHECK_POSTCONDITION(library && function)
|
FILAMENT_CHECK_POSTCONDITION(library && function)
|
||||||
|
|||||||
@@ -18,8 +18,8 @@
|
|||||||
|
|
||||||
#include "MetalContext.h"
|
#include "MetalContext.h"
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/trap.h>
|
#include <utils/trap.h>
|
||||||
|
|
||||||
#include <thread>
|
#include <thread>
|
||||||
@@ -77,8 +77,7 @@ void MetalBufferPool::releaseBuffer(MetalBufferPoolEntry const *stage) noexcept
|
|||||||
|
|
||||||
auto iter = mUsedStages.find(stage);
|
auto iter = mUsedStages.find(stage);
|
||||||
if (iter == mUsedStages.end()) {
|
if (iter == mUsedStages.end()) {
|
||||||
utils::slog.e << "Unknown Metal buffer: " << stage->capacity << " bytes"
|
LOG(ERROR) << "Unknown Metal buffer: " << stage->capacity << " bytes";
|
||||||
<< utils::io::endl;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
stage->lastAccessed = mCurrentFrame;
|
stage->lastAccessed = mCurrentFrame;
|
||||||
|
|||||||
@@ -18,8 +18,9 @@
|
|||||||
|
|
||||||
#include "MetalHandles.h"
|
#include "MetalHandles.h"
|
||||||
|
|
||||||
#include <utils/debug.h>
|
|
||||||
#include <utils/FixedCapacityVector.h>
|
#include <utils/FixedCapacityVector.h>
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/debug.h>
|
||||||
|
|
||||||
#include <utility>
|
#include <utility>
|
||||||
|
|
||||||
@@ -112,8 +113,8 @@ id<MTLCommandBuffer> getPendingCommandBuffer(MetalContext* context) {
|
|||||||
auto errorCode = (MTLCommandBufferError)buffer.error.code;
|
auto errorCode = (MTLCommandBufferError)buffer.error.code;
|
||||||
if (@available(macOS 11.0, *)) {
|
if (@available(macOS 11.0, *)) {
|
||||||
if (errorCode == MTLCommandBufferErrorMemoryless) {
|
if (errorCode == MTLCommandBufferErrorMemoryless) {
|
||||||
utils::slog.w << "Metal: memoryless geometry limit reached. "
|
LOG(WARNING) << "Metal: memoryless geometry limit reached. Continuing with private "
|
||||||
"Continuing with private storage mode." << utils::io::endl;
|
"storage mode.";
|
||||||
context->memorylessLimitsReached = true;
|
context->memorylessLimitsReached = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -38,10 +38,10 @@
|
|||||||
#include <Metal/Metal.h>
|
#include <Metal/Metal.h>
|
||||||
#include <QuartzCore/QuartzCore.h>
|
#include <QuartzCore/QuartzCore.h>
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Invocable.h>
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/sstream.h>
|
#include <utils/sstream.h>
|
||||||
#include <utils/Invocable.h>
|
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
|
|
||||||
@@ -78,20 +78,18 @@ Driver* MetalDriverFactory::create(PlatformMetal* const platform, const Platform
|
|||||||
// MetalVertexBufferInfo : 552 moderate
|
// MetalVertexBufferInfo : 552 moderate
|
||||||
// -- less than or equal to 552 bytes
|
// -- less than or equal to 552 bytes
|
||||||
|
|
||||||
utils::slog.d
|
DLOG(INFO) << "MetalSwapChain: " << sizeof(MetalSwapChain);
|
||||||
<< "\nMetalSwapChain: " << sizeof(MetalSwapChain)
|
DLOG(INFO) << "MetalBufferObject: " << sizeof(MetalBufferObject);
|
||||||
<< "\nMetalBufferObject: " << sizeof(MetalBufferObject)
|
DLOG(INFO) << "MetalVertexBuffer: " << sizeof(MetalVertexBuffer);
|
||||||
<< "\nMetalVertexBuffer: " << sizeof(MetalVertexBuffer)
|
DLOG(INFO) << "MetalVertexBufferInfo: " << sizeof(MetalVertexBufferInfo);
|
||||||
<< "\nMetalVertexBufferInfo: " << sizeof(MetalVertexBufferInfo)
|
DLOG(INFO) << "MetalIndexBuffer: " << sizeof(MetalIndexBuffer);
|
||||||
<< "\nMetalIndexBuffer: " << sizeof(MetalIndexBuffer)
|
DLOG(INFO) << "MetalRenderPrimitive: " << sizeof(MetalRenderPrimitive);
|
||||||
<< "\nMetalRenderPrimitive: " << sizeof(MetalRenderPrimitive)
|
DLOG(INFO) << "MetalTexture: " << sizeof(MetalTexture);
|
||||||
<< "\nMetalTexture: " << sizeof(MetalTexture)
|
DLOG(INFO) << "MetalTimerQuery: " << sizeof(MetalTimerQuery);
|
||||||
<< "\nMetalTimerQuery: " << sizeof(MetalTimerQuery)
|
DLOG(INFO) << "HwStream: " << sizeof(HwStream);
|
||||||
<< "\nHwStream: " << sizeof(HwStream)
|
DLOG(INFO) << "MetalRenderTarget: " << sizeof(MetalRenderTarget);
|
||||||
<< "\nMetalRenderTarget: " << sizeof(MetalRenderTarget)
|
DLOG(INFO) << "MetalFence: " << sizeof(MetalFence);
|
||||||
<< "\nMetalFence: " << sizeof(MetalFence)
|
DLOG(INFO) << "MetalProgram: " << sizeof(MetalProgram);
|
||||||
<< "\nMetalProgram: " << sizeof(MetalProgram)
|
|
||||||
<< utils::io::endl;
|
|
||||||
#endif
|
#endif
|
||||||
return MetalDriver::create(platform, driverConfig);
|
return MetalDriver::create(platform, driverConfig);
|
||||||
}
|
}
|
||||||
@@ -135,19 +133,18 @@ MetalDriver::MetalDriver(
|
|||||||
|
|
||||||
initializeSupportedGpuFamilies(mContext);
|
initializeSupportedGpuFamilies(mContext);
|
||||||
|
|
||||||
utils::slog.v << "Supported GPU families: " << utils::io::endl;
|
LOG(INFO) << "Supported GPU families: ";
|
||||||
if (mContext->highestSupportedGpuFamily.common > 0) {
|
if (mContext->highestSupportedGpuFamily.common > 0) {
|
||||||
utils::slog.v << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl;
|
LOG(INFO) << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common;
|
||||||
}
|
}
|
||||||
if (mContext->highestSupportedGpuFamily.apple > 0) {
|
if (mContext->highestSupportedGpuFamily.apple > 0) {
|
||||||
utils::slog.v << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl;
|
LOG(INFO) << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple;
|
||||||
}
|
}
|
||||||
if (mContext->highestSupportedGpuFamily.mac > 0) {
|
if (mContext->highestSupportedGpuFamily.mac > 0) {
|
||||||
utils::slog.v << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl;
|
LOG(INFO) << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac;
|
||||||
}
|
}
|
||||||
utils::slog.v << "Features:" << utils::io::endl;
|
LOG(INFO) << "Features:";
|
||||||
utils::slog.v << " readWriteTextureSupport: " <<
|
LOG(INFO) << " readWriteTextureSupport: " << (bool) mContext->device.readWriteTextureSupport;
|
||||||
(bool) mContext->device.readWriteTextureSupport << utils::io::endl;
|
|
||||||
|
|
||||||
// In order to support texture swizzling, the GPU needs to support it and the system be running
|
// In order to support texture swizzling, the GPU needs to support it and the system be running
|
||||||
// iOS 13+.
|
// iOS 13+.
|
||||||
@@ -588,7 +585,7 @@ void MetalDriver::createProgramR(Handle<HwProgram> rph, Program&& program) {
|
|||||||
#if FILAMENT_METAL_DEBUG_LOG
|
#if FILAMENT_METAL_DEBUG_LOG
|
||||||
auto handleId = rph.getId();
|
auto handleId = rph.getId();
|
||||||
DEBUG_LOG("createProgramR(rph = %d, program = ", handleId);
|
DEBUG_LOG("createProgramR(rph = %d, program = ", handleId);
|
||||||
utils::slog.d << program << utils::io::endl;
|
DLOG(INFO) << program;
|
||||||
#endif
|
#endif
|
||||||
construct_handle<MetalProgram>(rph, *mContext, std::move(program));
|
construct_handle<MetalProgram>(rph, *mContext, std::move(program));
|
||||||
}
|
}
|
||||||
@@ -2077,7 +2074,7 @@ void MetalDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGro
|
|||||||
error:&error];
|
error:&error];
|
||||||
if (error) {
|
if (error) {
|
||||||
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
utils::slog.e << description << utils::io::endl;
|
LOG(ERROR) << description;
|
||||||
}
|
}
|
||||||
assert_invariant(!error);
|
assert_invariant(!error);
|
||||||
|
|
||||||
|
|||||||
@@ -20,14 +20,14 @@
|
|||||||
#include "MetalEnums.h"
|
#include "MetalEnums.h"
|
||||||
#include "MetalUtils.h"
|
#include "MetalUtils.h"
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/trap.h>
|
#include <utils/trap.h>
|
||||||
|
|
||||||
#define NSERROR_CHECK(message) \
|
#define NSERROR_CHECK(message) \
|
||||||
if (error) { \
|
if (error) { \
|
||||||
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding]; \
|
auto description = [error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding]; \
|
||||||
utils::slog.e << description << utils::io::endl; \
|
LOG(ERROR) << description; \
|
||||||
} \
|
} \
|
||||||
FILAMENT_CHECK_POSTCONDITION(error == nil) << message;
|
FILAMENT_CHECK_POSTCONDITION(error == nil) << message;
|
||||||
|
|
||||||
|
|||||||
@@ -27,10 +27,11 @@
|
|||||||
|
|
||||||
#include "private/backend/BackendUtils.h"
|
#include "private/backend/BackendUtils.h"
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/trap.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
|
#include <utils/trap.h>
|
||||||
|
|
||||||
#include <math/scalar.h>
|
#include <math/scalar.h>
|
||||||
|
|
||||||
@@ -115,14 +116,14 @@ MetalSwapChain::MetalSwapChain(
|
|||||||
type(SwapChainType::CAMETALLAYER) {
|
type(SwapChainType::CAMETALLAYER) {
|
||||||
|
|
||||||
if (!(flags & SwapChain::CONFIG_TRANSPARENT) && !nativeWindow.opaque) {
|
if (!(flags & SwapChain::CONFIG_TRANSPARENT) && !nativeWindow.opaque) {
|
||||||
utils::slog.w << "Warning: Filament SwapChain has no CONFIG_TRANSPARENT flag, "
|
LOG(WARNING) << "Warning: Filament SwapChain has no CONFIG_TRANSPARENT flag, but the "
|
||||||
"but the CAMetaLayer(" << (__bridge void*) nativeWindow << ")"
|
"CAMetaLayer("
|
||||||
" has .opaque set to NO." << utils::io::endl;
|
<< (__bridge void*) nativeWindow << ") has .opaque set to NO.";
|
||||||
}
|
}
|
||||||
if ((flags & SwapChain::CONFIG_TRANSPARENT) && nativeWindow.opaque) {
|
if ((flags & SwapChain::CONFIG_TRANSPARENT) && nativeWindow.opaque) {
|
||||||
utils::slog.w << "Warning: Filament SwapChain has the CONFIG_TRANSPARENT flag, "
|
LOG(WARNING) << "Warning: Filament SwapChain has the CONFIG_TRANSPARENT flag, but the "
|
||||||
"but the CAMetaLayer(" << (__bridge void*) nativeWindow << ")"
|
"CAMetaLayer("
|
||||||
" has .opaque set to YES." << utils::io::endl;
|
<< (__bridge void*) nativeWindow << ") has .opaque set to YES.";
|
||||||
}
|
}
|
||||||
|
|
||||||
// Needed so we can use the SwapChain as a blit source.
|
// Needed so we can use the SwapChain as a blit source.
|
||||||
|
|||||||
@@ -21,6 +21,7 @@
|
|||||||
#include <backend/Program.h>
|
#include <backend/Program.h>
|
||||||
|
|
||||||
#include <utils/JobSystem.h>
|
#include <utils/JobSystem.h>
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/Mutex.h>
|
#include <utils/Mutex.h>
|
||||||
|
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@@ -147,7 +148,7 @@ bool MetalShaderCompiler::isParallelShaderCompileSupported() const noexcept {
|
|||||||
if (error) {
|
if (error) {
|
||||||
auto description =
|
auto description =
|
||||||
[error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
[error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
utils::slog.w << description << utils::io::endl;
|
LOG(WARNING) << description;
|
||||||
errorMessage = error.localizedDescription;
|
errorMessage = error.localizedDescription;
|
||||||
}
|
}
|
||||||
PANIC_LOG("Failed to compile Metal program.");
|
PANIC_LOG("Failed to compile Metal program.");
|
||||||
@@ -178,7 +179,7 @@ bool MetalShaderCompiler::isParallelShaderCompileSupported() const noexcept {
|
|||||||
if (error) {
|
if (error) {
|
||||||
auto description =
|
auto description =
|
||||||
[error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
[error.localizedDescription cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
utils::slog.w << description << utils::io::endl;
|
LOG(WARNING) << description;
|
||||||
errorMessage = error.localizedDescription;
|
errorMessage = error.localizedDescription;
|
||||||
}
|
}
|
||||||
PANIC_LOG("Failed to load main0 in Metal program.");
|
PANIC_LOG("Failed to load main0 in Metal program.");
|
||||||
|
|||||||
@@ -18,7 +18,7 @@
|
|||||||
|
|
||||||
#include "MetalEnums.h"
|
#include "MetalEnums.h"
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
namespace filament {
|
namespace filament {
|
||||||
namespace backend {
|
namespace backend {
|
||||||
@@ -95,7 +95,7 @@ id<MTLRenderPipelineState> PipelineStateCreator::operator()(id<MTLDevice> device
|
|||||||
[NSString stringWithFormat:@"Could not create Metal pipeline state: %@",
|
[NSString stringWithFormat:@"Could not create Metal pipeline state: %@",
|
||||||
error ? error.localizedDescription : @"unknown error"];
|
error ? error.localizedDescription : @"unknown error"];
|
||||||
auto description = [errorMessage cStringUsingEncoding:NSUTF8StringEncoding];
|
auto description = [errorMessage cStringUsingEncoding:NSUTF8StringEncoding];
|
||||||
utils::slog.e << description << utils::io::endl;
|
LOG(ERROR) << description;
|
||||||
[[NSException exceptionWithName:@"MetalRenderPipelineFailure"
|
[[NSException exceptionWithName:@"MetalRenderPipelineFailure"
|
||||||
reason:errorMessage
|
reason:errorMessage
|
||||||
userInfo:nil] raise];
|
userInfo:nil] raise];
|
||||||
@@ -155,7 +155,7 @@ id<MTLSamplerState> SamplerStateCreator::operator()(id<MTLDevice> device,
|
|||||||
// MTLSamplerDescriptor.
|
// MTLSamplerDescriptor.
|
||||||
// In practice, this means shadows are not supported when running in the simulator.
|
// In practice, this means shadows are not supported when running in the simulator.
|
||||||
if (![device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) {
|
if (![device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily3_v1]) {
|
||||||
utils::slog.w << "Warning: sample comparison not supported by this GPU" << utils::io::endl;
|
LOG(WARNING) << "Warning: sample comparison not supported by this GPU";
|
||||||
samplerDescriptor.compareFunction = MTLCompareFunctionNever;
|
samplerDescriptor.compareFunction = MTLCompareFunctionNever;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
|
|
||||||
#include "MetalDriverFactory.h"
|
#include "MetalDriverFactory.h"
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
#import <Foundation/Foundation.h>
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
@@ -53,6 +53,9 @@ PlatformMetal::~PlatformMetal() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::DriverConfig& driverConfig) noexcept {
|
||||||
|
pImpl->mDrawableFailureBehavior = driverConfig.metalDisablePanicOnDrawableFailure
|
||||||
|
? DrawableFailureBehavior::ABORT_FRAME
|
||||||
|
: DrawableFailureBehavior::PANIC;
|
||||||
return MetalDriverFactory::create(this, driverConfig);
|
return MetalDriverFactory::create(this, driverConfig);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -129,9 +132,8 @@ void PlatformMetalImpl::createDeviceImpl(MetalDevice& outDevice) {
|
|||||||
result = MTLCreateSystemDefaultDevice();
|
result = MTLCreateSystemDefaultDevice();
|
||||||
}
|
}
|
||||||
|
|
||||||
utils::slog.i << "Selected physical device '"
|
LOG(INFO) << "Selected physical device '"
|
||||||
<< [result.name cStringUsingEncoding:NSUTF8StringEncoding] << "'"
|
<< [result.name cStringUsingEncoding:NSUTF8StringEncoding] << "'";
|
||||||
<< utils::io::endl;
|
|
||||||
|
|
||||||
outDevice.device = result;
|
outDevice.device = result;
|
||||||
mDevice = result;
|
mDevice = result;
|
||||||
|
|||||||
@@ -162,8 +162,11 @@ void GLDescriptorSet::update(OpenGLContext&,
|
|||||||
}, descriptors[binding].desc);
|
}, descriptors[binding].desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDescriptorSet::update(OpenGLContext& gl,
|
void GLDescriptorSet::update(OpenGLContext& gl, HandleAllocatorGL& handleAllocator,
|
||||||
descriptor_binding_t binding, GLTexture* t, SamplerParams params) noexcept {
|
descriptor_binding_t binding, TextureHandle th, SamplerParams params) noexcept {
|
||||||
|
|
||||||
|
GLTexture* t = th ? handleAllocator.handle_cast<GLTexture*>(th) : nullptr;
|
||||||
|
|
||||||
assert_invariant(binding < descriptors.size());
|
assert_invariant(binding < descriptors.size());
|
||||||
std::visit([=, &gl](auto&& arg) mutable {
|
std::visit([=, &gl](auto&& arg) mutable {
|
||||||
using T = std::decay_t<decltype(arg)>;
|
using T = std::decay_t<decltype(arg)>;
|
||||||
@@ -196,20 +199,12 @@ void GLDescriptorSet::update(OpenGLContext& gl,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
arg.target = t ? t->gl.target : 0;
|
arg.handle = th;
|
||||||
arg.id = t ? t->gl.id : 0;
|
|
||||||
arg.external = t ? t->gl.external : false;
|
|
||||||
if constexpr (std::is_same_v<T, Sampler> ||
|
if constexpr (std::is_same_v<T, Sampler> ||
|
||||||
std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
||||||
if constexpr (std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
if constexpr (std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
||||||
arg.anisotropy = float(1u << params.anisotropyLog2);
|
arg.anisotropy = float(1u << params.anisotropyLog2);
|
||||||
}
|
}
|
||||||
if (t) {
|
|
||||||
arg.ref = t->ref;
|
|
||||||
arg.baseLevel = t->gl.baseLevel;
|
|
||||||
arg.maxLevel = t->gl.maxLevel;
|
|
||||||
arg.swizzle = t->gl.swizzle;
|
|
||||||
}
|
|
||||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||||
arg.sampler = gl.getSampler(params);
|
arg.sampler = gl.getSampler(params);
|
||||||
#else
|
#else
|
||||||
@@ -225,39 +220,39 @@ void GLDescriptorSet::update(OpenGLContext& gl,
|
|||||||
}, descriptors[binding].desc);
|
}, descriptors[binding].desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
void GLDescriptorSet::updateTextureView(OpenGLContext& gl,
|
void GLDescriptorSet::updateTextureView(OpenGLContext& gl,
|
||||||
HandleAllocatorGL& handleAllocator, GLuint unit, T const& desc) noexcept {
|
HandleAllocatorGL& handleAllocator, GLuint unit, GLTexture const* t) noexcept {
|
||||||
// The common case is that we don't have a ref handle (we only have one if
|
// The common case is that we don't have a ref handle (we only have one if
|
||||||
// the texture ever had a View on it).
|
// the texture ever had a View on it).
|
||||||
assert_invariant(desc.ref);
|
assert_invariant(t);
|
||||||
GLTextureRef* const ref = handleAllocator.handle_cast<GLTextureRef*>(desc.ref);
|
assert_invariant(t->ref);
|
||||||
if (UTILS_UNLIKELY((desc.baseLevel != ref->baseLevel || desc.maxLevel != ref->maxLevel))) {
|
GLTextureRef* const ref = handleAllocator.handle_cast<GLTextureRef*>(t->ref);
|
||||||
|
if (UTILS_UNLIKELY((t->gl.baseLevel != ref->baseLevel || t->gl.maxLevel != ref->maxLevel))) {
|
||||||
// If we have views, then it's still uncommon that we'll switch often
|
// If we have views, then it's still uncommon that we'll switch often
|
||||||
// handle the case where we reset to the original texture
|
// handle the case where we reset to the original texture
|
||||||
GLint baseLevel = GLint(desc.baseLevel); // NOLINT(*-signed-char-misuse)
|
GLint baseLevel = GLint(t->gl.baseLevel); // NOLINT(*-signed-char-misuse)
|
||||||
GLint maxLevel = GLint(desc.maxLevel); // NOLINT(*-signed-char-misuse)
|
GLint maxLevel = GLint(t->gl.maxLevel); // NOLINT(*-signed-char-misuse)
|
||||||
if (baseLevel > maxLevel) {
|
if (baseLevel > maxLevel) {
|
||||||
baseLevel = 0;
|
baseLevel = 0;
|
||||||
maxLevel = 1000; // per OpenGL spec
|
maxLevel = 1000; // per OpenGL spec
|
||||||
}
|
}
|
||||||
// that is very unfortunate that we have to call activeTexture here
|
// that is very unfortunate that we have to call activeTexture here
|
||||||
gl.activeTexture(unit);
|
gl.activeTexture(unit);
|
||||||
glTexParameteri(desc.target, GL_TEXTURE_BASE_LEVEL, baseLevel);
|
glTexParameteri(t->gl.target, GL_TEXTURE_BASE_LEVEL, baseLevel);
|
||||||
glTexParameteri(desc.target, GL_TEXTURE_MAX_LEVEL, maxLevel);
|
glTexParameteri(t->gl.target, GL_TEXTURE_MAX_LEVEL, maxLevel);
|
||||||
ref->baseLevel = desc.baseLevel;
|
ref->baseLevel = t->gl.baseLevel;
|
||||||
ref->maxLevel = desc.maxLevel;
|
ref->maxLevel = t->gl.maxLevel;
|
||||||
}
|
}
|
||||||
if (UTILS_UNLIKELY(desc.swizzle != ref->swizzle)) {
|
if (UTILS_UNLIKELY(t->gl.swizzle != ref->swizzle)) {
|
||||||
using namespace GLUtils;
|
using namespace GLUtils;
|
||||||
gl.activeTexture(unit);
|
gl.activeTexture(unit);
|
||||||
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||||
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_R, (GLint)getSwizzleChannel(desc.swizzle[0]));
|
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_R, (GLint)getSwizzleChannel(t->gl.swizzle[0]));
|
||||||
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_G, (GLint)getSwizzleChannel(desc.swizzle[1]));
|
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_G, (GLint)getSwizzleChannel(t->gl.swizzle[1]));
|
||||||
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_B, (GLint)getSwizzleChannel(desc.swizzle[2]));
|
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_B, (GLint)getSwizzleChannel(t->gl.swizzle[2]));
|
||||||
glTexParameteri(desc.target, GL_TEXTURE_SWIZZLE_A, (GLint)getSwizzleChannel(desc.swizzle[3]));
|
glTexParameteri(t->gl.target, GL_TEXTURE_SWIZZLE_A, (GLint)getSwizzleChannel(t->gl.swizzle[3]));
|
||||||
#endif
|
#endif
|
||||||
ref->swizzle = desc.swizzle;
|
ref->swizzle = t->gl.swizzle;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -310,27 +305,31 @@ void GLDescriptorSet::bind(
|
|||||||
}
|
}
|
||||||
} else if constexpr (std::is_same_v<T, Sampler>) {
|
} else if constexpr (std::is_same_v<T, Sampler>) {
|
||||||
GLuint const unit = p.getTextureUnit(set, binding);
|
GLuint const unit = p.getTextureUnit(set, binding);
|
||||||
if (arg.target) {
|
|
||||||
gl.bindTexture(unit, arg.target, arg.id, arg.external);
|
|
||||||
|
if (arg.handle) {
|
||||||
|
GLTexture const* const t = handleAllocator.handle_cast<GLTexture*>(arg.handle);
|
||||||
|
gl.bindTexture(unit, t->gl.target, t->gl.id, t->gl.external);
|
||||||
gl.bindSampler(unit, arg.sampler);
|
gl.bindSampler(unit, arg.sampler);
|
||||||
if (UTILS_UNLIKELY(arg.ref)) {
|
if (UTILS_UNLIKELY(t->ref)) {
|
||||||
updateTextureView(gl, handleAllocator, unit, arg);
|
updateTextureView(gl, handleAllocator, unit, t);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
gl.unbindTextureUnit(unit);
|
gl.unbindTextureUnit(unit);
|
||||||
}
|
}
|
||||||
} else if constexpr (std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
} else if constexpr (std::is_same_v<T, SamplerWithAnisotropyWorkaround>) {
|
||||||
GLuint const unit = p.getTextureUnit(set, binding);
|
GLuint const unit = p.getTextureUnit(set, binding);
|
||||||
if (arg.target) {
|
if (arg.handle) {
|
||||||
gl.bindTexture(unit, arg.target, arg.id, arg.external);
|
GLTexture const* const t = handleAllocator.handle_cast<GLTexture*>(arg.handle);
|
||||||
|
gl.bindTexture(unit, t->gl.target, t->gl.id, t->gl.external);
|
||||||
gl.bindSampler(unit, arg.sampler);
|
gl.bindSampler(unit, arg.sampler);
|
||||||
if (UTILS_UNLIKELY(arg.ref)) {
|
if (UTILS_UNLIKELY(t->ref)) {
|
||||||
updateTextureView(gl, handleAllocator, unit, arg);
|
updateTextureView(gl, handleAllocator, unit, t);
|
||||||
}
|
}
|
||||||
#if defined(GL_EXT_texture_filter_anisotropic)
|
#if defined(GL_EXT_texture_filter_anisotropic)
|
||||||
// Driver claims to support anisotropic filtering, but it fails when set on
|
// Driver claims to support anisotropic filtering, but it fails when set on
|
||||||
// the sampler, we have to set it on the texture instead.
|
// the sampler, we have to set it on the texture instead.
|
||||||
glTexParameterf(arg.target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
glTexParameterf(t->gl.target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||||
std::min(gl.gets.max_anisotropy, float(arg.anisotropy)));
|
std::min(gl.gets.max_anisotropy, float(arg.anisotropy)));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@@ -339,19 +338,20 @@ void GLDescriptorSet::bind(
|
|||||||
} else if constexpr (std::is_same_v<T, SamplerGLES2>) {
|
} else if constexpr (std::is_same_v<T, SamplerGLES2>) {
|
||||||
// in ES2 the sampler parameters need to be set on the texture itself
|
// in ES2 the sampler parameters need to be set on the texture itself
|
||||||
GLuint const unit = p.getTextureUnit(set, binding);
|
GLuint const unit = p.getTextureUnit(set, binding);
|
||||||
if (arg.target) {
|
if (arg.handle) {
|
||||||
gl.bindTexture(unit, arg.target, arg.id, arg.external);
|
GLTexture const* const t = handleAllocator.handle_cast<GLTexture*>(arg.handle);
|
||||||
|
gl.bindTexture(unit, t->gl.target, t->gl.id, t->gl.external);
|
||||||
SamplerParams const params = arg.params;
|
SamplerParams const params = arg.params;
|
||||||
glTexParameteri(arg.target, GL_TEXTURE_MIN_FILTER,
|
glTexParameteri(t->gl.target, GL_TEXTURE_MIN_FILTER,
|
||||||
(GLint)GLUtils::getTextureFilter(params.filterMin));
|
(GLint)GLUtils::getTextureFilter(params.filterMin));
|
||||||
glTexParameteri(arg.target, GL_TEXTURE_MAG_FILTER,
|
glTexParameteri(t->gl.target, GL_TEXTURE_MAG_FILTER,
|
||||||
(GLint)GLUtils::getTextureFilter(params.filterMag));
|
(GLint)GLUtils::getTextureFilter(params.filterMag));
|
||||||
glTexParameteri(arg.target, GL_TEXTURE_WRAP_S,
|
glTexParameteri(t->gl.target, GL_TEXTURE_WRAP_S,
|
||||||
(GLint)GLUtils::getWrapMode(params.wrapS));
|
(GLint)GLUtils::getWrapMode(params.wrapS));
|
||||||
glTexParameteri(arg.target, GL_TEXTURE_WRAP_T,
|
glTexParameteri(t->gl.target, GL_TEXTURE_WRAP_T,
|
||||||
(GLint)GLUtils::getWrapMode(params.wrapT));
|
(GLint)GLUtils::getWrapMode(params.wrapT));
|
||||||
#if defined(GL_EXT_texture_filter_anisotropic)
|
#if defined(GL_EXT_texture_filter_anisotropic)
|
||||||
glTexParameterf(arg.target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
glTexParameterf(t->gl.target, GL_TEXTURE_MAX_ANISOTROPY_EXT,
|
||||||
std::min(gl.gets.max_anisotropy, arg.anisotropy));
|
std::min(gl.gets.max_anisotropy, arg.anisotropy));
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
@@ -360,7 +360,7 @@ void GLDescriptorSet::bind(
|
|||||||
}
|
}
|
||||||
}, entry.desc);
|
}, entry.desc);
|
||||||
});
|
});
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void GLDescriptorSet::validate(HandleAllocatorGL& allocator,
|
void GLDescriptorSet::validate(HandleAllocatorGL& allocator,
|
||||||
|
|||||||
@@ -59,8 +59,8 @@ struct GLDescriptorSet : public HwDescriptorSet {
|
|||||||
descriptor_binding_t binding, GLBufferObject* bo, size_t offset, size_t size) noexcept;
|
descriptor_binding_t binding, GLBufferObject* bo, size_t offset, size_t size) noexcept;
|
||||||
|
|
||||||
// update a sampler descriptor in the set
|
// update a sampler descriptor in the set
|
||||||
void update(OpenGLContext& gl,
|
void update(OpenGLContext& gl, HandleAllocatorGL& handleAllocator,
|
||||||
descriptor_binding_t binding, GLTexture* t, SamplerParams params) noexcept;
|
descriptor_binding_t binding, TextureHandle th, SamplerParams params) noexcept;
|
||||||
|
|
||||||
// conceptually bind the set to the command buffer
|
// conceptually bind the set to the command buffer
|
||||||
void bind(
|
void bind(
|
||||||
@@ -111,46 +111,19 @@ private:
|
|||||||
|
|
||||||
// A sampler descriptor
|
// A sampler descriptor
|
||||||
struct Sampler {
|
struct Sampler {
|
||||||
uint16_t target; // 2 (GLenum)
|
TextureHandle handle; // 4
|
||||||
bool external = false; // 1
|
|
||||||
bool reserved = false; // 1
|
|
||||||
GLuint id = 0; // 4
|
|
||||||
GLuint sampler = 0; // 4
|
GLuint sampler = 0; // 4
|
||||||
Handle<GLTextureRef> ref; // 4
|
|
||||||
int8_t baseLevel = 0x7f; // 1
|
|
||||||
int8_t maxLevel = -1; // 1
|
|
||||||
std::array<TextureSwizzle, 4> swizzle{ // 4
|
|
||||||
TextureSwizzle::CHANNEL_0,
|
|
||||||
TextureSwizzle::CHANNEL_1,
|
|
||||||
TextureSwizzle::CHANNEL_2,
|
|
||||||
TextureSwizzle::CHANNEL_3
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
struct SamplerWithAnisotropyWorkaround {
|
struct SamplerWithAnisotropyWorkaround {
|
||||||
uint16_t target; // 2 (GLenum)
|
TextureHandle handle; // 4
|
||||||
bool external = false; // 1
|
|
||||||
bool reserved = false; // 1
|
|
||||||
GLuint id = 0; // 4
|
|
||||||
GLuint sampler = 0; // 4
|
GLuint sampler = 0; // 4
|
||||||
Handle<GLTextureRef> ref; // 4
|
|
||||||
math::half anisotropy = 1.0f; // 2
|
math::half anisotropy = 1.0f; // 2
|
||||||
int8_t baseLevel = 0x7f; // 1
|
|
||||||
int8_t maxLevel = -1; // 1
|
|
||||||
std::array<TextureSwizzle, 4> swizzle{ // 4
|
|
||||||
TextureSwizzle::CHANNEL_0,
|
|
||||||
TextureSwizzle::CHANNEL_1,
|
|
||||||
TextureSwizzle::CHANNEL_2,
|
|
||||||
TextureSwizzle::CHANNEL_3
|
|
||||||
};
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// A sampler descriptor for ES2
|
// A sampler descriptor for ES2
|
||||||
struct SamplerGLES2 {
|
struct SamplerGLES2 {
|
||||||
uint16_t target; // 2 (GLenum)
|
TextureHandle handle; // 4
|
||||||
bool external = false; // 1
|
|
||||||
bool reserved = false; // 1
|
|
||||||
GLuint id = 0; // 4
|
|
||||||
SamplerParams params{}; // 4
|
SamplerParams params{}; // 4
|
||||||
float anisotropy = 1.0f; // 4
|
float anisotropy = 1.0f; // 4
|
||||||
};
|
};
|
||||||
@@ -165,9 +138,8 @@ private:
|
|||||||
};
|
};
|
||||||
static_assert(sizeof(Descriptor) <= 32);
|
static_assert(sizeof(Descriptor) <= 32);
|
||||||
|
|
||||||
template<typename T>
|
|
||||||
static void updateTextureView(OpenGLContext& gl,
|
static void updateTextureView(OpenGLContext& gl,
|
||||||
HandleAllocatorGL& handleAllocator, GLuint unit, T const& desc) noexcept;
|
HandleAllocatorGL& handleAllocator, GLuint unit, GLTexture const* t) noexcept;
|
||||||
|
|
||||||
utils::FixedCapacityVector<Descriptor> descriptors; // 16
|
utils::FixedCapacityVector<Descriptor> descriptors; // 16
|
||||||
utils::bitset64 dynamicBuffers; // 8
|
utils::bitset64 dynamicBuffers; // 8
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
|
|
||||||
#include "private/backend/Driver.h"
|
#include "private/backend/Driver.h"
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
#include <utils/trap.h>
|
#include <utils/trap.h>
|
||||||
@@ -25,6 +26,7 @@
|
|||||||
#include <string_view>
|
#include <string_view>
|
||||||
|
|
||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
|
#include <cstdio>
|
||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
@@ -55,19 +57,21 @@ std::string_view getGLErrorString(GLenum error) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
GLenum checkGLError(io::ostream& out, const char* function, size_t line) noexcept {
|
GLenum checkGLError(const char* function, size_t line) noexcept {
|
||||||
GLenum const error = glGetError();
|
GLenum const error = glGetError();
|
||||||
if (UTILS_VERY_UNLIKELY(error != GL_NO_ERROR)) {
|
if (UTILS_VERY_UNLIKELY(error != GL_NO_ERROR)) {
|
||||||
auto const string = getGLErrorString(error);
|
auto const string = getGLErrorString(error);
|
||||||
out << "OpenGL error " << io::hex << error << " (" << string << ") in \""
|
char hexError[16];
|
||||||
<< function << "\" at line " << io::dec << line << io::endl;
|
snprintf(hexError, sizeof(hexError), "%#x", error);
|
||||||
|
LOG(ERROR) << "OpenGL error " << hexError << " (" << string << ") in \"" << function
|
||||||
|
<< "\" at line " << line;
|
||||||
}
|
}
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
void assertGLError(io::ostream& out, const char* function, size_t line) noexcept {
|
void assertGLError(const char* function, size_t line) noexcept {
|
||||||
GLenum const err = checkGLError(out, function, line);
|
GLenum const err = checkGLError(function, line);
|
||||||
if (UTILS_VERY_UNLIKELY(err != GL_NO_ERROR)) {
|
if (UTILS_VERY_UNLIKELY(err != GL_NO_ERROR)) {
|
||||||
debug_trap();
|
debug_trap();
|
||||||
}
|
}
|
||||||
@@ -97,19 +101,21 @@ std::string_view getFramebufferStatusString(GLenum status) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
GLenum checkFramebufferStatus(io::ostream& out, GLenum target, const char* function, size_t line) noexcept {
|
GLenum checkFramebufferStatus(GLenum target, const char* function, size_t line) noexcept {
|
||||||
GLenum const status = glCheckFramebufferStatus(target);
|
GLenum const status = glCheckFramebufferStatus(target);
|
||||||
if (UTILS_VERY_UNLIKELY(status != GL_FRAMEBUFFER_COMPLETE)) {
|
if (UTILS_VERY_UNLIKELY(status != GL_FRAMEBUFFER_COMPLETE)) {
|
||||||
auto const string = getFramebufferStatusString(status);
|
auto const string = getFramebufferStatusString(status);
|
||||||
out << "OpenGL framebuffer error " << io::hex << status << " (" << string << ") in \""
|
char hexStatus[16];
|
||||||
<< function << "\" at line " << io::dec << line << io::endl;
|
snprintf(hexStatus, sizeof(hexStatus), "%#x", status);
|
||||||
|
LOG(ERROR) << "OpenGL framebuffer error " << hexStatus << " (" << string << ") in \""
|
||||||
|
<< function << "\" at line " << line;
|
||||||
}
|
}
|
||||||
return status;
|
return status;
|
||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
void assertFramebufferStatus(io::ostream& out, GLenum target, const char* function, size_t line) noexcept {
|
void assertFramebufferStatus(GLenum target, const char* function, size_t line) noexcept {
|
||||||
GLenum const status = checkFramebufferStatus(out, target, function, line);
|
GLenum const status = checkFramebufferStatus(target, function, line);
|
||||||
if (UTILS_VERY_UNLIKELY(status != GL_FRAMEBUFFER_COMPLETE)) {
|
if (UTILS_VERY_UNLIKELY(status != GL_FRAMEBUFFER_COMPLETE)) {
|
||||||
debug_trap();
|
debug_trap();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -33,21 +33,21 @@
|
|||||||
namespace filament::backend::GLUtils {
|
namespace filament::backend::GLUtils {
|
||||||
|
|
||||||
std::string_view getGLErrorString(GLenum error) noexcept;
|
std::string_view getGLErrorString(GLenum error) noexcept;
|
||||||
GLenum checkGLError(utils::io::ostream& out, const char* function, size_t line) noexcept;
|
GLenum checkGLError(const char* function, size_t line) noexcept;
|
||||||
void assertGLError(utils::io::ostream& out, const char* function, size_t line) noexcept;
|
void assertGLError(const char* function, size_t line) noexcept;
|
||||||
|
|
||||||
std::string_view getFramebufferStatusString(GLenum err) noexcept;
|
std::string_view getFramebufferStatusString(GLenum err) noexcept;
|
||||||
GLenum checkFramebufferStatus(utils::io::ostream& out, GLenum target, const char* function, size_t line) noexcept;
|
GLenum checkFramebufferStatus(GLenum target, const char* function, size_t line) noexcept;
|
||||||
void assertFramebufferStatus(utils::io::ostream& out, GLenum target, const char* function, size_t line) noexcept;
|
void assertFramebufferStatus(GLenum target, const char* function, size_t line) noexcept;
|
||||||
|
|
||||||
#ifdef NDEBUG
|
#ifdef NDEBUG
|
||||||
# define CHECK_GL_ERROR(out)
|
# define CHECK_GL_ERROR()
|
||||||
# define CHECK_GL_ERROR_NON_FATAL(out)
|
# define CHECK_GL_ERROR_NON_FATAL()
|
||||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target)
|
# define CHECK_GL_FRAMEBUFFER_STATUS(target)
|
||||||
#else
|
#else
|
||||||
# define CHECK_GL_ERROR(out) { GLUtils::assertGLError(out, __func__, __LINE__); }
|
# define CHECK_GL_ERROR() { GLUtils::assertGLError(__func__, __LINE__); }
|
||||||
# define CHECK_GL_ERROR_NON_FATAL(out) { GLUtils::checkGLError(out, __func__, __LINE__); }
|
# define CHECK_GL_ERROR_NON_FATAL() { GLUtils::checkGLError(__func__, __LINE__); }
|
||||||
# define CHECK_GL_FRAMEBUFFER_STATUS(out, target) { GLUtils::checkFramebufferStatus(out, target, __func__, __LINE__); }
|
# define CHECK_GL_FRAMEBUFFER_STATUS(target) { GLUtils::checkFramebufferStatus( target, __func__, __LINE__); }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
constexpr GLuint getComponentCount(ElementType const type) noexcept {
|
constexpr GLuint getComponentCount(ElementType const type) noexcept {
|
||||||
|
|||||||
@@ -22,9 +22,9 @@
|
|||||||
#include <backend/platforms/OpenGLPlatform.h>
|
#include <backend/platforms/OpenGLPlatform.h>
|
||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#include <functional>
|
#include <functional>
|
||||||
@@ -77,8 +77,8 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
|||||||
state.version = (char const*)glGetString(GL_VERSION);
|
state.version = (char const*)glGetString(GL_VERSION);
|
||||||
state.shader = (char const*)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
state.shader = (char const*)glGetString(GL_SHADING_LANGUAGE_VERSION);
|
||||||
|
|
||||||
slog.v << "[" << state.vendor << "], [" << state.renderer << "], "
|
LOG(INFO) << "[" << state.vendor << "], [" << state.renderer << "], "
|
||||||
"[" << state.version << "], [" << state.shader << "]" << io::endl;
|
"[" << state.version << "], [" << state.shader << "]";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Figure out GL / GLES version, extensions and capabilities we need to
|
* Figure out GL / GLES version, extensions and capabilities we need to
|
||||||
@@ -164,51 +164,33 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
slog.v << "Feature level: " << +mFeatureLevel << '\n';
|
LOG(INFO) << "Feature level: " << +mFeatureLevel;
|
||||||
slog.v << "Active workarounds: " << '\n';
|
LOG(INFO) << "Active workarounds: ";
|
||||||
UTILS_NOUNROLL
|
UTILS_NOUNROLL
|
||||||
for (auto [enabled, name, _] : mBugDatabase) {
|
for (auto [enabled, name, _] : mBugDatabase) {
|
||||||
if (enabled) {
|
if (enabled) {
|
||||||
slog.v << name << '\n';
|
LOG(INFO) << name;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flush(slog.v);
|
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
// this is useful for development
|
// this is useful for development
|
||||||
slog.v
|
LOG(INFO) << "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = " << gets.max_anisotropy;
|
||||||
<< "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT = "
|
LOG(INFO) << "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = " << gets.max_combined_texture_image_units;
|
||||||
<< gets.max_anisotropy << '\n'
|
LOG(INFO) << "GL_MAX_TEXTURE_SIZE = " << gets.max_texture_size;
|
||||||
<< "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS = "
|
LOG(INFO) << "GL_MAX_CUBE_MAP_TEXTURE_SIZE = " << gets.max_cubemap_texture_size;
|
||||||
<< gets.max_combined_texture_image_units << '\n'
|
LOG(INFO) << "GL_MAX_3D_TEXTURE_SIZE = " << gets.max_3d_texture_size;
|
||||||
<< "GL_MAX_TEXTURE_SIZE = "
|
LOG(INFO) << "GL_MAX_ARRAY_TEXTURE_LAYERS = " << gets.max_array_texture_layers;
|
||||||
<< gets.max_texture_size << '\n'
|
LOG(INFO) << "GL_MAX_DRAW_BUFFERS = " << gets.max_draw_buffers;
|
||||||
<< "GL_MAX_CUBE_MAP_TEXTURE_SIZE = "
|
LOG(INFO) << "GL_MAX_RENDERBUFFER_SIZE = " << gets.max_renderbuffer_size;
|
||||||
<< gets.max_cubemap_texture_size << '\n'
|
LOG(INFO) << "GL_MAX_SAMPLES = " << gets.max_samples;
|
||||||
<< "GL_MAX_3D_TEXTURE_SIZE = "
|
LOG(INFO) << "GL_MAX_TEXTURE_IMAGE_UNITS = " << gets.max_texture_image_units;
|
||||||
<< gets.max_3d_texture_size << '\n'
|
LOG(INFO) << "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = "
|
||||||
<< "GL_MAX_ARRAY_TEXTURE_LAYERS = "
|
<< gets.max_transform_feedback_separate_attribs;
|
||||||
<< gets.max_array_texture_layers << '\n'
|
LOG(INFO) << "GL_MAX_UNIFORM_BLOCK_SIZE = " << gets.max_uniform_block_size;
|
||||||
<< "GL_MAX_DRAW_BUFFERS = "
|
LOG(INFO) << "GL_MAX_UNIFORM_BUFFER_BINDINGS = " << gets.max_uniform_buffer_bindings;
|
||||||
<< gets.max_draw_buffers << '\n'
|
LOG(INFO) << "GL_NUM_PROGRAM_BINARY_FORMATS = " << gets.num_program_binary_formats;
|
||||||
<< "GL_MAX_RENDERBUFFER_SIZE = "
|
LOG(INFO) << "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = " << gets.uniform_buffer_offset_alignment;
|
||||||
<< gets.max_renderbuffer_size << '\n'
|
|
||||||
<< "GL_MAX_SAMPLES = "
|
|
||||||
<< gets.max_samples << '\n'
|
|
||||||
<< "GL_MAX_TEXTURE_IMAGE_UNITS = "
|
|
||||||
<< gets.max_texture_image_units << '\n'
|
|
||||||
<< "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS = "
|
|
||||||
<< gets.max_transform_feedback_separate_attribs << '\n'
|
|
||||||
<< "GL_MAX_UNIFORM_BLOCK_SIZE = "
|
|
||||||
<< gets.max_uniform_block_size << '\n'
|
|
||||||
<< "GL_MAX_UNIFORM_BUFFER_BINDINGS = "
|
|
||||||
<< gets.max_uniform_buffer_bindings << '\n'
|
|
||||||
<< "GL_NUM_PROGRAM_BINARY_FORMATS = "
|
|
||||||
<< gets.num_program_binary_formats << '\n'
|
|
||||||
<< "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT = "
|
|
||||||
<< gets.uniform_buffer_offset_alignment << '\n'
|
|
||||||
;
|
|
||||||
flush(slog.v);
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
#ifndef FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2
|
||||||
@@ -242,15 +224,14 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
|||||||
if (ext.KHR_debug) {
|
if (ext.KHR_debug) {
|
||||||
auto cb = +[](GLenum, GLenum type, GLuint, GLenum severity, GLsizei length,
|
auto cb = +[](GLenum, GLenum type, GLuint, GLenum severity, GLsizei length,
|
||||||
const GLchar* message, const void *) {
|
const GLchar* message, const void *) {
|
||||||
io::ostream* stream = &slog.i;
|
auto logSeverity = utils::LogSeverity::kInfo;
|
||||||
switch (severity) {
|
switch (severity) {
|
||||||
case GL_DEBUG_SEVERITY_HIGH: stream = &slog.e; break;
|
case GL_DEBUG_SEVERITY_HIGH: logSeverity = utils::LogSeverity::kError; break;
|
||||||
case GL_DEBUG_SEVERITY_MEDIUM: stream = &slog.w; break;
|
case GL_DEBUG_SEVERITY_MEDIUM: logSeverity = utils::LogSeverity::kWarning; break;
|
||||||
case GL_DEBUG_SEVERITY_LOW: stream = &slog.d; break;
|
case GL_DEBUG_SEVERITY_LOW: logSeverity = utils::LogSeverity::kInfo; break;
|
||||||
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
case GL_DEBUG_SEVERITY_NOTIFICATION:
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
io::ostream& out = *stream;
|
|
||||||
const char* level = ": ";
|
const char* level = ": ";
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case GL_DEBUG_TYPE_ERROR: level = "ERROR: "; break;
|
case GL_DEBUG_TYPE_ERROR: level = "ERROR: "; break;
|
||||||
@@ -262,7 +243,7 @@ OpenGLContext::OpenGLContext(OpenGLPlatform& platform,
|
|||||||
case GL_DEBUG_TYPE_MARKER: level = "MARKER: "; break;
|
case GL_DEBUG_TYPE_MARKER: level = "MARKER: "; break;
|
||||||
default: break;
|
default: break;
|
||||||
}
|
}
|
||||||
out << "KHR_debug " << level << std::string_view{ message, size_t(length) } << io::endl;
|
LOG(LEVEL(logSeverity)) << "KHR_debug " << level << std::string_view{ message, size_t(length) };
|
||||||
};
|
};
|
||||||
glEnable(GL_DEBUG_OUTPUT);
|
glEnable(GL_DEBUG_OUTPUT);
|
||||||
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS);
|
||||||
@@ -707,9 +688,8 @@ void OpenGLContext::initExtensionsGLES(Extensions* ext, GLint major, GLint minor
|
|||||||
GLUtils::unordered_string_set const exts = GLUtils::split(extensions);
|
GLUtils::unordered_string_set const exts = GLUtils::split(extensions);
|
||||||
if constexpr (DEBUG_PRINT_EXTENSIONS) {
|
if constexpr (DEBUG_PRINT_EXTENSIONS) {
|
||||||
for (auto extension: exts) {
|
for (auto extension: exts) {
|
||||||
slog.d << "\"" << std::string_view(extension) << "\"\n";
|
DLOG(INFO) << "\"" << std::string_view(extension) << "\"";
|
||||||
}
|
}
|
||||||
flush(slog.d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// figure out and initialize the extensions we need
|
// figure out and initialize the extensions we need
|
||||||
@@ -783,9 +763,8 @@ void OpenGLContext::initExtensionsGL(Extensions* ext, GLint major, GLint minor)
|
|||||||
}
|
}
|
||||||
if constexpr (DEBUG_PRINT_EXTENSIONS) {
|
if constexpr (DEBUG_PRINT_EXTENSIONS) {
|
||||||
for (auto extension: exts) {
|
for (auto extension: exts) {
|
||||||
slog.d << "\"" << std::string_view(extension) << "\"\n";
|
DLOG(INFO) << "\"" << std::string_view(extension) << "\"";
|
||||||
}
|
}
|
||||||
flush(slog.d);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
using namespace std::literals;
|
using namespace std::literals;
|
||||||
@@ -1045,7 +1024,7 @@ GLuint OpenGLContext::getSamplerSlow(SamplerParams params) const noexcept {
|
|||||||
std::min(gets.max_anisotropy, anisotropy));
|
std::min(gets.max_anisotropy, anisotropy));
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
mSamplerMap[params] = s;
|
mSamplerMap[params] = s;
|
||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,12 +48,13 @@
|
|||||||
|
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
#include <utils/BitmaskEnum.h>
|
#include <utils/BitmaskEnum.h>
|
||||||
#include <utils/FixedCapacityVector.h>
|
|
||||||
#include <utils/CString.h>
|
#include <utils/CString.h>
|
||||||
|
#include <utils/FixedCapacityVector.h>
|
||||||
#include <utils/Invocable.h>
|
#include <utils/Invocable.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
#include <utils/Slice.h>
|
#include <utils/Slice.h>
|
||||||
|
#include <utils/Systrace.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
@@ -184,20 +185,18 @@ OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* platform,
|
|||||||
// GLVertexBufferInfo : 132 moderate
|
// GLVertexBufferInfo : 132 moderate
|
||||||
// -- less than or equal to 136 bytes
|
// -- less than or equal to 136 bytes
|
||||||
|
|
||||||
slog.d
|
DLOG(INFO) << "GLSwapChain: " << sizeof(GLSwapChain);
|
||||||
<< "\nGLSwapChain: " << sizeof(GLSwapChain)
|
DLOG(INFO) << "GLBufferObject: " << sizeof(GLBufferObject);
|
||||||
<< "\nGLBufferObject: " << sizeof(GLBufferObject)
|
DLOG(INFO) << "GLVertexBuffer: " << sizeof(GLVertexBuffer);
|
||||||
<< "\nGLVertexBuffer: " << sizeof(GLVertexBuffer)
|
DLOG(INFO) << "GLVertexBufferInfo: " << sizeof(GLVertexBufferInfo);
|
||||||
<< "\nGLVertexBufferInfo: " << sizeof(GLVertexBufferInfo)
|
DLOG(INFO) << "GLIndexBuffer: " << sizeof(GLIndexBuffer);
|
||||||
<< "\nGLIndexBuffer: " << sizeof(GLIndexBuffer)
|
DLOG(INFO) << "GLRenderPrimitive: " << sizeof(GLRenderPrimitive);
|
||||||
<< "\nGLRenderPrimitive: " << sizeof(GLRenderPrimitive)
|
DLOG(INFO) << "GLTexture: " << sizeof(GLTexture);
|
||||||
<< "\nGLTexture: " << sizeof(GLTexture)
|
DLOG(INFO) << "GLTimerQuery: " << sizeof(GLTimerQuery);
|
||||||
<< "\nGLTimerQuery: " << sizeof(GLTimerQuery)
|
DLOG(INFO) << "GLStream: " << sizeof(GLStream);
|
||||||
<< "\nGLStream: " << sizeof(GLStream)
|
DLOG(INFO) << "GLRenderTarget: " << sizeof(GLRenderTarget);
|
||||||
<< "\nGLRenderTarget: " << sizeof(GLRenderTarget)
|
DLOG(INFO) << "GLFence: " << sizeof(GLFence);
|
||||||
<< "\nGLFence: " << sizeof(GLFence)
|
DLOG(INFO) << "OpenGLProgram: " << sizeof(OpenGLProgram);
|
||||||
<< "\nOpenGLProgram: " << sizeof(OpenGLProgram)
|
|
||||||
<< io::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// here we check we're on a supported version of GL before initializing the driver
|
// here we check we're on a supported version of GL before initializing the driver
|
||||||
@@ -289,7 +288,7 @@ OpenGLDriver::OpenGLDriver(OpenGLPlatform* platform, const Platform::DriverConfi
|
|||||||
mStreamsWithPendingAcquiredImage.reserve(8);
|
mStreamsWithPendingAcquiredImage.reserve(8);
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
slog.i << "OS version: " << mPlatform.getOSVersion() << io::endl;
|
LOG(INFO) << "OS version: " << mPlatform.getOSVersion();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// Timer queries are core in GL 3.3, otherwise we need EXT_disjoint_timer_query
|
// Timer queries are core in GL 3.3, otherwise we need EXT_disjoint_timer_query
|
||||||
@@ -668,7 +667,7 @@ void OpenGLDriver::createIndexBufferR(
|
|||||||
gl.bindVertexArray(nullptr);
|
gl.bindVertexArray(nullptr);
|
||||||
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
|
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
|
||||||
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, nullptr, getBufferUsage(usage));
|
glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, nullptr, getBufferUsage(usage));
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
|
void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
|
||||||
@@ -693,7 +692,7 @@ void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
|
|||||||
glBufferData(bo->gl.binding, byteCount, nullptr, getBufferUsage(usage));
|
glBufferData(bo->gl.binding, byteCount, nullptr, getBufferUsage(usage));
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
||||||
@@ -730,7 +729,7 @@ void OpenGLDriver::createRenderPrimitiveR(Handle<HwRenderPrimitive> rph,
|
|||||||
// this records the index buffer into the currently bound VAO
|
// this records the index buffer into the currently bound VAO
|
||||||
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
|
gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, ib->gl.buffer);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
||||||
@@ -760,7 +759,7 @@ void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
construct<OpenGLProgram>(ph, *this, std::move(program));
|
construct<OpenGLProgram>(ph, *this, std::move(program));
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
@@ -932,7 +931,12 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
|||||||
#if defined(BACKEND_OPENGL_LEVEL_GLES31)
|
#if defined(BACKEND_OPENGL_LEVEL_GLES31)
|
||||||
if (gl.features.multisample_texture) {
|
if (gl.features.multisample_texture) {
|
||||||
// multi-sample texture on GL 3.2 / GLES 3.1 and above
|
// multi-sample texture on GL 3.2 / GLES 3.1 and above
|
||||||
t->gl.target = GL_TEXTURE_2D_MULTISAMPLE;
|
if (depth <= 1) {
|
||||||
|
// We forcibly change the target to 2D-multisample only for flat texture.
|
||||||
|
// A depth value greater than 1 may indicate multiview usage, which requires
|
||||||
|
// GL_TEXTURE_2D_ARRAY. Also 2D MSAA won't work with non-flat texture anyway.
|
||||||
|
t->gl.target = GL_TEXTURE_2D_MULTISAMPLE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Turn off multi-sampling for that texture. It's just not supported.
|
// Turn off multi-sampling for that texture. It's just not supported.
|
||||||
}
|
}
|
||||||
@@ -948,7 +952,7 @@ void OpenGLDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
|||||||
renderBufferStorage(t->gl.id, internalFormat, w, h, samples);
|
renderBufferStorage(t->gl.id, internalFormat, w, h, samples);
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
||||||
@@ -994,7 +998,7 @@ void OpenGLDriver::createTextureViewR(Handle<HwTexture> th,
|
|||||||
assert_invariant(ref);
|
assert_invariant(ref);
|
||||||
ref->count++;
|
ref->count++;
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwTexture> srch,
|
||||||
@@ -1057,7 +1061,7 @@ void OpenGLDriver::createTextureViewSwizzleR(Handle<HwTexture> th, Handle<HwText
|
|||||||
assert_invariant(ref);
|
assert_invariant(ref);
|
||||||
ref->count++;
|
ref->count++;
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
|
void OpenGLDriver::createTextureExternalImage2R(Handle<HwTexture> th, SamplerType target,
|
||||||
@@ -1208,14 +1212,19 @@ void OpenGLDriver::importTextureR(Handle<HwTexture> th, intptr_t id,
|
|||||||
#if defined(BACKEND_OPENGL_LEVEL_GLES31)
|
#if defined(BACKEND_OPENGL_LEVEL_GLES31)
|
||||||
if (gl.features.multisample_texture) {
|
if (gl.features.multisample_texture) {
|
||||||
// multi-sample texture on GL 3.2 / GLES 3.1 and above
|
// multi-sample texture on GL 3.2 / GLES 3.1 and above
|
||||||
t->gl.target = GL_TEXTURE_2D_MULTISAMPLE;
|
if (depth <= 1) {
|
||||||
|
// We forcibly change the target to 2D-multisample only for flat texture.
|
||||||
|
// A depth value greater than 1 may indicate multiview usage, which requires
|
||||||
|
// GL_TEXTURE_2D_ARRAY. Also 2D MSAA won't work with non-flat texture anyway.
|
||||||
|
t->gl.target = GL_TEXTURE_2D_MULTISAMPLE;
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// Turn off multi-sampling for that texture. It's just not supported.
|
// Turn off multi-sampling for that texture. It's just not supported.
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::updateVertexArrayObject(GLRenderPrimitive* rp, GLVertexBuffer const* vb) {
|
void OpenGLDriver::updateVertexArrayObject(GLRenderPrimitive* rp, GLVertexBuffer const* vb) {
|
||||||
@@ -1453,8 +1462,15 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
|||||||
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_IOS)
|
#if !defined(__EMSCRIPTEN__) && !defined(FILAMENT_IOS)
|
||||||
if (layerCount > 1) {
|
if (layerCount > 1) {
|
||||||
// if layerCount > 1, it means we use the multiview extension.
|
// if layerCount > 1, it means we use the multiview extension.
|
||||||
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, attachment,
|
if (rt->gl.samples > 1) {
|
||||||
t->gl.id, 0, binfo.layer, layerCount);
|
// For MSAA
|
||||||
|
glFramebufferTextureMultisampleMultiviewOVR(GL_FRAMEBUFFER, attachment,
|
||||||
|
t->gl.id, 0, rt->gl.samples, binfo.layer, layerCount);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
glFramebufferTextureMultiviewOVR(GL_FRAMEBUFFER, attachment, t->gl.id, 0,
|
||||||
|
binfo.layer, layerCount);
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
#endif // !defined(__EMSCRIPTEN__) && !defined(FILAMENT_IOS)
|
#endif // !defined(__EMSCRIPTEN__) && !defined(FILAMENT_IOS)
|
||||||
{
|
{
|
||||||
@@ -1468,7 +1484,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
|||||||
// we shouldn't be here
|
// we shouldn't be here
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
} else
|
} else
|
||||||
#ifndef __EMSCRIPTEN__
|
#ifndef __EMSCRIPTEN__
|
||||||
#ifdef GL_EXT_multisampled_render_to_texture
|
#ifdef GL_EXT_multisampled_render_to_texture
|
||||||
@@ -1489,7 +1505,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
|||||||
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment,
|
glFramebufferRenderbuffer(GL_FRAMEBUFFER, attachment,
|
||||||
GL_RENDERBUFFER, t->gl.id);
|
GL_RENDERBUFFER, t->gl.id);
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
} else
|
} else
|
||||||
#endif // GL_EXT_multisampled_render_to_texture
|
#endif // GL_EXT_multisampled_render_to_texture
|
||||||
#endif // __EMSCRIPTEN__
|
#endif // __EMSCRIPTEN__
|
||||||
@@ -1571,13 +1587,13 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
rt->gl.resolve |= resolveFlags;
|
rt->gl.resolve |= resolveFlags;
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_FRAMEBUFFER)
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32_t width, // NOLINT(readability-convert-member-functions-to-static)
|
void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32_t width, // NOLINT(readability-convert-member-functions-to-static)
|
||||||
@@ -1606,7 +1622,7 @@ void OpenGLDriver::renderBufferStorage(GLuint rbo, GLenum internalformat, uint32
|
|||||||
// unbind the renderbuffer, to avoid any later confusion
|
// unbind the renderbuffer, to avoid any later confusion
|
||||||
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
glBindRenderbuffer(GL_RENDERBUFFER, 0);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createDefaultRenderTargetR(
|
void OpenGLDriver::createDefaultRenderTargetR(
|
||||||
@@ -1703,7 +1719,7 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
|||||||
if (UTILS_LIKELY(!getContext().isES2())) {
|
if (UTILS_LIKELY(!getContext().isES2())) {
|
||||||
glDrawBuffers((GLsizei)maxDrawBuffers, bufs);
|
glDrawBuffers((GLsizei)maxDrawBuffers, bufs);
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -1743,7 +1759,7 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
|
|||||||
assert_invariant(any(targets & TargetBufferFlags::ALL));
|
assert_invariant(any(targets & TargetBufferFlags::ALL));
|
||||||
assert_invariant(tmin == tmax);
|
assert_invariant(tmin == tmax);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::createFenceR(Handle<HwFence> fh, int) {
|
void OpenGLDriver::createFenceR(Handle<HwFence> fh, int) {
|
||||||
@@ -2094,7 +2110,7 @@ void OpenGLDriver::setAcquiredImage(Handle<HwStream> sh, void* hwbuffer, const m
|
|||||||
|
|
||||||
if (UTILS_UNLIKELY(glstream->user_thread.pending.image)) {
|
if (UTILS_UNLIKELY(glstream->user_thread.pending.image)) {
|
||||||
scheduleRelease(glstream->user_thread.pending);
|
scheduleRelease(glstream->user_thread.pending);
|
||||||
slog.w << "Acquired image is set more than once per frame." << io::endl;
|
LOG(WARNING) << "Acquired image is set more than once per frame.";
|
||||||
}
|
}
|
||||||
|
|
||||||
glstream->user_thread.pending = mPlatform.transformAcquiredImage({
|
glstream->user_thread.pending = mPlatform.transformAcquiredImage({
|
||||||
@@ -2514,13 +2530,36 @@ void OpenGLDriver::makeCurrent(Handle<HwSwapChain> schDraw, Handle<HwSwapChain>
|
|||||||
|
|
||||||
mPlatform.makeCurrent(scDraw->swapChain, scRead->swapChain,
|
mPlatform.makeCurrent(scDraw->swapChain, scRead->swapChain,
|
||||||
[this]() {
|
[this]() {
|
||||||
|
for (auto t: mTexturesWithStreamsAttached) {
|
||||||
|
if (t->hwStream->streamType == StreamType::NATIVE) {
|
||||||
|
mPlatform.detach(t->hwStream->stream);
|
||||||
|
}
|
||||||
|
}
|
||||||
// OpenGL context is about to change, unbind everything
|
// OpenGL context is about to change, unbind everything
|
||||||
mContext.unbindEverything();
|
mContext.unbindEverything();
|
||||||
},
|
},
|
||||||
[this](size_t index) {
|
[this](size_t index) {
|
||||||
|
for (auto t: mTexturesWithStreamsAttached) {
|
||||||
|
if (t->hwStream->streamType == StreamType::NATIVE) {
|
||||||
|
if (t->externalTexture) {
|
||||||
|
glGenTextures(1, &t->externalTexture->id);
|
||||||
|
t->gl.id = t->externalTexture->id;
|
||||||
|
} else {
|
||||||
|
glGenTextures(1, &t->gl.id);
|
||||||
|
}
|
||||||
|
mPlatform.attach(t->hwStream->stream, t->gl.id);
|
||||||
|
mContext.updateTexImage(GL_TEXTURE_EXTERNAL_OES, t->gl.id);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// force invalidation of all bound descriptor sets
|
||||||
|
decltype(mInvalidDescriptorSetBindings) changed;
|
||||||
|
changed.setValue((1 << MAX_DESCRIPTOR_SET_COUNT) - 1);
|
||||||
|
mInvalidDescriptorSetBindings |= changed;
|
||||||
|
|
||||||
// OpenGL context has changed, resynchronize the state with the cache
|
// OpenGL context has changed, resynchronize the state with the cache
|
||||||
mContext.synchronizeStateAndCache(index);
|
mContext.synchronizeStateAndCache(index);
|
||||||
slog.d << "*** OpenGL context change : " << (index ? "protected" : "default") << io::endl;
|
DLOG(INFO) << "*** OpenGL context change : " << (index ? "protected" : "default");
|
||||||
});
|
});
|
||||||
|
|
||||||
mCurrentDrawSwapChain = scDraw;
|
mCurrentDrawSwapChain = scDraw;
|
||||||
@@ -2561,7 +2600,7 @@ void OpenGLDriver::setVertexBufferObject(Handle<HwVertexBuffer> vbh,
|
|||||||
vb->bufferObjectsVersion = (version + 1) % kMaxVersion;
|
vb->bufferObjectsVersion = (version + 1) % kMaxVersion;
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::updateIndexBuffer(
|
void OpenGLDriver::updateIndexBuffer(
|
||||||
@@ -2578,7 +2617,7 @@ void OpenGLDriver::updateIndexBuffer(
|
|||||||
|
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::registerBufferObjectStreams(Handle<HwBufferObject> boh, BufferObjectStreamDescriptor&& streams) {
|
void OpenGLDriver::registerBufferObjectStreams(Handle<HwBufferObject> boh, BufferObjectStreamDescriptor&& streams) {
|
||||||
@@ -2658,7 +2697,7 @@ void OpenGLDriver::updateBufferObject(
|
|||||||
|
|
||||||
scheduleDestroy(std::move(bd));
|
scheduleDestroy(std::move(bd));
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::updateBufferObjectUnsynchronized(
|
void OpenGLDriver::updateBufferObjectUnsynchronized(
|
||||||
@@ -2705,7 +2744,7 @@ retry:
|
|||||||
scheduleDestroy(std::move(bd));
|
scheduleDestroy(std::move(bd));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2755,7 +2794,7 @@ void OpenGLDriver::generateMipmaps(Handle<HwTexture> th) {
|
|||||||
|
|
||||||
glGenerateMipmap(t->gl.target);
|
glGenerateMipmap(t->gl.target);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::setTextureData(GLTexture const* t, uint32_t level,
|
void OpenGLDriver::setTextureData(GLTexture const* t, uint32_t level,
|
||||||
@@ -2864,7 +2903,7 @@ void OpenGLDriver::setTextureData(GLTexture const* t, uint32_t level,
|
|||||||
|
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::setCompressedTextureData(GLTexture const* t, uint32_t level,
|
void OpenGLDriver::setCompressedTextureData(GLTexture const* t, uint32_t level,
|
||||||
@@ -2950,7 +2989,7 @@ void OpenGLDriver::setCompressedTextureData(GLTexture const* t, uint32_t level,
|
|||||||
|
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
void OpenGLDriver::setupExternalImage2(Platform::ExternalImageHandleRef image) {
|
||||||
@@ -2992,6 +3031,7 @@ void OpenGLDriver::attachStream(GLTexture* t, GLStream* hwStream) noexcept {
|
|||||||
switch (hwStream->streamType) {
|
switch (hwStream->streamType) {
|
||||||
case StreamType::NATIVE:
|
case StreamType::NATIVE:
|
||||||
mPlatform.attach(hwStream->stream, t->gl.id);
|
mPlatform.attach(hwStream->stream, t->gl.id);
|
||||||
|
mContext.updateTexImage(GL_TEXTURE_EXTERNAL_OES, t->gl.id);
|
||||||
break;
|
break;
|
||||||
case StreamType::ACQUIRED:
|
case StreamType::ACQUIRED:
|
||||||
break;
|
break;
|
||||||
@@ -3020,7 +3060,12 @@ void OpenGLDriver::detachStream(GLTexture* t) noexcept {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
glGenTextures(1, &t->gl.id);
|
if (t->externalTexture) {
|
||||||
|
glGenTextures(1, &t->externalTexture->id);
|
||||||
|
t->gl.id = t->externalTexture->id;
|
||||||
|
} else {
|
||||||
|
glGenTextures(1, &t->gl.id);
|
||||||
|
}
|
||||||
|
|
||||||
t->hwStream = nullptr;
|
t->hwStream = nullptr;
|
||||||
}
|
}
|
||||||
@@ -3044,8 +3089,14 @@ void OpenGLDriver::replaceStream(GLTexture* texture, GLStream* newStream) noexce
|
|||||||
|
|
||||||
switch (newStream->streamType) {
|
switch (newStream->streamType) {
|
||||||
case StreamType::NATIVE:
|
case StreamType::NATIVE:
|
||||||
glGenTextures(1, &texture->gl.id);
|
if (texture->externalTexture) {
|
||||||
|
glGenTextures(1, &texture->externalTexture->id);
|
||||||
|
texture->gl.id = texture->externalTexture->id;
|
||||||
|
} else {
|
||||||
|
glGenTextures(1, &texture->gl.id);
|
||||||
|
}
|
||||||
mPlatform.attach(newStream->stream, texture->gl.id);
|
mPlatform.attach(newStream->stream, texture->gl.id);
|
||||||
|
mContext.updateTexImage(GL_TEXTURE_EXTERNAL_OES, texture->gl.id);
|
||||||
break;
|
break;
|
||||||
case StreamType::ACQUIRED:
|
case StreamType::ACQUIRED:
|
||||||
// Just re-use the old texture id.
|
// Just re-use the old texture id.
|
||||||
@@ -3101,7 +3152,7 @@ void OpenGLDriver::beginRenderPass(Handle<HwRenderTarget> rth,
|
|||||||
TargetBufferFlags discardFlags = params.flags.discardStart & rt->targets;
|
TargetBufferFlags discardFlags = params.flags.discardStart & rt->targets;
|
||||||
|
|
||||||
GLuint const fbo = gl.bindFramebuffer(GL_FRAMEBUFFER, rt->gl.fbo);
|
GLuint const fbo = gl.bindFramebuffer(GL_FRAMEBUFFER, rt->gl.fbo);
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_FRAMEBUFFER)
|
||||||
|
|
||||||
// each render-pass starts with a disabled scissor
|
// each render-pass starts with a disabled scissor
|
||||||
gl.disable(GL_SCISSOR_TEST);
|
gl.disable(GL_SCISSOR_TEST);
|
||||||
@@ -3113,7 +3164,7 @@ void OpenGLDriver::beginRenderPass(Handle<HwRenderTarget> rth,
|
|||||||
if (attachmentCount) {
|
if (attachmentCount) {
|
||||||
gl.procs.invalidateFramebuffer(GL_FRAMEBUFFER, attachmentCount, attachments.data());
|
gl.procs.invalidateFramebuffer(GL_FRAMEBUFFER, attachmentCount, attachments.data());
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
} else {
|
} else {
|
||||||
// It's important to clear the framebuffer before drawing, as it resets
|
// It's important to clear the framebuffer before drawing, as it resets
|
||||||
// the fb to a known state (resets fb compression and possibly other things).
|
// the fb to a known state (resets fb compression and possibly other things).
|
||||||
@@ -3200,7 +3251,7 @@ void OpenGLDriver::endRenderPass(int) {
|
|||||||
if (attachmentCount) {
|
if (attachmentCount) {
|
||||||
gl.procs.invalidateFramebuffer(GL_FRAMEBUFFER, attachmentCount, attachments.data());
|
gl.procs.invalidateFramebuffer(GL_FRAMEBUFFER, attachmentCount, attachments.data());
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -3246,13 +3297,13 @@ void OpenGLDriver::resolvePass(ResolveAction action, GLRenderTarget const* rt,
|
|||||||
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, read);
|
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, read);
|
||||||
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, draw);
|
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, draw);
|
||||||
|
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_READ_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_READ_FRAMEBUFFER)
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_DRAW_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_DRAW_FRAMEBUFFER)
|
||||||
|
|
||||||
gl.disable(GL_SCISSOR_TEST);
|
gl.disable(GL_SCISSOR_TEST);
|
||||||
glBlitFramebuffer(0, 0, (GLint)rt->width, (GLint)rt->height,
|
glBlitFramebuffer(0, 0, (GLint)rt->width, (GLint)rt->height,
|
||||||
0, 0, (GLint)rt->width, (GLint)rt->height, mask, GL_NEAREST);
|
0, 0, (GLint)rt->width, (GLint)rt->height, mask, GL_NEAREST);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -3431,7 +3482,7 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
|
|||||||
if (buffer) {
|
if (buffer) {
|
||||||
gl.bindFramebuffer(GL_FRAMEBUFFER, s->gl.fbo_read ? s->gl.fbo_read : s->gl.fbo);
|
gl.bindFramebuffer(GL_FRAMEBUFFER, s->gl.fbo_read ? s->gl.fbo_read : s->gl.fbo);
|
||||||
glReadPixels(GLint(x), GLint(y), GLint(width), GLint(height), glFormat, glType, buffer);
|
glReadPixels(GLint(x), GLint(y), GLint(width), GLint(height), glFormat, glType, buffer);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// now we need to flip the buffer vertically to match our API
|
// now we need to flip the buffer vertically to match our API
|
||||||
size_t const stride = p.stride ? p.stride : width;
|
size_t const stride = p.stride ? p.stride : width;
|
||||||
@@ -3463,7 +3514,7 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
|
|||||||
glBufferData(GL_PIXEL_PACK_BUFFER, pboSize, nullptr, GL_STATIC_DRAW);
|
glBufferData(GL_PIXEL_PACK_BUFFER, pboSize, nullptr, GL_STATIC_DRAW);
|
||||||
glReadPixels(GLint(x), GLint(y), GLint(width), GLint(height), glFormat, glType, nullptr);
|
glReadPixels(GLint(x), GLint(y), GLint(width), GLint(height), glFormat, glType, nullptr);
|
||||||
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// we're forced to make a copy on the heap because otherwise it deletes std::function<> copy
|
// we're forced to make a copy on the heap because otherwise it deletes std::function<> copy
|
||||||
// constructor.
|
// constructor.
|
||||||
@@ -3503,7 +3554,7 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
|
|||||||
glDeleteBuffers(1, &pbo);
|
glDeleteBuffers(1, &pbo);
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
delete pUserBuffer;
|
delete pUserBuffer;
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
});
|
});
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -3528,7 +3579,7 @@ void OpenGLDriver::readBufferSubData(BufferObjectHandle boh,
|
|||||||
glCopyBufferSubData(bo->gl.binding, GL_PIXEL_PACK_BUFFER, offset, 0, size);
|
glCopyBufferSubData(bo->gl.binding, GL_PIXEL_PACK_BUFFER, offset, 0, size);
|
||||||
gl.bindBuffer(bo->gl.binding, 0);
|
gl.bindBuffer(bo->gl.binding, 0);
|
||||||
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
gl.bindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// then, we schedule a mapBuffer of the PBO later, once the fence has signaled
|
// then, we schedule a mapBuffer of the PBO later, once the fence has signaled
|
||||||
auto* pUserBuffer = new BufferDescriptor(std::move(p));
|
auto* pUserBuffer = new BufferDescriptor(std::move(p));
|
||||||
@@ -3545,7 +3596,7 @@ void OpenGLDriver::readBufferSubData(BufferObjectHandle boh,
|
|||||||
glDeleteBuffers(1, &pbo);
|
glDeleteBuffers(1, &pbo);
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
delete pUserBuffer;
|
delete pUserBuffer;
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
gl.bindBuffer(bo->gl.binding, bo->gl.id);
|
gl.bindBuffer(bo->gl.binding, bo->gl.id);
|
||||||
@@ -3558,7 +3609,7 @@ void OpenGLDriver::readBufferSubData(BufferObjectHandle boh,
|
|||||||
}
|
}
|
||||||
gl.bindBuffer(bo->gl.binding, 0);
|
gl.bindBuffer(bo->gl.binding, 0);
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
@@ -3588,7 +3639,7 @@ void OpenGLDriver::whenFrameComplete(const std::function<void()>& fn) noexcept {
|
|||||||
void OpenGLDriver::whenGpuCommandsComplete(const std::function<void()>& fn) noexcept {
|
void OpenGLDriver::whenGpuCommandsComplete(const std::function<void()>& fn) noexcept {
|
||||||
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
GLsync sync = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||||
mGpuCommandCompleteOps.emplace_back(sync, fn);
|
mGpuCommandCompleteOps.emplace_back(sync, fn);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::executeGpuCommandsCompleteOps() noexcept {
|
void OpenGLDriver::executeGpuCommandsCompleteOps() noexcept {
|
||||||
@@ -3708,8 +3759,7 @@ void OpenGLDriver::updateDescriptorSetTexture(
|
|||||||
TextureHandle th,
|
TextureHandle th,
|
||||||
SamplerParams params) {
|
SamplerParams params) {
|
||||||
GLDescriptorSet* ds = handle_cast<GLDescriptorSet*>(dsh);
|
GLDescriptorSet* ds = handle_cast<GLDescriptorSet*>(dsh);
|
||||||
GLTexture* t = th ? handle_cast<GLTexture*>(th) : nullptr;
|
ds->update(mContext, mHandleAllocator, binding, th, params);
|
||||||
ds->update(mContext, binding, t, params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::flush(int) {
|
void OpenGLDriver::flush(int) {
|
||||||
@@ -3807,7 +3857,7 @@ void OpenGLDriver::clearWithRasterPipe(TargetBufferFlags clearFlags,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLDriver::resolve(
|
void OpenGLDriver::resolve(
|
||||||
@@ -3918,7 +3968,7 @@ void OpenGLDriver::blit(
|
|||||||
case SamplerType::SAMPLER_EXTERNAL:
|
case SamplerType::SAMPLER_EXTERNAL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_DRAW_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_DRAW_FRAMEBUFFER)
|
||||||
|
|
||||||
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo[1]);
|
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, fbo[1]);
|
||||||
switch (s->target) {
|
switch (s->target) {
|
||||||
@@ -3944,14 +3994,14 @@ void OpenGLDriver::blit(
|
|||||||
case SamplerType::SAMPLER_EXTERNAL:
|
case SamplerType::SAMPLER_EXTERNAL:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_READ_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_READ_FRAMEBUFFER)
|
||||||
|
|
||||||
gl.disable(GL_SCISSOR_TEST);
|
gl.disable(GL_SCISSOR_TEST);
|
||||||
glBlitFramebuffer(
|
glBlitFramebuffer(
|
||||||
srcOrigin.x, srcOrigin.y, srcOrigin.x + size.x, srcOrigin.y + size.y,
|
srcOrigin.x, srcOrigin.y, srcOrigin.x + size.x, srcOrigin.y + size.y,
|
||||||
dstOrigin.x, dstOrigin.y, dstOrigin.x + size.x, dstOrigin.y + size.y,
|
dstOrigin.x, dstOrigin.y, dstOrigin.x + size.x, dstOrigin.y + size.y,
|
||||||
mask, GL_NEAREST);
|
mask, GL_NEAREST);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
gl.unbindFramebuffer(GL_DRAW_FRAMEBUFFER);
|
gl.unbindFramebuffer(GL_DRAW_FRAMEBUFFER);
|
||||||
gl.unbindFramebuffer(GL_READ_FRAMEBUFFER);
|
gl.unbindFramebuffer(GL_READ_FRAMEBUFFER);
|
||||||
@@ -4014,15 +4064,15 @@ void OpenGLDriver::blitDEPRECATED(TargetBufferFlags buffers,
|
|||||||
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, s->gl.fbo);
|
gl.bindFramebuffer(GL_READ_FRAMEBUFFER, s->gl.fbo);
|
||||||
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, d->gl.fbo);
|
gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, d->gl.fbo);
|
||||||
|
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_READ_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_READ_FRAMEBUFFER)
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_DRAW_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_DRAW_FRAMEBUFFER)
|
||||||
|
|
||||||
gl.disable(GL_SCISSOR_TEST);
|
gl.disable(GL_SCISSOR_TEST);
|
||||||
glBlitFramebuffer(
|
glBlitFramebuffer(
|
||||||
srcRect.left, srcRect.bottom, srcRect.right(), srcRect.top(),
|
srcRect.left, srcRect.bottom, srcRect.right(), srcRect.top(),
|
||||||
dstRect.left, dstRect.bottom, dstRect.right(), dstRect.top(),
|
dstRect.left, dstRect.bottom, dstRect.right(), dstRect.top(),
|
||||||
GL_COLOR_BUFFER_BIT, glFilterMode);
|
GL_COLOR_BUFFER_BIT, glFilterMode);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4149,9 +4199,9 @@ void OpenGLDriver::draw2(uint32_t indexOffset, uint32_t indexCount, uint32_t ins
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FILAMENT_ENABLE_MATDBG
|
#if FILAMENT_ENABLE_MATDBG
|
||||||
CHECK_GL_ERROR_NON_FATAL(utils::slog.e)
|
CHECK_GL_ERROR_NON_FATAL()
|
||||||
#else
|
#else
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4181,9 +4231,9 @@ void OpenGLDriver::draw2GLES2(uint32_t indexOffset, uint32_t indexCount, uint32_
|
|||||||
reinterpret_cast<const void*>(indexOffset << rp->gl.indicesShift));
|
reinterpret_cast<const void*>(indexOffset << rp->gl.indicesShift));
|
||||||
|
|
||||||
#if FILAMENT_ENABLE_MATDBG
|
#if FILAMENT_ENABLE_MATDBG
|
||||||
CHECK_GL_ERROR_NON_FATAL(utils::slog.e)
|
CHECK_GL_ERROR_NON_FATAL()
|
||||||
#else
|
#else
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -4233,9 +4283,9 @@ void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, uint3 workGroupCou
|
|||||||
#endif // BACKEND_OPENGL_LEVEL_GLES31
|
#endif // BACKEND_OPENGL_LEVEL_GLES31
|
||||||
|
|
||||||
#if FILAMENT_ENABLE_MATDBG
|
#if FILAMENT_ENABLE_MATDBG
|
||||||
CHECK_GL_ERROR_NON_FATAL(utils::slog.e)
|
CHECK_GL_ERROR_NON_FATAL()
|
||||||
#else
|
#else
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ utils::CString OpenGLPlatform::getRendererString(Driver const* driver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void OpenGLPlatform::makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
|
void OpenGLPlatform::makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
|
||||||
utils::Invocable<void()>, utils::Invocable<void(size_t)>) noexcept {
|
utils::Invocable<void()>, utils::Invocable<void(size_t)>) {
|
||||||
makeCurrent(getCurrentContextType(), drawSwapChain, readSwapChain);
|
makeCurrent(getCurrentContextType(), drawSwapChain, readSwapChain);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,7 @@ void OpenGLProgram::initializeProgramState(OpenGLContext& context, GLuint progra
|
|||||||
case DescriptorType::INPUT_ATTACHMENT:
|
case DescriptorType::INPUT_ATTACHMENT:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -114,14 +114,14 @@ void TimerQueryNativeFactory::createTimerQuery(GLTimerQuery* tq) {
|
|||||||
|
|
||||||
tq->state = std::make_shared<GLTimerQuery::State>();
|
tq->state = std::make_shared<GLTimerQuery::State>();
|
||||||
mContext.procs.genQueries(1u, &tq->state->gl.query);
|
mContext.procs.genQueries(1u, &tq->state->gl.query);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerQueryNativeFactory::destroyTimerQuery(GLTimerQuery* tq) {
|
void TimerQueryNativeFactory::destroyTimerQuery(GLTimerQuery* tq) {
|
||||||
assert_invariant(tq->state);
|
assert_invariant(tq->state);
|
||||||
|
|
||||||
mContext.procs.deleteQueries(1u, &tq->state->gl.query);
|
mContext.procs.deleteQueries(1u, &tq->state->gl.query);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
tq->state.reset();
|
tq->state.reset();
|
||||||
}
|
}
|
||||||
@@ -131,14 +131,14 @@ void TimerQueryNativeFactory::beginTimeElapsedQuery(GLTimerQuery* tq) {
|
|||||||
|
|
||||||
tq->state->elapsed.store(int64_t(TimerQueryResult::NOT_READY), std::memory_order_relaxed);
|
tq->state->elapsed.store(int64_t(TimerQueryResult::NOT_READY), std::memory_order_relaxed);
|
||||||
mContext.procs.beginQuery(GL_TIME_ELAPSED, tq->state->gl.query);
|
mContext.procs.beginQuery(GL_TIME_ELAPSED, tq->state->gl.query);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
void TimerQueryNativeFactory::endTimeElapsedQuery(OpenGLDriver& driver, GLTimerQuery* tq) {
|
void TimerQueryNativeFactory::endTimeElapsedQuery(OpenGLDriver& driver, GLTimerQuery* tq) {
|
||||||
assert_invariant(tq->state);
|
assert_invariant(tq->state);
|
||||||
|
|
||||||
mContext.procs.endQuery(GL_TIME_ELAPSED);
|
mContext.procs.endQuery(GL_TIME_ELAPSED);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
std::weak_ptr<GLTimerQuery::State> const weak = tq->state;
|
std::weak_ptr<GLTimerQuery::State> const weak = tq->state;
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ void TimerQueryNativeFactory::endTimeElapsedQuery(OpenGLDriver& driver, GLTimerQ
|
|||||||
|
|
||||||
GLuint available = 0;
|
GLuint available = 0;
|
||||||
context.procs.getQueryObjectuiv(state->gl.query, GL_QUERY_RESULT_AVAILABLE, &available);
|
context.procs.getQueryObjectuiv(state->gl.query, GL_QUERY_RESULT_AVAILABLE, &available);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
if (!available) {
|
if (!available) {
|
||||||
// we need to try this one again later
|
// we need to try this one again later
|
||||||
return false;
|
return false;
|
||||||
|
|||||||
@@ -23,6 +23,7 @@
|
|||||||
#include "OpenGLDriver.h"
|
#include "OpenGLDriver.h"
|
||||||
|
|
||||||
#include <iterator>
|
#include <iterator>
|
||||||
|
#include <optional>
|
||||||
#include <private/backend/BackendUtils.h>
|
#include <private/backend/BackendUtils.h>
|
||||||
|
|
||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
@@ -30,14 +31,14 @@
|
|||||||
|
|
||||||
#include <private/utils/Tracing.h>
|
#include <private/utils/Tracing.h>
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
#include <utils/CString.h>
|
#include <utils/CString.h>
|
||||||
#include <utils/debug.h>
|
|
||||||
#include <utils/FixedCapacityVector.h>
|
#include <utils/FixedCapacityVector.h>
|
||||||
#include <utils/JobSystem.h>
|
#include <utils/JobSystem.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/ostream.h>
|
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
#include <utils/debug.h>
|
||||||
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
#include <array>
|
||||||
@@ -64,9 +65,9 @@ static std::string to_string(bool const b) { return b ? "true" : "false"; }
|
|||||||
static std::string to_string(int const i) { return std::to_string(i); }
|
static std::string to_string(int const i) { return std::to_string(i); }
|
||||||
static std::string to_string(float const f) { return "float(" + std::to_string(f) + ")"; }
|
static std::string to_string(float const f) { return "float(" + std::to_string(f) + ")"; }
|
||||||
|
|
||||||
static void logCompilationError(io::ostream& out, ShaderStage shaderType, const char* name,
|
static void logCompilationError(ShaderStage shaderType, const char* name, GLuint shaderId,
|
||||||
GLuint shaderId, CString const& sourceCode) noexcept;
|
CString const& sourceCode) noexcept;
|
||||||
static void logProgramLinkError(io::ostream& out, char const* name, GLuint program) noexcept;
|
static void logProgramLinkError(char const* name, GLuint program) noexcept;
|
||||||
|
|
||||||
static void process_GOOGLE_cpp_style_line_directive(OpenGLContext const& context, char* source,
|
static void process_GOOGLE_cpp_style_line_directive(OpenGLContext const& context, char* source,
|
||||||
size_t len) noexcept;
|
size_t len) noexcept;
|
||||||
@@ -110,17 +111,33 @@ struct ShaderCompilerService::OpenGLProgramToken : ProgramToken {
|
|||||||
cond.wait(l, [this] { return signaled; });
|
cond.wait(l, [this] { return signaled; });
|
||||||
}
|
}
|
||||||
|
|
||||||
CallbackManager::Handle handle{};
|
// This is invoked upon token completion, which occurs after a successful `gl.program`
|
||||||
|
// population or upon cancellation. In either scenario, the callback handle must be submitted
|
||||||
|
// to notify the caller that resource loading has concluded.
|
||||||
|
void trySubmittingCallback() noexcept {
|
||||||
|
if (handle) {
|
||||||
|
compiler.submitCallbackHandle(*handle);
|
||||||
|
handle = std::nullopt;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::optional<CallbackManager::Handle> handle{};
|
||||||
|
|
||||||
|
// Only valid when the blob functions are provided by users. The validity of this variable
|
||||||
|
// doesn't guarantee that the program was created from the cache blob.
|
||||||
BlobCacheKey key;
|
BlobCacheKey key;
|
||||||
|
|
||||||
// Used for the `THREAD_POOL` mode.
|
// Used for the `THREAD_POOL` mode.
|
||||||
mutable Mutex lock;
|
mutable Mutex lock;
|
||||||
mutable Condition cond;
|
mutable Condition cond;
|
||||||
bool signaled = false;
|
bool signaled = false;
|
||||||
|
|
||||||
|
// Indicate this program was created from the cache blob.
|
||||||
|
bool retrievedFromBlobCache = false;
|
||||||
};
|
};
|
||||||
|
|
||||||
ShaderCompilerService::OpenGLProgramToken::~OpenGLProgramToken() {
|
ShaderCompilerService::OpenGLProgramToken::~OpenGLProgramToken() {
|
||||||
compiler.submitCallbackHandle(handle);
|
trySubmittingCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ void ShaderCompilerService::setUserData(const program_token_t& token,
|
/* static */ void ShaderCompilerService::setUserData(const program_token_t& token,
|
||||||
@@ -248,6 +265,7 @@ ShaderCompilerService::program_token_t ShaderCompilerService::createProgram(
|
|||||||
// Try retrieving the cached program blob if available.
|
// Try retrieving the cached program blob if available.
|
||||||
token->gl.program = mBlobCache.retrieve(&token->key, mDriver.mPlatform, program);
|
token->gl.program = mBlobCache.retrieve(&token->key, mDriver.mPlatform, program);
|
||||||
if (token->gl.program) {
|
if (token->gl.program) {
|
||||||
|
token->retrievedFromBlobCache = true;
|
||||||
return token;
|
return token;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,12 +344,15 @@ GLuint ShaderCompilerService::getProgram(program_token_t& token) {
|
|||||||
|
|
||||||
assert_invariant(token);// This function should be called when the token is still alive.
|
assert_invariant(token);// This function should be called when the token is still alive.
|
||||||
|
|
||||||
if (token->compiler.mMode == Mode::THREAD_POOL) {
|
// Finalize any pending shader compilation tasks only when the token was created without cache.
|
||||||
auto const job = token->compiler.mCompilerThreadPool.dequeue(token);
|
if (!token->retrievedFromBlobCache) {
|
||||||
if (!job) {
|
if (token->compiler.mMode == Mode::THREAD_POOL) {
|
||||||
// It's likely that the job was already completed. But it may be still being
|
auto const job = token->compiler.mCompilerThreadPool.dequeue(token);
|
||||||
// executed at this moment. Just try waiting for it to avoid a race.
|
if (!job) {
|
||||||
token->wait();
|
// It's likely that the job was already completed. But it may be still being
|
||||||
|
// executed at this moment. Just try waiting for it to avoid a race.
|
||||||
|
token->wait();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -339,7 +360,7 @@ GLuint ShaderCompilerService::getProgram(program_token_t& token) {
|
|||||||
|
|
||||||
// Cleanup the token.
|
// Cleanup the token.
|
||||||
token->compiler.cancelTickOp(token);
|
token->compiler.cancelTickOp(token);
|
||||||
token = nullptr;// This will submit a callback condition (handle) to the callback manager.
|
token = nullptr; // This will try submitting a callback handle to the callback manager.
|
||||||
}
|
}
|
||||||
|
|
||||||
void ShaderCompilerService::tick() {
|
void ShaderCompilerService::tick() {
|
||||||
@@ -392,7 +413,7 @@ GLuint ShaderCompilerService::initialize(program_token_t& token) {
|
|||||||
|
|
||||||
// Cleanup the token.
|
// Cleanup the token.
|
||||||
token->compiler.cancelTickOp(token);
|
token->compiler.cancelTickOp(token);
|
||||||
token = nullptr;// This will submit a callback condition (handle) to the callback manager.
|
token = nullptr;
|
||||||
|
|
||||||
return program;
|
return program;
|
||||||
}
|
}
|
||||||
@@ -422,8 +443,9 @@ void ShaderCompilerService::ensureTokenIsReady(program_token_t const& token) {
|
|||||||
// just log warnings here instead of repeatedly checking compile status. If this turns
|
// just log warnings here instead of repeatedly checking compile status. If this turns
|
||||||
// out to be a real issue later, we would need to consider doing the canonical way.
|
// out to be a real issue later, we would need to consider doing the canonical way.
|
||||||
if (!isCompileCompleted(token)) {
|
if (!isCompileCompleted(token)) {
|
||||||
slog.w << "Shader compilation for OpenGL program " << token->name.c_str_safe()
|
LOG(WARNING)
|
||||||
<< " is not completed yet. The following program link may not succeed.";
|
<< "Shader compilation for OpenGL program " << token->name.c_str_safe()
|
||||||
|
<< " is not completed yet. The following program link may not succeed.";
|
||||||
}
|
}
|
||||||
|
|
||||||
linkProgram(mDriver.getContext(), token);
|
linkProgram(mDriver.getContext(), token);
|
||||||
@@ -633,8 +655,7 @@ void ShaderCompilerService::executeTickOps() noexcept {
|
|||||||
}
|
}
|
||||||
// Something went wrong. Log the error message.
|
// Something went wrong. Log the error message.
|
||||||
const ShaderStage type = static_cast<ShaderStage>(i);
|
const ShaderStage type = static_cast<ShaderStage>(i);
|
||||||
logCompilationError(slog.e, type, token->name.c_str_safe(), shader,
|
logCompilationError(type, token->name.c_str_safe(), shader, token->shaderSourceCode[i]);
|
||||||
token->shaderSourceCode[i]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -659,6 +680,7 @@ void ShaderCompilerService::executeTickOps() noexcept {
|
|||||||
}
|
}
|
||||||
glLinkProgram(program);
|
glLinkProgram(program);
|
||||||
token->gl.program = program;
|
token->gl.program = program;
|
||||||
|
token->trySubmittingCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
/* static */ bool ShaderCompilerService::isLinkCompleted(program_token_t const& token) noexcept {
|
/* static */ bool ShaderCompilerService::isLinkCompleted(program_token_t const& token) noexcept {
|
||||||
@@ -685,7 +707,7 @@ void ShaderCompilerService::executeTickOps() noexcept {
|
|||||||
glGetProgramiv(token->gl.program, GL_LINK_STATUS, &status);
|
glGetProgramiv(token->gl.program, GL_LINK_STATUS, &status);
|
||||||
if (UTILS_UNLIKELY(status != GL_TRUE)) {
|
if (UTILS_UNLIKELY(status != GL_TRUE)) {
|
||||||
// Something went wrong. Log the error message.
|
// Something went wrong. Log the error message.
|
||||||
logProgramLinkError(slog.e, token->name.c_str_safe(), token->gl.program);
|
logProgramLinkError(token->name.c_str_safe(), token->gl.program);
|
||||||
linked = false;
|
linked = false;
|
||||||
}
|
}
|
||||||
// No need to keep the shaders around regardless of the result of the program linking.
|
// No need to keep the shaders around regardless of the result of the program linking.
|
||||||
@@ -735,7 +757,7 @@ void ShaderCompilerService::executeTickOps() noexcept {
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
/* static */ void logCompilationError(io::ostream& out, ShaderStage shaderType, const char* name,
|
/* static */ void logCompilationError(ShaderStage shaderType, const char* name,
|
||||||
GLuint const shaderId, UTILS_UNUSED_IN_RELEASE CString const& sourceCode) noexcept {
|
GLuint const shaderId, UTILS_UNUSED_IN_RELEASE CString const& sourceCode) noexcept {
|
||||||
|
|
||||||
{ // scope for the temporary string storage
|
{ // scope for the temporary string storage
|
||||||
@@ -757,8 +779,9 @@ UTILS_NOINLINE
|
|||||||
CString infoLog(length);
|
CString infoLog(length);
|
||||||
glGetShaderInfoLog(shaderId, length, nullptr, infoLog.data());
|
glGetShaderInfoLog(shaderId, length, nullptr, infoLog.data());
|
||||||
|
|
||||||
out << "Compilation error in " << to_string(shaderType) << " shader \"" << name << "\":\n"
|
LOG(ERROR) << "Compilation error in " << to_string(shaderType) << " shader \"" << name
|
||||||
<< "\"" << infoLog.c_str() << "\"" << io::endl;
|
<< "\":";
|
||||||
|
LOG(ERROR) << "\"" << infoLog.c_str() << "\"";
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef NDEBUG
|
#ifndef NDEBUG
|
||||||
@@ -773,26 +796,25 @@ UTILS_NOINLINE
|
|||||||
} else {
|
} else {
|
||||||
line = shader.substr(start, end - start);
|
line = shader.substr(start, end - start);
|
||||||
}
|
}
|
||||||
out << lc++ << ": " << line.c_str() << '\n';
|
LOG(ERROR) << lc++ << ": " << line.c_str();
|
||||||
if (end == std::string::npos) {
|
if (end == std::string::npos) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
start = end + 1;
|
start = end + 1;
|
||||||
}
|
}
|
||||||
out << io::endl;
|
LOG(ERROR) << "";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
UTILS_NOINLINE
|
UTILS_NOINLINE
|
||||||
/* static */ void logProgramLinkError(io::ostream& out, char const* name, GLuint program) noexcept {
|
/* static */ void logProgramLinkError(char const* name, GLuint program) noexcept {
|
||||||
GLint length = 0;
|
GLint length = 0;
|
||||||
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
|
glGetProgramiv(program, GL_INFO_LOG_LENGTH, &length);
|
||||||
|
|
||||||
CString infoLog(length);
|
CString infoLog(length);
|
||||||
glGetProgramInfoLog(program, length, nullptr, infoLog.data());
|
glGetProgramInfoLog(program, length, nullptr, infoLog.data());
|
||||||
|
|
||||||
out << "Link error in \"" << name << "\":\n"
|
LOG(ERROR) << "Link error in \"" << name << "\":\n" << "\"" << infoLog.c_str() << "\"";
|
||||||
<< "\"" << infoLog.c_str() << "\"" << io::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// If usages of the Google-style line directive are present, remove them, as some
|
// If usages of the Google-style line directive are present, remove them, as some
|
||||||
|
|||||||
@@ -70,6 +70,9 @@ PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glMaxShaderCompilerThreadsKHR;
|
|||||||
#ifdef GL_OVR_multiview
|
#ifdef GL_OVR_multiview
|
||||||
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR;
|
PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef GL_OVR_multiview_multisampled_render_to_texture
|
||||||
|
PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC glFramebufferTextureMultisampleMultiviewOVR;
|
||||||
|
#endif
|
||||||
|
|
||||||
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||||
// On Android, If we want to support a build system less than ANDROID_API 21, we need to
|
// On Android, If we want to support a build system less than ANDROID_API 21, we need to
|
||||||
@@ -123,6 +126,9 @@ void importGLESExtensionsEntryPoints() {
|
|||||||
#ifdef GL_OVR_multiview
|
#ifdef GL_OVR_multiview
|
||||||
getProcAddress(glFramebufferTextureMultiviewOVR, "glFramebufferTextureMultiviewOVR");
|
getProcAddress(glFramebufferTextureMultiviewOVR, "glFramebufferTextureMultiviewOVR");
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef GL_OVR_multiview_multisampled_render_to_texture
|
||||||
|
getProcAddress(glFramebufferTextureMultisampleMultiviewOVR, "glFramebufferTextureMultisampleMultiviewOVR");
|
||||||
|
#endif
|
||||||
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||||
getProcAddress(glDispatchCompute, "glDispatchCompute");
|
getProcAddress(glDispatchCompute, "glDispatchCompute");
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -154,6 +154,9 @@ extern PFNGLMAXSHADERCOMPILERTHREADSKHRPROC glMaxShaderCompilerThreadsKHR;
|
|||||||
#ifdef GL_OVR_multiview
|
#ifdef GL_OVR_multiview
|
||||||
extern PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR;
|
extern PFNGLFRAMEBUFFERTEXTUREMULTIVIEWOVRPROC glFramebufferTextureMultiviewOVR;
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef GL_OVR_multiview_multisampled_render_to_texture
|
||||||
|
extern PFNGLFRAMEBUFFERTEXTUREMULTISAMPLEMULTIVIEWOVRPROC glFramebufferTextureMultisampleMultiviewOVR;
|
||||||
|
#endif
|
||||||
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
#if defined(__ANDROID__) && !defined(FILAMENT_SILENCE_NOT_SUPPORTED_BY_ES2)
|
||||||
extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
|
extern PFNGLDISPATCHCOMPUTEPROC glDispatchCompute;
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -96,7 +96,7 @@ CocoaExternalImage::SharedGl::~SharedGl() noexcept {
|
|||||||
CocoaExternalImage::CocoaExternalImage(const CVOpenGLTextureCacheRef textureCache,
|
CocoaExternalImage::CocoaExternalImage(const CVOpenGLTextureCacheRef textureCache,
|
||||||
const SharedGl &sharedGl) noexcept : mSharedGl(sharedGl), mTextureCache(textureCache) {
|
const SharedGl &sharedGl) noexcept : mSharedGl(sharedGl), mTextureCache(textureCache) {
|
||||||
glGenFramebuffers(1, &mFBO);
|
glGenFramebuffers(1, &mFBO);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
CocoaExternalImage::~CocoaExternalImage() noexcept {
|
CocoaExternalImage::~CocoaExternalImage() noexcept {
|
||||||
@@ -125,7 +125,7 @@ bool CocoaExternalImage::set(CVPixelBufferRef image) noexcept {
|
|||||||
mTexture = createTextureFromImage(image);
|
mTexture = createTextureFromImage(image);
|
||||||
mRgbaTexture = encodeCopyRectangleToTexture2D(CVOpenGLTextureGetName(mTexture),
|
mRgbaTexture = encodeCopyRectangleToTexture2D(CVOpenGLTextureGetName(mTexture),
|
||||||
CVPixelBufferGetWidth(image), CVPixelBufferGetHeight(image));
|
CVPixelBufferGetWidth(image), CVPixelBufferGetHeight(image));
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@@ -182,33 +182,33 @@ GLuint CocoaExternalImage::encodeCopyRectangleToTexture2D(GLuint rectangle,
|
|||||||
// Create a texture to hold the result of the blit image.
|
// Create a texture to hold the result of the blit image.
|
||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
|
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// source textures
|
// source textures
|
||||||
glBindSampler(0, mSharedGl.sampler);
|
glBindSampler(0, mSharedGl.sampler);
|
||||||
glActiveTexture(GL_TEXTURE0);
|
glActiveTexture(GL_TEXTURE0);
|
||||||
glBindTexture(GL_TEXTURE_RECTANGLE, rectangle);
|
glBindTexture(GL_TEXTURE_RECTANGLE, rectangle);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// destination texture
|
// destination texture
|
||||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_FRAMEBUFFER)
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// draw
|
// draw
|
||||||
glViewport(0, 0, width, height);
|
glViewport(0, 0, width, height);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
glUseProgram(mSharedGl.program);
|
glUseProgram(mSharedGl.program);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
glDisableVertexAttribArray(0);
|
glDisableVertexAttribArray(0);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
mState.restore();
|
mState.restore();
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
return texture;
|
return texture;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -119,7 +119,7 @@ CocoaTouchExternalImage::CocoaTouchExternalImage(const CVOpenGLESTextureCacheRef
|
|||||||
|
|
||||||
glGenFramebuffers(1, &mFBO);
|
glGenFramebuffers(1, &mFBO);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
}
|
}
|
||||||
|
|
||||||
CocoaTouchExternalImage::~CocoaTouchExternalImage() noexcept {
|
CocoaTouchExternalImage::~CocoaTouchExternalImage() noexcept {
|
||||||
@@ -247,7 +247,7 @@ GLuint CocoaTouchExternalImage::encodeColorConversionPass(GLuint yPlaneTexture,
|
|||||||
glBindTexture(GL_TEXTURE_2D, texture);
|
glBindTexture(GL_TEXTURE_2D, texture);
|
||||||
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
|
glTexStorage2D(GL_TEXTURE_2D, 1, GL_RGBA8, width, height);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
// source textures
|
// source textures
|
||||||
glBindSampler(0, mSharedGl.sampler);
|
glBindSampler(0, mSharedGl.sampler);
|
||||||
@@ -261,8 +261,8 @@ GLuint CocoaTouchExternalImage::encodeColorConversionPass(GLuint yPlaneTexture,
|
|||||||
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
glBindFramebuffer(GL_FRAMEBUFFER, mFBO);
|
||||||
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
CHECK_GL_FRAMEBUFFER_STATUS(utils::slog.e, GL_FRAMEBUFFER)
|
CHECK_GL_FRAMEBUFFER_STATUS(GL_FRAMEBUFFER)
|
||||||
|
|
||||||
// geometry
|
// geometry
|
||||||
glBindVertexArray(0);
|
glBindVertexArray(0);
|
||||||
@@ -275,7 +275,7 @@ GLuint CocoaTouchExternalImage::encodeColorConversionPass(GLuint yPlaneTexture,
|
|||||||
glUseProgram(mSharedGl.program);
|
glUseProgram(mSharedGl.program);
|
||||||
glDrawArrays(GL_TRIANGLES, 0, 3);
|
glDrawArrays(GL_TRIANGLES, 0, 3);
|
||||||
|
|
||||||
CHECK_GL_ERROR(utils::slog.e)
|
CHECK_GL_ERROR()
|
||||||
|
|
||||||
mState.restore();
|
mState.restore();
|
||||||
|
|
||||||
|
|||||||
@@ -20,9 +20,9 @@
|
|||||||
|
|
||||||
#include <backend/Platform.h>
|
#include <backend/Platform.h>
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/debug.h>
|
#include <utils/debug.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#if __has_include(<android/surface_texture.h>)
|
#if __has_include(<android/surface_texture.h>)
|
||||||
@@ -59,7 +59,7 @@ void ExternalStreamManagerAndroid::destroy(ExternalStreamManagerAndroid* pExtern
|
|||||||
ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
|
ExternalStreamManagerAndroid::ExternalStreamManagerAndroid() noexcept
|
||||||
: mVm(VirtualMachineEnv::get()) {
|
: mVm(VirtualMachineEnv::get()) {
|
||||||
if (__builtin_available(android 28, *)) {
|
if (__builtin_available(android 28, *)) {
|
||||||
slog.d << "Using ASurfaceTexture" << io::endl;
|
DLOG(INFO) << "Using ASurfaceTexture";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -255,7 +255,7 @@ void PlatformCocoaGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformCocoaGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool PlatformCocoaGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
|
ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
|
||||||
"ContextManagerCocoa does not support using distinct draw/read swap chains.");
|
"ContextManagerCocoa does not support using distinct draw/read swap chains.");
|
||||||
CocoaGLSwapChain* swapChain = (CocoaGLSwapChain*)drawSwapChain;
|
CocoaGLSwapChain* swapChain = (CocoaGLSwapChain*)drawSwapChain;
|
||||||
|
|||||||
@@ -155,7 +155,7 @@ uint32_t PlatformCocoaTouchGL::getDefaultFramebufferObject() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformCocoaTouchGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool PlatformCocoaTouchGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
|
ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
|
||||||
"PlatformCocoaTouchGL does not support using distinct draw/read swap chains.");
|
"PlatformCocoaTouchGL does not support using distinct draw/read swap chains.");
|
||||||
CAEAGLLayer* const glLayer = (__bridge CAEAGLLayer*) drawSwapChain;
|
CAEAGLLayer* const glLayer = (__bridge CAEAGLLayer*) drawSwapChain;
|
||||||
|
|||||||
@@ -32,9 +32,9 @@
|
|||||||
#endif
|
#endif
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
#include <utils/debug.h>
|
|
||||||
#include <utils/Invocable.h>
|
#include <utils/Invocable.h>
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/debug.h>
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
@@ -74,7 +74,7 @@ void PlatformEGL::logEglError(const char* name) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void PlatformEGL::logEglError(const char* name, EGLint error) noexcept {
|
void PlatformEGL::logEglError(const char* name, EGLint error) noexcept {
|
||||||
slog.e << name << " failed with " << getEglErrorName(error) << io::endl;
|
LOG(ERROR) << name << " failed with " << getEglErrorName(error);
|
||||||
}
|
}
|
||||||
|
|
||||||
const char* PlatformEGL::getEglErrorName(EGLint error) noexcept {
|
const char* PlatformEGL::getEglErrorName(EGLint error) noexcept {
|
||||||
@@ -101,7 +101,7 @@ void PlatformEGL::clearGlError() noexcept {
|
|||||||
// clear GL error that may have been set by previous calls
|
// clear GL error that may have been set by previous calls
|
||||||
GLenum const error = glGetError();
|
GLenum const error = glGetError();
|
||||||
if (error != GL_NO_ERROR) {
|
if (error != GL_NO_ERROR) {
|
||||||
slog.w << "Ignoring pending GL error " << io::hex << error << io::endl;
|
LOG(WARNING) << "Ignoring pending GL error " << io::hex << error;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +142,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& drive
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (UTILS_UNLIKELY(!initialized)) {
|
if (UTILS_UNLIKELY(!initialized)) {
|
||||||
slog.e << "eglInitialize failed" << io::endl;
|
LOG(ERROR) << "eglInitialize failed";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -577,18 +577,18 @@ OpenGLPlatform::ContextType PlatformEGL::getCurrentContextType() const noexcept
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformEGL::makeCurrent(ContextType type,
|
bool PlatformEGL::makeCurrent(ContextType type,
|
||||||
SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept {
|
SwapChain* drawSwapChain, SwapChain* readSwapChain) {
|
||||||
SwapChainEGL const* const dsc = static_cast<SwapChainEGL const*>(drawSwapChain);
|
SwapChainEGL const* const dsc = static_cast<SwapChainEGL const*>(drawSwapChain);
|
||||||
SwapChainEGL const* const rsc = static_cast<SwapChainEGL const*>(readSwapChain);
|
SwapChainEGL const* const rsc = static_cast<SwapChainEGL const*>(readSwapChain);
|
||||||
EGLContext context = getContextForType(type);
|
EGLContext context = getContextForType(type);
|
||||||
EGLBoolean const success = egl.makeCurrent(context, dsc->sur, rsc->sur);
|
EGLBoolean const success = egl.makeCurrent(context, dsc->sur, rsc->sur);
|
||||||
return success == EGL_TRUE ? true : false;
|
return success == EGL_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
void PlatformEGL::makeCurrent(SwapChain* drawSwapChain,
|
void PlatformEGL::makeCurrent(SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain,
|
SwapChain* readSwapChain,
|
||||||
Invocable<void()> preContextChange,
|
Invocable<void()> preContextChange,
|
||||||
Invocable<void(size_t index)> postContextChange) noexcept {
|
Invocable<void(size_t index)> postContextChange) {
|
||||||
|
|
||||||
assert_invariant(drawSwapChain);
|
assert_invariant(drawSwapChain);
|
||||||
assert_invariant(readSwapChain);
|
assert_invariant(readSwapChain);
|
||||||
@@ -796,7 +796,7 @@ void PlatformEGL::Config::erase(EGLint name) noexcept {
|
|||||||
// ------------------------------------------------------------------------------------------------
|
// ------------------------------------------------------------------------------------------------
|
||||||
|
|
||||||
EGLBoolean PlatformEGL::EGL::makeCurrent(EGLContext context, EGLSurface drawSurface,
|
EGLBoolean PlatformEGL::EGL::makeCurrent(EGLContext context, EGLSurface drawSurface,
|
||||||
EGLSurface readSurface) noexcept {
|
EGLSurface readSurface) {
|
||||||
if (UTILS_UNLIKELY((
|
if (UTILS_UNLIKELY((
|
||||||
mCurrentContext != context ||
|
mCurrentContext != context ||
|
||||||
drawSurface != mCurrentDrawSurface || readSurface != mCurrentReadSurface))) {
|
drawSurface != mCurrentDrawSurface || readSurface != mCurrentReadSurface))) {
|
||||||
|
|||||||
@@ -29,13 +29,12 @@
|
|||||||
#include <android/native_window.h>
|
#include <android/native_window.h>
|
||||||
#include <android/hardware_buffer.h>
|
#include <android/hardware_buffer.h>
|
||||||
|
|
||||||
|
#include <utils/Logger.h>
|
||||||
|
#include <utils/Panic.h>
|
||||||
#include <utils/android/PerformanceHintManager.h>
|
#include <utils/android/PerformanceHintManager.h>
|
||||||
|
#include <utils/compiler.h>
|
||||||
#include <utils/compiler.h>
|
#include <utils/compiler.h>
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
#include <utils/Panic.h>
|
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/compiler.h>
|
|
||||||
#include <utils/ostream.h>
|
#include <utils/ostream.h>
|
||||||
|
|
||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
@@ -135,7 +134,7 @@ static constexpr const std::string_view kNativeWindowInvalidMsg =
|
|||||||
|
|
||||||
bool PlatformEGLAndroid::makeCurrent(ContextType type,
|
bool PlatformEGLAndroid::makeCurrent(ContextType type,
|
||||||
SwapChain* drawSwapChain,
|
SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
|
|
||||||
// fast & safe path
|
// fast & safe path
|
||||||
if (UTILS_LIKELY(!mAssertNativeWindowIsValid)) {
|
if (UTILS_LIKELY(!mAssertNativeWindowIsValid)) {
|
||||||
@@ -327,7 +326,7 @@ bool PlatformEGLAndroid::setImage(ExternalImageEGLAndroid const* eglExternalImag
|
|||||||
EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
|
EGL_NATIVE_BUFFER_ANDROID, clientBuffer, imageAttrs);
|
||||||
if (eglImage == EGL_NO_IMAGE_KHR) {
|
if (eglImage == EGL_NO_IMAGE_KHR) {
|
||||||
// Handle error
|
// Handle error
|
||||||
slog.e << "Failed to create EGL image" << io::endl;
|
LOG(ERROR) << "Failed to create EGL image";
|
||||||
glDeleteTextures(1, &texture->id);
|
glDeleteTextures(1, &texture->id);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@@ -340,7 +339,7 @@ bool PlatformEGLAndroid::setImage(ExternalImageEGLAndroid const* eglExternalImag
|
|||||||
glBindTexture(texture->target, texture->id);
|
glBindTexture(texture->target, texture->id);
|
||||||
GLenum error = glGetError();
|
GLenum error = glGetError();
|
||||||
if (UTILS_UNLIKELY(error != GL_NO_ERROR)) {
|
if (UTILS_UNLIKELY(error != GL_NO_ERROR)) {
|
||||||
slog.e << "Error after glBindTexture: " << error << io::endl;
|
LOG(ERROR) << "Error after glBindTexture: " << error;
|
||||||
glDeleteTextures(1, &texture->id);
|
glDeleteTextures(1, &texture->id);
|
||||||
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
|
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
|
||||||
glActiveTexture(prevActiveTexture);
|
glActiveTexture(prevActiveTexture);
|
||||||
@@ -350,7 +349,7 @@ bool PlatformEGLAndroid::setImage(ExternalImageEGLAndroid const* eglExternalImag
|
|||||||
glEGLImageTargetTexture2DOES(texture->target, static_cast<GLeglImageOES>(eglImage));
|
glEGLImageTargetTexture2DOES(texture->target, static_cast<GLeglImageOES>(eglImage));
|
||||||
error = glGetError();
|
error = glGetError();
|
||||||
if (UTILS_UNLIKELY(error != GL_NO_ERROR)) {
|
if (UTILS_UNLIKELY(error != GL_NO_ERROR)) {
|
||||||
slog.e << "Error after glEGLImageTargetTexture2DOES: " << error << io::endl;
|
LOG(ERROR) << "Error after glEGLImageTargetTexture2DOES: " << error;
|
||||||
glDeleteTextures(1, &texture->id);
|
glDeleteTextures(1, &texture->id);
|
||||||
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
|
eglDestroyImageKHR(eglGetCurrentDisplay(), eglImage);
|
||||||
glActiveTexture(prevActiveTexture);
|
glActiveTexture(prevActiveTexture);
|
||||||
@@ -408,7 +407,7 @@ AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage source) n
|
|||||||
|
|
||||||
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(pHardwareBuffer);
|
EGLClientBuffer clientBuffer = eglGetNativeClientBufferANDROID(pHardwareBuffer);
|
||||||
if (!clientBuffer) {
|
if (!clientBuffer) {
|
||||||
slog.e << "Unable to get EGLClientBuffer from AHardwareBuffer." << io::endl;
|
LOG(ERROR) << "Unable to get EGLClientBuffer from AHardwareBuffer.";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -427,7 +426,7 @@ AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage source) n
|
|||||||
EGLImageKHR eglImage = eglCreateImageKHR(mEGLDisplay,
|
EGLImageKHR eglImage = eglCreateImageKHR(mEGLDisplay,
|
||||||
EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attributes.data());
|
EGL_NO_CONTEXT, EGL_NATIVE_BUFFER_ANDROID, clientBuffer, attributes.data());
|
||||||
if (eglImage == EGL_NO_IMAGE_KHR) {
|
if (eglImage == EGL_NO_IMAGE_KHR) {
|
||||||
slog.e << "eglCreateImageKHR returned no image." << io::endl;
|
LOG(ERROR) << "eglCreateImageKHR returned no image.";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -442,7 +441,7 @@ AcquiredImage PlatformEGLAndroid::transformAcquiredImage(AcquiredImage source) n
|
|||||||
auto patchedCallback = [](void* image, void* userdata) {
|
auto patchedCallback = [](void* image, void* userdata) {
|
||||||
Closure* closure = (Closure*)userdata;
|
Closure* closure = (Closure*)userdata;
|
||||||
if (eglDestroyImageKHR(closure->display, (EGLImageKHR) image) == EGL_FALSE) {
|
if (eglDestroyImageKHR(closure->display, (EGLImageKHR) image) == EGL_FALSE) {
|
||||||
slog.e << "eglDestroyImageKHR failed." << io::endl;
|
LOG(ERROR) << "eglDestroyImageKHR failed.";
|
||||||
}
|
}
|
||||||
closure->acquiredImage.callback(closure->acquiredImage.image, closure->acquiredImage.userData);
|
closure->acquiredImage.callback(closure->acquiredImage.image, closure->acquiredImage.userData);
|
||||||
delete closure;
|
delete closure;
|
||||||
|
|||||||
@@ -21,9 +21,9 @@
|
|||||||
#include <EGL/egl.h>
|
#include <EGL/egl.h>
|
||||||
#include <EGL/eglext.h>
|
#include <EGL/eglext.h>
|
||||||
|
|
||||||
#include <utils/compiler.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Log.h>
|
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
#include <utils/compiler.h>
|
||||||
|
|
||||||
using namespace utils;
|
using namespace utils;
|
||||||
|
|
||||||
@@ -42,12 +42,12 @@ backend::Driver* PlatformEGLHeadless::createDriver(void* sharedContext,
|
|||||||
const Platform::DriverConfig& driverConfig) noexcept {
|
const Platform::DriverConfig& driverConfig) noexcept {
|
||||||
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_API);
|
EGLBoolean bindAPI = eglBindAPI(EGL_OPENGL_API);
|
||||||
if (UTILS_UNLIKELY(!bindAPI)) {
|
if (UTILS_UNLIKELY(!bindAPI)) {
|
||||||
slog.e << "eglBindAPI EGL_OPENGL_API failed" << io::endl;
|
LOG(ERROR) << "eglBindAPI EGL_OPENGL_API failed";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
int bindBlueGL = bluegl::bind();
|
int bindBlueGL = bluegl::bind();
|
||||||
if (UTILS_UNLIKELY(bindBlueGL != 0)) {
|
if (UTILS_UNLIKELY(bindBlueGL != 0)) {
|
||||||
slog.e << "bluegl bind failed" << io::endl;
|
LOG(ERROR) << "bluegl bind failed";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -16,7 +16,7 @@
|
|||||||
|
|
||||||
#include <backend/platforms/PlatformGLX.h>
|
#include <backend/platforms/PlatformGLX.h>
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
|
||||||
#include <X11/Xlib.h>
|
#include <X11/Xlib.h>
|
||||||
@@ -84,7 +84,7 @@ static PFNGLXGETPROCADDRESSPROC getProcAddress;
|
|||||||
static bool loadLibraries() {
|
static bool loadLibraries() {
|
||||||
g_glx.library = dlopen(LIBRARY_GLX, RTLD_LOCAL | RTLD_NOW);
|
g_glx.library = dlopen(LIBRARY_GLX, RTLD_LOCAL | RTLD_NOW);
|
||||||
if (!g_glx.library) {
|
if (!g_glx.library) {
|
||||||
utils::slog.e << "Could not find library " << LIBRARY_GLX << utils::io::endl;
|
LOG(ERROR) << "Could not find library " << LIBRARY_GLX;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -115,7 +115,7 @@ static bool loadLibraries() {
|
|||||||
|
|
||||||
g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW);
|
g_x11.library = dlopen(LIBRARY_X11, RTLD_LOCAL | RTLD_NOW);
|
||||||
if (!g_x11.library) {
|
if (!g_x11.library) {
|
||||||
utils::slog.e << "Could not find library " << LIBRARY_X11 << utils::io::endl;
|
LOG(ERROR) << "Could not find library " << LIBRARY_X11;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -134,7 +134,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
|||||||
// Get the display device
|
// Get the display device
|
||||||
mGLXDisplay = g_x11.openDisplay(NULL);
|
mGLXDisplay = g_x11.openDisplay(NULL);
|
||||||
if (mGLXDisplay == nullptr) {
|
if (mGLXDisplay == nullptr) {
|
||||||
utils::slog.e << "Failed to open X display. (exiting)." << utils::io::endl;
|
LOG(ERROR) << "Failed to open X display. (exiting).";
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -145,8 +145,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
|||||||
|
|
||||||
r = g_glx.queryContext(mGLXDisplay, sharedCtx, GLX_FBCONFIG_ID, &usedFbId);
|
r = g_glx.queryContext(mGLXDisplay, sharedCtx, GLX_FBCONFIG_ID, &usedFbId);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
utils::slog.e << "Failed to get GLX_FBCONFIG_ID from shared GL context."
|
LOG(ERROR) << "Failed to get GLX_FBCONFIG_ID from shared GL context.";
|
||||||
<< utils::io::endl;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -154,7 +153,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
|||||||
GLXFBConfig* fbConfigs = g_glx.getFbConfigs(mGLXDisplay, 0, &numConfigs);
|
GLXFBConfig* fbConfigs = g_glx.getFbConfigs(mGLXDisplay, 0, &numConfigs);
|
||||||
|
|
||||||
if (fbConfigs == nullptr) {
|
if (fbConfigs == nullptr) {
|
||||||
utils::slog.e << "Failed to get the available GLXFBConfigs." << utils::io::endl;
|
LOG(ERROR) << "Failed to get the available GLXFBConfigs.";
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -164,8 +163,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
|||||||
for (int i = 0; i < numConfigs; ++i) {
|
for (int i = 0; i < numConfigs; ++i) {
|
||||||
r = g_glx.getFbConfigAttrib(mGLXDisplay, fbConfigs[i], GLX_FBCONFIG_ID, &fbId);
|
r = g_glx.getFbConfigAttrib(mGLXDisplay, fbConfigs[i], GLX_FBCONFIG_ID, &fbId);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
utils::slog.e << "Failed to get GLX_FBCONFIG_ID for entry " << i << "."
|
LOG(ERROR) << "Failed to get GLX_FBCONFIG_ID for entry " << i << ".";
|
||||||
<< utils::io::endl;
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -176,8 +174,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (fbIndex < 0) {
|
if (fbIndex < 0) {
|
||||||
utils::slog.e << "Failed to find an `GLXFBConfig` with the requested ID."
|
LOG(ERROR) << "Failed to find an `GLXFBConfig` with the requested ID.";
|
||||||
<< utils::io::endl;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -202,8 +199,7 @@ Driver* PlatformGLX::createDriver(void* sharedGLContext,
|
|||||||
getProcAddress((GLubyte*)"glXCreateContextAttribsARB");
|
getProcAddress((GLubyte*)"glXCreateContextAttribsARB");
|
||||||
|
|
||||||
if (glXCreateContextAttribs == nullptr) {
|
if (glXCreateContextAttribs == nullptr) {
|
||||||
utils::slog.i << "Unable to retrieve function pointer for `glXCreateContextAttribs()`."
|
LOG(INFO) << "Unable to retrieve function pointer for `glXCreateContextAttribs()`.";
|
||||||
<< utils::io::endl;
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -266,7 +262,7 @@ void PlatformGLX::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformGLX::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool PlatformGLX::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
g_glx.setCurrentContext(mGLXDisplay,
|
g_glx.setCurrentContext(mGLXDisplay,
|
||||||
(GLXDrawable)drawSwapChain, (GLXDrawable)readSwapChain, mGLXContext);
|
(GLXDrawable)drawSwapChain, (GLXDrawable)readSwapChain, mGLXContext);
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -169,7 +169,7 @@ void PlatformOSMesa::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformOSMesa::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool PlatformOSMesa::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
|
OSMesaAPI* api = (OSMesaAPI*) mOsMesaApi;
|
||||||
OSMesaSwapchain* impl = (OSMesaSwapchain*) drawSwapChain;
|
OSMesaSwapchain* impl = (OSMesaSwapchain*) drawSwapChain;
|
||||||
|
|
||||||
|
|||||||
@@ -32,7 +32,7 @@
|
|||||||
#include "GL/glext.h"
|
#include "GL/glext.h"
|
||||||
#include "GL/wglext.h"
|
#include "GL/wglext.h"
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
@@ -55,8 +55,7 @@ void reportWindowsError(DWORD dwError) {
|
|||||||
0, nullptr
|
0, nullptr
|
||||||
);
|
);
|
||||||
|
|
||||||
utils::slog.e << "Windows error code: " << dwError << ". " << lpMessageBuffer
|
LOG(ERROR) << "Windows error code: " << dwError << ". " << lpMessageBuffer;
|
||||||
<< utils::io::endl;
|
|
||||||
|
|
||||||
LocalFree(lpMessageBuffer);
|
LocalFree(lpMessageBuffer);
|
||||||
}
|
}
|
||||||
@@ -106,7 +105,7 @@ Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
|||||||
HDC whdc = mWhdc = GetDC(mHWnd);
|
HDC whdc = mWhdc = GetDC(mHWnd);
|
||||||
if (whdc == NULL) {
|
if (whdc == NULL) {
|
||||||
dwError = GetLastError();
|
dwError = GetLastError();
|
||||||
utils::slog.e << "CreateWindowA() failed" << utils::io::endl;
|
LOG(ERROR) << "CreateWindowA() failed";
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -117,8 +116,7 @@ Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
|||||||
tempContext = wglCreateContext(whdc);
|
tempContext = wglCreateContext(whdc);
|
||||||
if (!wglMakeCurrent(whdc, tempContext)) {
|
if (!wglMakeCurrent(whdc, tempContext)) {
|
||||||
dwError = GetLastError();
|
dwError = GetLastError();
|
||||||
utils::slog.e << "wglMakeCurrent() failed, whdc=" << whdc << ", tempContext=" <<
|
LOG(ERROR) << "wglMakeCurrent() failed, whdc=" << whdc << ", tempContext=" << tempContext;
|
||||||
tempContext << utils::io::endl;
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -142,7 +140,7 @@ Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!mContext) {
|
if (!mContext) {
|
||||||
utils::slog.e << "wglCreateContextAttribs() failed, whdc=" << whdc << utils::io::endl;
|
LOG(ERROR) << "wglCreateContextAttribs() failed, whdc=" << whdc;
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -152,8 +150,7 @@ Driver* PlatformWGL::createDriver(void* sharedGLContext,
|
|||||||
|
|
||||||
if (!wglMakeCurrent(whdc, mContext)) {
|
if (!wglMakeCurrent(whdc, mContext)) {
|
||||||
dwError = GetLastError();
|
dwError = GetLastError();
|
||||||
utils::slog.e << "wglMakeCurrent() failed, whdc=" << whdc << ", mContext=" <<
|
LOG(ERROR) << "wglMakeCurrent() failed, whdc=" << whdc << ", mContext=" << mContext;
|
||||||
mContext << utils::io::endl;
|
|
||||||
goto error;
|
goto error;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -262,7 +259,7 @@ void PlatformWGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformWGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool PlatformWGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
|
ASSERT_PRECONDITION_NON_FATAL(drawSwapChain == readSwapChain,
|
||||||
"PlatformWGL does not support distinct draw/read swap chains.");
|
"PlatformWGL does not support distinct draw/read swap chains.");
|
||||||
|
|
||||||
|
|||||||
@@ -47,7 +47,7 @@ void PlatformWebGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
bool PlatformWebGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
bool PlatformWebGL::makeCurrent(ContextType type, SwapChain* drawSwapChain,
|
||||||
SwapChain* readSwapChain) noexcept {
|
SwapChain* readSwapChain) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -40,7 +40,7 @@ inline void blitFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect, V
|
|||||||
FVK_LOGD << "Fast blit from=" << src.texture->getVkImage() << ",level=" << (int) src.level
|
FVK_LOGD << "Fast blit from=" << src.texture->getVkImage() << ",level=" << (int) src.level
|
||||||
<< " layout=" << src.getLayout()
|
<< " layout=" << src.getLayout()
|
||||||
<< " to=" << dst.texture->getVkImage() << ",level=" << (int) dst.level
|
<< " to=" << dst.texture->getVkImage() << ",level=" << (int) dst.level
|
||||||
<< " layout=" << dst.getLayout() << utils::io::endl;
|
<< " layout=" << dst.getLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageSubresourceRange const srcRange = src.getSubresourceRange();
|
VkImageSubresourceRange const srcRange = src.getSubresourceRange();
|
||||||
@@ -80,7 +80,7 @@ inline void resolveFast(VulkanCommandBuffer* commands, VkImageAspectFlags aspect
|
|||||||
FVK_LOGD << "Fast blit from=" << src.texture->getVkImage() << ",level=" << (int) src.level
|
FVK_LOGD << "Fast blit from=" << src.texture->getVkImage() << ",level=" << (int) src.level
|
||||||
<< " layout=" << src.getLayout()
|
<< " layout=" << src.getLayout()
|
||||||
<< " to=" << dst.texture->getVkImage() << ",level=" << (int) dst.level
|
<< " to=" << dst.texture->getVkImage() << ",level=" << (int) dst.level
|
||||||
<< " layout=" << dst.getLayout() << utils::io::endl;
|
<< " layout=" << dst.getLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkImageSubresourceRange const srcRange = src.getSubresourceRange();
|
VkImageSubresourceRange const srcRange = src.getSubresourceRange();
|
||||||
|
|||||||
@@ -17,35 +17,36 @@
|
|||||||
#ifndef TNT_FILAMENT_BACKEND_VULKANBUFFER_H
|
#ifndef TNT_FILAMENT_BACKEND_VULKANBUFFER_H
|
||||||
#define TNT_FILAMENT_BACKEND_VULKANBUFFER_H
|
#define TNT_FILAMENT_BACKEND_VULKANBUFFER_H
|
||||||
|
|
||||||
#include "VulkanContext.h"
|
|
||||||
#include "VulkanStagePool.h"
|
|
||||||
#include "VulkanMemory.h"
|
#include "VulkanMemory.h"
|
||||||
|
#include "memory/Resource.h"
|
||||||
|
|
||||||
|
#include <functional>
|
||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
// Encapsulates a Vulkan buffer, its attached DeviceMemory and a staging area.
|
class VulkanBuffer : public fvkmemory::Resource {
|
||||||
class VulkanBuffer {
|
|
||||||
public:
|
public:
|
||||||
VulkanBuffer(VmaAllocator allocator, VulkanStagePool& stagePool, VkBufferUsageFlags usage,
|
// Because we need to recycle the unused `VulkanGpuBuffer`, we allow for a callback that the
|
||||||
uint32_t numBytes);
|
// "Pool" can use to acquire the buffer back.
|
||||||
~VulkanBuffer();
|
using OnRecycle = std::function<void(VulkanGpuBuffer const*)>;
|
||||||
void loadFromCpu(VkCommandBuffer cmdbuf, const void* cpuData, uint32_t byteOffset,
|
|
||||||
uint32_t numBytes);
|
VulkanBuffer(VulkanGpuBuffer const* gpuBuffer, OnRecycle&& onRecycleFn)
|
||||||
VkBuffer getGpuBuffer() const {
|
: mGpuBuffer(gpuBuffer),
|
||||||
return mGpuBuffer;
|
mOnRecycleFn(onRecycleFn) {}
|
||||||
|
|
||||||
|
~VulkanBuffer() {
|
||||||
|
if (mOnRecycleFn) {
|
||||||
|
mOnRecycleFn(mGpuBuffer);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private:
|
VulkanGpuBuffer const* getGpuBuffer() const { return mGpuBuffer; }
|
||||||
VmaAllocator mAllocator;
|
|
||||||
VulkanStagePool& mStagePool;
|
|
||||||
|
|
||||||
VmaAllocation mGpuMemory = VK_NULL_HANDLE;
|
private:
|
||||||
VkBuffer mGpuBuffer = VK_NULL_HANDLE;
|
VulkanGpuBuffer const* mGpuBuffer;
|
||||||
VkBufferUsageFlags mUsage = {};
|
OnRecycle mOnRecycleFn;
|
||||||
uint32_t mUpdatedOffset = 0;
|
|
||||||
uint32_t mUpdatedBytes = 0;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace filament::backend
|
}// namespace filament::backend
|
||||||
|
|
||||||
#endif // TNT_FILAMENT_BACKEND_VULKANBUFFER_H
|
#endif// TNT_FILAMENT_BACKEND_VULKANBUFFER_H
|
||||||
|
|||||||
@@ -0,0 +1,207 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "VulkanBufferCache.h"
|
||||||
|
|
||||||
|
#include "VulkanBuffer.h"
|
||||||
|
#include "VulkanConstants.h"
|
||||||
|
#include "VulkanMemory.h"
|
||||||
|
#include "memory/Resource.h"
|
||||||
|
#include "memory/ResourceManager.h"
|
||||||
|
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
namespace {
|
||||||
|
|
||||||
|
VkBufferUsageFlags getVkBufferUsage(VulkanBufferUsage usage) {
|
||||||
|
switch (usage) {
|
||||||
|
case VulkanBufferUsage::VERTEX:
|
||||||
|
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
||||||
|
case VulkanBufferUsage::INDEX:
|
||||||
|
return VK_BUFFER_USAGE_INDEX_BUFFER_BIT;
|
||||||
|
case VulkanBufferUsage::UNIFORM:
|
||||||
|
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
||||||
|
case VulkanBufferUsage::SHADER_STORAGE:
|
||||||
|
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
||||||
|
case VulkanBufferUsage::UNKNOWN:
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace
|
||||||
|
|
||||||
|
VulkanBufferCache::VulkanBufferCache(VulkanContext const& context,
|
||||||
|
fvkmemory::ResourceManager& resourceManager, VmaAllocator allocator)
|
||||||
|
: mContext(context),
|
||||||
|
mResourceManager(resourceManager),
|
||||||
|
mAllocator(allocator) {}
|
||||||
|
|
||||||
|
fvkmemory::resource_ptr<VulkanBuffer> VulkanBufferCache::acquire(VulkanBufferUsage usage,
|
||||||
|
uint32_t numBytes) noexcept {
|
||||||
|
assert_invariant(usage != VulkanBufferUsage::UNKNOWN);
|
||||||
|
|
||||||
|
BufferPool& bufferPool = getPool(usage);
|
||||||
|
|
||||||
|
// First check if an allocation exists whose capacity is greater than or equal to the requested
|
||||||
|
// size.
|
||||||
|
auto iter = bufferPool.lower_bound(numBytes);
|
||||||
|
if (iter != bufferPool.end()) {
|
||||||
|
VulkanGpuBuffer const* gpuBuffer = iter->second.gpuBuffer;
|
||||||
|
bufferPool.erase(iter);
|
||||||
|
return fvkmemory::resource_ptr<VulkanBuffer>::construct(&mResourceManager, gpuBuffer,
|
||||||
|
[this](VulkanGpuBuffer const* gpuBuffer) { this->release(gpuBuffer); });
|
||||||
|
}
|
||||||
|
|
||||||
|
// We were not able to find a sufficiently large allocation, so create a new one that is
|
||||||
|
// recycled after being yielded.
|
||||||
|
VulkanGpuBuffer const* gpuBuffer = allocate(usage, numBytes);
|
||||||
|
return fvkmemory::resource_ptr<VulkanBuffer>::construct(&mResourceManager, gpuBuffer,
|
||||||
|
[this](VulkanGpuBuffer const* gpuBuffer) { this->release(gpuBuffer); });
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanBufferCache::gc() noexcept {
|
||||||
|
FVK_SYSTRACE_CONTEXT();
|
||||||
|
FVK_SYSTRACE_START("VulkanBufferCache::gc");
|
||||||
|
|
||||||
|
// If this is one of the first few frames, return early to avoid wrapping unsigned integers.
|
||||||
|
constexpr uint32_t TIME_BEFORE_EVICTION = 3;
|
||||||
|
if (++mCurrentFrame <= TIME_BEFORE_EVICTION) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const uint64_t evictionTime = mCurrentFrame - TIME_BEFORE_EVICTION;
|
||||||
|
|
||||||
|
// Destroy buffers that have not been used for several frames.
|
||||||
|
for (auto& bufferPool: mGpuBufferPools) {
|
||||||
|
for (auto poolIter = bufferPool.begin(); poolIter != bufferPool.end();) {
|
||||||
|
if (poolIter->second.lastAccessed < evictionTime) {
|
||||||
|
#if FVK_ENABLED(FVK_DEBUG_VULKAN_BUFFER_CACHE)
|
||||||
|
FVK_LOGD << "VulkanBufferCache - Destroyed vkBuffer "
|
||||||
|
<< poolIter->second.gpuBuffer->vkbuffer << " with usage "
|
||||||
|
<< static_cast<int>(poolIter->second.gpuBuffer->usage) << utils::io::endl;
|
||||||
|
#endif// FVK_DEBUG_VULKAN_BUFFER_CACHE
|
||||||
|
|
||||||
|
destroy(poolIter->second.gpuBuffer);
|
||||||
|
poolIter = bufferPool.erase(poolIter);
|
||||||
|
} else {
|
||||||
|
++poolIter;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
FVK_SYSTRACE_END();
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanBufferCache::terminate() noexcept {
|
||||||
|
for (auto& bufferPool: mGpuBufferPools) {
|
||||||
|
for (auto& poolEntry: bufferPool) {
|
||||||
|
destroy(poolEntry.second.gpuBuffer);
|
||||||
|
}
|
||||||
|
bufferPool.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanBufferCache::release(VulkanGpuBuffer const* gpuBuffer) noexcept {
|
||||||
|
assert_invariant(gpuBuffer != nullptr);
|
||||||
|
|
||||||
|
BufferPool& bufferPool = getPool(gpuBuffer->usage);
|
||||||
|
bufferPool.insert(std::make_pair(gpuBuffer->numBytes, UnusedGpuBuffer{
|
||||||
|
.lastAccessed = mCurrentFrame,
|
||||||
|
.gpuBuffer = gpuBuffer,
|
||||||
|
}));
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanGpuBuffer const* VulkanBufferCache::allocate(VulkanBufferUsage usage,
|
||||||
|
uint32_t numBytes) noexcept {
|
||||||
|
VkBufferCreateInfo const bufferInfo{
|
||||||
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
|
.size = numBytes,
|
||||||
|
// `VK_BUFFER_USAGE_TRANSFER_DST_BIT` is needed to allow updating the buffer through
|
||||||
|
// a staging using `vkCmdCopyBuffer`.
|
||||||
|
.usage = getVkBufferUsage(usage) | VK_BUFFER_USAGE_TRANSFER_DST_BIT,
|
||||||
|
};
|
||||||
|
|
||||||
|
VmaAllocationCreateFlags vmaFlags = 0;
|
||||||
|
if (usage == VulkanBufferUsage::UNIFORM) {
|
||||||
|
// In the case of UMA, the uniform buffers will always be mappable
|
||||||
|
if (mContext.isUnifiedMemoryArchitecture()) {
|
||||||
|
vmaFlags |= VMA_ALLOCATION_CREATE_MAPPED_BIT |
|
||||||
|
VMA_ALLOCATION_CREATE_HOST_ACCESS_SEQUENTIAL_WRITE_BIT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanGpuBuffer* gpuBuffer = new VulkanGpuBuffer{
|
||||||
|
.numBytes = numBytes,
|
||||||
|
.usage = usage,
|
||||||
|
};
|
||||||
|
VmaAllocationCreateInfo const allocInfo{
|
||||||
|
.flags = vmaFlags,
|
||||||
|
.usage = VMA_MEMORY_USAGE_AUTO,
|
||||||
|
.requiredFlags = VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT,
|
||||||
|
};
|
||||||
|
UTILS_UNUSED_IN_RELEASE VkResult result = vmaCreateBuffer(mAllocator, &bufferInfo, &allocInfo,
|
||||||
|
&gpuBuffer->vkbuffer, &gpuBuffer->vmaAllocation, &gpuBuffer->allocationInfo);
|
||||||
|
|
||||||
|
#if FVK_ENABLED(FVK_DEBUG_VULKAN_BUFFER_CACHE)
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
FVK_LOGE << "VulkanBufferCache - failed to allocate a new vkBuffer of size " << numBytes
|
||||||
|
<< " and usage " << static_cast<int>(usage) << ", error: " << result
|
||||||
|
<< utils::io::endl;
|
||||||
|
} else {
|
||||||
|
FVK_LOGD << "VulkanBufferCache - allocated a vkBuffer " << gpuBuffer->vkbuffer
|
||||||
|
<< " of size " << numBytes << " and usage = " << static_cast<int>(usage)
|
||||||
|
<< " successfully" << utils::io::endl;
|
||||||
|
}
|
||||||
|
#endif// FVK_DEBUG_VULKAN_BUFFER_CACHE
|
||||||
|
|
||||||
|
return gpuBuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanBufferCache::destroy(VulkanGpuBuffer const* gpuBuffer) noexcept {
|
||||||
|
vmaDestroyBuffer(mAllocator, gpuBuffer->vkbuffer, gpuBuffer->vmaAllocation);
|
||||||
|
delete gpuBuffer;
|
||||||
|
gpuBuffer = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanBufferCache::BufferPool& VulkanBufferCache::getPool(VulkanBufferUsage usage) noexcept {
|
||||||
|
|
||||||
|
int poolIndex = -1;
|
||||||
|
switch (usage) {
|
||||||
|
case VulkanBufferUsage::VERTEX:
|
||||||
|
poolIndex = 0;
|
||||||
|
break;
|
||||||
|
case VulkanBufferUsage::INDEX:
|
||||||
|
poolIndex = 1;
|
||||||
|
break;
|
||||||
|
case VulkanBufferUsage::UNIFORM:
|
||||||
|
poolIndex = 2;
|
||||||
|
break;
|
||||||
|
case VulkanBufferUsage::SHADER_STORAGE:
|
||||||
|
poolIndex = 3;
|
||||||
|
break;
|
||||||
|
case VulkanBufferUsage::UNKNOWN:
|
||||||
|
PANIC_LOG("There's no pool for buffers with unkown usage.");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
assert_invariant(poolIndex >= 0 && poolIndex < MAX_POOL_COUNT);
|
||||||
|
return mGpuBufferPools[poolIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace filament::backend
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2025 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_FILAMENT_BACKEND_VULKANBUFFERCACHE_H
|
||||||
|
#define TNT_FILAMENT_BACKEND_VULKANBUFFERCACHE_H
|
||||||
|
|
||||||
|
#include "VulkanBuffer.h"
|
||||||
|
#include "VulkanContext.h"
|
||||||
|
#include "VulkanMemory.h"
|
||||||
|
#include "memory/Resource.h"
|
||||||
|
#include "memory/ResourceManager.h"
|
||||||
|
|
||||||
|
#include <map>
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
class VulkanBufferCache {
|
||||||
|
public:
|
||||||
|
VulkanBufferCache(VulkanContext const& context, fvkmemory::ResourceManager& resourceManager,
|
||||||
|
VmaAllocator allocator);
|
||||||
|
|
||||||
|
// `VulkanBufferCache` is not copyable.
|
||||||
|
VulkanBufferCache(const VulkanBufferCache&) = delete;
|
||||||
|
VulkanBufferCache& operator=(const VulkanBufferCache&) = delete;
|
||||||
|
|
||||||
|
// Allocates or reuse a new VkBuffer that is device local.
|
||||||
|
// In the case of Unified memory architecture, uniform buffers are also host visible.
|
||||||
|
fvkmemory::resource_ptr<VulkanBuffer> acquire(VulkanBufferUsage usage,
|
||||||
|
uint32_t numBytes) noexcept;
|
||||||
|
|
||||||
|
// Evicts old unused `VulkanGpuBuffer` and bumps the current frame number
|
||||||
|
void gc() noexcept;
|
||||||
|
|
||||||
|
// Destroys all unused `VulkanGpuBuffer`.
|
||||||
|
// This should be called while the context's VkDevice is still alive.
|
||||||
|
void terminate() noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
struct UnusedGpuBuffer {
|
||||||
|
uint64_t lastAccessed;
|
||||||
|
VulkanGpuBuffer const* gpuBuffer;
|
||||||
|
};
|
||||||
|
|
||||||
|
using BufferPool = std::multimap<uint32_t, UnusedGpuBuffer>;
|
||||||
|
|
||||||
|
// Return a `VulkanGpuBuffer` back to its corresponding pool
|
||||||
|
void release(VulkanGpuBuffer const* gpuBuffer) noexcept;
|
||||||
|
|
||||||
|
// Allocate a new VkBuffer from the VMA pool of the corresponding `numBytes` and `usage`.
|
||||||
|
VulkanGpuBuffer const* allocate(VulkanBufferUsage usage, uint32_t numBytes) noexcept;
|
||||||
|
|
||||||
|
// Destroy the corresponding VkBuffer and return the VkDeviceMemory to the VMA pool.
|
||||||
|
void destroy(VulkanGpuBuffer const* gpuBuffer) noexcept;
|
||||||
|
|
||||||
|
BufferPool& getPool(VulkanBufferUsage usage) noexcept;
|
||||||
|
|
||||||
|
VulkanContext const& mContext;
|
||||||
|
fvkmemory::ResourceManager& mResourceManager;
|
||||||
|
VmaAllocator mAllocator;
|
||||||
|
|
||||||
|
// Buffers can be recycled, after they are released. Each type of buffer have its own pool
|
||||||
|
static constexpr int MAX_POOL_COUNT = 4;
|
||||||
|
BufferPool mGpuBufferPools[MAX_POOL_COUNT];
|
||||||
|
|
||||||
|
// Store the current "time" (really just a frame count) and LRU eviction parameters.
|
||||||
|
uint64_t mCurrentFrame = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace filament::backend
|
||||||
|
|
||||||
|
#endif// TNT_FILAMENT_BACKEND_VULKANBUFFERCACHE_H
|
||||||
+42
-48
@@ -14,49 +14,35 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "VulkanBuffer.h"
|
#include "VulkanBufferProxy.h"
|
||||||
|
#include "VulkanCommands.h"
|
||||||
#include "VulkanMemory.h"
|
#include "VulkanMemory.h"
|
||||||
|
|
||||||
#include <utils/Panic.h>
|
#include "VulkanBufferCache.h"
|
||||||
|
#include "VulkanMemory.h"
|
||||||
|
|
||||||
using namespace bluevk;
|
using namespace bluevk;
|
||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
VulkanBuffer::VulkanBuffer(VmaAllocator allocator, VulkanStagePool& stagePool,
|
VulkanBufferProxy::VulkanBufferProxy(VmaAllocator allocator, VulkanStagePool& stagePool,
|
||||||
VkBufferUsageFlags usage, uint32_t numBytes)
|
VulkanBufferCache& bufferCache, VulkanBufferUsage usage, uint32_t numBytes)
|
||||||
: mAllocator(allocator),
|
: mAllocator(allocator),
|
||||||
mStagePool(stagePool),
|
mStagePool(stagePool),
|
||||||
mUsage(usage),
|
mBufferCache(bufferCache),
|
||||||
|
mBuffer(mBufferCache.acquire(usage, numBytes)),
|
||||||
mUpdatedOffset(0),
|
mUpdatedOffset(0),
|
||||||
mUpdatedBytes(0) {
|
mUpdatedBytes(0) {}
|
||||||
// for now make sure that only 1 bit is set in usage
|
|
||||||
// (because loadFromCpu() assumes that somewhat)
|
|
||||||
assert_invariant(usage && !(usage & (usage - 1)));
|
|
||||||
|
|
||||||
// Create the VkBuffer.
|
void VulkanBufferProxy::loadFromCpu(VulkanCommandBuffer& commands, const void* cpuData,
|
||||||
VkBufferCreateInfo bufferInfo {
|
uint32_t byteOffset, uint32_t numBytes) {
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
// Note: this should be stored within the command buffer before going out of
|
||||||
.size = numBytes,
|
// scope, so that the command buffer can manage its lifecycle.
|
||||||
.usage = usage | VK_BUFFER_USAGE_TRANSFER_DST_BIT
|
fvkmemory::resource_ptr<VulkanStage::Segment> stage = mStagePool.acquireStage(numBytes);
|
||||||
};
|
assert_invariant(stage->memory());
|
||||||
|
commands.acquire(stage);
|
||||||
VmaAllocationCreateInfo allocInfo { .usage = VMA_MEMORY_USAGE_GPU_ONLY };
|
memcpy(stage->mapping(), cpuData, numBytes);
|
||||||
vmaCreateBuffer(mAllocator, &bufferInfo, &allocInfo, &mGpuBuffer, &mGpuMemory, nullptr);
|
vmaFlushAllocation(mAllocator, stage->memory(), stage->offset(), numBytes);
|
||||||
}
|
|
||||||
|
|
||||||
VulkanBuffer::~VulkanBuffer() {
|
|
||||||
vmaDestroyBuffer(mAllocator, mGpuBuffer, mGpuMemory);
|
|
||||||
}
|
|
||||||
|
|
||||||
void VulkanBuffer::loadFromCpu(VkCommandBuffer cmdbuf, const void* cpuData, uint32_t byteOffset,
|
|
||||||
uint32_t numBytes) {
|
|
||||||
VulkanStage const* stage = mStagePool.acquireStage(numBytes);
|
|
||||||
void* mapped;
|
|
||||||
vmaMapMemory(mAllocator, stage->memory, &mapped);
|
|
||||||
memcpy(mapped, cpuData, numBytes);
|
|
||||||
vmaUnmapMemory(mAllocator, stage->memory);
|
|
||||||
vmaFlushAllocation(mAllocator, stage->memory, 0, numBytes);
|
|
||||||
|
|
||||||
// If there was a previous update, then we need to make sure the following write is properly
|
// If there was a previous update, then we need to make sure the following write is properly
|
||||||
// synced with the previous read.
|
// synced with the previous read.
|
||||||
@@ -64,13 +50,13 @@ void VulkanBuffer::loadFromCpu(VkCommandBuffer cmdbuf, const void* cpuData, uint
|
|||||||
(byteOffset >= mUpdatedOffset && byteOffset <= (mUpdatedOffset + mUpdatedBytes))) {
|
(byteOffset >= mUpdatedOffset && byteOffset <= (mUpdatedOffset + mUpdatedBytes))) {
|
||||||
VkAccessFlags srcAccess = 0;
|
VkAccessFlags srcAccess = 0;
|
||||||
VkPipelineStageFlags srcStage = 0;
|
VkPipelineStageFlags srcStage = 0;
|
||||||
if (mUsage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
|
if (getUsage() == VulkanBufferUsage::UNIFORM) {
|
||||||
srcAccess = VK_ACCESS_SHADER_READ_BIT;
|
srcAccess = VK_ACCESS_SHADER_READ_BIT;
|
||||||
srcStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
srcStage = VK_PIPELINE_STAGE_VERTEX_SHADER_BIT | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
|
||||||
} else if (mUsage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) {
|
} else if (getUsage() == VulkanBufferUsage::VERTEX) {
|
||||||
srcAccess = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
|
srcAccess = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
|
||||||
srcStage = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
srcStage = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
||||||
} else if (mUsage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) {
|
} else if (getUsage() == VulkanBufferUsage::INDEX) {
|
||||||
srcAccess = VK_ACCESS_INDEX_READ_BIT;
|
srcAccess = VK_ACCESS_INDEX_READ_BIT;
|
||||||
srcStage = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
srcStage = VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
||||||
}
|
}
|
||||||
@@ -81,20 +67,20 @@ void VulkanBuffer::loadFromCpu(VkCommandBuffer cmdbuf, const void* cpuData, uint
|
|||||||
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
.dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.buffer = mGpuBuffer,
|
.buffer = getVkBuffer(),
|
||||||
.offset = byteOffset,
|
.offset = byteOffset,
|
||||||
.size = numBytes,
|
.size = numBytes,
|
||||||
};
|
};
|
||||||
vkCmdPipelineBarrier(cmdbuf, srcStage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0, nullptr, 1,
|
vkCmdPipelineBarrier(commands.buffer(), srcStage, VK_PIPELINE_STAGE_TRANSFER_BIT, 0, 0,
|
||||||
&barrier, 0, nullptr);
|
nullptr, 1, &barrier, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
VkBufferCopy region = {
|
VkBufferCopy region = {
|
||||||
.srcOffset = 0,
|
.srcOffset = stage->offset(),
|
||||||
.dstOffset = byteOffset,
|
.dstOffset = byteOffset,
|
||||||
.size = numBytes,
|
.size = numBytes,
|
||||||
};
|
};
|
||||||
vkCmdCopyBuffer(cmdbuf, stage->buffer, mGpuBuffer, 1, ®ion);
|
vkCmdCopyBuffer(commands.buffer(), stage->buffer(), getVkBuffer(), 1, ®ion);
|
||||||
|
|
||||||
mUpdatedOffset = byteOffset;
|
mUpdatedOffset = byteOffset;
|
||||||
mUpdatedBytes = numBytes;
|
mUpdatedBytes = numBytes;
|
||||||
@@ -106,16 +92,16 @@ void VulkanBuffer::loadFromCpu(VkCommandBuffer cmdbuf, const void* cpuData, uint
|
|||||||
VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
VkAccessFlags dstAccessMask = VK_ACCESS_TRANSFER_WRITE_BIT;
|
||||||
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
VkPipelineStageFlags dstStageMask = VK_PIPELINE_STAGE_TRANSFER_BIT;
|
||||||
|
|
||||||
if (mUsage & VK_BUFFER_USAGE_VERTEX_BUFFER_BIT) {
|
if (getUsage() == VulkanBufferUsage::VERTEX) {
|
||||||
dstAccessMask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
|
dstAccessMask |= VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT;
|
||||||
dstStageMask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
dstStageMask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
||||||
} else if (mUsage & VK_BUFFER_USAGE_INDEX_BUFFER_BIT) {
|
} else if (getUsage() == VulkanBufferUsage::INDEX) {
|
||||||
dstAccessMask |= VK_ACCESS_INDEX_READ_BIT;
|
dstAccessMask |= VK_ACCESS_INDEX_READ_BIT;
|
||||||
dstStageMask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
dstStageMask |= VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
|
||||||
} else if (mUsage & VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT) {
|
} else if (getUsage() == VulkanBufferUsage::UNIFORM) {
|
||||||
dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
|
dstAccessMask |= VK_ACCESS_SHADER_READ_BIT;
|
||||||
dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
dstStageMask |= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | VK_PIPELINE_STAGE_VERTEX_SHADER_BIT;
|
||||||
} else if (mUsage & VK_BUFFER_USAGE_STORAGE_BUFFER_BIT) {
|
} else if (getUsage() == VulkanBufferUsage::SHADER_STORAGE) {
|
||||||
// TODO: implement me
|
// TODO: implement me
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,13 +111,21 @@ void VulkanBuffer::loadFromCpu(VkCommandBuffer cmdbuf, const void* cpuData, uint
|
|||||||
.dstAccessMask = dstAccessMask,
|
.dstAccessMask = dstAccessMask,
|
||||||
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED,
|
||||||
.buffer = mGpuBuffer,
|
.buffer = getVkBuffer(),
|
||||||
.offset = byteOffset,
|
.offset = byteOffset,
|
||||||
.size = numBytes,
|
.size = numBytes,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkCmdPipelineBarrier(cmdbuf, VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, 0, 0, nullptr, 1,
|
vkCmdPipelineBarrier(commands.buffer(), VK_PIPELINE_STAGE_TRANSFER_BIT, dstStageMask, 0, 0,
|
||||||
&barrier, 0, nullptr);
|
nullptr, 1, &barrier, 0, nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace filament::backend
|
VkBuffer VulkanBufferProxy::getVkBuffer() const noexcept {
|
||||||
|
return mBuffer->getGpuBuffer()->vkbuffer;
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanBufferUsage VulkanBufferProxy::getUsage() const noexcept {
|
||||||
|
return mBuffer->getGpuBuffer()->usage;
|
||||||
|
}
|
||||||
|
|
||||||
|
}// namespace filament::backend
|
||||||
@@ -0,0 +1,54 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2018 The Android Open Source Project
|
||||||
|
*
|
||||||
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
* you may not use this file except in compliance with the License.
|
||||||
|
* You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing, software
|
||||||
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
|
* See the License for the specific language governing permissions and
|
||||||
|
* limitations under the License.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef TNT_FILAMENT_BACKEND_VULKANBUFFERPROXY_H
|
||||||
|
#define TNT_FILAMENT_BACKEND_VULKANBUFFERPROXY_H
|
||||||
|
|
||||||
|
#include "VulkanBufferCache.h"
|
||||||
|
#include "VulkanCommands.h"
|
||||||
|
#include "VulkanContext.h"
|
||||||
|
#include "VulkanMemory.h"
|
||||||
|
#include "VulkanStagePool.h"
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
// This class acts as a dynamic wrapper for a `VulkanBuffer`. It allows you to modify the
|
||||||
|
// `VulkanBuffer` it references at runtime, wihtout affecting any external objects.
|
||||||
|
class VulkanBufferProxy {
|
||||||
|
public:
|
||||||
|
VulkanBufferProxy(VmaAllocator allocator, VulkanStagePool& stagePool,
|
||||||
|
VulkanBufferCache& bufferCache, VulkanBufferUsage usage, uint32_t numBytes);
|
||||||
|
|
||||||
|
void loadFromCpu(VulkanCommandBuffer& commands, const void* cpuData, uint32_t byteOffset,
|
||||||
|
uint32_t numBytes);
|
||||||
|
|
||||||
|
VkBuffer getVkBuffer() const noexcept;
|
||||||
|
|
||||||
|
VulkanBufferUsage getUsage() const noexcept;
|
||||||
|
|
||||||
|
private:
|
||||||
|
VmaAllocator mAllocator;
|
||||||
|
VulkanStagePool& mStagePool;
|
||||||
|
VulkanBufferCache& mBufferCache;
|
||||||
|
|
||||||
|
fvkmemory::resource_ptr<VulkanBuffer> mBuffer;
|
||||||
|
uint32_t mUpdatedOffset = 0;
|
||||||
|
uint32_t mUpdatedBytes = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
}// namespace filament::backend
|
||||||
|
|
||||||
|
#endif// TNT_FILAMENT_BACKEND_VULKANBUFFERPROXY_H
|
||||||
@@ -215,7 +215,7 @@ VkSemaphore VulkanCommandBuffer::submit() {
|
|||||||
}
|
}
|
||||||
FVK_LOGI << ") "
|
FVK_LOGI << ") "
|
||||||
<< " signal=" << mSubmission
|
<< " signal=" << mSubmission
|
||||||
<< " fence=" << mFence << utils::io::endl;
|
<< " fence=" << mFence;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mFenceStatus->setStatus(VK_NOT_READY);
|
mFenceStatus->setStatus(VK_NOT_READY);
|
||||||
@@ -224,7 +224,7 @@ VkSemaphore VulkanCommandBuffer::submit() {
|
|||||||
|
|
||||||
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
|
#if FVK_ENABLED(FVK_DEBUG_COMMAND_BUFFER)
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
FVK_LOGD << "Failed command buffer submission result: " << result << utils::io::endl;
|
FVK_LOGD << "Failed command buffer submission result: " << result;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
assert_invariant(result == VK_SUCCESS);
|
assert_invariant(result == VK_SUCCESS);
|
||||||
@@ -490,7 +490,7 @@ void VulkanCommands::pushGroupMarker(char const* str, VulkanGroupMarkers::Timest
|
|||||||
mProtectedPool->pushMarker(str, timestamp);
|
mProtectedPool->pushMarker(str, timestamp);
|
||||||
}
|
}
|
||||||
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
|
#if FVK_ENABLED(FVK_DEBUG_PRINT_GROUP_MARKERS)
|
||||||
FVK_LOGD << "----> " << str << utils::io::endl;
|
FVK_LOGD << "----> " << str;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -502,8 +502,7 @@ void VulkanCommands::popGroupMarker() {
|
|||||||
auto const& startTime = ret.second;
|
auto const& startTime = ret.second;
|
||||||
auto const endTime = std::chrono::high_resolution_clock::now();
|
auto const endTime = std::chrono::high_resolution_clock::now();
|
||||||
std::chrono::duration<double> diff = endTime - startTime;
|
std::chrono::duration<double> diff = endTime - startTime;
|
||||||
FVK_LOGD << "<---- " << marker << " elapsed: " << (diff.count() * 1000) << " ms"
|
FVK_LOGD << "<---- " << marker << " elapsed: " << (diff.count() * 1000) << " ms";
|
||||||
<< utils::io::endl;
|
|
||||||
#else
|
#else
|
||||||
mPool->popMarker();
|
mPool->popMarker();
|
||||||
#endif // FVK_DEBUG_PRINT_GROUP_MARKERS
|
#endif // FVK_DEBUG_PRINT_GROUP_MARKERS
|
||||||
|
|||||||
@@ -17,7 +17,7 @@
|
|||||||
#ifndef TNT_FILAMENT_BACKEND_VULKANCONSTANTS_H
|
#ifndef TNT_FILAMENT_BACKEND_VULKANCONSTANTS_H
|
||||||
#define TNT_FILAMENT_BACKEND_VULKANCONSTANTS_H
|
#define TNT_FILAMENT_BACKEND_VULKANCONSTANTS_H
|
||||||
|
|
||||||
#include <utils/Log.h>
|
#include <utils/Logger.h>
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
@@ -73,14 +73,16 @@
|
|||||||
#define FVK_DEBUG_RESOURCE_LEAK 0x00010000
|
#define FVK_DEBUG_RESOURCE_LEAK 0x00010000
|
||||||
|
|
||||||
// Set this to enable logging "only" to one output stream. This is useful in the case where we want
|
// Set this to enable logging "only" to one output stream. This is useful in the case where we want
|
||||||
// to debug with print statements and want ordered logging (e.g slog.i and slog.e will not appear in
|
// to debug with print statements and want ordered logging (e.g LOG(INFO) and LOG(ERROR) will not
|
||||||
// order of calls).
|
// appear in order of calls).
|
||||||
#define FVK_DEBUG_FORCE_LOG_TO_I 0x00020000
|
#define FVK_DEBUG_FORCE_LOG_TO_I 0x00020000
|
||||||
|
|
||||||
// Enable a minimal set of traces to assess the performance of the backend.
|
// Enable a minimal set of traces to assess the performance of the backend.
|
||||||
// All other debug features must be disabled.
|
// All other debug features must be disabled.
|
||||||
#define FVK_DEBUG_PROFILING 0x00040000
|
#define FVK_DEBUG_PROFILING 0x00040000
|
||||||
|
|
||||||
|
#define FVK_DEBUG_VULKAN_BUFFER_CACHE 0x00080000
|
||||||
|
|
||||||
// Useful default combinations
|
// Useful default combinations
|
||||||
#define FVK_DEBUG_EVERYTHING (0xFFFFFFFF & ~FVK_DEBUG_PROFILING)
|
#define FVK_DEBUG_EVERYTHING (0xFFFFFFFF & ~FVK_DEBUG_PROFILING)
|
||||||
#define FVK_DEBUG_PERFORMANCE \
|
#define FVK_DEBUG_PERFORMANCE \
|
||||||
@@ -172,15 +174,15 @@ static_assert(FVK_ENABLED(FVK_DEBUG_VALIDATION));
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if FVK_ENABLED(FVK_DEBUG_FORCE_LOG_TO_I)
|
#if FVK_ENABLED(FVK_DEBUG_FORCE_LOG_TO_I)
|
||||||
#define FVK_LOGI (utils::slog.i)
|
#define FVK_LOGI LOG(INFO)
|
||||||
#define FVK_LOGD FVK_LOGI
|
#define FVK_LOGD FVK_LOGI
|
||||||
#define FVK_LOGE FVK_LOGI
|
#define FVK_LOGE FVK_LOGI
|
||||||
#define FVK_LOGW FVK_LOGI
|
#define FVK_LOGW FVK_LOGI
|
||||||
#else
|
#else
|
||||||
#define FVK_LOGE (utils::slog.e)
|
#define FVK_LOGE LOG(ERROR)
|
||||||
#define FVK_LOGW (utils::slog.w)
|
#define FVK_LOGW LOG(WARNING)
|
||||||
#define FVK_LOGD (utils::slog.d)
|
#define FVK_LOGD DLOG(INFO)
|
||||||
#define FVK_LOGI (utils::slog.i)
|
#define FVK_LOGI LOG(INFO)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// All vkCreate* functions take an optional allocator. For now we select the default allocator by
|
// All vkCreate* functions take an optional allocator. For now we select the default allocator by
|
||||||
|
|||||||
@@ -71,23 +71,23 @@ struct VulkanRenderPass {
|
|||||||
struct VulkanContext {
|
struct VulkanContext {
|
||||||
public:
|
public:
|
||||||
static uint32_t selectMemoryType(VkPhysicalDeviceMemoryProperties const& memoryProperties,
|
static uint32_t selectMemoryType(VkPhysicalDeviceMemoryProperties const& memoryProperties,
|
||||||
uint32_t flags, VkFlags reqs) {
|
uint32_t types, VkFlags reqs) {
|
||||||
for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
|
for (uint32_t i = 0; i < VK_MAX_MEMORY_TYPES; i++) {
|
||||||
if (flags & 1) {
|
if (types & 1) {
|
||||||
if ((memoryProperties.memoryTypes[i].propertyFlags & reqs) == reqs) {
|
if ((memoryProperties.memoryTypes[i].propertyFlags & reqs) == reqs) {
|
||||||
return i;
|
return i;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
flags >>= 1;
|
types >>= 1;
|
||||||
}
|
}
|
||||||
return (uint32_t) VK_MAX_MEMORY_TYPES;
|
return (uint32_t) VK_MAX_MEMORY_TYPES;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline uint32_t selectMemoryType(uint32_t flags, VkFlags reqs) const {
|
inline uint32_t selectMemoryType(uint32_t types, VkFlags reqs) const {
|
||||||
if ((reqs & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0) {
|
if ((reqs & VK_MEMORY_PROPERTY_PROTECTED_BIT) != 0) {
|
||||||
assert_invariant(isProtectedMemorySupported());
|
assert_invariant(isProtectedMemorySupported());
|
||||||
}
|
}
|
||||||
return selectMemoryType(mMemoryProperties, flags, reqs);
|
return selectMemoryType(mMemoryProperties, types, reqs);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline fvkutils::VkFormatList const& getAttachmentDepthStencilFormats() const {
|
inline fvkutils::VkFormatList const& getAttachmentDepthStencilFormats() const {
|
||||||
|
|||||||
@@ -320,7 +320,7 @@ void VulkanDescriptorSetCache::updateBuffer(fvkmemory::resource_ptr<VulkanDescri
|
|||||||
uint8_t binding, fvkmemory::resource_ptr<VulkanBufferObject> bufferObject,
|
uint8_t binding, fvkmemory::resource_ptr<VulkanBufferObject> bufferObject,
|
||||||
VkDeviceSize offset, VkDeviceSize size) noexcept {
|
VkDeviceSize offset, VkDeviceSize size) noexcept {
|
||||||
VkDescriptorBufferInfo const info = {
|
VkDescriptorBufferInfo const info = {
|
||||||
.buffer = bufferObject->buffer.getGpuBuffer(),
|
.buffer = bufferObject->buffer.getVkBuffer(),
|
||||||
.offset = offset,
|
.offset = offset,
|
||||||
.range = size,
|
.range = size,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -19,7 +19,8 @@
|
|||||||
#include "CommandStreamDispatcher.h"
|
#include "CommandStreamDispatcher.h"
|
||||||
#include "SystraceProfile.h"
|
#include "SystraceProfile.h"
|
||||||
#include "VulkanAsyncHandles.h"
|
#include "VulkanAsyncHandles.h"
|
||||||
#include "VulkanBuffer.h"
|
#include "VulkanBufferCache.h"
|
||||||
|
#include "VulkanBufferProxy.h"
|
||||||
#include "VulkanCommands.h"
|
#include "VulkanCommands.h"
|
||||||
#include "VulkanDriverFactory.h"
|
#include "VulkanDriverFactory.h"
|
||||||
#include "VulkanHandles.h"
|
#include "VulkanHandles.h"
|
||||||
@@ -84,7 +85,11 @@ VmaAllocator createAllocator(VkInstance instance, VkPhysicalDevice physicalDevic
|
|||||||
.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR
|
.vkGetImageMemoryRequirements2KHR = vkGetImageMemoryRequirements2KHR
|
||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
VmaAllocatorCreateInfo const allocatorInfo {
|
VmaAllocatorCreateInfo const allocatorInfo{
|
||||||
|
// Disable the internal VMA synchronization because the backend is singled threaded.
|
||||||
|
// Improve CPU performance when using VMA functions. The backend will guarantee that all
|
||||||
|
// access to VMA is done in a thread safe way.
|
||||||
|
.flags = VMA_ALLOCATOR_CREATE_EXTERNALLY_SYNCHRONIZED_BIT,
|
||||||
.physicalDevice = physicalDevice,
|
.physicalDevice = physicalDevice,
|
||||||
.device = device,
|
.device = device,
|
||||||
.pVulkanFunctions = &funcs,
|
.pVulkanFunctions = &funcs,
|
||||||
@@ -99,15 +104,15 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugReportCallback(VkDebugReportFlagsEXT flags,
|
|||||||
VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location,
|
VkDebugReportObjectTypeEXT objectType, uint64_t object, size_t location,
|
||||||
int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) {
|
int32_t messageCode, const char* pLayerPrefix, const char* pMessage, void* pUserData) {
|
||||||
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
if (flags & VK_DEBUG_REPORT_ERROR_BIT_EXT) {
|
||||||
FVK_LOGE << "VULKAN ERROR: (" << pLayerPrefix << ") " << pMessage << utils::io::endl;
|
FVK_LOGE << "VULKAN ERROR: (" << pLayerPrefix << ") " << pMessage;
|
||||||
} else {
|
} else {
|
||||||
// TODO: emit best practices warnings about aggressive pipeline barriers.
|
// TODO: emit best practices warnings about aggressive pipeline barriers.
|
||||||
if (strstr(pMessage, "ALL_GRAPHICS_BIT") || strstr(pMessage, "ALL_COMMANDS_BIT")) {
|
if (strstr(pMessage, "ALL_GRAPHICS_BIT") || strstr(pMessage, "ALL_COMMANDS_BIT")) {
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
FVK_LOGW << "VULKAN WARNING: (" << pLayerPrefix << ") " << pMessage << utils::io::endl;
|
FVK_LOGW << "VULKAN WARNING: (" << pLayerPrefix << ") " << pMessage;
|
||||||
}
|
}
|
||||||
FVK_LOGE << utils::io::endl;
|
FVK_LOGE;
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
#endif // FVK_ENABLED(FVK_DEBUG_VALIDATION)
|
#endif // FVK_ENABLED(FVK_DEBUG_VALIDATION)
|
||||||
@@ -117,18 +122,16 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsCallback(VkDebugUtilsMessageSeverityFla
|
|||||||
VkDebugUtilsMessageTypeFlagsEXT types, const VkDebugUtilsMessengerCallbackDataEXT* cbdata,
|
VkDebugUtilsMessageTypeFlagsEXT types, const VkDebugUtilsMessengerCallbackDataEXT* cbdata,
|
||||||
void* pUserData) {
|
void* pUserData) {
|
||||||
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
|
if (severity & VK_DEBUG_UTILS_MESSAGE_SEVERITY_ERROR_BIT_EXT) {
|
||||||
FVK_LOGE << "VULKAN ERROR: (" << cbdata->pMessageIdName << ") " << cbdata->pMessage
|
FVK_LOGE << "VULKAN ERROR: (" << cbdata->pMessageIdName << ") " << cbdata->pMessage;
|
||||||
<< utils::io::endl;
|
|
||||||
} else {
|
} else {
|
||||||
// TODO: emit best practices warnings about aggressive pipeline barriers.
|
// TODO: emit best practices warnings about aggressive pipeline barriers.
|
||||||
if (strstr(cbdata->pMessage, "ALL_GRAPHICS_BIT")
|
if (strstr(cbdata->pMessage, "ALL_GRAPHICS_BIT")
|
||||||
|| strstr(cbdata->pMessage, "ALL_COMMANDS_BIT")) {
|
|| strstr(cbdata->pMessage, "ALL_COMMANDS_BIT")) {
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
FVK_LOGW << "VULKAN WARNING: (" << cbdata->pMessageIdName << ") " << cbdata->pMessage
|
FVK_LOGW << "VULKAN WARNING: (" << cbdata->pMessageIdName << ") " << cbdata->pMessage;
|
||||||
<< utils::io::endl;
|
|
||||||
}
|
}
|
||||||
FVK_LOGE << utils::io::endl;
|
FVK_LOGE << "";
|
||||||
return VK_FALSE;
|
return VK_FALSE;
|
||||||
}
|
}
|
||||||
#endif // FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
#endif // FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
|
||||||
@@ -209,7 +212,8 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext const& contex
|
|||||||
mPlatform->getProtectedGraphicsQueueFamilyIndex(), &mContext),
|
mPlatform->getProtectedGraphicsQueueFamilyIndex(), &mContext),
|
||||||
mPipelineLayoutCache(mPlatform->getDevice()),
|
mPipelineLayoutCache(mPlatform->getDevice()),
|
||||||
mPipelineCache(mPlatform->getDevice()),
|
mPipelineCache(mPlatform->getDevice()),
|
||||||
mStagePool(mAllocator, &mCommands),
|
mStagePool(mAllocator, &mResourceManager, &mCommands, &mContext.getPhysicalDeviceLimits()),
|
||||||
|
mBufferCache(context, mResourceManager, mAllocator),
|
||||||
mFramebufferCache(mPlatform->getDevice()),
|
mFramebufferCache(mPlatform->getDevice()),
|
||||||
mYcbcrConversionCache(mPlatform->getDevice()),
|
mYcbcrConversionCache(mPlatform->getDevice()),
|
||||||
mSamplerCache(mPlatform->getDevice()),
|
mSamplerCache(mPlatform->getDevice()),
|
||||||
@@ -270,20 +274,18 @@ Driver* VulkanDriver::create(VulkanPlatform* platform, VulkanContext const& cont
|
|||||||
// VulkanRenderTarget : 312 few
|
// VulkanRenderTarget : 312 few
|
||||||
// -- less than or equal to 312 bytes
|
// -- less than or equal to 312 bytes
|
||||||
|
|
||||||
FVK_LOGD
|
FVK_LOGD << "VulkanSwapChain: " << sizeof(VulkanSwapChain);
|
||||||
<< "\nVulkanSwapChain: " << sizeof(VulkanSwapChain)
|
FVK_LOGD << "VulkanBufferObject: " << sizeof(VulkanBufferObject);
|
||||||
<< "\nVulkanBufferObject: " << sizeof(VulkanBufferObject)
|
FVK_LOGD << "VulkanVertexBuffer: " << sizeof(VulkanVertexBuffer);
|
||||||
<< "\nVulkanVertexBuffer: " << sizeof(VulkanVertexBuffer)
|
FVK_LOGD << "VulkanVertexBufferInfo: " << sizeof(VulkanVertexBufferInfo);
|
||||||
<< "\nVulkanVertexBufferInfo: " << sizeof(VulkanVertexBufferInfo)
|
FVK_LOGD << "VulkanIndexBuffer: " << sizeof(VulkanIndexBuffer);
|
||||||
<< "\nVulkanIndexBuffer: " << sizeof(VulkanIndexBuffer)
|
FVK_LOGD << "VulkanRenderPrimitive: " << sizeof(VulkanRenderPrimitive);
|
||||||
<< "\nVulkanRenderPrimitive: " << sizeof(VulkanRenderPrimitive)
|
FVK_LOGD << "VulkanTexture: " << sizeof(VulkanTexture);
|
||||||
<< "\nVulkanTexture: " << sizeof(VulkanTexture)
|
FVK_LOGD << "VulkanTimerQuery: " << sizeof(VulkanTimerQuery);
|
||||||
<< "\nVulkanTimerQuery: " << sizeof(VulkanTimerQuery)
|
FVK_LOGD << "HwStream: " << sizeof(HwStream);
|
||||||
<< "\nHwStream: " << sizeof(HwStream)
|
FVK_LOGD << "VulkanRenderTarget: " << sizeof(VulkanRenderTarget);
|
||||||
<< "\nVulkanRenderTarget: " << sizeof(VulkanRenderTarget)
|
FVK_LOGD << "VulkanFence: " << sizeof(VulkanFence);
|
||||||
<< "\nVulkanFence: " << sizeof(VulkanFence)
|
FVK_LOGD << "VulkanProgram: " << sizeof(VulkanProgram);
|
||||||
<< "\nVulkanProgram: " << sizeof(VulkanProgram)
|
|
||||||
<< utils::io::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
assert_invariant(platform);
|
assert_invariant(platform);
|
||||||
@@ -328,7 +330,6 @@ void VulkanDriver::terminate() {
|
|||||||
// descriptorSetLayoutCache
|
// descriptorSetLayoutCache
|
||||||
mExternalImageManager.terminate();
|
mExternalImageManager.terminate();
|
||||||
|
|
||||||
mStagePool.terminate();
|
|
||||||
mPipelineCache.terminate();
|
mPipelineCache.terminate();
|
||||||
mFramebufferCache.terminate();
|
mFramebufferCache.terminate();
|
||||||
mSamplerCache.terminate();
|
mSamplerCache.terminate();
|
||||||
@@ -339,6 +340,15 @@ void VulkanDriver::terminate() {
|
|||||||
// Before terminating ResourceManager, we must make sure all of the resource_ptrs have been unset.
|
// Before terminating ResourceManager, we must make sure all of the resource_ptrs have been unset.
|
||||||
mResourceManager.terminate();
|
mResourceManager.terminate();
|
||||||
|
|
||||||
|
// Must come after `mResourceManager`.
|
||||||
|
// Before terminating the memory pool, we must make sure all the VulkanBufferMemory are yielded
|
||||||
|
// back to the pool.
|
||||||
|
mBufferCache.terminate();
|
||||||
|
|
||||||
|
// Before terminating stagePool, we need all resources to have been
|
||||||
|
// reclaimed, as they perform cleanup within the stage pool.
|
||||||
|
mStagePool.terminate();
|
||||||
|
|
||||||
#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK)
|
#if FVK_ENABLED(FVK_DEBUG_RESOURCE_LEAK)
|
||||||
mResourceManager.print();
|
mResourceManager.print();
|
||||||
#endif
|
#endif
|
||||||
@@ -371,6 +381,7 @@ void VulkanDriver::collectGarbage() {
|
|||||||
mCommands.gc();
|
mCommands.gc();
|
||||||
mDescriptorSetCache.gc();
|
mDescriptorSetCache.gc();
|
||||||
mStagePool.gc();
|
mStagePool.gc();
|
||||||
|
mBufferCache.gc();
|
||||||
mFramebufferCache.gc();
|
mFramebufferCache.gc();
|
||||||
mPipelineCache.gc();
|
mPipelineCache.gc();
|
||||||
|
|
||||||
@@ -514,7 +525,7 @@ void VulkanDriver::createIndexBufferR(Handle<HwIndexBuffer> ibh, ElementType ele
|
|||||||
FVK_SYSTRACE_SCOPE();
|
FVK_SYSTRACE_SCOPE();
|
||||||
auto elementSize = (uint8_t) getElementTypeSize(elementType);
|
auto elementSize = (uint8_t) getElementTypeSize(elementType);
|
||||||
auto ib = resource_ptr<VulkanIndexBuffer>::make(&mResourceManager, ibh, mAllocator, mStagePool,
|
auto ib = resource_ptr<VulkanIndexBuffer>::make(&mResourceManager, ibh, mAllocator, mStagePool,
|
||||||
elementSize, indexCount);
|
mBufferCache, elementSize, indexCount);
|
||||||
ib.inc();
|
ib.inc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -531,7 +542,7 @@ void VulkanDriver::createBufferObjectR(Handle<HwBufferObject> boh, uint32_t byte
|
|||||||
BufferObjectBinding bindingType, BufferUsage usage) {
|
BufferObjectBinding bindingType, BufferUsage usage) {
|
||||||
FVK_SYSTRACE_SCOPE();
|
FVK_SYSTRACE_SCOPE();
|
||||||
auto bo = resource_ptr<VulkanBufferObject>::make(&mResourceManager, boh, mAllocator, mStagePool,
|
auto bo = resource_ptr<VulkanBufferObject>::make(&mResourceManager, boh, mAllocator, mStagePool,
|
||||||
byteCount, bindingType);
|
mBufferCache, byteCount, bindingType);
|
||||||
bo.inc();
|
bo.inc();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -784,14 +795,12 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
|||||||
mResourceManager.gc();
|
mResourceManager.gc();
|
||||||
|
|
||||||
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
||||||
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it"
|
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it";
|
||||||
<< utils::io::endl;
|
|
||||||
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
||||||
}
|
}
|
||||||
if (flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
|
if (flags & backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT) {
|
||||||
if (!isProtectedContentSupported()) {
|
if (!isProtectedContentSupported()) {
|
||||||
FVK_LOGW << "protected swapchain requested, but Platform does not support it"
|
FVK_LOGW << "protected swapchain requested, but Platform does not support it";
|
||||||
<< utils::io::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
auto swapChain = resource_ptr<VulkanSwapChain>::make(&mResourceManager, sch, mPlatform,
|
auto swapChain = resource_ptr<VulkanSwapChain>::make(&mResourceManager, sch, mPlatform,
|
||||||
@@ -802,8 +811,7 @@ void VulkanDriver::createSwapChainR(Handle<HwSwapChain> sch, void* nativeWindow,
|
|||||||
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
void VulkanDriver::createSwapChainHeadlessR(Handle<HwSwapChain> sch, uint32_t width,
|
||||||
uint32_t height, uint64_t flags) {
|
uint32_t height, uint64_t flags) {
|
||||||
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
if ((flags & backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE) != 0 && !isSRGBSwapChainSupported()) {
|
||||||
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it"
|
FVK_LOGW << "sRGB swapchain requested, but Platform does not support it";
|
||||||
<< utils::io::endl;
|
|
||||||
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
flags = flags | ~(backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE);
|
||||||
}
|
}
|
||||||
assert_invariant(width > 0 && height > 0 && "Vulkan requires non-zero swap chain dimensions.");
|
assert_invariant(width > 0 && height > 0 && "Vulkan requires non-zero swap chain dimensions.");
|
||||||
@@ -1223,7 +1231,7 @@ void VulkanDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor
|
|||||||
VulkanCommandBuffer& commands = mCommands.get();
|
VulkanCommandBuffer& commands = mCommands.get();
|
||||||
auto ib = resource_ptr<VulkanIndexBuffer>::cast(&mResourceManager, ibh);
|
auto ib = resource_ptr<VulkanIndexBuffer>::cast(&mResourceManager, ibh);
|
||||||
commands.acquire(ib);
|
commands.acquire(ib);
|
||||||
ib->buffer.loadFromCpu(commands.buffer(), p.buffer, byteOffset, p.size);
|
ib->buffer.loadFromCpu(commands, p.buffer, byteOffset, p.size);
|
||||||
|
|
||||||
scheduleDestroy(std::move(p));
|
scheduleDestroy(std::move(p));
|
||||||
}
|
}
|
||||||
@@ -1238,7 +1246,7 @@ void VulkanDriver::updateBufferObject(Handle<HwBufferObject> boh, BufferDescript
|
|||||||
|
|
||||||
auto bo = resource_ptr<VulkanBufferObject>::cast(&mResourceManager, boh);
|
auto bo = resource_ptr<VulkanBufferObject>::cast(&mResourceManager, boh);
|
||||||
commands.acquire(bo);
|
commands.acquire(bo);
|
||||||
bo->buffer.loadFromCpu(commands.buffer(), bd.buffer, byteOffset, bd.size);
|
bo->buffer.loadFromCpu(commands, bd.buffer, byteOffset, bd.size);
|
||||||
|
|
||||||
scheduleDestroy(std::move(bd));
|
scheduleDestroy(std::move(bd));
|
||||||
}
|
}
|
||||||
@@ -1249,7 +1257,7 @@ void VulkanDriver::updateBufferObjectUnsynchronized(Handle<HwBufferObject> boh,
|
|||||||
auto bo = resource_ptr<VulkanBufferObject>::cast(&mResourceManager, boh);
|
auto bo = resource_ptr<VulkanBufferObject>::cast(&mResourceManager, boh);
|
||||||
commands.acquire(bo);
|
commands.acquire(bo);
|
||||||
// TODO: implement unsynchronized version
|
// TODO: implement unsynchronized version
|
||||||
bo->buffer.loadFromCpu(commands.buffer(), bd.buffer, byteOffset, bd.size);
|
bo->buffer.loadFromCpu(commands, bd.buffer, byteOffset, bd.size);
|
||||||
scheduleDestroy(std::move(bd));
|
scheduleDestroy(std::move(bd));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1291,7 +1299,7 @@ TimerQueryResult VulkanDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint
|
|||||||
uint64_t const end = results.endTime;
|
uint64_t const end = results.endTime;
|
||||||
if (begin >= end) {
|
if (begin >= end) {
|
||||||
// TODO: queries might have ran on different command buffers.
|
// TODO: queries might have ran on different command buffers.
|
||||||
FVK_LOGW << "Timestamps are not monotonically increasing. " << utils::io::endl;
|
FVK_LOGW << "Timestamps are not monotonically increasing. ";
|
||||||
*elapsedTime = 0;
|
*elapsedTime = 0;
|
||||||
return TimerQueryResult::ERROR;
|
return TimerQueryResult::ERROR;
|
||||||
}
|
}
|
||||||
@@ -1622,8 +1630,8 @@ void VulkanDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y
|
|||||||
mReadPixels.run(
|
mReadPixels.run(
|
||||||
srcTarget, x, y, width, height, mPlatform->getGraphicsQueueFamilyIndex(),
|
srcTarget, x, y, width, height, mPlatform->getGraphicsQueueFamilyIndex(),
|
||||||
std::move(pbd),
|
std::move(pbd),
|
||||||
[&context = mContext](uint32_t reqs, VkFlags flags) {
|
[&context = mContext](uint32_t types, VkFlags reqs) {
|
||||||
return context.selectMemoryType(reqs, flags);
|
return context.selectMemoryType(types, reqs);
|
||||||
},
|
},
|
||||||
[this](PixelBufferDescriptor&& pbd) {
|
[this](PixelBufferDescriptor&& pbd) {
|
||||||
scheduleDestroy(std::move(pbd));
|
scheduleDestroy(std::move(pbd));
|
||||||
@@ -1898,7 +1906,7 @@ void VulkanDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
|
|||||||
// avoid rebinding these if they are already bound, but since we do not (yet) support subranges
|
// avoid rebinding these if they are already bound, but since we do not (yet) support subranges
|
||||||
// it would be rare for a client to make consecutive draw calls with the same render primitive.
|
// it would be rare for a client to make consecutive draw calls with the same render primitive.
|
||||||
vkCmdBindVertexBuffers(cmdbuffer, 0, bufferCount, buffers, offsets);
|
vkCmdBindVertexBuffers(cmdbuffer, 0, bufferCount, buffers, offsets);
|
||||||
vkCmdBindIndexBuffer(cmdbuffer, prim->indexBuffer->buffer.getGpuBuffer(), 0,
|
vkCmdBindIndexBuffer(cmdbuffer, prim->indexBuffer->buffer.getVkBuffer(), 0,
|
||||||
prim->indexBuffer->indexType);
|
prim->indexBuffer->indexType);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2029,7 +2037,7 @@ void VulkanDriver::debugCommandBegin(CommandStream* cmds, bool synchronous, cons
|
|||||||
assert_invariant(inRenderPass);
|
assert_invariant(inRenderPass);
|
||||||
inRenderPass = false;
|
inRenderPass = false;
|
||||||
} else if (inRenderPass && OUTSIDE_COMMANDS.find(command) != OUTSIDE_COMMANDS.end()) {
|
} else if (inRenderPass && OUTSIDE_COMMANDS.find(command) != OUTSIDE_COMMANDS.end()) {
|
||||||
FVK_LOGE << command.data() << " issued inside a render pass." << utils::io::endl;
|
FVK_LOGE << command.data() << " issued inside a render pass.";
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -18,15 +18,17 @@
|
|||||||
#define TNT_FILAMENT_BACKEND_VULKANDRIVER_H
|
#define TNT_FILAMENT_BACKEND_VULKANDRIVER_H
|
||||||
|
|
||||||
#include "VulkanBlitter.h"
|
#include "VulkanBlitter.h"
|
||||||
|
#include "VulkanBufferCache.h"
|
||||||
#include "VulkanConstants.h"
|
#include "VulkanConstants.h"
|
||||||
#include "VulkanContext.h"
|
#include "VulkanContext.h"
|
||||||
#include "VulkanFboCache.h"
|
#include "VulkanFboCache.h"
|
||||||
#include "VulkanHandles.h"
|
#include "VulkanHandles.h"
|
||||||
|
#include "VulkanMemory.h"
|
||||||
#include "VulkanPipelineCache.h"
|
#include "VulkanPipelineCache.h"
|
||||||
|
#include "VulkanQueryManager.h"
|
||||||
#include "VulkanReadPixels.h"
|
#include "VulkanReadPixels.h"
|
||||||
#include "VulkanSamplerCache.h"
|
#include "VulkanSamplerCache.h"
|
||||||
#include "VulkanStagePool.h"
|
#include "VulkanStagePool.h"
|
||||||
#include "VulkanQueryManager.h"
|
|
||||||
#include "VulkanYcbcrConversionCache.h"
|
#include "VulkanYcbcrConversionCache.h"
|
||||||
#include "vulkan/VulkanDescriptorSetCache.h"
|
#include "vulkan/VulkanDescriptorSetCache.h"
|
||||||
#include "vulkan/VulkanDescriptorSetLayoutCache.h"
|
#include "vulkan/VulkanDescriptorSetLayoutCache.h"
|
||||||
@@ -138,6 +140,7 @@ private:
|
|||||||
VulkanPipelineLayoutCache mPipelineLayoutCache;
|
VulkanPipelineLayoutCache mPipelineLayoutCache;
|
||||||
VulkanPipelineCache mPipelineCache;
|
VulkanPipelineCache mPipelineCache;
|
||||||
VulkanStagePool mStagePool;
|
VulkanStagePool mStagePool;
|
||||||
|
VulkanBufferCache mBufferCache;
|
||||||
VulkanFboCache mFramebufferCache;
|
VulkanFboCache mFramebufferCache;
|
||||||
VulkanYcbcrConversionCache mYcbcrConversionCache;
|
VulkanYcbcrConversionCache mYcbcrConversionCache;
|
||||||
VulkanSamplerCache mSamplerCache;
|
VulkanSamplerCache mSamplerCache;
|
||||||
|
|||||||
@@ -100,8 +100,7 @@ VkFramebuffer VulkanFboCache::getFramebuffer(FboKey const& config) noexcept {
|
|||||||
<< "for render pass " << config.renderPass << ", "
|
<< "for render pass " << config.renderPass << ", "
|
||||||
<< "samples = " << int(config.samples) << ", "
|
<< "samples = " << int(config.samples) << ", "
|
||||||
<< "depth = " << (config.depth ? 1 : 0) << ", "
|
<< "depth = " << (config.depth ? 1 : 0) << ", "
|
||||||
<< "attachmentCount = " << attachmentCount
|
<< "attachmentCount = " << attachmentCount;
|
||||||
<< utils::io::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VkFramebufferCreateInfo info {
|
VkFramebufferCreateInfo info {
|
||||||
@@ -341,8 +340,7 @@ VkRenderPass VulkanFboCache::getRenderPass(RenderPassKey const& config) noexcept
|
|||||||
<< "needsResolveMask = " << int(config.needsResolveMask) << ", "
|
<< "needsResolveMask = " << int(config.needsResolveMask) << ", "
|
||||||
<< "usesLazilyAllocatedMemory = " << int(config.usesLazilyAllocatedMemory) << ", "
|
<< "usesLazilyAllocatedMemory = " << int(config.usesLazilyAllocatedMemory) << ", "
|
||||||
<< "viewCount = " << int(config.viewCount) << ", "
|
<< "viewCount = " << int(config.viewCount) << ", "
|
||||||
<< "colorAttachmentCount[0] = " << subpasses[0].colorAttachmentCount
|
<< "colorAttachmentCount[0] = " << subpasses[0].colorAttachmentCount;
|
||||||
<< utils::io::endl;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return renderPass;
|
return renderPass;
|
||||||
|
|||||||
@@ -287,7 +287,7 @@ VulkanProgram::VulkanProgram(VkDevice device, Program const& builder) noexcept
|
|||||||
|
|
||||||
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
||||||
FVK_LOGD << "Created VulkanProgram " << builder << ", shaders = (" << modules[0]
|
FVK_LOGD << "Created VulkanProgram " << builder << ", shaders = (" << modules[0]
|
||||||
<< ", " << modules[1] << ")" << utils::io::endl;
|
<< ", " << modules[1] << ")";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,22 +583,22 @@ void VulkanVertexBuffer::setBuffer(fvkmemory::resource_ptr<VulkanBufferObject> b
|
|||||||
int8_t const* const attribToBuffer = vbi->getAttributeToBuffer();
|
int8_t const* const attribToBuffer = vbi->getAttributeToBuffer();
|
||||||
for (uint8_t attribIndex = 0; attribIndex < count; attribIndex++) {
|
for (uint8_t attribIndex = 0; attribIndex < count; attribIndex++) {
|
||||||
if (attribToBuffer[attribIndex] == static_cast<int8_t>(index)) {
|
if (attribToBuffer[attribIndex] == static_cast<int8_t>(index)) {
|
||||||
vkbuffers[attribIndex] = bufferObject->buffer.getGpuBuffer();
|
vkbuffers[attribIndex] = bufferObject->buffer.getVkBuffer();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mResources.push_back(bufferObject);
|
mResources.push_back(bufferObject);
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanBufferObject::VulkanBufferObject(VmaAllocator allocator, VulkanStagePool& stagePool,
|
VulkanBufferObject::VulkanBufferObject(VmaAllocator allocator, VulkanStagePool& stagePool,
|
||||||
uint32_t byteCount, BufferObjectBinding bindingType)
|
VulkanBufferCache& bufferCache, uint32_t byteCount, BufferObjectBinding bindingType)
|
||||||
: HwBufferObject(byteCount),
|
: HwBufferObject(byteCount),
|
||||||
buffer(allocator, stagePool, getBufferObjectUsage(bindingType), byteCount),
|
buffer(allocator, stagePool, bufferCache, getBufferObjectUsage(bindingType), byteCount),
|
||||||
bindingType(bindingType) {}
|
bindingType(bindingType) {}
|
||||||
|
|
||||||
VulkanRenderPrimitive::VulkanRenderPrimitive(PrimitiveType pt,
|
VulkanRenderPrimitive::VulkanRenderPrimitive(PrimitiveType pt,
|
||||||
fvkmemory::resource_ptr<VulkanVertexBuffer> vb,
|
fvkmemory::resource_ptr<VulkanVertexBuffer> vb,
|
||||||
fvkmemory::resource_ptr<VulkanIndexBuffer> ib)
|
fvkmemory::resource_ptr<VulkanIndexBuffer> ib)
|
||||||
: HwRenderPrimitive{.type = pt},
|
: HwRenderPrimitive{ .type = pt },
|
||||||
vertexBuffer(vb),
|
vertexBuffer(vb),
|
||||||
indexBuffer(ib) {}
|
indexBuffer(ib) {}
|
||||||
|
|
||||||
|
|||||||
@@ -21,20 +21,21 @@
|
|||||||
#include "DriverBase.h"
|
#include "DriverBase.h"
|
||||||
|
|
||||||
#include "VulkanAsyncHandles.h"
|
#include "VulkanAsyncHandles.h"
|
||||||
#include "VulkanBuffer.h"
|
#include "VulkanBufferCache.h"
|
||||||
|
#include "VulkanBufferProxy.h"
|
||||||
#include "VulkanFboCache.h"
|
#include "VulkanFboCache.h"
|
||||||
#include "VulkanSwapChain.h"
|
#include "VulkanSwapChain.h"
|
||||||
#include "VulkanTexture.h"
|
#include "VulkanTexture.h"
|
||||||
#include "vulkan/memory/Resource.h"
|
#include "vulkan/memory/Resource.h"
|
||||||
#include "vulkan/utils/StaticVector.h"
|
|
||||||
#include "vulkan/utils/Definitions.h"
|
#include "vulkan/utils/Definitions.h"
|
||||||
|
#include "vulkan/utils/StaticVector.h"
|
||||||
|
|
||||||
#include <backend/Program.h>
|
#include <backend/Program.h>
|
||||||
|
|
||||||
#include <utils/bitset.h>
|
|
||||||
#include <utils/FixedCapacityVector.h>
|
#include <utils/FixedCapacityVector.h>
|
||||||
#include <utils/Mutex.h>
|
#include <utils/Mutex.h>
|
||||||
#include <utils/StructureOfArrays.h>
|
#include <utils/StructureOfArrays.h>
|
||||||
|
#include <utils/bitset.h>
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
|
||||||
@@ -428,21 +429,22 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
struct VulkanIndexBuffer : public HwIndexBuffer, fvkmemory::Resource {
|
struct VulkanIndexBuffer : public HwIndexBuffer, fvkmemory::Resource {
|
||||||
VulkanIndexBuffer(VmaAllocator allocator, VulkanStagePool& stagePool, uint8_t elementSize,
|
VulkanIndexBuffer(VmaAllocator allocator, VulkanStagePool& stagePool,
|
||||||
uint32_t indexCount)
|
VulkanBufferCache& bufferCache, uint8_t elementSize, uint32_t indexCount)
|
||||||
: HwIndexBuffer(elementSize, indexCount),
|
: HwIndexBuffer(elementSize, indexCount),
|
||||||
buffer(allocator, stagePool, VK_BUFFER_USAGE_INDEX_BUFFER_BIT, elementSize * indexCount),
|
buffer(allocator, stagePool, bufferCache, VulkanBufferUsage::INDEX,
|
||||||
|
elementSize * indexCount),
|
||||||
indexType(elementSize == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32) {}
|
indexType(elementSize == 2 ? VK_INDEX_TYPE_UINT16 : VK_INDEX_TYPE_UINT32) {}
|
||||||
|
|
||||||
VulkanBuffer buffer;
|
VulkanBufferProxy buffer;
|
||||||
const VkIndexType indexType;
|
const VkIndexType indexType;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VulkanBufferObject : public HwBufferObject, fvkmemory::Resource {
|
struct VulkanBufferObject : public HwBufferObject, fvkmemory::Resource {
|
||||||
VulkanBufferObject(VmaAllocator allocator, VulkanStagePool& stagePool, uint32_t byteCount,
|
VulkanBufferObject(VmaAllocator allocator, VulkanStagePool& stagePool,
|
||||||
BufferObjectBinding bindingType);
|
VulkanBufferCache& bufferCache, uint32_t byteCount, BufferObjectBinding bindingType);
|
||||||
|
|
||||||
VulkanBuffer buffer;
|
VulkanBufferProxy buffer;
|
||||||
const BufferObjectBinding bindingType;
|
const BufferObjectBinding bindingType;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -455,18 +457,19 @@ struct VulkanRenderPrimitive : public HwRenderPrimitive, fvkmemory::Resource {
|
|||||||
fvkmemory::resource_ptr<VulkanIndexBuffer> indexBuffer;
|
fvkmemory::resource_ptr<VulkanIndexBuffer> indexBuffer;
|
||||||
};
|
};
|
||||||
|
|
||||||
inline constexpr VkBufferUsageFlagBits getBufferObjectUsage(
|
inline constexpr VulkanBufferUsage getBufferObjectUsage(BufferObjectBinding bindingType) noexcept {
|
||||||
BufferObjectBinding bindingType) noexcept {
|
switch (bindingType) {
|
||||||
switch(bindingType) {
|
|
||||||
case BufferObjectBinding::VERTEX:
|
case BufferObjectBinding::VERTEX:
|
||||||
return VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
|
return VulkanBufferUsage::VERTEX;
|
||||||
case BufferObjectBinding::UNIFORM:
|
case BufferObjectBinding::UNIFORM:
|
||||||
return VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT;
|
return VulkanBufferUsage::UNIFORM;
|
||||||
case BufferObjectBinding::SHADER_STORAGE:
|
case BufferObjectBinding::SHADER_STORAGE:
|
||||||
return VK_BUFFER_USAGE_STORAGE_BUFFER_BIT;
|
return VulkanBufferUsage::SHADER_STORAGE;
|
||||||
// when adding more buffer-types here, make sure to update VulkanBuffer::loadFromCpu()
|
// when adding more buffer-types here, make sure to update VulkanBuffer::loadFromCpu()
|
||||||
// if necessary.
|
// if necessary.
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return VulkanBufferUsage::UNKNOWN;
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace filament::backend
|
} // namespace filament::backend
|
||||||
|
|||||||
@@ -37,4 +37,24 @@ VK_DEFINE_HANDLE(VmaAllocator)
|
|||||||
VK_DEFINE_HANDLE(VmaAllocation)
|
VK_DEFINE_HANDLE(VmaAllocation)
|
||||||
VK_DEFINE_HANDLE(VmaPool)
|
VK_DEFINE_HANDLE(VmaPool)
|
||||||
|
|
||||||
|
namespace filament::backend {
|
||||||
|
|
||||||
|
enum class VulkanBufferUsage : uint8_t {
|
||||||
|
UNKNOWN,
|
||||||
|
VERTEX,
|
||||||
|
INDEX,
|
||||||
|
UNIFORM,
|
||||||
|
SHADER_STORAGE,
|
||||||
|
};
|
||||||
|
|
||||||
|
struct VulkanGpuBuffer {
|
||||||
|
VkBuffer vkbuffer = VK_NULL_HANDLE;
|
||||||
|
VmaAllocation vmaAllocation = VK_NULL_HANDLE;
|
||||||
|
VmaAllocationInfo allocationInfo;
|
||||||
|
uint32_t numBytes = 0;
|
||||||
|
VulkanBufferUsage usage = VulkanBufferUsage::UNKNOWN;
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace filament::backend
|
||||||
|
|
||||||
#endif // TNT_FILAMENT_BACKEND_VULKANMEMORY_H
|
#endif // TNT_FILAMENT_BACKEND_VULKANMEMORY_H
|
||||||
|
|||||||
@@ -218,8 +218,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
|||||||
|
|
||||||
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
||||||
FVK_LOGD << "vkCreateGraphicsPipelines with shaders = ("
|
FVK_LOGD << "vkCreateGraphicsPipelines with shaders = ("
|
||||||
<< shaderStages[0].module << ", " << shaderStages[1].module << ")"
|
<< shaderStages[0].module << ", " << shaderStages[1].module << ")";
|
||||||
<< utils::io::endl;
|
|
||||||
#endif
|
#endif
|
||||||
PipelineCacheEntry cacheEntry = {
|
PipelineCacheEntry cacheEntry = {
|
||||||
.lastUsed = mCurrentTime,
|
.lastUsed = mCurrentTime,
|
||||||
@@ -228,7 +227,7 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
|||||||
VKALLOC, &cacheEntry.handle);
|
VKALLOC, &cacheEntry.handle);
|
||||||
assert_invariant(error == VK_SUCCESS);
|
assert_invariant(error == VK_SUCCESS);
|
||||||
if (error != VK_SUCCESS) {
|
if (error != VK_SUCCESS) {
|
||||||
FVK_LOGE << "vkCreateGraphicsPipelines error " << error << utils::io::endl;
|
FVK_LOGE << "vkCreateGraphicsPipelines error " << error;
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
return &mPipelines.emplace(mPipelineRequirements, cacheEntry).first.value();
|
return &mPipelines.emplace(mPipelineRequirements, cacheEntry).first.value();
|
||||||
@@ -242,7 +241,7 @@ void VulkanPipelineCache::bindProgram(fvkmemory::resource_ptr<VulkanProgram> pro
|
|||||||
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
|
||||||
if (mPipelineRequirements.shaders[0] == VK_NULL_HANDLE ||
|
if (mPipelineRequirements.shaders[0] == VK_NULL_HANDLE ||
|
||||||
mPipelineRequirements.shaders[1] == VK_NULL_HANDLE) {
|
mPipelineRequirements.shaders[1] == VK_NULL_HANDLE) {
|
||||||
FVK_LOGE << "Binding missing shader: " << program->name.c_str() << utils::io::endl;
|
FVK_LOGE << "Binding missing shader: " << program->name.c_str();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@ fvkmemory::resource_ptr<VulkanTimerQuery> VulkanQueryManager::getNextQuery(
|
|||||||
fvkmemory::ResourceManager* resourceManager) {
|
fvkmemory::ResourceManager* resourceManager) {
|
||||||
auto unused = ~mUsed;
|
auto unused = ~mUsed;
|
||||||
if (unused.empty()) {
|
if (unused.empty()) {
|
||||||
FVK_LOGE << "More than " << mUsed.size() << " timers are not supported." << utils::io::endl;
|
FVK_LOGE << "More than " << mUsed.size() << " timers are not supported.";
|
||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -143,7 +143,7 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
|||||||
mTaskHandler = std::make_unique<TaskHandler>();
|
mTaskHandler = std::make_unique<TaskHandler>();
|
||||||
}
|
}
|
||||||
|
|
||||||
VkCommandPool& cmdpool = mCommandPool;
|
VkCommandPool const cmdpool = mCommandPool;
|
||||||
|
|
||||||
fvkmemory::resource_ptr<VulkanTexture> srcTexture = srcTarget->getColor0().texture;
|
fvkmemory::resource_ptr<VulkanTexture> srcTexture = srcTarget->getColor0().texture;
|
||||||
assert_invariant(srcTexture);
|
assert_invariant(srcTexture);
|
||||||
@@ -152,17 +152,17 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
|||||||
= srcFormat == VK_FORMAT_B8G8R8A8_UNORM || srcFormat == VK_FORMAT_B8G8R8A8_SRGB;
|
= srcFormat == VK_FORMAT_B8G8R8A8_UNORM || srcFormat == VK_FORMAT_B8G8R8A8_SRGB;
|
||||||
|
|
||||||
// Create a host visible, linearly tiled image as a staging area.
|
// Create a host visible, linearly tiled image as a staging area.
|
||||||
VkImageCreateInfo const imageInfo{
|
VkImageCreateInfo const imageInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
|
||||||
.imageType = VK_IMAGE_TYPE_2D,
|
.imageType = VK_IMAGE_TYPE_2D,
|
||||||
.format = srcFormat,
|
.format = srcFormat,
|
||||||
.extent = {width, height, 1},
|
.extent = { width, height, 1 },
|
||||||
.mipLevels = 1,
|
.mipLevels = 1,
|
||||||
.arrayLayers = 1,
|
.arrayLayers = 1,
|
||||||
.samples = VK_SAMPLE_COUNT_1_BIT,
|
.samples = VK_SAMPLE_COUNT_1_BIT,
|
||||||
.tiling = VK_IMAGE_TILING_LINEAR,
|
.tiling = VK_IMAGE_TILING_LINEAR,
|
||||||
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
.usage = VK_IMAGE_USAGE_TRANSFER_DST_BIT,
|
||||||
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
.initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImage stagingImage;
|
VkImage stagingImage;
|
||||||
@@ -171,7 +171,7 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
|||||||
#if FVK_ENABLED(FVK_DEBUG_READ_PIXELS)
|
#if FVK_ENABLED(FVK_DEBUG_READ_PIXELS)
|
||||||
FVK_LOGD << "readPixels created image=" << stagingImage
|
FVK_LOGD << "readPixels created image=" << stagingImage
|
||||||
<< " to copy from image=" << srcTexture->getVkImage()
|
<< " to copy from image=" << srcTexture->getVkImage()
|
||||||
<< " src-layout=" << srcTexture->getLayout(0, 0) << utils::io::endl;
|
<< " src-layout=" << srcTexture->getLayout(0, 0);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
VkMemoryRequirements memReqs;
|
VkMemoryRequirements memReqs;
|
||||||
@@ -188,28 +188,27 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
|||||||
memoryTypeIndex = selectMemoryFunc(memReqs.memoryTypeBits,
|
memoryTypeIndex = selectMemoryFunc(memReqs.memoryTypeBits,
|
||||||
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT);
|
||||||
FVK_LOGW
|
FVK_LOGW
|
||||||
<< "readPixels is slow because VK_MEMORY_PROPERTY_HOST_CACHED_BIT is not available"
|
<< "readPixels is slow because VK_MEMORY_PROPERTY_HOST_CACHED_BIT is not available";
|
||||||
<< utils::io::endl;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
FILAMENT_CHECK_POSTCONDITION(memoryTypeIndex < VK_MAX_MEMORY_TYPES)
|
FILAMENT_CHECK_POSTCONDITION(memoryTypeIndex < VK_MAX_MEMORY_TYPES)
|
||||||
<< "VulkanReadPixels: unable to find a memory type that meets requirements.";
|
<< "VulkanReadPixels: unable to find a memory type that meets requirements.";
|
||||||
|
|
||||||
VkMemoryAllocateInfo const allocInfo = {
|
VkMemoryAllocateInfo const allocInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO,
|
||||||
.allocationSize = memReqs.size,
|
.allocationSize = memReqs.size,
|
||||||
.memoryTypeIndex = memoryTypeIndex,
|
.memoryTypeIndex = memoryTypeIndex,
|
||||||
};
|
};
|
||||||
|
|
||||||
vkAllocateMemory(device, &allocInfo, VKALLOC, &stagingMemory);
|
vkAllocateMemory(device, &allocInfo, VKALLOC, &stagingMemory);
|
||||||
vkBindImageMemory(device, stagingImage, stagingMemory, 0);
|
vkBindImageMemory(device, stagingImage, stagingMemory, 0);
|
||||||
|
|
||||||
VkCommandBuffer cmdbuffer;
|
VkCommandBuffer cmdbuffer;
|
||||||
VkCommandBufferAllocateInfo const allocateInfo{
|
VkCommandBufferAllocateInfo const allocateInfo = {
|
||||||
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_COMMAND_BUFFER_ALLOCATE_INFO,
|
||||||
.commandPool = cmdpool,
|
.commandPool = cmdpool,
|
||||||
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
.level = VK_COMMAND_BUFFER_LEVEL_PRIMARY,
|
||||||
.commandBufferCount = 1,
|
.commandBufferCount = 1,
|
||||||
};
|
};
|
||||||
vkAllocateCommandBuffers(device, &allocateInfo, &cmdbuffer);
|
vkAllocateCommandBuffers(device, &allocateInfo, &cmdbuffer);
|
||||||
|
|
||||||
@@ -304,9 +303,8 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
|||||||
cmdpool, cmdbuffer, pUserBuffer,
|
cmdpool, cmdbuffer, pUserBuffer,
|
||||||
fence = readCompleteFence]() mutable {
|
fence = readCompleteFence]() mutable {
|
||||||
VkResult status = vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
|
VkResult status = vkWaitForFences(device, 1, &fence, VK_TRUE, UINT64_MAX);
|
||||||
// Fence hasn't been reached. Try waiting again.
|
|
||||||
if (status != VK_SUCCESS) {
|
if (status != VK_SUCCESS) {
|
||||||
FVK_LOGE << "Failed to wait for readPixels fence" << utils::io::endl;
|
FVK_LOGE << "Failed to wait for readPixels fence";
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -324,7 +322,7 @@ void VulkanReadPixels::run(fvkmemory::resource_ptr<VulkanRenderTarget> srcTarget
|
|||||||
fvkutils::getComponentCount(srcFormat), srcPixels,
|
fvkutils::getComponentCount(srcFormat), srcPixels,
|
||||||
static_cast<int>(subResourceLayout.rowPitch), static_cast<int>(width),
|
static_cast<int>(subResourceLayout.rowPitch), static_cast<int>(width),
|
||||||
static_cast<int>(height), swizzle)) {
|
static_cast<int>(height), swizzle)) {
|
||||||
FVK_LOGE << "Unsupported PixelDataFormat or PixelDataType" << utils::io::endl;
|
FVK_LOGE << "Unsupported PixelDataFormat or PixelDataType";
|
||||||
}
|
}
|
||||||
|
|
||||||
vkUnmapMemory(device, stagingMemory);
|
vkUnmapMemory(device, stagingMemory);
|
||||||
|
|||||||
@@ -28,46 +28,111 @@ static constexpr uint32_t TIME_BEFORE_EVICTION = 3;
|
|||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
VulkanStagePool::VulkanStagePool(VmaAllocator allocator, VulkanCommands* commands)
|
namespace {
|
||||||
: mAllocator(allocator),
|
|
||||||
mCommands(commands) {}
|
|
||||||
|
|
||||||
VulkanStage const* VulkanStagePool::acquireStage(uint32_t numBytes) {
|
// Note: these are temporary values, they will be configurable.
|
||||||
// First check if a stage exists whose capacity is greater than or equal to the requested size.
|
static constexpr uint32_t MAX_EMPTY_STAGES_TO_RETAIN = 1;
|
||||||
auto iter = mFreeStages.lower_bound(numBytes);
|
constexpr uint32_t STAGE_SIZE = 1048576;
|
||||||
if (iter != mFreeStages.end()) {
|
|
||||||
auto stage = iter->second;
|
}// namespace
|
||||||
mFreeStages.erase(iter);
|
|
||||||
stage->lastAccessed = mCurrentFrame;
|
fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStage::acquireSegment(
|
||||||
mUsedStages.push_back(stage);
|
fvkmemory::ResourceManager* resManager, uint32_t numBytes) {
|
||||||
return stage;
|
auto segment = fvkmemory::resource_ptr<Segment>::construct(
|
||||||
}
|
resManager, this, numBytes, mCurrentOffset, [this](uint32_t offset) {
|
||||||
// We were not able to find a sufficiently large stage, so create a new one.
|
mSegments.erase(offset);
|
||||||
VulkanStage* stage = new VulkanStage({
|
|
||||||
.memory = VK_NULL_HANDLE,
|
|
||||||
.buffer = VK_NULL_HANDLE,
|
|
||||||
.capacity = numBytes,
|
|
||||||
.lastAccessed = mCurrentFrame,
|
|
||||||
});
|
});
|
||||||
|
mSegments.insert({mCurrentOffset, segment.get()});
|
||||||
|
mCurrentOffset += numBytes;
|
||||||
|
return segment;
|
||||||
|
}
|
||||||
|
|
||||||
// Create the VkBuffer.
|
VulkanStagePool::VulkanStagePool(VmaAllocator allocator, fvkmemory::ResourceManager* resManager,
|
||||||
mUsedStages.push_back(stage);
|
VulkanCommands* commands, const VkPhysicalDeviceLimits* deviceLimits)
|
||||||
VkBufferCreateInfo bufferInfo {
|
: mAllocator(allocator),
|
||||||
|
mResManager(resManager),
|
||||||
|
mCommands(commands),
|
||||||
|
mDeviceLimits(deviceLimits) {}
|
||||||
|
|
||||||
|
fvkmemory::resource_ptr<VulkanStage::Segment> VulkanStagePool::acquireStage(uint32_t numBytes) {
|
||||||
|
// Apply alignment to the byte count to ensure that, when we later flush
|
||||||
|
// data written by the host, we only flush the atoms that we modified, and
|
||||||
|
// no adjacent atoms.
|
||||||
|
numBytes = alignToNonCoherentAtomSize(numBytes);
|
||||||
|
|
||||||
|
// First check if a stage segment exists whose capacity is greater than or
|
||||||
|
// equal to the requested size.
|
||||||
|
auto iter = mStages.lower_bound(numBytes);
|
||||||
|
|
||||||
|
VulkanStage* pStage;
|
||||||
|
if (iter != mStages.end()) {
|
||||||
|
pStage = iter->second;
|
||||||
|
mStages.erase(iter);
|
||||||
|
} else {
|
||||||
|
pStage = allocateNewStage(std::max(numBytes, STAGE_SIZE));
|
||||||
|
}
|
||||||
|
|
||||||
|
// Note: this allocation updates `currentOffset` and `segments` within
|
||||||
|
// the parent stage. When destroyed, it will update `segments`.
|
||||||
|
fvkmemory::resource_ptr<VulkanStage::Segment> pSegment = pStage->acquireSegment(mResManager, numBytes);
|
||||||
|
|
||||||
|
// Update the stage's metadata, and reinsert it with the remaining segment
|
||||||
|
// capacity.
|
||||||
|
uint32_t spaceRemaining = pStage->capacity() - pStage->currentOffset();
|
||||||
|
mStages.insert({ spaceRemaining, pStage });
|
||||||
|
|
||||||
|
return pSegment;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t VulkanStagePool::alignToNonCoherentAtomSize(uint32_t bytes) {
|
||||||
|
VkDeviceSize alignment = mDeviceLimits->nonCoherentAtomSize;
|
||||||
|
if (alignment == 0) {
|
||||||
|
return bytes;
|
||||||
|
}
|
||||||
|
|
||||||
|
uint32_t remainder = bytes % alignment;
|
||||||
|
return remainder == 0 ? bytes : bytes + (alignment - remainder);
|
||||||
|
}
|
||||||
|
|
||||||
|
VulkanStage* VulkanStagePool::allocateNewStage(uint32_t capacity) {
|
||||||
|
VkBufferCreateInfo bufferInfo{
|
||||||
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,
|
||||||
.size = numBytes,
|
.size = alignToNonCoherentAtomSize(capacity),
|
||||||
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
.usage = VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
|
||||||
};
|
};
|
||||||
VmaAllocationCreateInfo allocInfo { .usage = VMA_MEMORY_USAGE_CPU_ONLY };
|
VmaAllocationCreateInfo allocInfo { .usage = VMA_MEMORY_USAGE_CPU_ONLY };
|
||||||
UTILS_UNUSED_IN_RELEASE VkResult result = vmaCreateBuffer(mAllocator, &bufferInfo,
|
VkBuffer buffer;
|
||||||
&allocInfo, &stage->buffer, &stage->memory, nullptr);
|
VmaAllocation memory;
|
||||||
|
VkResult result =
|
||||||
|
vmaCreateBuffer(mAllocator, &bufferInfo, &allocInfo, &buffer, &memory, nullptr);
|
||||||
|
|
||||||
#if FVK_ENABLED(FVK_DEBUG_STAGING_ALLOCATION)
|
#if FVK_ENABLED(FVK_DEBUG_STAGING_ALLOCATION)
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
FVK_LOGE << "Allocation error: " << result << utils::io::endl;
|
FVK_LOGE << "Allocation error: " << result;
|
||||||
|
} else {
|
||||||
|
FVK_LOGD << "Allocated stage with hndl " << buffer;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
return stage;
|
void* pMapping = nullptr;
|
||||||
|
if (result == VK_SUCCESS) {
|
||||||
|
result = vmaMapMemory(mAllocator, memory, &pMapping);
|
||||||
|
|
||||||
|
#if FVK_ENABLED(FVK_DEBUG_STAGING_ALLOCATION)
|
||||||
|
if (result != VK_SUCCESS) {
|
||||||
|
FVK_LOGE << "Memory mapping erryr: " << result << utils::io::endl;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
return new VulkanStage(memory, buffer, capacity, pMapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
void VulkanStagePool::destroyStage(VulkanStage const*&& stage) {
|
||||||
|
assert(stage->isSafeToReset()); // Ensure all segments have been reset already.
|
||||||
|
vmaUnmapMemory(mAllocator, stage->memory());
|
||||||
|
vmaDestroyBuffer(mAllocator, stage->buffer(), stage->memory());
|
||||||
|
delete stage;
|
||||||
}
|
}
|
||||||
|
|
||||||
VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, PixelDataType type,
|
VulkanStageImage const* VulkanStagePool::acquireImage(PixelDataFormat format, PixelDataType type,
|
||||||
@@ -141,27 +206,34 @@ void VulkanStagePool::gc() noexcept {
|
|||||||
}
|
}
|
||||||
const uint64_t evictionTime = mCurrentFrame - TIME_BEFORE_EVICTION;
|
const uint64_t evictionTime = mCurrentFrame - TIME_BEFORE_EVICTION;
|
||||||
|
|
||||||
// Destroy buffers that have not been used for several frames.
|
decltype(mStages) freeStages;
|
||||||
decltype(mFreeStages) freeStages;
|
freeStages.swap(mStages);
|
||||||
freeStages.swap(mFreeStages);
|
uint8_t freeStageCount = 0; // Assuming we'll never have > 255 free stages
|
||||||
for (auto pair : freeStages) {
|
for (auto& pair : freeStages) {
|
||||||
if (pair.second->lastAccessed < evictionTime) {
|
// First, find any stages that have no segments within them.
|
||||||
vmaDestroyBuffer(mAllocator, pair.second->buffer, pair.second->memory);
|
if (pair.second->isSafeToReset()) {
|
||||||
delete pair.second;
|
if (++freeStageCount > MAX_EMPTY_STAGES_TO_RETAIN) {
|
||||||
} else {
|
#if FVK_ENABLED(FVK_DEBUG_STAGING_ALLOCATION)
|
||||||
mFreeStages.insert(pair);
|
FVK_LOGD << "Destroying a staging buffer with hndl " << pair.second->buffer()
|
||||||
}
|
<< utils::io::endl;
|
||||||
}
|
#endif
|
||||||
|
destroyStage(std::move(pair.second));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
// Reclaim buffers that are no longer being used by any command buffer.
|
#if FVK_ENABLED(FVK_DEBUG_STAGING_ALLOCATION)
|
||||||
decltype(mUsedStages) usedStages;
|
if (pair.first == 0) {
|
||||||
usedStages.swap(mUsedStages);
|
FVK_LOGD << "Recycling an unused staging buffer with hndl " << pair.second->buffer()
|
||||||
for (auto stage : usedStages) {
|
<< utils::io::endl;
|
||||||
if (stage->lastAccessed < evictionTime) {
|
}
|
||||||
stage->lastAccessed = mCurrentFrame;
|
#endif
|
||||||
mFreeStages.insert(std::make_pair(stage->capacity, stage));
|
|
||||||
|
// Note - this segment is free, make sure the structure is cleared
|
||||||
|
// and reinsert it into our free stage list.
|
||||||
|
pair.second->reset();
|
||||||
|
mStages.insert({ pair.second->capacity(), pair.second });
|
||||||
} else {
|
} else {
|
||||||
mUsedStages.push_back(stage);
|
mStages.insert(pair);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -192,17 +264,10 @@ void VulkanStagePool::gc() noexcept {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void VulkanStagePool::terminate() noexcept {
|
void VulkanStagePool::terminate() noexcept {
|
||||||
for (auto stage : mUsedStages) {
|
for (auto& pair : mStages) {
|
||||||
vmaDestroyBuffer(mAllocator, stage->buffer, stage->memory);
|
destroyStage(std::move(pair.second));
|
||||||
delete stage;
|
|
||||||
}
|
}
|
||||||
mUsedStages.clear();
|
mStages.clear();
|
||||||
|
|
||||||
for (auto pair : mFreeStages) {
|
|
||||||
vmaDestroyBuffer(mAllocator, pair.second->buffer, pair.second->memory);
|
|
||||||
delete pair.second;
|
|
||||||
}
|
|
||||||
mFreeStages.clear();
|
|
||||||
|
|
||||||
for (auto image : mUsedImages) {
|
for (auto image : mUsedImages) {
|
||||||
vmaDestroyImage(mAllocator, image->image, image->memory);
|
vmaDestroyImage(mAllocator, image->image, image->memory);
|
||||||
|
|||||||
@@ -17,8 +17,11 @@
|
|||||||
#ifndef TNT_FILAMENT_BACKEND_VULKANSTAGEPOOL_H
|
#ifndef TNT_FILAMENT_BACKEND_VULKANSTAGEPOOL_H
|
||||||
#define TNT_FILAMENT_BACKEND_VULKANSTAGEPOOL_H
|
#define TNT_FILAMENT_BACKEND_VULKANSTAGEPOOL_H
|
||||||
|
|
||||||
#include "backend/DriverEnums.h"
|
|
||||||
#include "VulkanMemory.h"
|
#include "VulkanMemory.h"
|
||||||
|
#include "backend/DriverEnums.h"
|
||||||
|
#include "vulkan/memory/Resource.h"
|
||||||
|
#include "vulkan/memory/ResourceManager.h"
|
||||||
|
#include "vulkan/memory/ResourcePointer.h"
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
#include <unordered_set>
|
#include <unordered_set>
|
||||||
@@ -28,12 +31,96 @@ namespace filament::backend {
|
|||||||
|
|
||||||
class VulkanCommands;
|
class VulkanCommands;
|
||||||
|
|
||||||
// Immutable POD representing a shared CPU-GPU staging area.
|
// Object representing a shared CPU-GPU staging area, which can be subdivided
|
||||||
struct VulkanStage {
|
// into smaller buffers as needed.
|
||||||
VmaAllocation memory;
|
class VulkanStage {
|
||||||
VkBuffer buffer;
|
public:
|
||||||
uint32_t capacity;
|
VulkanStage(VmaAllocation memory, VkBuffer buffer, uint32_t capacity, void* mapping)
|
||||||
mutable uint64_t lastAccessed;
|
: mMemory(memory),
|
||||||
|
mBuffer(buffer),
|
||||||
|
mCapacity(capacity),
|
||||||
|
mMapping(mapping) {}
|
||||||
|
|
||||||
|
~VulkanStage() = default;
|
||||||
|
VulkanStage(const VulkanStage& other) = delete;
|
||||||
|
VulkanStage(VulkanStage&& other) = delete;
|
||||||
|
VulkanStage& operator=(const VulkanStage& other) = delete;
|
||||||
|
VulkanStage& operator=(VulkanStage&& other) = delete;
|
||||||
|
|
||||||
|
class Segment : public fvkmemory::Resource {
|
||||||
|
public:
|
||||||
|
using OnRecycle = std::function<void(uint32_t offset)>;
|
||||||
|
|
||||||
|
Segment(VulkanStage* parentStage, uint32_t capacity, uint32_t offset,
|
||||||
|
OnRecycle&& onRecycleFn)
|
||||||
|
: mParentStage(parentStage),
|
||||||
|
mCapacity(capacity),
|
||||||
|
mOffset(offset),
|
||||||
|
mOnRecycleFn(onRecycleFn) {}
|
||||||
|
|
||||||
|
~Segment() {
|
||||||
|
if (mOnRecycleFn) {
|
||||||
|
mOnRecycleFn(offset());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should not be copying this around.
|
||||||
|
Segment(const Segment& other) = delete;
|
||||||
|
Segment(Segment&& other) = delete;
|
||||||
|
Segment& operator=(const Segment& other) = delete;
|
||||||
|
Segment& operator=(Segment&& other) = delete;
|
||||||
|
|
||||||
|
inline VulkanStage* parentStage() const { return mParentStage; }
|
||||||
|
inline VkBuffer buffer() const { return parentStage()->buffer(); }
|
||||||
|
inline VmaAllocation memory() const { return parentStage()->memory(); }
|
||||||
|
inline uint32_t capacity() const { return mCapacity; }
|
||||||
|
inline uint32_t offset() const { return mOffset; }
|
||||||
|
|
||||||
|
inline void* mapping() const {
|
||||||
|
return reinterpret_cast<void*>(
|
||||||
|
reinterpret_cast<char*>(mParentStage->mapping()) + offset());
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
// Ensure parent class can access the terminate method.
|
||||||
|
friend class VulkanStage;
|
||||||
|
|
||||||
|
VulkanStage* const mParentStage;
|
||||||
|
const uint32_t mCapacity;
|
||||||
|
const uint32_t mOffset;
|
||||||
|
OnRecycle mOnRecycleFn;
|
||||||
|
};
|
||||||
|
|
||||||
|
inline VmaAllocation memory() const { return mMemory; }
|
||||||
|
inline VkBuffer buffer() const { return mBuffer; }
|
||||||
|
inline uint32_t capacity() const { return mCapacity; }
|
||||||
|
inline void* mapping() const { return mMapping; }
|
||||||
|
|
||||||
|
inline uint32_t currentOffset() { return mCurrentOffset; }
|
||||||
|
|
||||||
|
inline bool isSafeToReset() const { return mSegments.empty(); }
|
||||||
|
|
||||||
|
inline void reset() { mCurrentOffset = 0; }
|
||||||
|
|
||||||
|
// Marks a region of the block as "in-use", and provides information about
|
||||||
|
// the allocated region to the caller. Note: this assumes that numBytes
|
||||||
|
// is aligned to the physical device's nonCoherentAtomSize.
|
||||||
|
fvkmemory::resource_ptr<Segment> acquireSegment(fvkmemory::ResourceManager* resManager,
|
||||||
|
uint32_t numBytes);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const VmaAllocation mMemory;
|
||||||
|
const VkBuffer mBuffer;
|
||||||
|
const uint32_t mCapacity;
|
||||||
|
|
||||||
|
void* mMapping;
|
||||||
|
|
||||||
|
uint32_t mCurrentOffset = 0;
|
||||||
|
|
||||||
|
// Maps the start offset of a vulkan stage block to the stage block,
|
||||||
|
// for easy deletions later. This is managed by the blocks themselves, in an
|
||||||
|
// RAII pattern, during construction and destruction.
|
||||||
|
std::unordered_map<uint32_t, Segment*> mSegments;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct VulkanStageImage {
|
struct VulkanStageImage {
|
||||||
@@ -49,11 +136,15 @@ struct VulkanStageImage {
|
|||||||
// This class manages two types of host-mappable staging areas: buffer stages and image stages.
|
// This class manages two types of host-mappable staging areas: buffer stages and image stages.
|
||||||
class VulkanStagePool {
|
class VulkanStagePool {
|
||||||
public:
|
public:
|
||||||
VulkanStagePool(VmaAllocator allocator, VulkanCommands* commands);
|
VulkanStagePool(VmaAllocator allocator, fvkmemory::ResourceManager* resManager,
|
||||||
|
VulkanCommands* commands, const VkPhysicalDeviceLimits* deviceLimits);
|
||||||
|
|
||||||
// Finds or creates a stage whose capacity is at least the given number of bytes.
|
// Finds or creates a stage block whose capacity is at least the given
|
||||||
// The stage is automatically released back to the pool after TIME_BEFORE_EVICTION frames.
|
// number of bytes. Internally, creates and manages and subdivides large
|
||||||
VulkanStage const* acquireStage(uint32_t numBytes);
|
// buffers so that we have less objects around that we have to keep track
|
||||||
|
// of.
|
||||||
|
// This function is NOT thread-safe.
|
||||||
|
fvkmemory::resource_ptr<VulkanStage::Segment> acquireStage(uint32_t numBytes);
|
||||||
|
|
||||||
// Images have VK_IMAGE_LAYOUT_GENERAL and must not be transitioned to any other layout
|
// Images have VK_IMAGE_LAYOUT_GENERAL and must not be transitioned to any other layout
|
||||||
VulkanStageImage const* acquireImage(PixelDataFormat format, PixelDataType type,
|
VulkanStageImage const* acquireImage(PixelDataFormat format, PixelDataType type,
|
||||||
@@ -64,17 +155,37 @@ public:
|
|||||||
|
|
||||||
// Destroys all unused stages and asserts that there are no stages currently in use.
|
// Destroys all unused stages and asserts that there are no stages currently in use.
|
||||||
// This should be called while the context's VkDevice is still alive.
|
// This should be called while the context's VkDevice is still alive.
|
||||||
|
// Note: it is expected that all resources have been reclaimed before this
|
||||||
|
// is called. It is also expected that this stage pool does not hold any
|
||||||
|
// resource_ptrs, as this would lead to undefined behavior.
|
||||||
void terminate() noexcept;
|
void terminate() noexcept;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
VmaAllocator mAllocator;
|
VmaAllocator mAllocator;
|
||||||
|
fvkmemory::ResourceManager* mResManager;
|
||||||
VulkanCommands* mCommands;
|
VulkanCommands* mCommands;
|
||||||
|
const VkPhysicalDeviceLimits* mDeviceLimits;
|
||||||
|
|
||||||
|
// Takes a number of bytes, and aligns it to the non-coherent atom size.
|
||||||
|
// This allows us to ensure that when we flush buffers from the host, we
|
||||||
|
// never flush more atoms than we need to.
|
||||||
|
uint32_t alignToNonCoherentAtomSize(uint32_t numBytes);
|
||||||
|
|
||||||
|
// Allocates a new stage buffer, and optionally subdivides it into stage
|
||||||
|
// blocks. If subdivideBlocks is true, predefined divisions will be used.
|
||||||
|
// Otherwise, it's expected that capacity is defined to a value, and that
|
||||||
|
// is the size that will be used for the buffer (as well as the only block
|
||||||
|
// being created).
|
||||||
|
VulkanStage* allocateNewStage(uint32_t capacity);
|
||||||
|
|
||||||
|
// Performs any bookkeeping required to delete a VulkanStage object; namely,
|
||||||
|
// unmapping memory, freeing the allocation, and deleting the VulkanStage
|
||||||
|
// object. Note: takes an r-value because after this call, `stage` won't
|
||||||
|
// exist.
|
||||||
|
void destroyStage(VulkanStage const*&& stage);
|
||||||
|
|
||||||
// Use an ordered multimap for quick (capacity => stage) lookups using lower_bound().
|
// Use an ordered multimap for quick (capacity => stage) lookups using lower_bound().
|
||||||
std::multimap<uint32_t, VulkanStage const*> mFreeStages;
|
std::multimap<uint32_t, VulkanStage*> mStages;
|
||||||
|
|
||||||
// Simple unordered set for stashing a list of in-use stages that can be reclaimed later.
|
|
||||||
std::vector<VulkanStage const*> mUsedStages;
|
|
||||||
|
|
||||||
std::unordered_set<VulkanStageImage const*> mFreeImages;
|
std::unordered_set<VulkanStageImage const*> mFreeImages;
|
||||||
std::vector<VulkanStageImage const*> mUsedImages;
|
std::vector<VulkanStageImage const*> mUsedImages;
|
||||||
|
|||||||
@@ -25,6 +25,7 @@
|
|||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
#include <private/backend/BackendUtils.h>
|
#include <private/backend/BackendUtils.h>
|
||||||
|
|
||||||
|
#include <utils/compiler.h>
|
||||||
#include <utils/Panic.h>
|
#include <utils/Panic.h>
|
||||||
|
|
||||||
using namespace bluevk;
|
using namespace bluevk;
|
||||||
@@ -187,8 +188,8 @@ VkImageUsageFlags getUsage(VulkanContext const& context, uint8_t samples,
|
|||||||
VkFormatProperties props;
|
VkFormatProperties props;
|
||||||
vkGetPhysicalDeviceFormatProperties(physicalDevice, vkFormat, &props);
|
vkGetPhysicalDeviceFormatProperties(physicalDevice, vkFormat, &props);
|
||||||
if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
|
if (!(props.optimalTilingFeatures & VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT)) {
|
||||||
FVK_LOGW << "Texture usage is SAMPLEABLE but format " << vkFormat << " is not "
|
FVK_LOGW << "Texture usage is SAMPLEABLE but format " << vkFormat
|
||||||
"sampleable with optimal tiling." << utils::io::endl;
|
<< " is not sampleable with optimal tiling.";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -218,6 +219,40 @@ VkImageUsageFlags getUsage(VulkanContext const& context, uint8_t samples,
|
|||||||
return usage;
|
return usage;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void adjustedMemcpy(void* mapped, PixelBufferDescriptor const& p, size_t width, size_t height,
|
||||||
|
size_t depth) {
|
||||||
|
uint8_t* buf = (uint8_t*) p.buffer;
|
||||||
|
size_t const pixelSize = PixelBufferDescriptor::computeDataSize(p.format, p.type, 1, 1, 1);
|
||||||
|
size_t const pbdStride = p.stride ? p.stride : width;
|
||||||
|
|
||||||
|
// Slow path of copying row by row
|
||||||
|
assert_invariant(pbdStride >= width);
|
||||||
|
if (UTILS_UNLIKELY(p.left > 0 || p.top > 0 || pbdStride > width)) {
|
||||||
|
size_t const pbdRowSize =
|
||||||
|
PixelBufferDescriptor::computeDataSize(p.format, p.type, pbdStride, 1, p.alignment);
|
||||||
|
size_t const pbdHeight = p.size / pixelSize / pbdStride / depth;
|
||||||
|
size_t const pbdLayerSize = pbdRowSize * pbdHeight;
|
||||||
|
|
||||||
|
size_t const rowSize = width * pixelSize;
|
||||||
|
size_t const layerSize = width * height * pixelSize;
|
||||||
|
|
||||||
|
// Size of a row to write
|
||||||
|
size_t const writeSize = std::min(pbdStride - p.left, width) * pixelSize;
|
||||||
|
|
||||||
|
for (size_t z = 0; z < depth; z++) {
|
||||||
|
for (size_t y = p.top; y < pbdHeight; y++) {
|
||||||
|
uint8_t* buf = (uint8_t*) p.buffer +
|
||||||
|
((p.left * pixelSize) + (y * pbdRowSize) + (z * pbdLayerSize));
|
||||||
|
uint8_t* curMapped = (uint8_t*) mapped + ((y - p.top) * rowSize + z * layerSize);
|
||||||
|
memcpy(curMapped, buf, writeSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
size_t const writeSize = pixelSize * (width * height * depth);
|
||||||
|
memcpy(mapped, buf, writeSize);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // anonymous namespace
|
} // anonymous namespace
|
||||||
|
|
||||||
VulkanTextureState::VulkanTextureState(VulkanStagePool& stagePool, VulkanCommands* commands,
|
VulkanTextureState::VulkanTextureState(VulkanStagePool& stagePool, VulkanCommands* commands,
|
||||||
@@ -326,7 +361,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
|||||||
imageInfo.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
imageInfo.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
|
||||||
} else {
|
} else {
|
||||||
FVK_LOGW << "Note: creating 2D views on 3D image is not available on this platform. "
|
FVK_LOGW << "Note: creating 2D views on 3D image is not available on this platform. "
|
||||||
<< "i.e. we cannot render to slices of a 3D image" << utils::io::endl;
|
<< "i.e. we cannot render to slices of a 3D image";
|
||||||
}
|
}
|
||||||
} else if (target == SamplerType::SAMPLER_CUBEMAP) {
|
} else if (target == SamplerType::SAMPLER_CUBEMAP) {
|
||||||
imageInfo.arrayLayers = 6;
|
imageInfo.arrayLayers = 6;
|
||||||
@@ -385,7 +420,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
|
|||||||
<< "type = " << imageInfo.imageType << ", "
|
<< "type = " << imageInfo.imageType << ", "
|
||||||
<< "flags = " << imageInfo.flags << ", "
|
<< "flags = " << imageInfo.flags << ", "
|
||||||
<< "target = " << static_cast<int>(target) <<", "
|
<< "target = " << static_cast<int>(target) <<", "
|
||||||
<< "format = " << vkFormat << utils::io::endl;
|
<< "format = " << vkFormat;
|
||||||
}
|
}
|
||||||
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to create image."
|
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) << "Unable to create image."
|
||||||
<< " error=" << static_cast<int32_t>(result);
|
<< " error=" << static_cast<int32_t>(result);
|
||||||
@@ -480,30 +515,40 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
|||||||
assert_invariant(hostData->size > 0 && "Data is empty");
|
assert_invariant(hostData->size > 0 && "Data is empty");
|
||||||
|
|
||||||
// Otherwise, use vkCmdCopyBufferToImage.
|
// Otherwise, use vkCmdCopyBufferToImage.
|
||||||
void* mapped = nullptr;
|
size_t const bpp =
|
||||||
VulkanStage const* stage = mState->mStagePool.acquireStage(hostData->size);
|
PixelBufferDescriptor::computeDataSize(hostData->format, hostData->type, 1, 1, 1);
|
||||||
assert_invariant(stage->memory);
|
size_t const writeSize = width * height * depth * bpp;
|
||||||
vmaMapMemory(mState->mAllocator, stage->memory, &mapped);
|
|
||||||
memcpy(mapped, hostData->buffer, hostData->size);
|
// Note: the following stageSegment must be stored within the command buffer
|
||||||
vmaUnmapMemory(mState->mAllocator, stage->memory);
|
// before going out of scope, to ensure proper bookkeeping within the
|
||||||
vmaFlushAllocation(mState->mAllocator, stage->memory, 0, hostData->size);
|
// staging buffer pool.
|
||||||
|
fvkmemory::resource_ptr<VulkanStage::Segment> stageSegment =
|
||||||
|
mState->mStagePool.acquireStage(writeSize);
|
||||||
|
assert_invariant(stageSegment->memory());
|
||||||
|
adjustedMemcpy(stageSegment->mapping(), *hostData, width, height, depth);
|
||||||
|
vmaFlushAllocation(mState->mAllocator, stageSegment->memory(), stageSegment->offset(),
|
||||||
|
writeSize);
|
||||||
|
|
||||||
VulkanCommandBuffer& commands = mState->mCommands->get();
|
VulkanCommandBuffer& commands = mState->mCommands->get();
|
||||||
VkCommandBuffer const cmdbuf = commands.buffer();
|
VkCommandBuffer const cmdbuf = commands.buffer();
|
||||||
|
commands.acquire(stageSegment);
|
||||||
commands.acquire(fvkmemory::resource_ptr<VulkanTexture>::cast(this));
|
commands.acquire(fvkmemory::resource_ptr<VulkanTexture>::cast(this));
|
||||||
|
|
||||||
|
bool const isDepth = getImageAspect() & VK_IMAGE_ASPECT_DEPTH_BIT;
|
||||||
|
|
||||||
VkBufferImageCopy copyRegion = {
|
VkBufferImageCopy copyRegion = {
|
||||||
.bufferOffset = {},
|
.bufferOffset = stageSegment->offset(),
|
||||||
.bufferRowLength = {},
|
.bufferRowLength = {},
|
||||||
.bufferImageHeight = {},
|
.bufferImageHeight = {},
|
||||||
.imageSubresource = {
|
.imageSubresource = {
|
||||||
.aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
|
.aspectMask = VkImageAspectFlags(
|
||||||
|
isDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : VK_IMAGE_ASPECT_COLOR_BIT),
|
||||||
.mipLevel = miplevel,
|
.mipLevel = miplevel,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1
|
.layerCount = 1,
|
||||||
},
|
},
|
||||||
.imageOffset = { int32_t(xoffset), int32_t(yoffset), int32_t(zoffset) },
|
.imageOffset = { int32_t(xoffset), int32_t(yoffset), int32_t(zoffset) },
|
||||||
.imageExtent = { width, height, depth }
|
.imageExtent = { width, height, depth },
|
||||||
};
|
};
|
||||||
|
|
||||||
VkImageSubresourceRange transitionRange = {
|
VkImageSubresourceRange transitionRange = {
|
||||||
@@ -511,7 +556,7 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
|||||||
.baseMipLevel = miplevel,
|
.baseMipLevel = miplevel,
|
||||||
.levelCount = 1,
|
.levelCount = 1,
|
||||||
.baseArrayLayer = 0,
|
.baseArrayLayer = 0,
|
||||||
.layerCount = 1
|
.layerCount = 1,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Vulkan specifies subregions for 3D textures differently than from 2D arrays.
|
// Vulkan specifies subregions for 3D textures differently than from 2D arrays.
|
||||||
@@ -536,20 +581,25 @@ void VulkanTexture::updateImage(const PixelBufferDescriptor& data, uint32_t widt
|
|||||||
|
|
||||||
transitionLayout(&commands, transitionRange, newLayout);
|
transitionLayout(&commands, transitionRange, newLayout);
|
||||||
|
|
||||||
vkCmdCopyBufferToImage(cmdbuf, stage->buffer, mState->mTextureImage, newVkLayout, 1, ©Region);
|
vkCmdCopyBufferToImage(cmdbuf, stageSegment->buffer(), mState->mTextureImage, newVkLayout, 1,
|
||||||
|
©Region);
|
||||||
|
|
||||||
transitionLayout(&commands, transitionRange, nextLayout);
|
transitionLayout(&commands, transitionRange, nextLayout);
|
||||||
}
|
}
|
||||||
|
|
||||||
void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& hostData, uint32_t width,
|
void VulkanTexture::updateImageWithBlit(const PixelBufferDescriptor& data, uint32_t width,
|
||||||
uint32_t height, uint32_t depth, uint32_t miplevel) {
|
uint32_t height, uint32_t depth, uint32_t miplevel) {
|
||||||
|
// Otherwise, use vkCmdCopyBufferToImage.
|
||||||
|
size_t const bpp = PixelBufferDescriptor::computeDataSize(data.format, data.type, 1, 1, 1);
|
||||||
|
size_t const writeSize = width * height * depth * bpp;
|
||||||
|
|
||||||
void* mapped = nullptr;
|
void* mapped = nullptr;
|
||||||
VulkanStageImage const* stage
|
VulkanStageImage const* stage
|
||||||
= mState->mStagePool.acquireImage(hostData.format, hostData.type, width, height);
|
= mState->mStagePool.acquireImage(data.format, data.type, width, height);
|
||||||
vmaMapMemory(mState->mAllocator, stage->memory, &mapped);
|
vmaMapMemory(mState->mAllocator, stage->memory, &mapped);
|
||||||
memcpy(mapped, hostData.buffer, hostData.size);
|
adjustedMemcpy(mapped, data, width, height, depth);
|
||||||
vmaUnmapMemory(mState->mAllocator, stage->memory);
|
vmaUnmapMemory(mState->mAllocator, stage->memory);
|
||||||
vmaFlushAllocation(mState->mAllocator, stage->memory, 0, hostData.size);
|
vmaFlushAllocation(mState->mAllocator, stage->memory, 0, writeSize);
|
||||||
|
|
||||||
VulkanCommandBuffer& commands = mState->mCommands->get();
|
VulkanCommandBuffer& commands = mState->mCommands->get();
|
||||||
VkCommandBuffer const cmdbuf = commands.buffer();
|
VkCommandBuffer const cmdbuf = commands.buffer();
|
||||||
@@ -681,14 +731,14 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
|
|||||||
<< range.levelCount << ")" << " from=" << oldLayout << " to=" << newLayout
|
<< range.levelCount << ")" << " from=" << oldLayout << " to=" << newLayout
|
||||||
<< " format=" << mState->mVkFormat << " depth="
|
<< " format=" << mState->mVkFormat << " depth="
|
||||||
<< fvkutils::isVkDepthFormat(mState->mVkFormat)
|
<< fvkutils::isVkDepthFormat(mState->mVkFormat)
|
||||||
<< " slice-by-slice=" << transitionSliceBySlice << utils::io::endl;
|
<< " slice-by-slice=" << transitionSliceBySlice;
|
||||||
#endif
|
#endif
|
||||||
} else {
|
} else {
|
||||||
#if FVK_ENABLED(FVK_DEBUG_LAYOUT_TRANSITION)
|
#if FVK_ENABLED(FVK_DEBUG_LAYOUT_TRANSITION)
|
||||||
FVK_LOGD << "transition texture=" << mState->mTextureImage << " (" << range.baseArrayLayer
|
FVK_LOGD << "transition texture=" << mState->mTextureImage << " (" << range.baseArrayLayer
|
||||||
<< "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << ","
|
<< "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << ","
|
||||||
<< range.levelCount << ")" << " to=" << newLayout
|
<< range.levelCount << ")" << " to=" << newLayout
|
||||||
<< " is skipped because of no change in layout" << utils::io::endl;
|
<< " is skipped because of no change in layout";
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -799,8 +849,7 @@ void VulkanTexture::print() const {
|
|||||||
level < (mPrimaryViewRange.baseMipLevel + mPrimaryViewRange.levelCount);
|
level < (mPrimaryViewRange.baseMipLevel + mPrimaryViewRange.levelCount);
|
||||||
FVK_LOGD << "[" << mState->mTextureImage << "]: (" << layer << "," << level
|
FVK_LOGD << "[" << mState->mTextureImage << "]: (" << layer << "," << level
|
||||||
<< ")=" << getLayout(layer, level)
|
<< ")=" << getLayout(layer, level)
|
||||||
<< " primary=" << primary
|
<< " primary=" << primary;
|
||||||
<< utils::io::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -809,8 +858,7 @@ void VulkanTexture::print() const {
|
|||||||
FVK_LOGD << "[" << mState->mTextureImage << ", imageView=" << view.second << "]=>"
|
FVK_LOGD << "[" << mState->mTextureImage << ", imageView=" << view.second << "]=>"
|
||||||
<< " (" << range.baseArrayLayer << "," << range.baseMipLevel << ")"
|
<< " (" << range.baseArrayLayer << "," << range.baseMipLevel << ")"
|
||||||
<< " count=(" << range.layerCount << "," << range.levelCount << ")"
|
<< " count=(" << range.layerCount << "," << range.levelCount << ")"
|
||||||
<< " aspect=" << range.aspectMask << " viewType=" << view.first.type
|
<< " aspect=" << range.aspectMask << " viewType=" << view.first.type;
|
||||||
<< utils::io::endl;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -29,6 +29,8 @@ using namespace bluevk;
|
|||||||
|
|
||||||
namespace filament::backend {
|
namespace filament::backend {
|
||||||
|
|
||||||
|
using namespace fvkutils;
|
||||||
|
|
||||||
VulkanYcbcrConversionCache::VulkanYcbcrConversionCache(VkDevice device)
|
VulkanYcbcrConversionCache::VulkanYcbcrConversionCache(VkDevice device)
|
||||||
: mDevice(device) {}
|
: mDevice(device) {}
|
||||||
|
|
||||||
|
|||||||
@@ -17,6 +17,8 @@
|
|||||||
#ifndef TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
|
#ifndef TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
|
||||||
#define TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
|
#define TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
|
||||||
|
|
||||||
|
#include "utils/Definitions.h"
|
||||||
|
|
||||||
#include <backend/DriverEnums.h>
|
#include <backend/DriverEnums.h>
|
||||||
|
|
||||||
#include <utils/Hash.h>
|
#include <utils/Hash.h>
|
||||||
@@ -30,7 +32,7 @@ namespace filament::backend {
|
|||||||
class VulkanYcbcrConversionCache {
|
class VulkanYcbcrConversionCache {
|
||||||
public:
|
public:
|
||||||
struct Params {
|
struct Params {
|
||||||
SamplerYcbcrConversion conversion = {}; // 4
|
fvkutils::SamplerYcbcrConversion conversion = {}; // 4
|
||||||
VkFormat format; // 4
|
VkFormat format; // 4
|
||||||
uint64_t externalFormat = 0; // 8
|
uint64_t externalFormat = 0; // 8
|
||||||
};
|
};
|
||||||
@@ -45,16 +47,15 @@ private:
|
|||||||
|
|
||||||
struct ConversionEqualTo {
|
struct ConversionEqualTo {
|
||||||
bool operator()(Params lhs, Params rhs) const noexcept {
|
bool operator()(Params lhs, Params rhs) const noexcept {
|
||||||
SamplerYcbcrConversion::EqualTo equal;
|
fvkutils::SamplerYcbcrConversion::EqualTo equal;
|
||||||
return equal(lhs.conversion, rhs.conversion) &&
|
return equal(lhs.conversion, rhs.conversion) &&
|
||||||
lhs.externalFormat == rhs.externalFormat &&
|
lhs.externalFormat == rhs.externalFormat && lhs.format == rhs.format;
|
||||||
lhs.format == rhs.format;
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
using ConversionHashFn = utils::hash::MurmurHashFn<Params>;
|
using ConversionHashFn = utils::hash::MurmurHashFn<Params>;
|
||||||
tsl::robin_map<Params, VkSamplerYcbcrConversion, ConversionHashFn, ConversionEqualTo> mCache;
|
tsl::robin_map<Params, VkSamplerYcbcrConversion, ConversionHashFn, ConversionEqualTo> mCache;
|
||||||
};
|
};
|
||||||
|
|
||||||
}// namespace filament::backend
|
} // namespace filament::backend
|
||||||
|
|
||||||
#endif// TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
|
#endif// TNT_FILAMENT_BACKEND_VULKANYCBCRCONVERSIONCACHE_H
|
||||||
|
|||||||
@@ -26,6 +26,7 @@ template ResourceType getTypeEnum<VulkanIndexBuffer>() noexcept;
|
|||||||
template ResourceType getTypeEnum<VulkanProgram>() noexcept;
|
template ResourceType getTypeEnum<VulkanProgram>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanRenderTarget>() noexcept;
|
template ResourceType getTypeEnum<VulkanRenderTarget>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanSwapChain>() noexcept;
|
template ResourceType getTypeEnum<VulkanSwapChain>() noexcept;
|
||||||
|
template ResourceType getTypeEnum<VulkanStage::Segment>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanRenderPrimitive>() noexcept;
|
template ResourceType getTypeEnum<VulkanRenderPrimitive>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanTexture>() noexcept;
|
template ResourceType getTypeEnum<VulkanTexture>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanTextureState>() noexcept;
|
template ResourceType getTypeEnum<VulkanTextureState>() noexcept;
|
||||||
@@ -35,6 +36,7 @@ template ResourceType getTypeEnum<VulkanVertexBufferInfo>() noexcept;
|
|||||||
template ResourceType getTypeEnum<VulkanDescriptorSetLayout>() noexcept;
|
template ResourceType getTypeEnum<VulkanDescriptorSetLayout>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanDescriptorSet>() noexcept;
|
template ResourceType getTypeEnum<VulkanDescriptorSet>() noexcept;
|
||||||
template ResourceType getTypeEnum<VulkanFence>() noexcept;
|
template ResourceType getTypeEnum<VulkanFence>() noexcept;
|
||||||
|
template ResourceType getTypeEnum<VulkanBuffer>() noexcept;
|
||||||
|
|
||||||
template<typename D>
|
template<typename D>
|
||||||
ResourceType getTypeEnum() noexcept {
|
ResourceType getTypeEnum() noexcept {
|
||||||
@@ -53,6 +55,9 @@ ResourceType getTypeEnum() noexcept {
|
|||||||
if constexpr (std::is_same_v<D, VulkanSwapChain>) {
|
if constexpr (std::is_same_v<D, VulkanSwapChain>) {
|
||||||
return ResourceType::SWAP_CHAIN;
|
return ResourceType::SWAP_CHAIN;
|
||||||
}
|
}
|
||||||
|
if constexpr (std::is_same_v<D, VulkanStage::Segment>) {
|
||||||
|
return ResourceType::STAGE_SEGMENT;
|
||||||
|
}
|
||||||
if constexpr (std::is_same_v<D, VulkanRenderPrimitive>) {
|
if constexpr (std::is_same_v<D, VulkanRenderPrimitive>) {
|
||||||
return ResourceType::RENDER_PRIMITIVE;
|
return ResourceType::RENDER_PRIMITIVE;
|
||||||
}
|
}
|
||||||
@@ -80,6 +85,9 @@ ResourceType getTypeEnum() noexcept {
|
|||||||
if constexpr (std::is_same_v<D, VulkanFence>) {
|
if constexpr (std::is_same_v<D, VulkanFence>) {
|
||||||
return ResourceType::FENCE;
|
return ResourceType::FENCE;
|
||||||
}
|
}
|
||||||
|
if constexpr (std::is_same_v<D, VulkanBuffer>) {
|
||||||
|
return ResourceType::VULKAN_BUFFER;
|
||||||
|
}
|
||||||
return ResourceType::UNDEFINED_TYPE;
|
return ResourceType::UNDEFINED_TYPE;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -95,6 +103,8 @@ std::string getTypeStr(ResourceType type) {
|
|||||||
return "RenderTarget";
|
return "RenderTarget";
|
||||||
case ResourceType::SWAP_CHAIN:
|
case ResourceType::SWAP_CHAIN:
|
||||||
return "SwapChain";
|
return "SwapChain";
|
||||||
|
case ResourceType::STAGE_SEGMENT:
|
||||||
|
return "Stage::Segment";
|
||||||
case ResourceType::RENDER_PRIMITIVE:
|
case ResourceType::RENDER_PRIMITIVE:
|
||||||
return "RenderPrimitive";
|
return "RenderPrimitive";
|
||||||
case ResourceType::TEXTURE:
|
case ResourceType::TEXTURE:
|
||||||
@@ -113,6 +123,8 @@ std::string getTypeStr(ResourceType type) {
|
|||||||
return "DescriptorSet";
|
return "DescriptorSet";
|
||||||
case ResourceType::FENCE:
|
case ResourceType::FENCE:
|
||||||
return "Fence";
|
return "Fence";
|
||||||
|
case ResourceType::VULKAN_BUFFER:
|
||||||
|
return "VulkanBuffer";
|
||||||
case ResourceType::UNDEFINED_TYPE:
|
case ResourceType::UNDEFINED_TYPE:
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -49,7 +49,9 @@ enum class ResourceType : uint8_t {
|
|||||||
DESCRIPTOR_SET_LAYOUT = 11,
|
DESCRIPTOR_SET_LAYOUT = 11,
|
||||||
DESCRIPTOR_SET = 12,
|
DESCRIPTOR_SET = 12,
|
||||||
FENCE = 13,
|
FENCE = 13,
|
||||||
UNDEFINED_TYPE = 14, // Must be the last enum because we use it for iterating over the enums.
|
VULKAN_BUFFER = 14,
|
||||||
|
STAGE_SEGMENT = 15,
|
||||||
|
UNDEFINED_TYPE = 16, // Must be the last enum because we use it for iterating over the enums.
|
||||||
};
|
};
|
||||||
|
|
||||||
template<typename D>
|
template<typename D>
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user