Compare commits
1
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6474cb0bcd |
@@ -1,17 +0,0 @@
|
||||
name: 'Android Continuous'
|
||||
inputs:
|
||||
build-abi:
|
||||
description: 'The target platform ABI'
|
||||
required: true
|
||||
default: 'armeabi-v7a'
|
||||
runs:
|
||||
using: "composite"
|
||||
steps:
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/android && printf "y" | ./build.sh continuous ${{ inputs.build-abi }}
|
||||
shell: bash
|
||||
@@ -8,35 +8,32 @@ on:
|
||||
- rc/**
|
||||
|
||||
jobs:
|
||||
build-android-armv7:
|
||||
name: build-android-armv7
|
||||
build-android:
|
||||
name: build-android
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Run Android Continuous
|
||||
uses: ./.github/actions/android-continuous
|
||||
- uses: actions/setup-java@v3
|
||||
with:
|
||||
build-abi: armeabi-v7a
|
||||
|
||||
build-android-armv8a:
|
||||
name: build-android-armv8a
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Run Android Continuous
|
||||
uses: ./.github/actions/android-continuous
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
- name: Run build script
|
||||
run: |
|
||||
cd build/android && printf "y" | ./build.sh continuous
|
||||
- uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
build-abi: arm64-v8a
|
||||
|
||||
build-android-x86_64:
|
||||
name: build-android-x86_64
|
||||
runs-on: macos-14
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4.1.6
|
||||
- name: Run Android Continuous
|
||||
uses: ./.github/actions/android-continuous
|
||||
name: filament-android
|
||||
path: out/filament-android-release.aar
|
||||
- uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
build-abi: x86_64
|
||||
name: filamat-android-full
|
||||
path: out/filamat-android-release.aar
|
||||
- uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
name: gltfio-android-release
|
||||
path: out/gltfio-android-release.aar
|
||||
- uses: actions/upload-artifact@v1.0.0
|
||||
with:
|
||||
name: filament-utils-android-release
|
||||
path: out/filament-utils-android-release.aar
|
||||
|
||||
@@ -49,10 +49,8 @@ jobs:
|
||||
distribution: 'temurin'
|
||||
java-version: '17'
|
||||
- name: Run build script
|
||||
# Only build 1 64 bit target during presubmit to cut down build times during presubmit
|
||||
# Continuous builds will build everything
|
||||
run: |
|
||||
cd build/android && printf "y" | ./build.sh presubmit arm64-v8a
|
||||
cd build/android && printf "y" | ./build.sh presubmit
|
||||
|
||||
build-ios:
|
||||
name: build-iOS
|
||||
|
||||
@@ -120,7 +120,7 @@ jobs:
|
||||
env:
|
||||
TAG: ${{ steps.git_ref.outputs.tag }}
|
||||
run: |
|
||||
cd build/android && printf "y" | ./build.sh release armeabi-v7a,arm64-v8a,x86,x86_64
|
||||
cd build/android && printf "y" | ./build.sh release
|
||||
cd ../..
|
||||
mv out/filament-android-release.aar out/filament-${TAG}-android.aar
|
||||
mv out/filamat-android-release.aar out/filamat-${TAG}-android.aar
|
||||
|
||||
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.54.3'
|
||||
implementation 'com.google.android.filament:filament-android:1.54.1'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,9 +51,19 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```shell
|
||||
pod 'Filament', '~> 1.54.3'
|
||||
pod 'Filament', '~> 1.54.1'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
If you prefer to live on the edge, you can download a continuous build by following the following
|
||||
steps:
|
||||
|
||||
1. Find the [commit](https://github.com/google/filament/commits/main) you're interested in.
|
||||
2. Click the green check mark under the commit message.
|
||||
3. Click on the _Details_ link for the platform you're interested in.
|
||||
4. On the top left click _Summary_, then in the _Artifacts_ section choose the desired artifact.
|
||||
|
||||
## Documentation
|
||||
|
||||
- [Filament](https://google.github.io/filament/Filament.html), an in-depth explanation of
|
||||
|
||||
@@ -7,9 +7,6 @@ A new header is inserted each time a *tag* is created.
|
||||
Instead, if you are authoring a PR for the main branch, add your release note to
|
||||
[NEW_RELEASE_NOTES.md](./NEW_RELEASE_NOTES.md).
|
||||
|
||||
## v1.54.3
|
||||
|
||||
|
||||
## v1.54.2
|
||||
|
||||
- Add a `name` API to Filament objects for debugging handle use-after-free assertions
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.54.3
|
||||
VERSION_NAME=1.54.1
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
+7
-15
@@ -60,7 +60,13 @@ if [[ ! -d "${ANDROID_HOME}/ndk/$FILAMENT_NDK_VERSION" ]]; then
|
||||
yes | ${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager --licenses
|
||||
${ANDROID_HOME}/cmdline-tools/latest/bin/sdkmanager "ndk;$FILAMENT_NDK_VERSION"
|
||||
fi
|
||||
|
||||
# Only build 1 64 bit target during presubmit to cut down build times during presubmit
|
||||
# Continuous builds will build everything
|
||||
ANDROID_ABIS=
|
||||
if [[ "$TARGET" == "presubmit" ]]; then
|
||||
ANDROID_ABIS="-q arm64-v8a"
|
||||
fi
|
||||
|
||||
# Build the Android sample-gltf-viewer APK during release.
|
||||
BUILD_SAMPLES=
|
||||
@@ -68,19 +74,5 @@ if [[ "$TARGET" == "release" ]]; then
|
||||
BUILD_SAMPLES="-k sample-gltf-viewer"
|
||||
fi
|
||||
|
||||
function build_android() {
|
||||
local ABI=$1
|
||||
|
||||
# Do the following in two steps so that we do not run out of space
|
||||
if [[ -n "${BUILD_DEBUG}" ]]; then
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION} ./build.sh -p android -q ${ABI} -c ${BUILD_SAMPLES} ${GENERATE_ARCHIVES} ${BUILD_DEBUG}
|
||||
rm -rf out/cmake-android-debug-*
|
||||
fi
|
||||
if [[ -n "${BUILD_RELEASE}" ]]; then
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION} ./build.sh -p android -q ${ABI} -c ${BUILD_SAMPLES} ${GENERATE_ARCHIVES} ${BUILD_RELEASE}
|
||||
rm -rf out/cmake-android-release-*
|
||||
fi
|
||||
}
|
||||
|
||||
pushd `dirname $0`/../.. > /dev/null
|
||||
build_android $2
|
||||
FILAMENT_NDK_VERSION=${FILAMENT_NDK_VERSION} ./build.sh -p android $ANDROID_ABIS -c $BUILD_SAMPLES $GENERATE_ARCHIVES $BUILD_DEBUG $BUILD_RELEASE
|
||||
|
||||
@@ -1058,7 +1058,7 @@ struct RasterState {
|
||||
bool inverseFrontFaces : 1; // 31
|
||||
|
||||
//! padding, must be 0
|
||||
bool depthClamp : 1; // 32
|
||||
uint8_t padding : 1; // 32
|
||||
};
|
||||
uint32_t u = 0;
|
||||
};
|
||||
|
||||
@@ -309,7 +309,6 @@ DECL_DRIVER_API_SYNCHRONOUS_0(bool, isParallelShaderCompileSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthStencilResolveSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_N(bool, isDepthStencilBlitSupported, backend::TextureFormat, format)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isProtectedTexturesSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(bool, isDepthClampSupported)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(uint8_t, getMaxDrawBuffers)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(size_t, getMaxUniformBufferSize)
|
||||
DECL_DRIVER_API_SYNCHRONOUS_0(math::float2, getClipSpaceParams)
|
||||
@@ -444,10 +443,12 @@ DECL_DRIVER_API_N(setPushConstant,
|
||||
backend::PushConstantVariant, value)
|
||||
|
||||
DECL_DRIVER_API_N(insertEventMarker,
|
||||
const char*, string)
|
||||
const char*, string,
|
||||
uint32_t, len = 0)
|
||||
|
||||
DECL_DRIVER_API_N(pushGroupMarker,
|
||||
const char*, string)
|
||||
const char*, string,
|
||||
uint32_t, len = 0)
|
||||
|
||||
DECL_DRIVER_API_0(popGroupMarker)
|
||||
|
||||
|
||||
@@ -208,8 +208,14 @@ public:
|
||||
// TODO: for now, only pool handles check for use-after-free, so we only keep tags for
|
||||
// those
|
||||
if (isPoolHandle(id)) {
|
||||
// Truncate the age to get the debug tag
|
||||
uint32_t const key = id & ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK);
|
||||
// Truncate the tag's age to N bits.
|
||||
constexpr uint8_t N = 2; // support a history of 4 tags
|
||||
constexpr uint8_t mask = (1 << N) - 1;
|
||||
|
||||
uint8_t const age = (id & HANDLE_AGE_MASK) >> HANDLE_AGE_SHIFT;
|
||||
uint8_t const newAge = age & mask;
|
||||
uint32_t const key = (id & ~HANDLE_AGE_MASK) | (newAge << HANDLE_AGE_SHIFT);
|
||||
|
||||
// This line is the costly part. In the future, we could potentially use a custom
|
||||
// allocator.
|
||||
mDebugTags[key] = std::move(tag);
|
||||
@@ -220,8 +226,7 @@ public:
|
||||
if (!isPoolHandle(id)) {
|
||||
return "(no tag)";
|
||||
}
|
||||
uint32_t const key = id & ~(HANDLE_DEBUG_TAG_MASK ^ HANDLE_AGE_MASK);
|
||||
if (auto pos = mDebugTags.find(key); pos != mDebugTags.end()) {
|
||||
if (auto pos = mDebugTags.find(id); pos != mDebugTags.end()) {
|
||||
return pos->second;
|
||||
}
|
||||
return "(no tag)";
|
||||
@@ -344,24 +349,12 @@ private:
|
||||
}
|
||||
}
|
||||
|
||||
// number if bits allotted to the handle's age (currently 4 max)
|
||||
static constexpr uint32_t HANDLE_AGE_BIT_COUNT = 4;
|
||||
// number if bits allotted to the handle's debug tag (HANDLE_AGE_BIT_COUNT max)
|
||||
static constexpr uint32_t HANDLE_DEBUG_TAG_BIT_COUNT = 2;
|
||||
// bit shift for both the age and debug tag
|
||||
static constexpr uint32_t HANDLE_AGE_SHIFT = 27;
|
||||
// mask for the heap (vs pool) flag
|
||||
static constexpr uint32_t HANDLE_HEAP_FLAG = 0x80000000u;
|
||||
// mask for the age
|
||||
static constexpr uint32_t HANDLE_AGE_MASK =
|
||||
((1 << HANDLE_AGE_BIT_COUNT) - 1) << HANDLE_AGE_SHIFT;
|
||||
// mask for the debug tag
|
||||
static constexpr uint32_t HANDLE_DEBUG_TAG_MASK =
|
||||
((1 << HANDLE_DEBUG_TAG_BIT_COUNT) - 1) << HANDLE_AGE_SHIFT;
|
||||
// mask for the index
|
||||
static constexpr uint32_t HANDLE_INDEX_MASK = 0x07FFFFFFu;
|
||||
|
||||
static_assert(HANDLE_DEBUG_TAG_BIT_COUNT <= HANDLE_AGE_BIT_COUNT);
|
||||
// we handle a 4 bits age per address
|
||||
static constexpr uint32_t HANDLE_HEAP_FLAG = 0x80000000u; // pool vs heap handle
|
||||
static constexpr uint32_t HANDLE_AGE_MASK = 0x78000000u; // handle's age
|
||||
static constexpr uint32_t HANDLE_INDEX_MASK = 0x07FFFFFFu; // handle index
|
||||
static constexpr uint32_t HANDLE_TAG_MASK = HANDLE_AGE_MASK;
|
||||
static constexpr uint32_t HANDLE_AGE_SHIFT = 27;
|
||||
|
||||
static bool isPoolHandle(HandleBase::HandleId id) noexcept {
|
||||
return (id & HANDLE_HEAP_FLAG) == 0u;
|
||||
@@ -376,7 +369,7 @@ private:
|
||||
// a non-pool handle.
|
||||
if (UTILS_LIKELY(isPoolHandle(id))) {
|
||||
char* const base = (char*)mHandleArena.getArea().begin();
|
||||
uint32_t const tag = id & HANDLE_AGE_MASK;
|
||||
uint32_t const tag = id & HANDLE_TAG_MASK;
|
||||
size_t const offset = (id & HANDLE_INDEX_MASK) * Allocator::getAlignment();
|
||||
return { static_cast<void*>(base + offset), tag };
|
||||
}
|
||||
@@ -391,7 +384,7 @@ private:
|
||||
size_t const offset = (char*)p - base;
|
||||
assert_invariant((offset % Allocator::getAlignment()) == 0);
|
||||
auto id = HandleBase::HandleId(offset / Allocator::getAlignment());
|
||||
id |= tag & HANDLE_AGE_MASK;
|
||||
id |= tag & HANDLE_TAG_MASK;
|
||||
assert_invariant((id & HANDLE_HEAP_FLAG) == 0);
|
||||
return id;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
#include <utils/debug.h>
|
||||
#include <utils/ostream.h>
|
||||
|
||||
#if !defined(WIN32) && !defined(__EMSCRIPTEN__)
|
||||
#if !defined(WIN32) && !defined(__EMSCRIPTEN__) && !defined(IOS)
|
||||
# include <sys/mman.h>
|
||||
# include <unistd.h>
|
||||
# define HAS_MMAP 1
|
||||
|
||||
@@ -112,7 +112,6 @@ struct MetalContext {
|
||||
std::array<BufferState, MAX_SSBO_COUNT> ssboState;
|
||||
CullModeStateTracker cullModeState;
|
||||
WindingStateTracker windingState;
|
||||
DepthClampStateTracker depthClampState;
|
||||
Handle<HwRenderPrimitive> currentRenderPrimitive;
|
||||
|
||||
// State caches.
|
||||
|
||||
@@ -857,10 +857,6 @@ bool MetalDriver::isProtectedTexturesSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool MetalDriver::isDepthClampSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool MetalDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU:
|
||||
@@ -1302,11 +1298,11 @@ void MetalDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
pushConstants.setPushConstant(value, index);
|
||||
}
|
||||
|
||||
void MetalDriver::insertEventMarker(const char* string) {
|
||||
void MetalDriver::insertEventMarker(const char* string, uint32_t len) {
|
||||
|
||||
}
|
||||
|
||||
void MetalDriver::pushGroupMarker(const char* string) {
|
||||
void MetalDriver::pushGroupMarker(const char* string, uint32_t len) {
|
||||
mContext->groupMarkers.push(string);
|
||||
}
|
||||
|
||||
@@ -1778,13 +1774,6 @@ void MetalDriver::bindPipeline(PipelineState const& ps) {
|
||||
[mContext->currentRenderPassEncoder setFrontFacingWinding:winding];
|
||||
}
|
||||
|
||||
// depth clip mode
|
||||
MTLDepthClipMode depthClipMode = rs.depthClamp ? MTLDepthClipModeClamp : MTLDepthClipModeClip;
|
||||
mContext->depthClampState.updateState(depthClipMode);
|
||||
if (mContext->depthClampState.stateChanged()) {
|
||||
[mContext->currentRenderPassEncoder setDepthClipMode:depthClipMode];
|
||||
}
|
||||
|
||||
// Set the depth-stencil state, if a state change is needed.
|
||||
DepthStencilState depthState;
|
||||
if (depthAttachment) {
|
||||
|
||||
@@ -382,7 +382,6 @@ using SamplerStateCache = StateCache<SamplerState, id<MTLSamplerState>, SamplerS
|
||||
|
||||
using CullModeStateTracker = StateTracker<MTLCullMode>;
|
||||
using WindingStateTracker = StateTracker<MTLWinding>;
|
||||
using DepthClampStateTracker = StateTracker<MTLDepthClipMode>;
|
||||
|
||||
// Argument encoder
|
||||
|
||||
|
||||
@@ -202,10 +202,6 @@ bool NoopDriver::isProtectedTexturesSupported() {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool NoopDriver::isDepthClampSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool NoopDriver::isWorkaroundNeeded(Workaround) {
|
||||
return false;
|
||||
}
|
||||
@@ -320,10 +316,10 @@ void NoopDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
backend::PushConstantVariant value) {
|
||||
}
|
||||
|
||||
void NoopDriver::insertEventMarker(char const* string) {
|
||||
void NoopDriver::insertEventMarker(char const* string, uint32_t len) {
|
||||
}
|
||||
|
||||
void NoopDriver::pushGroupMarker(char const* string) {
|
||||
void NoopDriver::pushGroupMarker(char const* string, uint32_t len) {
|
||||
}
|
||||
|
||||
void NoopDriver::popGroupMarker(int) {
|
||||
|
||||
@@ -676,7 +676,6 @@ void OpenGLContext::initExtensionsGLES(Extensions* ext, GLint major, GLint minor
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
#endif
|
||||
ext->EXT_depth_clamp = exts.has("GL_EXT_depth_clamp"sv);
|
||||
ext->EXT_discard_framebuffer = exts.has("GL_EXT_discard_framebuffer"sv);
|
||||
#ifndef __EMSCRIPTEN__
|
||||
ext->EXT_disjoint_timer_query = exts.has("GL_EXT_disjoint_timer_query"sv);
|
||||
@@ -747,7 +746,6 @@ void OpenGLContext::initExtensionsGL(Extensions* ext, GLint major, GLint minor)
|
||||
ext->EXT_color_buffer_half_float = true; // Assumes core profile.
|
||||
ext->EXT_clip_cull_distance = true;
|
||||
ext->EXT_debug_marker = exts.has("GL_EXT_debug_marker"sv);
|
||||
ext->EXT_depth_clamp = true;
|
||||
ext->EXT_discard_framebuffer = false;
|
||||
ext->EXT_disjoint_timer_query = true;
|
||||
ext->EXT_multisampled_render_to_texture = false;
|
||||
|
||||
@@ -220,9 +220,8 @@ public:
|
||||
bool EXT_color_buffer_float;
|
||||
bool EXT_color_buffer_half_float;
|
||||
bool EXT_debug_marker;
|
||||
bool EXT_depth_clamp;
|
||||
bool EXT_discard_framebuffer;
|
||||
bool EXT_disjoint_timer_query;
|
||||
bool EXT_discard_framebuffer;
|
||||
bool EXT_multisampled_render_to_texture2;
|
||||
bool EXT_multisampled_render_to_texture;
|
||||
bool EXT_protected_textures;
|
||||
@@ -240,10 +239,10 @@ public:
|
||||
bool KHR_parallel_shader_compile;
|
||||
bool KHR_texture_compression_astc_hdr;
|
||||
bool KHR_texture_compression_astc_ldr;
|
||||
bool OES_EGL_image_external_essl3;
|
||||
bool OES_depth24;
|
||||
bool OES_depth_texture;
|
||||
bool OES_depth24;
|
||||
bool OES_packed_depth_stencil;
|
||||
bool OES_EGL_image_external_essl3;
|
||||
bool OES_rgb8_rgba8;
|
||||
bool OES_standard_derivatives;
|
||||
bool OES_texture_npot;
|
||||
@@ -628,7 +627,6 @@ constexpr size_t OpenGLContext::getIndexForCap(GLenum cap) noexcept { //NOLINT
|
||||
#ifdef BACKEND_OPENGL_VERSION_GL
|
||||
case GL_PROGRAM_POINT_SIZE: index = 10; break;
|
||||
#endif
|
||||
case GL_DEPTH_CLAMP: index = 11; break;
|
||||
default: break;
|
||||
}
|
||||
assert_invariant(index < state.enables.caps.size());
|
||||
|
||||
@@ -451,14 +451,6 @@ void OpenGLDriver::setRasterState(RasterState rs) noexcept {
|
||||
} else {
|
||||
gl.disable(GL_SAMPLE_ALPHA_TO_COVERAGE);
|
||||
}
|
||||
|
||||
if (gl.ext.EXT_depth_clamp) {
|
||||
if (rs.depthClamp) {
|
||||
gl.enable(GL_DEPTH_CLAMP);
|
||||
} else {
|
||||
gl.disable(GL_DEPTH_CLAMP);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void OpenGLDriver::setStencilState(StencilState ss) noexcept {
|
||||
@@ -2127,10 +2119,6 @@ bool OpenGLDriver::isProtectedTexturesSupported() {
|
||||
return getContext().ext.EXT_protected_textures;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isDepthClampSupported() {
|
||||
return getContext().ext.EXT_depth_clamp;
|
||||
}
|
||||
|
||||
bool OpenGLDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU:
|
||||
@@ -3196,23 +3184,23 @@ void OpenGLDriver::bindSamplers(uint32_t index, Handle<HwSamplerGroup> sbh) {
|
||||
CHECK_GL_ERROR(utils::slog.e)
|
||||
}
|
||||
|
||||
void OpenGLDriver::insertEventMarker(char const* string) {
|
||||
void OpenGLDriver::insertEventMarker(char const* string, uint32_t len) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_debug_marker
|
||||
auto& gl = mContext;
|
||||
if (gl.ext.EXT_debug_marker) {
|
||||
glInsertEventMarkerEXT(GLsizei(strlen(string)), string);
|
||||
glInsertEventMarkerEXT(GLsizei(len ? len : strlen(string)), string);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
|
||||
void OpenGLDriver::pushGroupMarker(char const* string) {
|
||||
void OpenGLDriver::pushGroupMarker(char const* string, uint32_t len) {
|
||||
#ifndef __EMSCRIPTEN__
|
||||
#ifdef GL_EXT_debug_marker
|
||||
#if DEBUG_GROUP_MARKER_LEVEL & DEBUG_GROUP_MARKER_OPENGL
|
||||
if (UTILS_LIKELY(mContext.ext.EXT_debug_marker)) {
|
||||
glPushGroupMarkerEXT(GLsizei(strlen(string)), string);
|
||||
glPushGroupMarkerEXT(GLsizei(len ? len : strlen(string)), string);
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -201,12 +201,6 @@ using namespace glext;
|
||||
# define GL_CLIP_DISTANCE1 0x3001
|
||||
#endif
|
||||
|
||||
#if defined(GL_EXT_depth_clamp)
|
||||
# define GL_DEPTH_CLAMP GL_DEPTH_CLAMP_EXT
|
||||
#else
|
||||
# define GL_DEPTH_CLAMP 0x864F
|
||||
#endif
|
||||
|
||||
#if defined(GL_KHR_debug)
|
||||
# define GL_DEBUG_OUTPUT GL_DEBUG_OUTPUT_KHR
|
||||
# define GL_DEBUG_OUTPUT_SYNCHRONOUS GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR
|
||||
|
||||
@@ -165,14 +165,14 @@ constexpr static const int FVK_REQUIRED_VERSION_MINOR = 1;
|
||||
// buffers that have been submitted but have not yet finished rendering. Note that Filament can
|
||||
// issue multiple commit calls in a single frame, and that we use a triple buffered swap chain on
|
||||
// some platforms.
|
||||
constexpr static const int FVK_MAX_COMMAND_BUFFERS = 10;
|
||||
constexpr static const int FVK_MAX_COMMAND_BUFFERS = 3;
|
||||
|
||||
// Number of command buffer submissions that should occur before an unused pipeline is removed
|
||||
// from the cache.
|
||||
//
|
||||
// If this number is low, VkPipeline construction will occur frequently, which can
|
||||
// be extremely slow. If this number is high, the memory footprint will be large.
|
||||
constexpr static const int FVK_MAX_PIPELINE_AGE = 10;
|
||||
constexpr static const int FVK_MAX_PIPELINE_AGE = 3;
|
||||
|
||||
// VulkanPipelineCache does not track which command buffers contain references to which pipelines,
|
||||
// instead it simply waits for at least FVK_MAX_COMMAND_BUFFERS submissions to occur before
|
||||
|
||||
@@ -125,10 +125,6 @@ public:
|
||||
return mPhysicalDeviceFeatures.imageCubeArray == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isDepthClampSupported() const noexcept {
|
||||
return mPhysicalDeviceFeatures.depthClamp == VK_TRUE;
|
||||
}
|
||||
|
||||
inline bool isDebugMarkersSupported() const noexcept {
|
||||
return mDebugMarkersSupported;
|
||||
}
|
||||
|
||||
@@ -530,6 +530,8 @@ void VulkanDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint
|
||||
auto vktexture = mResourceAllocator.construct<VulkanTexture>(th, mPlatform->getDevice(),
|
||||
mPlatform->getPhysicalDevice(), mContext, mAllocator, &mCommands, target, levels,
|
||||
format, samples, w, h, depth, usage, mStagePool);
|
||||
// FVK_LOGE <<"created texture: " << vktexture->getVkImage() << " dim=" <<
|
||||
// vktexture->width << "x" << vktexture->height << utils::io::endl;
|
||||
mResourceManager.acquire(vktexture);
|
||||
}
|
||||
|
||||
@@ -944,10 +946,6 @@ bool VulkanDriver::isProtectedTexturesSupported() {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool VulkanDriver::isDepthClampSupported() {
|
||||
return mContext.isDepthClampSupported();
|
||||
}
|
||||
|
||||
bool VulkanDriver::isWorkaroundNeeded(Workaround workaround) {
|
||||
switch (workaround) {
|
||||
case Workaround::SPLIT_EASU: {
|
||||
@@ -1606,13 +1604,13 @@ void VulkanDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
|
||||
value);
|
||||
}
|
||||
|
||||
void VulkanDriver::insertEventMarker(char const* string) {
|
||||
void VulkanDriver::insertEventMarker(char const* string, uint32_t len) {
|
||||
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
|
||||
mCommands.insertEventMarker(string, strlen(string));
|
||||
mCommands.insertEventMarker(string, len);
|
||||
#endif
|
||||
}
|
||||
|
||||
void VulkanDriver::pushGroupMarker(char const* string) {
|
||||
void VulkanDriver::pushGroupMarker(char const* string, uint32_t) {
|
||||
// Turns out all the markers are 0-terminated, so we can just pass it without len.
|
||||
#if FVK_ENABLED(FVK_DEBUG_GROUP_MARKERS)
|
||||
mCommands.pushGroupMarker(string);
|
||||
@@ -1820,7 +1818,6 @@ void VulkanDriver::bindPipeline(PipelineState const& pipelineState) {
|
||||
.dstAlphaBlendFactor = getBlendFactor(rasterState.blendFunctionDstAlpha),
|
||||
.colorWriteMask = (VkColorComponentFlags) (rasterState.colorWrite ? 0xf : 0x0),
|
||||
.rasterizationSamples = rt->getSamples(),
|
||||
.depthClamp = rasterState.depthClamp,
|
||||
.colorTargetCount = rt->getColorTargetCount(mCurrentRenderPass),
|
||||
.colorBlendOp = rasterState.blendEquationRGB,
|
||||
.alphaBlendOp = rasterState.blendEquationAlpha,
|
||||
|
||||
@@ -184,7 +184,6 @@ VulkanPipelineCache::PipelineCacheEntry* VulkanPipelineCache::createPipeline() n
|
||||
vkRaster.polygonMode = VK_POLYGON_MODE_FILL;
|
||||
vkRaster.cullMode = raster.cullMode;
|
||||
vkRaster.frontFace = raster.frontFace;
|
||||
vkRaster.depthClampEnable = raster.depthClamp;
|
||||
vkRaster.depthBiasEnable = raster.depthBiasEnable;
|
||||
vkRaster.depthBiasConstantFactor = raster.depthBiasConstantFactor;
|
||||
vkRaster.depthBiasClamp = 0.0f;
|
||||
|
||||
@@ -90,8 +90,7 @@ public:
|
||||
VkBlendFactor srcAlphaBlendFactor : 5;
|
||||
VkBlendFactor dstAlphaBlendFactor : 5;
|
||||
VkColorComponentFlags colorWriteMask : 4;
|
||||
uint8_t rasterizationSamples : 4;// offset = 4 bytes
|
||||
uint8_t depthClamp : 4;
|
||||
uint8_t rasterizationSamples; // offset = 4 bytes
|
||||
uint8_t colorTargetCount; // offset = 5 bytes
|
||||
BlendEquation colorBlendOp : 4; // offset = 6 bytes
|
||||
BlendEquation alphaBlendOp : 4;
|
||||
|
||||
@@ -325,7 +325,6 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
|
||||
// We could simply enable all supported features, but since that may have performance
|
||||
// consequences let's just enable the features we need.
|
||||
VkPhysicalDeviceFeatures enabledFeatures{
|
||||
.depthClamp = features.depthClamp,
|
||||
.samplerAnisotropy = features.samplerAnisotropy,
|
||||
.textureCompressionETC2 = features.textureCompressionETC2,
|
||||
.textureCompressionBC = features.textureCompressionBC,
|
||||
|
||||
@@ -55,8 +55,7 @@ public:
|
||||
template<typename T>
|
||||
using BuilderBase = utils::PrivateImplementation<T>;
|
||||
|
||||
// This needs to be public because it is used in the following template.
|
||||
UTILS_PUBLIC void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept;
|
||||
void builderMakeName(utils::CString& outName, const char* name, size_t len) noexcept;
|
||||
|
||||
template <typename Builder>
|
||||
class UTILS_PUBLIC BuilderNameMixin {
|
||||
|
||||
@@ -459,12 +459,10 @@ void PerViewUniforms::bind(backend::DriverApi& driver) noexcept {
|
||||
|
||||
void PerViewUniforms::unbindSamplers() noexcept {
|
||||
auto& samplerGroup = mSamplers;
|
||||
samplerGroup.clearSampler(PerViewSib::SHADOW_MAP);
|
||||
samplerGroup.clearSampler(PerViewSib::IBL_SPECULAR);
|
||||
samplerGroup.clearSampler(PerViewSib::SSAO);
|
||||
samplerGroup.clearSampler(PerViewSib::SSR);
|
||||
samplerGroup.clearSampler(PerViewSib::STRUCTURE);
|
||||
samplerGroup.clearSampler(PerViewSib::FOG);
|
||||
samplerGroup.clearSampler(PerViewSib::SHADOW_MAP);
|
||||
}
|
||||
|
||||
} // namespace filament
|
||||
|
||||
@@ -419,8 +419,7 @@ RenderPass::Command* RenderPass::instanceify(FEngine& engine,
|
||||
UTILS_ALWAYS_INLINE // This function exists only to make the code more readable. we want it inlined.
|
||||
inline // and we don't need it in the compilation unit
|
||||
void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
FMaterialInstance const* const UTILS_RESTRICT mi,
|
||||
bool inverseFrontFaces, bool hasDepthClamp) noexcept {
|
||||
FMaterialInstance const* const UTILS_RESTRICT mi, bool inverseFrontFaces) noexcept {
|
||||
|
||||
FMaterial const * const UTILS_RESTRICT ma = mi->getMaterial();
|
||||
variant = Variant::filterVariant(variant, ma->isVariantLit());
|
||||
@@ -461,7 +460,6 @@ void RenderPass::setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
cmdDraw.info.rasterState.colorWrite = mi->isColorWriteEnabled();
|
||||
cmdDraw.info.rasterState.depthWrite = mi->isDepthWriteEnabled();
|
||||
cmdDraw.info.rasterState.depthFunc = mi->getDepthFunc();
|
||||
cmdDraw.info.rasterState.depthClamp = hasDepthClamp;
|
||||
cmdDraw.info.materialVariant = variant;
|
||||
// we keep "RasterState::colorWrite" to the value set by material (could be disabled)
|
||||
}
|
||||
@@ -560,9 +558,6 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
bool const hasInstancedStereo =
|
||||
renderFlags & IS_INSTANCED_STEREOSCOPIC;
|
||||
|
||||
bool const hasDepthClamp =
|
||||
renderFlags & HAS_DEPTH_CLAMP;
|
||||
|
||||
float const cameraPositionDotCameraForward = dot(cameraPosition, cameraForward);
|
||||
|
||||
auto const* const UTILS_RESTRICT soaWorldAABBCenter = soa.data<FScene::WORLD_AABB_CENTER>();
|
||||
@@ -582,7 +577,6 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
cmd.info.rasterState.depthWrite = true;
|
||||
cmd.info.rasterState.depthFunc = RasterState::DepthFunc::GE;
|
||||
cmd.info.rasterState.alphaToCoverage = false;
|
||||
cmd.info.rasterState.depthClamp = hasDepthClamp;
|
||||
}
|
||||
|
||||
for (uint32_t i = range.first; i < range.last; ++i) {
|
||||
@@ -697,8 +691,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(RenderPass::CommandTypeFla
|
||||
cmd.info.morphingOffset = primitive.getMorphingBufferOffset();
|
||||
|
||||
if constexpr (isColorPass) {
|
||||
RenderPass::setupColorCommand(cmd, renderableVariant, mi,
|
||||
inverseFrontFaces, hasDepthClamp);
|
||||
RenderPass::setupColorCommand(cmd, renderableVariant, mi, inverseFrontFaces);
|
||||
const bool blendPass = Pass(cmd.key & PASS_MASK) == Pass::BLENDED;
|
||||
if (blendPass) {
|
||||
// TODO: at least for transparent objects, AABB should be per primitive
|
||||
|
||||
@@ -284,7 +284,6 @@ public:
|
||||
static constexpr RenderFlags HAS_SHADOWING = 0x01;
|
||||
static constexpr RenderFlags HAS_INVERSE_FRONT_FACES = 0x02;
|
||||
static constexpr RenderFlags IS_INSTANCED_STEREOSCOPIC = 0x04;
|
||||
static constexpr RenderFlags HAS_DEPTH_CLAMP = 0x08;
|
||||
|
||||
// Arena used for commands
|
||||
using Arena = utils::Arena<
|
||||
@@ -445,7 +444,7 @@ private:
|
||||
uint8_t instancedStereoEyeCount) noexcept;
|
||||
|
||||
static void setupColorCommand(Command& cmdDraw, Variant variant,
|
||||
FMaterialInstance const* mi, bool inverseFrontFaces, bool hasDepthClamp) noexcept;
|
||||
FMaterialInstance const* mi, bool inverseFrontFaces) noexcept;
|
||||
|
||||
static void updateSummedPrimitiveCounts(
|
||||
FScene::RenderableSoa& renderableData, utils::Range<uint32_t> vr) noexcept;
|
||||
|
||||
@@ -143,14 +143,12 @@ void ResourceAllocator::terminate() noexcept {
|
||||
}
|
||||
}
|
||||
|
||||
RenderTargetHandle ResourceAllocator::createRenderTarget(const char* name,
|
||||
RenderTargetHandle ResourceAllocator::createRenderTarget(const char*,
|
||||
TargetBufferFlags targetBufferFlags, uint32_t width, uint32_t height,
|
||||
uint8_t samples, uint8_t layerCount, MRT color, TargetBufferInfo depth,
|
||||
TargetBufferInfo stencil) noexcept {
|
||||
auto handle = mBackend.createRenderTarget(targetBufferFlags,
|
||||
return mBackend.createRenderTarget(targetBufferFlags,
|
||||
width, height, samples ? samples : 1u, layerCount, color, depth, stencil);
|
||||
mBackend.setDebugTag(handle.getId(), CString{ name });
|
||||
return handle;
|
||||
}
|
||||
|
||||
void ResourceAllocator::destroyRenderTarget(RenderTargetHandle h) noexcept {
|
||||
@@ -172,9 +170,9 @@ backend::TextureHandle ResourceAllocator::createTexture(const char* name,
|
||||
|
||||
// do we have a suitable texture in the cache?
|
||||
TextureHandle handle;
|
||||
TextureKey const key{ name, target, levels, format, samples, width, height, depth, usage, swizzle };
|
||||
if constexpr (mEnabled) {
|
||||
auto& textureCache = mTextureCache;
|
||||
const TextureKey key{ name, target, levels, format, samples, width, height, depth, usage, swizzle };
|
||||
auto it = textureCache.find(key);
|
||||
if (UTILS_LIKELY(it != textureCache.end())) {
|
||||
// we do, move the entry to the in-use list, and remove from the cache
|
||||
@@ -192,6 +190,7 @@ backend::TextureHandle ResourceAllocator::createTexture(const char* name,
|
||||
swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
|
||||
}
|
||||
}
|
||||
mDisposer->checkout(handle, key);
|
||||
} else {
|
||||
if (swizzle == defaultSwizzle) {
|
||||
handle = mBackend.createTexture(
|
||||
@@ -202,14 +201,12 @@ backend::TextureHandle ResourceAllocator::createTexture(const char* name,
|
||||
swizzle[0], swizzle[1], swizzle[2], swizzle[3]);
|
||||
}
|
||||
}
|
||||
mDisposer->checkout(handle, key);
|
||||
mBackend.setDebugTag(handle.getId(), CString{ name });
|
||||
return handle;
|
||||
}
|
||||
|
||||
void ResourceAllocator::destroyTexture(TextureHandle h) noexcept {
|
||||
auto const key = mDisposer->checkin(h);
|
||||
if constexpr (mEnabled) {
|
||||
auto const key = mDisposer->checkin(h);
|
||||
if (UTILS_LIKELY(key.has_value())) {
|
||||
uint32_t const size = key.value().getSize();
|
||||
mTextureCache.emplace(key.value(), TextureCachePayload{ h, mAge, size });
|
||||
|
||||
@@ -829,13 +829,13 @@ ShadowMap::Corners ShadowMap::computeFrustumCorners(
|
||||
Corners const csViewFrustumCorners = {
|
||||
.vertices = {
|
||||
{ -1, -1, far },
|
||||
{ 1, -1, far },
|
||||
{ -1, 1, far },
|
||||
{ 1, 1, far },
|
||||
{ 1, -1, far },
|
||||
{ -1, 1, far },
|
||||
{ 1, 1, far },
|
||||
{ -1, -1, near },
|
||||
{ 1, -1, near },
|
||||
{ -1, 1, near },
|
||||
{ 1, 1, near },
|
||||
{ 1, -1, near },
|
||||
{ -1, 1, near },
|
||||
{ 1, 1, near },
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -66,15 +66,15 @@ namespace filament {
|
||||
using namespace backend;
|
||||
using namespace math;
|
||||
|
||||
ShadowMapManager::ShadowMapManager(FEngine& engine)
|
||||
: mIsDepthClampSupported(engine.getDriverApi().isDepthClampSupported()) {
|
||||
// do this only if depth-clamp is available
|
||||
static constexpr bool USE_DEPTH_CLAMP = false;
|
||||
|
||||
ShadowMapManager::ShadowMapManager(FEngine& engine) {
|
||||
FDebugRegistry& debugRegistry = engine.getDebugRegistry();
|
||||
debugRegistry.registerProperty("d.shadowmap.visualize_cascades",
|
||||
&engine.debug.shadowmap.visualize_cascades);
|
||||
debugRegistry.registerProperty("d.shadowmap.disable_light_frustum_align",
|
||||
&engine.debug.shadowmap.disable_light_frustum_align);
|
||||
debugRegistry.registerProperty("d.shadowmap.depth_clamp",
|
||||
&engine.debug.shadowmap.depth_clamp);
|
||||
}
|
||||
|
||||
ShadowMapManager::~ShadowMapManager() {
|
||||
@@ -367,20 +367,7 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
|
||||
|
||||
// generate and sort the commands for rendering the shadow map
|
||||
|
||||
RenderPass::RenderFlags renderPassFlags{};
|
||||
|
||||
bool const canUseDepthClamp =
|
||||
shadowMap.getShadowType() == ShadowType::DIRECTIONAL &&
|
||||
!view.hasVSM() &&
|
||||
mIsDepthClampSupported &&
|
||||
engine.debug.shadowmap.depth_clamp;
|
||||
|
||||
if (canUseDepthClamp) {
|
||||
renderPassFlags |= RenderPass::HAS_DEPTH_CLAMP;
|
||||
}
|
||||
|
||||
RenderPass const pass = passBuilder
|
||||
.renderFlags(RenderPass::HAS_DEPTH_CLAMP, renderPassFlags)
|
||||
.camera(cameraInfo)
|
||||
.visibilityMask(entry.visibilityMask)
|
||||
.geometry(scene->getRenderableData(),
|
||||
@@ -654,14 +641,8 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
|
||||
cameraInfo.zf = -nearFarPlanes[i + 1];
|
||||
updateNearFarPlanes(&cameraInfo.cullingProjection, cameraInfo.zn, cameraInfo.zf);
|
||||
|
||||
bool const canUseDepthClamp =
|
||||
!view.hasVSM() &&
|
||||
mIsDepthClampSupported &&
|
||||
engine.debug.shadowmap.depth_clamp;
|
||||
|
||||
auto shaderParameters = shadowMap.updateDirectional(engine,
|
||||
lightData, 0, cameraInfo, shadowMapInfo, sceneInfo,
|
||||
canUseDepthClamp);
|
||||
lightData, 0, cameraInfo, shadowMapInfo, sceneInfo, USE_DEPTH_CLAMP);
|
||||
|
||||
if (shadowMap.hasVisibleShadows()) {
|
||||
const size_t shadowIndex = shadowMap.getShadowIndex();
|
||||
|
||||
@@ -232,7 +232,6 @@ private:
|
||||
ShadowMapCacheContainer mShadowMapCache;
|
||||
uint32_t mDirectionalShadowMapCount = 0;
|
||||
uint32_t mSpotShadowMapCount = 0;
|
||||
bool const mIsDepthClampSupported;
|
||||
bool mInitialized = false;
|
||||
|
||||
ShadowMap& getShadowMap(size_t index) noexcept {
|
||||
|
||||
@@ -600,7 +600,6 @@ public:
|
||||
bool focus_shadowcasters = true;
|
||||
bool visualize_cascades = false;
|
||||
bool disable_light_frustum_align = false;
|
||||
bool depth_clamp = true;
|
||||
float dzn = -1.0f;
|
||||
float dzf = 1.0f;
|
||||
float display_shadow_texture_scale = 0.25f;
|
||||
|
||||
@@ -34,7 +34,7 @@ struct RenderTarget::BuilderDetails {
|
||||
uint32_t mWidth{};
|
||||
uint32_t mHeight{};
|
||||
uint8_t mSamples = 1; // currently not settable in the public facing API
|
||||
uint8_t mLayerCount = 0;// currently not settable in the public facing API
|
||||
uint8_t mLayerCount = 1;// currently not settable in the public facing API
|
||||
};
|
||||
|
||||
using BuilderType = RenderTarget;
|
||||
|
||||
@@ -651,19 +651,14 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
|
||||
const bool isProtectedContent = mSwapChain && mSwapChain->isProtected();
|
||||
|
||||
// Conditions to meet to be able to use the sub-pass rendering path. This is regardless of
|
||||
// whether the backend supports subpasses (or if they are disabled in the debugRegistry).
|
||||
const bool isSubpassPossible =
|
||||
msaaSampleCount <= 1 &&
|
||||
hasColorGrading &&
|
||||
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled;
|
||||
|
||||
// asSubpass is disabled with TAA (although it's supported) because performance was degraded
|
||||
// on qualcomm hardware -- we might need a backend dependent toggle at some point
|
||||
const PostProcessManager::ColorGradingConfig colorGradingConfig{
|
||||
.asSubpass =
|
||||
isSubpassPossible &&
|
||||
msaaSampleCount <= 1 &&
|
||||
driver.isFrameBufferFetchSupported() &&
|
||||
hasColorGrading &&
|
||||
!bloomOptions.enabled && !dofOptions.enabled && !taaOptions.enabled &&
|
||||
!engine.debug.renderer.disable_subpasses,
|
||||
.customResolve =
|
||||
msaaSampleCount > 1 &&
|
||||
@@ -707,8 +702,8 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
// this case, we would need an extra blit to "resolve" the buffer padding (because there are no
|
||||
// other pass that can do it as a side effect). In this case, it is better to skip the padding,
|
||||
// which won't be helping much.
|
||||
const bool noBufferPadding = (isSubpassPossible &&
|
||||
!hasFXAA && !scaled) || engine.debug.renderer.disable_buffer_padding;
|
||||
const bool noBufferPadding
|
||||
= (!hasFXAA && !scaled) || engine.debug.renderer.disable_buffer_padding;
|
||||
|
||||
// guardBand must be a multiple of 16 to guarantee the same exact rendering up to 4 mip levels.
|
||||
float const guardBand = guardBandOptions.enabled ? 16.0f : 0.0f;
|
||||
@@ -823,14 +818,14 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
blackboard["shadows"] = shadows;
|
||||
}
|
||||
|
||||
// When we don't have a custom RenderTarget, customRenderTarget below is nullptr and is
|
||||
// When we don't have a custom RenderTarget, currentRenderTarget below is nullptr and is
|
||||
// recorded in the list of targets already rendered into -- this ensures that
|
||||
// initializeClearFlags() is called only once for the default RenderTarget.
|
||||
auto& previousRenderTargets = mPreviousRenderTargets;
|
||||
FRenderTarget* const customRenderTarget = downcast(view.getRenderTarget());
|
||||
FRenderTarget* const currentRenderTarget = downcast(view.getRenderTarget());
|
||||
if (UTILS_LIKELY(
|
||||
previousRenderTargets.find(customRenderTarget) == previousRenderTargets.end())) {
|
||||
previousRenderTargets.insert(customRenderTarget);
|
||||
previousRenderTargets.find(currentRenderTarget) == previousRenderTargets.end())) {
|
||||
previousRenderTargets.insert(currentRenderTarget);
|
||||
initializeClearFlags();
|
||||
}
|
||||
|
||||
@@ -847,10 +842,10 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
const TargetBufferFlags keepOverrideStartFlags = TargetBufferFlags::ALL & ~discardStartFlags;
|
||||
TargetBufferFlags keepOverrideEndFlags = TargetBufferFlags::NONE;
|
||||
|
||||
if (customRenderTarget) {
|
||||
if (currentRenderTarget) {
|
||||
// For custom RenderTarget, we look at each attachment flag and if they have their
|
||||
// SAMPLEABLE usage bit set, we assume they must not be discarded after the render pass.
|
||||
keepOverrideEndFlags |= customRenderTarget->getSampleableAttachmentsMask();
|
||||
keepOverrideEndFlags |= currentRenderTarget->getSampleableAttachmentsMask();
|
||||
}
|
||||
|
||||
// Renderer's ClearOptions apply once at the beginning of the frame (not for each View),
|
||||
@@ -1019,10 +1014,6 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
{ .width = svp.width, .height = svp.height });
|
||||
|
||||
if (UTILS_LIKELY(reflections)) {
|
||||
fg.addTrivialSideEffectPass("SSR Cleanup", [&view](DriverApi& driver) {
|
||||
view.getPerViewUniforms().prepareStructure({});
|
||||
view.commitUniforms(driver);
|
||||
});
|
||||
// generate the mipchain
|
||||
PostProcessManager::generateMipmapSSR(ppm, fg,
|
||||
reflections, ssrConfig.reflection, false, ssrConfig);
|
||||
@@ -1138,12 +1129,6 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
}
|
||||
}
|
||||
|
||||
fg.addTrivialSideEffectPass("Finish Color Passes", [&view](DriverApi& driver) {
|
||||
// Unbind SSAO sampler, b/c the FrameGraph will delete the texture at the end of the pass.
|
||||
view.cleanupRenderPasses();
|
||||
view.commitUniforms(driver);
|
||||
});
|
||||
|
||||
if (colorGradingConfig.customResolve) {
|
||||
assert_invariant(fg.getDescriptor(colorPassOutput.linearColor).samples <= 1);
|
||||
// TODO: we have to "uncompress" (i.e. detonemap) the color buffer here because it's used
|
||||
@@ -1182,11 +1167,16 @@ void FRenderer::renderJob(RootArenaScope& rootArenaScope, FView& view) {
|
||||
// this is the output of the color pass / input to post processing,
|
||||
// this is only used later for comparing it with the output after post-processing
|
||||
FrameGraphId<FrameGraphTexture> const postProcessInput = colorGradingConfig.asSubpass ?
|
||||
colorPassOutput.tonemappedColor :
|
||||
colorPassOutput.linearColor;
|
||||
colorPassOutput.tonemappedColor :
|
||||
colorPassOutput.linearColor;
|
||||
|
||||
// input can change below
|
||||
FrameGraphId<FrameGraphTexture> input = postProcessInput;
|
||||
fg.addTrivialSideEffectPass("Finish Color Passes", [&view](DriverApi& driver) {
|
||||
// Unbind SSAO sampler, b/c the FrameGraph will delete the texture at the end of the pass.
|
||||
view.cleanupRenderPasses();
|
||||
view.commitUniforms(driver);
|
||||
});
|
||||
|
||||
// Resolve depth -- which might be needed because of TAA or DoF. This pass will be culled
|
||||
// if the depth is not used below or if the depth is not MS (e.g. it could have been
|
||||
|
||||
@@ -245,8 +245,6 @@ FTexture::FTexture(FEngine& engine, const Builder& builder) {
|
||||
}
|
||||
if (auto name = builder.getName(); !name.empty()) {
|
||||
driver.setDebugTag(mHandle.getId(), std::move(name));
|
||||
} else {
|
||||
driver.setDebugTag(mHandle.getId(), CString{"FTexture"});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1040,8 +1040,10 @@ void FView::commitFrameHistory(FEngine& engine) noexcept {
|
||||
auto& frameHistory = mFrameHistory;
|
||||
|
||||
FrameHistoryEntry& last = frameHistory.back();
|
||||
disposer.destroy(std::move(last.taa.color.handle));
|
||||
disposer.destroy(std::move(last.ssr.color.handle));
|
||||
disposer.destroy(last.taa.color.handle);
|
||||
disposer.destroy(last.ssr.color.handle);
|
||||
last.taa.color.handle.clear();
|
||||
last.ssr.color.handle.clear();
|
||||
|
||||
// and then push the new history entry to the history stack
|
||||
frameHistory.commit();
|
||||
@@ -1053,8 +1055,10 @@ void FView::clearFrameHistory(FEngine& engine) noexcept {
|
||||
auto& frameHistory = mFrameHistory;
|
||||
for (size_t i = 0; i < frameHistory.size(); ++i) {
|
||||
FrameHistoryEntry& last = frameHistory[i];
|
||||
disposer.destroy(std::move(last.taa.color.handle));
|
||||
disposer.destroy(std::move(last.ssr.color.handle));
|
||||
disposer.destroy(last.taa.color.handle);
|
||||
disposer.destroy(last.ssr.color.handle);
|
||||
last.taa.color.handle.clear();
|
||||
last.ssr.color.handle.clear();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.54.3"
|
||||
spec.version = "1.54.1"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.54.3/filament-v1.54.3-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.54.1/filament-v1.54.1-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -671,13 +671,15 @@ void GLSLPostProcessor::fixupClipDistance(
|
||||
// - triggers a crash on some Adreno drivers (b/291140208, b/289401984, b/289393290)
|
||||
// However Metal requires this pass in order to correctly generate half-precision MSL
|
||||
//
|
||||
// CreateSimplificationPass() creates a lot of problems:
|
||||
// Note: CreateSimplificationPass() used to creates a lot of problems:
|
||||
// - Adreno GPU show artifacts after running simplification passes (Vulkan)
|
||||
// - spirv-cross fails generating working glsl
|
||||
// (https://github.com/KhronosGroup/SPIRV-Cross/issues/2162)
|
||||
// - generally it makes the code more complicated, e.g.: replacing for loops with
|
||||
// while-if-break, unclear if it helps for anything.
|
||||
// However, the simplification passes below are necessary when targeting Metal, otherwise the
|
||||
//
|
||||
// However this problem was addressed in spirv-cross here:
|
||||
// https://github.com/KhronosGroup/SPIRV-Cross/pull/2163
|
||||
//
|
||||
// The simplification passes below are necessary when targeting Metal, otherwise the
|
||||
// result is mismatched half / float assignments in MSL.
|
||||
|
||||
|
||||
@@ -710,11 +712,11 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
|
||||
RegisterPass(CreateAggressiveDCEPass());
|
||||
RegisterPass(CreateRedundancyEliminationPass());
|
||||
RegisterPass(CreateCombineAccessChainsPass());
|
||||
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
|
||||
RegisterPass(CreateSimplificationPass());
|
||||
RegisterPass(CreateVectorDCEPass());
|
||||
RegisterPass(CreateDeadInsertElimPass());
|
||||
RegisterPass(CreateDeadBranchElimPass());
|
||||
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
|
||||
RegisterPass(CreateSimplificationPass());
|
||||
RegisterPass(CreateIfConversionPass());
|
||||
RegisterPass(CreateCopyPropagateArraysPass());
|
||||
RegisterPass(CreateReduceLoadSizePass());
|
||||
@@ -723,7 +725,7 @@ void GLSLPostProcessor::registerPerformancePasses(Optimizer& optimizer, Config c
|
||||
RegisterPass(CreateRedundancyEliminationPass());
|
||||
RegisterPass(CreateDeadBranchElimPass());
|
||||
RegisterPass(CreateBlockMergePass());
|
||||
RegisterPass(CreateSimplificationPass(), MaterialBuilder::TargetApi::METAL);
|
||||
RegisterPass(CreateSimplificationPass());
|
||||
}
|
||||
|
||||
void GLSLPostProcessor::registerSizePasses(Optimizer& optimizer, Config const& config) {
|
||||
|
||||
@@ -39,6 +39,7 @@ set(MATERIAL_SRCS
|
||||
materials/sandboxSubsurface.mat
|
||||
materials/sandboxUnlit.mat
|
||||
materials/texturedLit.mat
|
||||
materials/iconTest.mat
|
||||
)
|
||||
|
||||
if (CMAKE_CROSSCOMPILING)
|
||||
@@ -270,6 +271,7 @@ if (NOT ANDROID)
|
||||
add_demo(viewtest)
|
||||
|
||||
# Sample app specific
|
||||
target_link_libraries(hellotriangle PRIVATE gltf-demo-resources uberarchive gltfio)
|
||||
target_link_libraries(frame_generator PRIVATE imageio)
|
||||
target_link_libraries(gltf_viewer PRIVATE gltf-demo-resources uberarchive gltfio viewer)
|
||||
target_link_libraries(gltf_instances PRIVATE gltf-demo-resources uberarchive gltfio viewer)
|
||||
|
||||
@@ -905,8 +905,6 @@ int main(int argc, char** argv) {
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.focus_shadowcasters"));
|
||||
ImGui::Checkbox("Disable light frustum alignment",
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.disable_light_frustum_align"));
|
||||
ImGui::Checkbox("Depth clamp",
|
||||
debug.getPropertyAddress<bool>("d.shadowmap.depth_clamp"));
|
||||
|
||||
bool debugDirectionalShadowmap;
|
||||
if (debug.getProperty("d.shadowmap.debug_directional_shadowmap",
|
||||
|
||||
+449
-151
@@ -1,192 +1,490 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
#include <fstream>
|
||||
#include <iostream>
|
||||
|
||||
#include <filament/Camera.h>
|
||||
#include <filament/Engine.h>
|
||||
#include <filament/IndexBuffer.h>
|
||||
#include <filament/Material.h>
|
||||
#include <filament/MaterialInstance.h>
|
||||
#include <filament/LightManager.h>
|
||||
#include <filament/RenderableManager.h>
|
||||
#include <filament/Renderer.h>
|
||||
#include <filament/Scene.h>
|
||||
#include <filament/Skybox.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/VertexBuffer.h>
|
||||
#include <filament/View.h>
|
||||
#include <filament/Viewport.h>
|
||||
#include <filament/SwapChain.h>
|
||||
#include <filament/Texture.h>
|
||||
#include <filament/TransformManager.h>
|
||||
#include <filament/RenderTarget.h>
|
||||
|
||||
#include <filamat/MaterialBuilder.h>
|
||||
|
||||
#include <utils/EntityManager.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#include <filamentapp/Config.h>
|
||||
#include <filamentapp/FilamentApp.h>
|
||||
#include <math/norm.h>
|
||||
|
||||
#include <getopt/getopt.h>
|
||||
#include <gltfio/AssetLoader.h>
|
||||
#include <gltfio/ResourceLoader.h>
|
||||
|
||||
#include <cmath>
|
||||
#include <iostream>
|
||||
#include <SDL.h>
|
||||
#include <SDL_syswm.h>
|
||||
#include <SDL_video.h>
|
||||
|
||||
#include <filamentapp/NativeWindowHelper.h>
|
||||
|
||||
#include "generated/resources/resources.h"
|
||||
#include "materials/uberarchive.h"
|
||||
|
||||
#include <vector>
|
||||
|
||||
using namespace filament;
|
||||
using utils::Entity;
|
||||
using utils::EntityManager;
|
||||
using namespace math;
|
||||
using namespace utils;
|
||||
|
||||
struct App {
|
||||
Config config;
|
||||
VertexBuffer* vb;
|
||||
IndexBuffer* ib;
|
||||
Material* mat;
|
||||
Camera* cam;
|
||||
Entity camera;
|
||||
Skybox* skybox;
|
||||
Entity renderable;
|
||||
namespace {
|
||||
|
||||
const static uint32_t gIndices[] = {0, 1, 2, 2, 3, 0};
|
||||
|
||||
float const QUAD_WIDTH = .5;
|
||||
|
||||
const static math::float3 gVertices[] = {
|
||||
float3 {0, 0, 0} * QUAD_WIDTH,
|
||||
float3 {0, 1, 0} * QUAD_WIDTH,
|
||||
float3 {1, 1, 0} * QUAD_WIDTH,
|
||||
float3 {1, 0, 0} * QUAD_WIDTH,
|
||||
};
|
||||
|
||||
struct Vertex {
|
||||
filament::math::float2 position;
|
||||
uint32_t color;
|
||||
const static math::float2 gUVs[] = {
|
||||
{0, 0},
|
||||
{0, 1},
|
||||
{1, 1},
|
||||
{1, 0},
|
||||
};
|
||||
|
||||
static const Vertex TRIANGLE_VERTICES[3] = {
|
||||
{{1, 0}, 0xffff0000u},
|
||||
{{cos(M_PI * 2 / 3), sin(M_PI * 2 / 3)}, 0xff00ff00u},
|
||||
{{cos(M_PI * 4 / 3), sin(M_PI * 4 / 3)}, 0xff0000ffu},
|
||||
};
|
||||
const static short4 tbn = math::packSnorm16(mat3f::packTangentFrame(
|
||||
math::mat3f{float3{1.0f, 0.0f, 0.0f}, float3{0.0f, 0.0f, 1.0f},
|
||||
float3{0.0f, 1.0f, 0.0f}}).xyzw);
|
||||
|
||||
static constexpr uint16_t TRIANGLE_INDICES[3] = { 0, 1, 2 };
|
||||
const static math::short4 gNormals[]{tbn, tbn, tbn, tbn};
|
||||
|
||||
static void printUsage(char* name) {
|
||||
std::string exec_name(utils::Path(name).getName());
|
||||
std::string usage(
|
||||
"HELLOTRIANGLE renders a spinning colored triangle\n"
|
||||
"Usage:\n"
|
||||
" HELLOTRIANGLE [options]\n"
|
||||
"Options:\n"
|
||||
" --help, -h\n"
|
||||
" Prints this message\n\n"
|
||||
" --api, -a\n"
|
||||
" Specify the backend API: opengl, vulkan, or metal\n"
|
||||
);
|
||||
const std::string from("HELLOTRIANGLE");
|
||||
for (size_t pos = usage.find(from); pos != std::string::npos; pos = usage.find(from, pos)) {
|
||||
usage.replace(pos, from.length(), exec_name);
|
||||
struct TestPrimitive {
|
||||
TestPrimitive(Engine* engine) {
|
||||
vertexBuffer =
|
||||
VertexBuffer::Builder()
|
||||
.vertexCount(4)
|
||||
.bufferCount(3)
|
||||
.attribute(VertexAttribute::POSITION, 0,
|
||||
VertexBuffer::AttributeType::FLOAT3)
|
||||
.attribute(VertexAttribute::UV0, 1, VertexBuffer::AttributeType::FLOAT2)
|
||||
.attribute(VertexAttribute::TANGENTS, 2, VertexBuffer::AttributeType::FLOAT4)
|
||||
.build(*engine);
|
||||
vertexBuffer->setBufferAt(*engine, 0,
|
||||
VertexBuffer::BufferDescriptor(gVertices,
|
||||
vertexBuffer->getVertexCount() * sizeof(gVertices[0])));
|
||||
vertexBuffer->setBufferAt(*engine, 1,
|
||||
VertexBuffer::BufferDescriptor(gUVs,
|
||||
vertexBuffer->getVertexCount() * sizeof(gUVs[0])));
|
||||
vertexBuffer->setBufferAt(*engine, 2,
|
||||
VertexBuffer::BufferDescriptor(gNormals,
|
||||
vertexBuffer->getVertexCount() * sizeof(gNormals[0])));
|
||||
|
||||
indexBuffer = IndexBuffer::Builder().indexCount(6).build(*engine);
|
||||
|
||||
indexBuffer->setBuffer(*engine, IndexBuffer::BufferDescriptor(gIndices,
|
||||
indexBuffer->getIndexCount() * sizeof(uint32_t)));
|
||||
}
|
||||
std::cout << usage;
|
||||
|
||||
VertexBuffer* verts() const { return vertexBuffer; }
|
||||
IndexBuffer* inds() const { return indexBuffer; }
|
||||
|
||||
private:
|
||||
VertexBuffer* vertexBuffer;
|
||||
IndexBuffer* indexBuffer;
|
||||
};
|
||||
|
||||
struct TestMaterial {
|
||||
TestMaterial(Engine* engine) {
|
||||
material = Material::Builder()
|
||||
.package(RESOURCES_ICONTEST_DATA, RESOURCES_ICONTEST_SIZE)
|
||||
.build(*engine);
|
||||
}
|
||||
|
||||
MaterialInstance* instance() {
|
||||
auto inst = material->createInstance();
|
||||
instances.push_back(inst);
|
||||
return inst;
|
||||
}
|
||||
|
||||
private:
|
||||
Material* material;
|
||||
std::vector<MaterialInstance*> instances;
|
||||
};
|
||||
|
||||
struct TestTexture {
|
||||
TestTexture(Engine* engine, size_t width, size_t height, bool attachment=false) {
|
||||
auto usage = Texture::Usage::DEFAULT;
|
||||
if (attachment) {
|
||||
usage = usage | Texture::Usage::COLOR_ATTACHMENT;
|
||||
}
|
||||
texture = Texture::Builder()
|
||||
.width(width).height(height).levels(1)
|
||||
.usage(usage)
|
||||
.format(Texture::InternalFormat::RGBA8).build(*engine);
|
||||
uint8_t* data = (uint8_t*) malloc(width * height * 4);
|
||||
std::memset(data, 0xFF, width * height * 4);
|
||||
Texture::PixelBufferDescriptor buffer(data, size_t(width * height * 4),
|
||||
Texture::Format::RGBA, Texture::Type::UBYTE,
|
||||
[](void* buf, size_t size, void* user) {
|
||||
free(buf);
|
||||
});
|
||||
texture->setImage(*engine, 0, 0, 0, 0, width, height, 1, std::move(buffer));
|
||||
}
|
||||
Texture* get() const { return texture; }
|
||||
private:
|
||||
Texture* texture;
|
||||
};
|
||||
|
||||
std::pair<SDL_Window*, void*> createSDLwindow() {
|
||||
const uint32_t windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
|
||||
SDL_Window* win = SDL_CreateWindow("Hello World!", 0, 100, 800, 800, windowFlags);
|
||||
if (win == nullptr) {
|
||||
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
|
||||
SDL_Quit();
|
||||
return {NULL, NULL};
|
||||
}
|
||||
|
||||
void* nativeWindow = getNativeWindow(win);
|
||||
#if defined(__APPLE__)
|
||||
prepareNativeWindow(win);
|
||||
setUpMetalLayer(nativeWindow);
|
||||
#endif
|
||||
|
||||
return {win, nativeWindow};
|
||||
}
|
||||
|
||||
static int handleCommandLineArguments(int argc, char* argv[], App* app) {
|
||||
static constexpr const char* OPTSTR = "ha:";
|
||||
static const struct option OPTIONS[] = {
|
||||
{ "help", no_argument, nullptr, 'h' },
|
||||
{ "api", required_argument, nullptr, 'a' },
|
||||
{ nullptr, 0, nullptr, 0 }
|
||||
struct IconScene {
|
||||
|
||||
struct Option {
|
||||
float border=1.4;
|
||||
bool postProcessing=true;
|
||||
bool useSkybox=false;
|
||||
};
|
||||
int opt;
|
||||
int option_index = 0;
|
||||
while ((opt = getopt_long(argc, argv, OPTSTR, OPTIONS, &option_index)) >= 0) {
|
||||
std::string arg(optarg ? optarg : "");
|
||||
switch (opt) {
|
||||
default:
|
||||
case 'h':
|
||||
printUsage(argv[0]);
|
||||
exit(0);
|
||||
case 'a':
|
||||
if (arg == "opengl") {
|
||||
app->config.backend = Engine::Backend::OPENGL;
|
||||
} else if (arg == "vulkan") {
|
||||
app->config.backend = Engine::Backend::VULKAN;
|
||||
} else if (arg == "metal") {
|
||||
app->config.backend = Engine::Backend::METAL;
|
||||
} else {
|
||||
std::cerr << "Unrecognized backend. Must be 'opengl'|'vulkan'|'metal'.\n";
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
||||
IconScene(Engine* engine, Renderer* renderer, uint32_t w, uint32_t h, Option option)
|
||||
: engine(engine),
|
||||
renderer(renderer),
|
||||
material(engine),
|
||||
primitives(engine) {
|
||||
cameraEntity = EntityManager::get().create();
|
||||
camera = engine->createCamera(cameraEntity);
|
||||
camera->lookAt(float3(0, 0, -10.f), float3(0, 0, 0), float3(0, 1.0f, 0));
|
||||
float halfWidth = (QUAD_WIDTH / 2) * option.border;
|
||||
camera->setProjection(Camera::Projection::ORTHO,
|
||||
-halfWidth , halfWidth, -halfWidth, halfWidth, -50, 50);
|
||||
|
||||
scene = engine->createScene();
|
||||
|
||||
view = engine->createView();
|
||||
view->setViewport({0, 0, w, h});
|
||||
view->setScene(scene);
|
||||
view->setCamera(camera);
|
||||
view->setPostProcessingEnabled(false);
|
||||
|
||||
Entity renderable = EntityManager::get().create();
|
||||
matInstance = material.instance();
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-10, -10, -10}, {10, 10, 10}})
|
||||
.material(0, matInstance)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES,
|
||||
primitives.verts(), primitives.inds(), 0, 6)
|
||||
.culling(false)
|
||||
.build(*engine, renderable);
|
||||
|
||||
scene->addEntity(renderable);
|
||||
|
||||
auto& tcm = engine->getTransformManager();
|
||||
tcm.create(renderable);
|
||||
auto inst = tcm.getInstance(renderable);
|
||||
mat4f xlate = mat4f::translation(float3(QUAD_WIDTH / -2.0, QUAD_WIDTH / -2.0, 0));
|
||||
tcm.setTransform(inst, xlate);
|
||||
}
|
||||
|
||||
void render(Texture* texture, Texture* renderTargetTexture, float3 const& multiplier) {
|
||||
TextureSampler sampler{TextureSampler::MinFilter::NEAREST,
|
||||
TextureSampler::MagFilter::NEAREST};
|
||||
|
||||
matInstance->setParameter("tex", texture, sampler);
|
||||
matInstance->setParameter("multiplier", multiplier);
|
||||
|
||||
RenderTarget* target;
|
||||
if (auto itr = targets.find(renderTargetTexture); itr != targets.end()) {
|
||||
target = itr->second;
|
||||
} else {
|
||||
target = RenderTarget::Builder()
|
||||
.texture(RenderTarget::AttachmentPoint::COLOR, renderTargetTexture)
|
||||
.build(*engine);
|
||||
targets[renderTargetTexture] = target;
|
||||
}
|
||||
|
||||
view->setRenderTarget(target);
|
||||
renderer->renderStandaloneView(view);
|
||||
}
|
||||
|
||||
void renderToSwapChain(SwapChain* swapChain, Texture* texture) {
|
||||
TextureSampler sampler{TextureSampler::MinFilter::NEAREST,
|
||||
TextureSampler::MagFilter::NEAREST};
|
||||
matInstance->setParameter("tex", texture, sampler);
|
||||
matInstance->setParameter("multiplier", float3 {1});
|
||||
|
||||
if (renderer->beginFrame(swapChain)) {
|
||||
// for each View
|
||||
renderer->render(view);
|
||||
renderer->endFrame();
|
||||
}
|
||||
}
|
||||
return optind;
|
||||
|
||||
|
||||
private:
|
||||
Engine* engine;
|
||||
Renderer* renderer;
|
||||
View* view;
|
||||
Scene* scene;
|
||||
Camera* camera;
|
||||
TestMaterial material;
|
||||
TestPrimitive primitives;
|
||||
Entity cameraEntity;
|
||||
Skybox* skybox;
|
||||
MaterialInstance* matInstance;
|
||||
std::unordered_map<Texture*, RenderTarget*> targets;
|
||||
};
|
||||
|
||||
struct MainScene {
|
||||
using TextureMatrix = std::vector<std::vector<Texture*>>;
|
||||
|
||||
MainScene(Engine* engine, Renderer* renderer, uint32_t w, uint32_t h, uint32_t nrows,
|
||||
uint32_t ncols)
|
||||
: renderer(renderer),
|
||||
primitives{engine},
|
||||
material(engine),
|
||||
engine(engine) {
|
||||
cameraEntity = EntityManager::get().create();
|
||||
|
||||
camera = engine->createCamera(cameraEntity);
|
||||
camera->lookAt(float3(0, 0, -10.f), float3(0, 0, 0), float3(0, 1.0f, 0));
|
||||
camera->setProjection(45.0, double(w) / h, 0.1, 50, Camera::Fov::VERTICAL);
|
||||
|
||||
scene = engine->createScene();
|
||||
|
||||
// skybox = Skybox::Builder().color({0.2, 0.2, 0.2, 1.0}).build(*engine);
|
||||
// scene->setSkybox(skybox);
|
||||
|
||||
view = engine->createView();
|
||||
view->setViewport({0, 0, w, h});
|
||||
view->setScene(scene);
|
||||
view->setCamera(camera);
|
||||
view->setPostProcessingEnabled(false);
|
||||
|
||||
root = EntityManager::get().create();
|
||||
auto& tcm = engine->getTransformManager();
|
||||
tcm.create(root);
|
||||
auto rootInst = tcm.getInstance(root);
|
||||
mat4f xlate = mat4f::translation(float3(-QUAD_WIDTH / 2 * nrows , -QUAD_WIDTH / 2 * ncols, 0));
|
||||
tcm.setTransform(rootInst, xlate);
|
||||
|
||||
matInst = material.instance();
|
||||
|
||||
renderable = EntityManager::get().create();
|
||||
scene->addEntity(renderable);
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{-10, -10, -10}, {10, 10, 10}})
|
||||
.material(0, matInst)
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES,
|
||||
primitives.verts(), primitives.inds(), 0, 6)
|
||||
.culling(false)
|
||||
.build(*engine, renderable);
|
||||
|
||||
auto transformInst = tcm.getInstance(renderable);
|
||||
tcm.setParent(transformInst, rootInst);
|
||||
}
|
||||
|
||||
void render(Texture* texture, RenderTarget* target, uint32_t r, uint32_t c) {
|
||||
auto& tcm = engine->getTransformManager();
|
||||
TextureSampler sampler{TextureSampler::MinFilter::NEAREST,
|
||||
TextureSampler::MagFilter::NEAREST};
|
||||
matInst->setParameter("tex", texture, sampler);
|
||||
matInst->setParameter("multiplier", float3 {1});
|
||||
|
||||
auto transformInst = tcm.getInstance(renderable);
|
||||
mat4f xlate = mat4f::translation(float3(QUAD_WIDTH * r, QUAD_WIDTH * c, 0));
|
||||
tcm.setTransform(transformInst, xlate);
|
||||
|
||||
view->setRenderTarget(target);
|
||||
renderer->renderStandaloneView(view);
|
||||
}
|
||||
|
||||
void renderToSwapChain(SwapChain* swapChain, Texture* texture, uint32_t r, uint32_t c){
|
||||
auto& tcm = engine->getTransformManager();
|
||||
TextureSampler sampler{TextureSampler::MinFilter::NEAREST,
|
||||
TextureSampler::MagFilter::NEAREST};
|
||||
matInst->setParameter("tex", texture, sampler);
|
||||
matInst->setParameter("multiplier", float3 {1});
|
||||
|
||||
auto transformInst = tcm.getInstance(renderable);
|
||||
mat4f xlate = mat4f::translation(float3(QUAD_WIDTH * r, QUAD_WIDTH * c, 0));
|
||||
tcm.setTransform(transformInst, xlate);
|
||||
|
||||
if (renderer->beginFrame(swapChain)) {
|
||||
// for each View
|
||||
renderer->render(view);
|
||||
renderer->endFrame();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Scene* get() const { return scene; }
|
||||
Camera* getCamera() const { return camera; }
|
||||
View* getView() const { return view; }
|
||||
|
||||
private:
|
||||
Renderer* renderer;
|
||||
TestMaterial material;
|
||||
MaterialInstance* matInst;
|
||||
TestPrimitive primitives;
|
||||
TextureMatrix textures;
|
||||
Scene* scene;
|
||||
Entity light;
|
||||
Entity root;
|
||||
Entity renderable;
|
||||
Camera* camera;
|
||||
Entity cameraEntity;
|
||||
Skybox* skybox;
|
||||
View* view;
|
||||
std::vector<Entity> renderables;
|
||||
Engine* engine;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
App app{};
|
||||
app.config.title = "hellotriangle";
|
||||
app.config.featureLevel = backend::FeatureLevel::FEATURE_LEVEL_0;
|
||||
handleCommandLineArguments(argc, argv, &app);
|
||||
int main() {
|
||||
SDL_Init(SDL_INIT_EVERYTHING);
|
||||
auto const [window, nativeWindow] = createSDLwindow();
|
||||
|
||||
auto setup = [&app](Engine* engine, View* view, Scene* scene) {
|
||||
app.skybox = Skybox::Builder().color({0.1, 0.125, 0.25, 1.0}).build(*engine);
|
||||
scene->setSkybox(app.skybox);
|
||||
view->setPostProcessingEnabled(false);
|
||||
static_assert(sizeof(Vertex) == 12, "Strange vertex size.");
|
||||
app.vb = VertexBuffer::Builder()
|
||||
.vertexCount(3)
|
||||
.bufferCount(1)
|
||||
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT2, 0, 12)
|
||||
.attribute(VertexAttribute::COLOR, 0, VertexBuffer::AttributeType::UBYTE4, 8, 12)
|
||||
.normalized(VertexAttribute::COLOR)
|
||||
.build(*engine);
|
||||
app.vb->setBufferAt(*engine, 0,
|
||||
VertexBuffer::BufferDescriptor(TRIANGLE_VERTICES, 36, nullptr));
|
||||
app.ib = IndexBuffer::Builder()
|
||||
.indexCount(3)
|
||||
.bufferType(IndexBuffer::IndexType::USHORT)
|
||||
.build(*engine);
|
||||
app.ib->setBuffer(*engine,
|
||||
IndexBuffer::BufferDescriptor(TRIANGLE_INDICES, 6, nullptr));
|
||||
app.mat = Material::Builder()
|
||||
.package(RESOURCES_BAKEDCOLOR_DATA, RESOURCES_BAKEDCOLOR_SIZE)
|
||||
.build(*engine);
|
||||
app.renderable = EntityManager::get().create();
|
||||
RenderableManager::Builder(1)
|
||||
.boundingBox({{ -1, -1, -1 }, { 1, 1, 1 }})
|
||||
.material(0, app.mat->getDefaultInstance())
|
||||
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, app.vb, app.ib, 0, 3)
|
||||
.culling(false)
|
||||
.receiveShadows(false)
|
||||
.castShadows(false)
|
||||
.build(*engine, app.renderable);
|
||||
scene->addEntity(app.renderable);
|
||||
app.camera = utils::EntityManager::get().create();
|
||||
app.cam = engine->createCamera(app.camera);
|
||||
view->setCamera(app.cam);
|
||||
Engine* engine = Engine::create(filament::backend::Backend::VULKAN);
|
||||
SwapChain* swapChain =
|
||||
engine->createSwapChain(nativeWindow, filament::SwapChain::CONFIG_HAS_STENCIL_BUFFER);
|
||||
Renderer* renderer = engine->createRenderer();
|
||||
|
||||
// Determine the current size of the window in physical pixels.
|
||||
uint32_t w, h;
|
||||
SDL_GL_GetDrawableSize(window, (int*) &w, (int*) &h);
|
||||
|
||||
filamat::MaterialBuilder::init();
|
||||
|
||||
TestTexture matTexture {engine, 27, 27};
|
||||
|
||||
size_t const nrow = 10, ncol = 10;
|
||||
|
||||
uint32_t const iconWidth = 50;
|
||||
uint32_t const iconHeight = 50;
|
||||
|
||||
IconScene iconScene {engine, renderer, iconWidth, iconHeight, {.useSkybox=false} };
|
||||
|
||||
auto buildTargets = [nrow, ncol, engine]() {
|
||||
std::vector<std::vector<Texture*>> targets;
|
||||
for (size_t r = 0; r < nrow; r++) {
|
||||
std::vector<Texture*> row;
|
||||
for (size_t c = 0; c < ncol; c++) {
|
||||
TestTexture ttex {engine, iconWidth, iconHeight, true };
|
||||
row.push_back(ttex.get());
|
||||
}
|
||||
targets.push_back(row);
|
||||
}
|
||||
return targets;
|
||||
};
|
||||
|
||||
auto cleanup = [&app](Engine* engine, View*, Scene*) {
|
||||
engine->destroy(app.skybox);
|
||||
engine->destroy(app.renderable);
|
||||
engine->destroy(app.mat);
|
||||
engine->destroy(app.vb);
|
||||
engine->destroy(app.ib);
|
||||
engine->destroyCameraComponent(app.camera);
|
||||
utils::EntityManager::get().destroy(app.camera);
|
||||
};
|
||||
std::vector<std::vector<Texture*>> targets0 = buildTargets();
|
||||
std::vector<std::vector<Texture*>> targets1 = buildTargets();
|
||||
std::vector<std::vector<Texture*>> targets2 = buildTargets();
|
||||
|
||||
FilamentApp::get().animate([&app](Engine* engine, View* view, double now) {
|
||||
constexpr float ZOOM = 1.5f;
|
||||
const uint32_t w = view->getViewport().width;
|
||||
const uint32_t h = view->getViewport().height;
|
||||
const float aspect = (float) w / h;
|
||||
app.cam->setProjection(Camera::Projection::ORTHO,
|
||||
-aspect * ZOOM, aspect * ZOOM,
|
||||
-ZOOM, ZOOM, 0, 1);
|
||||
auto& tcm = engine->getTransformManager();
|
||||
tcm.setTransform(tcm.getInstance(app.renderable),
|
||||
filament::math::mat4f::rotation(now, filament::math::float3{ 0, 0, 1 }));
|
||||
});
|
||||
MainScene scene(engine, renderer, w, h, nrow, ncol);
|
||||
|
||||
FilamentApp::get().run(app.config, setup, cleanup);
|
||||
renderer->setClearOptions({.clear = false});
|
||||
float3 const a {.7, .3, .3};
|
||||
float3 const b {.3, .7, .3};
|
||||
std::vector<std::pair<size_t, size_t>> coords;
|
||||
for (size_t r = 0; r < nrow; r++) {
|
||||
for (size_t c = 0; c < ncol; c++) {
|
||||
coords.push_back({r, c});
|
||||
}
|
||||
}
|
||||
|
||||
IconScene swapChainScene{engine, renderer, w, h, {
|
||||
.border = 1.0f, .postProcessing = false}};
|
||||
|
||||
TestTexture mainTex{engine, w, h, true};
|
||||
auto mainRT = RenderTarget::Builder()
|
||||
.texture(RenderTarget::AttachmentPoint::COLOR, mainTex.get())
|
||||
.build(*engine);
|
||||
|
||||
bool closeWindow = false;
|
||||
size_t count = 0;
|
||||
while (!closeWindow && ++count) {
|
||||
constexpr int kMaxEvents = 16;
|
||||
SDL_Event events[kMaxEvents];
|
||||
int nevents = 0;
|
||||
while (nevents < kMaxEvents && SDL_PollEvent(&events[nevents]) != 0) {
|
||||
nevents++;
|
||||
}
|
||||
|
||||
// Now, loop over the events a second time for app-side processing.
|
||||
for (int i = 0; i < nevents; i++) {
|
||||
const SDL_Event& event = events[i];
|
||||
switch (event.type) {
|
||||
case SDL_QUIT:
|
||||
closeWindow = true;
|
||||
break;
|
||||
case SDL_WINDOWEVENT:
|
||||
switch (event.window.event) {
|
||||
case SDL_WINDOWEVENT_RESIZED:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
auto [r, c] = coords[count % coords.size()];
|
||||
float3 color0 = (r + c) % 2 == 0 ? a : b;
|
||||
float3 color1 = (r + c) % 2 == 0 ? b : a;
|
||||
auto rt0 = targets0[r][c];
|
||||
auto rt1 = targets1[r][c];
|
||||
auto rt2 = targets2[r][c];
|
||||
iconScene.render(matTexture.get(), rt0, color0);
|
||||
iconScene.render(rt0, rt1, color1);
|
||||
iconScene.render(rt1, rt2, float3 {.8});
|
||||
// engine->flushAndWait();
|
||||
scene.render(rt2, mainRT, r, c);
|
||||
// engine->flushAndWait();
|
||||
// engine->flush();
|
||||
// scene.renderToSwapChain(swapChain, rt1, r, c);
|
||||
|
||||
|
||||
if (count % 27 == 0) {
|
||||
swapChainScene.renderToSwapChain(swapChain, mainTex.get());
|
||||
}
|
||||
SDL_Delay(16);
|
||||
|
||||
// if (renderer->beginFrame(swapChain)) {
|
||||
// // for each View
|
||||
// renderer->render(scene.getView());
|
||||
// renderer->endFrame();
|
||||
// }
|
||||
|
||||
|
||||
// SDL_Delay(16);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
material {
|
||||
name : Icon,
|
||||
shadingModel : unlit,
|
||||
requires : [
|
||||
uv0
|
||||
],
|
||||
parameters : [
|
||||
{
|
||||
type : sampler2d,
|
||||
name : tex
|
||||
},
|
||||
{
|
||||
type : float3,
|
||||
name : multiplier
|
||||
}
|
||||
],
|
||||
}
|
||||
|
||||
fragment {
|
||||
void material(inout MaterialInputs material) {
|
||||
prepareMaterial(material);
|
||||
vec3 m = materialParams.multiplier;
|
||||
vec3 rgb = texture(materialParams_tex, getUV0()).rgb * m;
|
||||
material.baseColor = vec4(rgb, 1.0);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.54.3",
|
||||
"version": "1.54.1",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user