Compare commits

..
Author SHA1 Message Date
Benjamin Doherty e9f4433324 OpenGL: handle glFenceSync returning null 2025-02-06 10:25:32 -08:00
62 changed files with 520 additions and 972 deletions
+2 -1
View File
@@ -8,4 +8,5 @@ appropriate header in [RELEASE_NOTES.md](./RELEASE_NOTES.md).
## Release notes for next branch cut ## Release notes for next branch cut
- Support including PlatformMetal.h in C++ files. - matdbg: Add support for debugging ESSL 1.0 shaders
- backend: New platform API to better handle external textures [⚠️ **New Material Version**]
+2 -2
View File
@@ -31,7 +31,7 @@ repositories {
} }
dependencies { dependencies {
implementation 'com.google.android.filament:filament-android:1.57.0' implementation 'com.google.android.filament:filament-android:1.56.7'
} }
``` ```
@@ -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.57.0' pod 'Filament', '~> 1.56.7'
``` ```
## Documentation ## Documentation
-8
View File
@@ -7,14 +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 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.57.1
## v1.57.0
- matdbg: Add support for debugging ESSL 1.0 shaders
- backend: New platform API to better handle external textures [⚠️ **New Material Version**]
## v1.56.8 ## v1.56.8
@@ -329,18 +329,6 @@ Java_com_google_android_filament_MaterialInstance_nSetCullingMode(JNIEnv*,
instance->setCullingMode((MaterialInstance::CullingMode) cullingMode); instance->setCullingMode((MaterialInstance::CullingMode) cullingMode);
} }
extern "C"
JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetCullingModeSeparate(JNIEnv*, jclass,
jlong nativeMaterialInstance,
jlong colorPassCullingMode, jlong shadowPassCullingMode) {
MaterialInstance* instance = (MaterialInstance*) nativeMaterialInstance;
instance->setCullingMode(
(MaterialInstance::CullingMode) colorPassCullingMode,
(MaterialInstance::CullingMode) shadowPassCullingMode);
}
extern "C" extern "C"
JNIEXPORT void JNICALL JNIEXPORT void JNICALL
Java_com_google_android_filament_MaterialInstance_nSetColorWrite(JNIEnv*, Java_com_google_android_filament_MaterialInstance_nSetColorWrite(JNIEnv*,
@@ -517,14 +505,6 @@ Java_com_google_android_filament_MaterialInstance_nGetCullingMode(JNIEnv* env, j
return (jint)instance->getCullingMode(); return (jint)instance->getCullingMode();
} }
extern "C"
JNIEXPORT jint JNICALL
Java_com_google_android_filament_MaterialInstance_nGetShadowCullingMode(JNIEnv* env, jclass,
jlong nativeMaterialInstance) {
MaterialInstance* instance = (MaterialInstance*)nativeMaterialInstance;
return (jint)instance->getShadowCullingMode();
}
extern "C" extern "C"
JNIEXPORT jboolean JNICALL JNIEXPORT jboolean JNICALL
Java_com_google_android_filament_MaterialInstance_nIsColorWriteEnabled(JNIEnv* env, jclass clazz, Java_com_google_android_filament_MaterialInstance_nIsColorWriteEnabled(JNIEnv* env, jclass clazz,
@@ -556,20 +556,6 @@ public class MaterialInstance {
nSetCullingMode(getNativeObject(), mode.ordinal()); nSetCullingMode(getNativeObject(), mode.ordinal());
} }
/**
* Overrides the default triangle culling state that was set on the material separately for the
* color and shadow passes
*
* @see
* <a href="https://google.github.io/filament/Materials.html#materialdefinitions/materialblock/rasterization:culling">
* Rasterization: culling</a>
*/
public void setCullingMode(@NonNull Material.CullingMode colorPassCullingMode,
@NonNull Material.CullingMode shadowPassCullingMode) {
nSetCullingModeSeparate(getNativeObject(),
colorPassCullingMode.ordinal(), shadowPassCullingMode.ordinal());
}
/** /**
* Returns the face culling mode. * Returns the face culling mode.
*/ */
@@ -578,14 +564,6 @@ public class MaterialInstance {
return sCullingModeValues[nGetCullingMode(getNativeObject())]; return sCullingModeValues[nGetCullingMode(getNativeObject())];
} }
/**
* Returns the face culling mode for the shadow passes.
*/
@NonNull
public Material.CullingMode getShadowCullingMode() {
return sCullingModeValues[nGetShadowCullingMode(getNativeObject())];
}
/** /**
* Overrides the default color-buffer write state that was set on the material. * Overrides the default color-buffer write state that was set on the material.
* *
@@ -942,8 +920,6 @@ public class MaterialInstance {
private static native void nSetDoubleSided(long nativeMaterialInstance, boolean doubleSided); private static native void nSetDoubleSided(long nativeMaterialInstance, boolean doubleSided);
private static native void nSetCullingMode(long nativeMaterialInstance, long mode); private static native void nSetCullingMode(long nativeMaterialInstance, long mode);
private static native void nSetCullingModeSeparate(long nativeMaterialInstance,
long colorPassCullingMode, long shadowPassCullingMode);
private static native void nSetColorWrite(long nativeMaterialInstance, boolean enable); private static native void nSetColorWrite(long nativeMaterialInstance, boolean enable);
private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable); private static native void nSetDepthWrite(long nativeMaterialInstance, boolean enable);
private static native void nSetStencilWrite(long nativeMaterialInstance, boolean enable); private static native void nSetStencilWrite(long nativeMaterialInstance, boolean enable);
@@ -976,7 +952,6 @@ public class MaterialInstance {
private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterialInstance); private static native float nGetSpecularAntiAliasingThreshold(long nativeMaterialInstance);
private static native boolean nIsDoubleSided(long nativeMaterialInstance); private static native boolean nIsDoubleSided(long nativeMaterialInstance);
private static native int nGetCullingMode(long nativeMaterialInstance); private static native int nGetCullingMode(long nativeMaterialInstance);
private static native int nGetShadowCullingMode(long nativeMaterialInstance);
private static native boolean nIsColorWriteEnabled(long nativeMaterialInstance); private static native boolean nIsColorWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance); private static native boolean nIsDepthWriteEnabled(long nativeMaterialInstance);
private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance); private static native boolean nIsStencilWriteEnabled(long nativeMaterialInstance);
+1 -1
View File
@@ -1,5 +1,5 @@
GROUP=com.google.android.filament GROUP=com.google.android.filament
VERSION_NAME=1.57.0 VERSION_NAME=1.56.7
POM_DESCRIPTION=Real-time physically based rendering engine for Android. POM_DESCRIPTION=Real-time physically based rendering engine for Android.
+1 -5
View File
@@ -79,10 +79,6 @@ public:
void clear() noexcept; void clear() noexcept;
void reset(ExternalImage* UTILS_NULLABLE p) noexcept; void reset(ExternalImage* UTILS_NULLABLE p) noexcept;
private:
friend utils::io::ostream& operator<<(utils::io::ostream& out,
ExternalImageHandle const& handle);
}; };
using ExternalImageHandleRef = ExternalImageHandle const&; using ExternalImageHandleRef = ExternalImageHandle const&;
@@ -169,7 +165,7 @@ public:
* *
* @return nullptr on failure, or a pointer to the newly created driver. * @return nullptr on failure, or a pointer to the newly created driver.
*/ */
virtual Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext, virtual backend::Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
const DriverConfig& driverConfig) noexcept = 0; const DriverConfig& driverConfig) noexcept = 0;
/** /**
@@ -23,7 +23,6 @@
#include <utils/compiler.h> #include <utils/compiler.h>
#include <utils/Invocable.h> #include <utils/Invocable.h>
#include <utils/CString.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
@@ -57,18 +56,6 @@ public:
unsigned int id; // GLuint id unsigned int id; // GLuint id
}; };
/**
* Return the OpenGL vendor string of the specified Driver instance.
* @return The GL_VENDOR string
*/
static utils::CString getVendorString(Driver const* UTILS_NONNULL driver);
/**
* Return the OpenGL vendor string of the specified Driver instance
* @return The GL_RENDERER string
*/
static utils::CString getRendererString(Driver const* UTILS_NONNULL driver);
/** /**
* Called by the driver to destroy the OpenGL context. This should clean up any windows * Called by the driver to destroy the OpenGL context. This should clean up any windows
* or buffers from initialization. This is for instance where `eglDestroyContext` would be * or buffers from initialization. This is for instance where `eglDestroyContext` would be
@@ -17,6 +17,7 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H #ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H #define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h> #include <backend/platforms/OpenGLPlatform.h>
#include <stdint.h> #include <stdint.h>
@@ -80,7 +80,8 @@ protected:
* Initializes EGL, creates the OpenGL context and returns a concrete Driver implementation * Initializes EGL, creates the OpenGL context and returns a concrete Driver implementation
* that supports OpenGL/OpenGL ES. * that supports OpenGL/OpenGL ES.
*/ */
Driver* createDriver(void* sharedContext, const DriverConfig& driverConfig) noexcept override; Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
/** /**
* This returns zero. This method can be overridden to return something more useful. * This returns zero. This method can be overridden to return something more useful.
@@ -1,38 +0,0 @@
/*
* 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_PRIVATE_PLATFORMMETAL_OBJC_H
#define TNT_FILAMENT_BACKEND_PRIVATE_PLATFORMMETAL_OBJC_H
#import <Metal/Metal.h>
namespace filament::backend {
struct MetalDevice {
id<MTLDevice> device;
};
struct MetalCommandQueue {
id<MTLCommandQueue> commandQueue;
};
struct MetalCommandBuffer {
id<MTLCommandBuffer> commandBuffer;
};
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRIVATE_PLATFORMMETAL_OBJC_H
@@ -20,17 +20,12 @@
#include <backend/DriverEnums.h> #include <backend/DriverEnums.h>
#include <backend/Platform.h> #include <backend/Platform.h>
#import <Metal/Metal.h>
namespace filament::backend { namespace filament::backend {
struct PlatformMetalImpl; struct PlatformMetalImpl;
// In order for this header to be compatible with Objective-C and C++, we use these wrappers around
// id<MTL*> objects.
// See PlatformMetal-Objc.h.
struct MetalDevice;
struct MetalCommandQueue;
struct MetalCommandBuffer;
class PlatformMetal final : public Platform { class PlatformMetal final : public Platform {
public: public:
PlatformMetal(); PlatformMetal();
@@ -46,22 +41,21 @@ public:
* free to decide which one to use. On mobile systems with a single GPU, implementations should * free to decide which one to use. On mobile systems with a single GPU, implementations should
* simply return the result of MTLCreateSystemDefaultDevice(); * simply return the result of MTLCreateSystemDefaultDevice();
*/ */
virtual void createDevice(MetalDevice& outDevice) noexcept; virtual id<MTLDevice> createDevice() noexcept;
/** /**
* Create a command submission queue on the Metal device object. * Create a command submission queue on the Metal device object.
* *
* @param device The device which was returned from createDevice() * @param device The device which was returned from createDevice()
*/ */
virtual void createCommandQueue( virtual id<MTLCommandQueue> createCommandQueue(id<MTLDevice> device) noexcept;
MetalDevice& device, MetalCommandQueue& outCommandQueue) noexcept;
/** /**
* Obtain a MTLCommandBuffer enqueued on this Platform's MTLCommandQueue. The command buffer is * Obtain a MTLCommandBuffer enqueued on this Platform's MTLCommandQueue. The command buffer is
* guaranteed to execute before all subsequent command buffers created either by Filament, or * guaranteed to execute before all subsequent command buffers created either by Filament, or
* further calls to this method. * further calls to this method.
*/ */
void createAndEnqueueCommandBuffer(MetalCommandBuffer& outCommandBuffer) noexcept; id<MTLCommandBuffer> createAndEnqueueCommandBuffer() noexcept;
/** /**
* The action to take if a Drawable cannot be acquired. * The action to take if a Drawable cannot be acquired.
@@ -71,9 +71,6 @@ public:
// where the gpu only has one graphics queue. Then the client needs to ensure that no // where the gpu only has one graphics queue. Then the client needs to ensure that no
// concurrent access can occur. // concurrent access can occur.
uint32_t graphicsQueueIndex = 0xFFFFFFFF; uint32_t graphicsQueueIndex = 0xFFFFFFFF;
bool debugUtilsSupported = false;
bool debugMarkersSupported = false;
bool multiviewSupported = false;
}; };
/** /**
@@ -91,7 +88,6 @@ public:
VkFormat colorFormat = VK_FORMAT_UNDEFINED; VkFormat colorFormat = VK_FORMAT_UNDEFINED;
VkFormat depthFormat = VK_FORMAT_UNDEFINED; VkFormat depthFormat = VK_FORMAT_UNDEFINED;
VkExtent2D extent = {0, 0}; VkExtent2D extent = {0, 0};
uint32_t layerCount = 1;
bool isProtected = false; bool isProtected = false;
}; };
@@ -307,11 +303,6 @@ public:
*/ */
uint32_t height; uint32_t height;
/**
* The layerCount of the external image
*/
uint32_t layerCount;
/** /**
* The layer count of the external image * The layer count of the external image
*/ */
@@ -50,7 +50,7 @@
#include <stdint.h> #include <stdint.h>
// Set to true to print every command out on log.d. This requires RTTI and DEBUG // Set to true to print every command out on log.d. This requires RTTI and DEBUG
#define DEBUG_COMMAND_STREAM true #define DEBUG_COMMAND_STREAM false
namespace filament::backend { namespace filament::backend {
+7 -16
View File
@@ -35,13 +35,12 @@ void Platform::ExternalImageHandle::incref(ExternalImage* p) noexcept {
void Platform::ExternalImageHandle::decref(ExternalImage* p) noexcept { void Platform::ExternalImageHandle::decref(ExternalImage* p) noexcept {
if (p) { if (p) {
// When decrementing the ref-count, unless it reaches zero, there is no need to acquire // When decrementing the ref-count, unless it reaches zero, there is no need to acquire data; we need to
// data; we need to release all previous writes though so they can be visible to the thread // release all previous writes though so they can be visible to the thread that will actually delete the
// that will actually delete the object. // object.
if (p->mRefCount.fetch_sub(1, std::memory_order_release) == 1) { if (p->mRefCount.fetch_sub(1, std::memory_order_release) == 1) {
// if we reach zero, we're about to delete the object, we need to acquire all previous // if we reach zero, we're about to delete the object, we need to acquire all previous writes from other
// writes from other threads (i.e.: the memory from other threads prior to the decref() // threads (i.e.: the memory from other threads prior to the decref() need to be visible now.
// need to be visible now.
std::atomic_thread_fence(std::memory_order_acquire); std::atomic_thread_fence(std::memory_order_acquire);
delete p; delete p;
} }
@@ -69,8 +68,7 @@ Platform::ExternalImageHandle::ExternalImageHandle(ExternalImageHandle&& rhs) no
rhs.mTarget = nullptr; rhs.mTarget = nullptr;
} }
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=( Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(ExternalImageHandle const& rhs) noexcept {
ExternalImageHandle const& rhs) noexcept {
if (UTILS_LIKELY(this != &rhs)) { if (UTILS_LIKELY(this != &rhs)) {
incref(rhs.mTarget); incref(rhs.mTarget);
decref(mTarget); decref(mTarget);
@@ -79,8 +77,7 @@ Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(
return *this; return *this;
} }
Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=( Platform::ExternalImageHandle& Platform::ExternalImageHandle::operator=(ExternalImageHandle&& rhs) noexcept {
ExternalImageHandle&& rhs) noexcept {
if (UTILS_LIKELY(this != &rhs)) { if (UTILS_LIKELY(this != &rhs)) {
decref(mTarget); decref(mTarget);
mTarget = rhs.mTarget; mTarget = rhs.mTarget;
@@ -100,12 +97,6 @@ void Platform::ExternalImageHandle::reset(ExternalImage* p) noexcept {
mTarget = p; mTarget = p;
} }
utils::io::ostream& operator<<(utils::io::ostream& out,
Platform::ExternalImageHandle const& handle) {
out << "ExternalImageHandle{" << handle.mTarget << "}";
return out;
}
// -------------------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------------------
Platform::ExternalImage::~ExternalImage() noexcept = default; Platform::ExternalImage::~ExternalImage() noexcept = default;
+2 -11
View File
@@ -31,7 +31,6 @@
#include "MetalTimerQuery.h" #include "MetalTimerQuery.h"
#include <backend/platforms/PlatformMetal.h> #include <backend/platforms/PlatformMetal.h>
#include <backend/platforms/PlatformMetal-ObjC.h>
#include <CoreVideo/CVMetalTexture.h> #include <CoreVideo/CVMetalTexture.h>
#include <CoreVideo/CVPixelBuffer.h> #include <CoreVideo/CVPixelBuffer.h>
@@ -121,10 +120,7 @@ MetalDriver::MetalDriver(
TrackedMetalBuffer::setPlatform(platform); TrackedMetalBuffer::setPlatform(platform);
ScopedAllocationTimer::setPlatform(platform); ScopedAllocationTimer::setPlatform(platform);
MetalDevice device; mContext->device = mPlatform.createDevice();
device.device = nil;
mPlatform.createDevice(device);
mContext->device = device.device;
assert_invariant(mContext->device); assert_invariant(mContext->device);
mContext->emptyBuffer = [mContext->device newBufferWithLength:16 mContext->emptyBuffer = [mContext->device newBufferWithLength:16
@@ -190,12 +186,7 @@ MetalDriver::MetalDriver(
[mContext->device.name containsString:@"Apple A8 GPU"] || [mContext->device.name containsString:@"Apple A8 GPU"] ||
[mContext->device.name containsString:@"Apple A7 GPU"]; [mContext->device.name containsString:@"Apple A7 GPU"];
MetalCommandQueue commandQueue; mContext->commandQueue = mPlatform.createCommandQueue(mContext->device);
commandQueue.commandQueue = nil;
mPlatform.createCommandQueue(device, commandQueue);
assert_invariant(commandQueue.commandQueue);
mContext->commandQueue = commandQueue.commandQueue;
mContext->pipelineStateCache.setDevice(mContext->device); mContext->pipelineStateCache.setDevice(mContext->device);
mContext->depthStencilStateCache.setDevice(mContext->device); mContext->depthStencilStateCache.setDevice(mContext->device);
mContext->samplerStateCache.setDevice(mContext->device); mContext->samplerStateCache.setDevice(mContext->device);
+7 -9
View File
@@ -15,7 +15,6 @@
*/ */
#include <backend/platforms/PlatformMetal.h> #include <backend/platforms/PlatformMetal.h>
#include <backend/platforms/PlatformMetal-ObjC.h>
#include "MetalDriverFactory.h" #include "MetalDriverFactory.h"
@@ -48,7 +47,7 @@ Driver* PlatformMetal::createDriver(void* /*sharedContext*/, const Platform::Dri
return MetalDriverFactory::create(this, driverConfig); return MetalDriverFactory::create(this, driverConfig);
} }
void PlatformMetal::createDevice(MetalDevice& outDevice) noexcept { id<MTLDevice> PlatformMetal::createDevice() noexcept {
id<MTLDevice> result; id<MTLDevice> result;
#if !defined(FILAMENT_IOS) #if !defined(FILAMENT_IOS)
@@ -73,20 +72,19 @@ void PlatformMetal::createDevice(MetalDevice& outDevice) noexcept {
<< [result.name cStringUsingEncoding:NSUTF8StringEncoding] << "'" << [result.name cStringUsingEncoding:NSUTF8StringEncoding] << "'"
<< utils::io::endl; << utils::io::endl;
outDevice.device = result; return result;
} }
void PlatformMetal::createCommandQueue( id<MTLCommandQueue> PlatformMetal::createCommandQueue(id<MTLDevice> device) noexcept {
MetalDevice& device, MetalCommandQueue& outCommandQueue) noexcept { pImpl->mCommandQueue = [device newCommandQueue];
pImpl->mCommandQueue = [device.device newCommandQueue];
pImpl->mCommandQueue.label = @"Filament"; pImpl->mCommandQueue.label = @"Filament";
outCommandQueue.commandQueue = pImpl->mCommandQueue; return pImpl->mCommandQueue;
} }
void PlatformMetal::createAndEnqueueCommandBuffer(MetalCommandBuffer& outCommandBuffer) noexcept { id<MTLCommandBuffer> PlatformMetal::createAndEnqueueCommandBuffer() noexcept {
id<MTLCommandBuffer> commandBuffer = [pImpl->mCommandQueue commandBuffer]; id<MTLCommandBuffer> commandBuffer = [pImpl->mCommandQueue commandBuffer];
[commandBuffer enqueue]; [commandBuffer enqueue];
outCommandBuffer.commandBuffer = commandBuffer; return commandBuffer;
} }
void PlatformMetal::setDrawableFailureBehavior(DrawableFailureBehavior behavior) noexcept { void PlatformMetal::setDrawableFailureBehavior(DrawableFailureBehavior behavior) noexcept {
-3
View File
@@ -14,9 +14,6 @@
* limitations under the License. * limitations under the License.
*/ */
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include "noop/NoopDriver.h" #include "noop/NoopDriver.h"
#include "CommandStreamDispatcher.h" #include "CommandStreamDispatcher.h"
+50 -44
View File
@@ -39,7 +39,6 @@
#include <backend/Program.h> #include <backend/Program.h>
#include <backend/TargetBufferInfo.h> #include <backend/TargetBufferInfo.h>
#include "private/backend/CommandStream.h"
#include "private/backend/Dispatcher.h" #include "private/backend/Dispatcher.h"
#include "private/backend/DriverApi.h" #include "private/backend/DriverApi.h"
@@ -47,11 +46,9 @@
#include <utils/BitmaskEnum.h> #include <utils/BitmaskEnum.h>
#include <utils/FixedCapacityVector.h> #include <utils/FixedCapacityVector.h>
#include <utils/CString.h> #include <utils/CString.h>
#include <utils/Invocable.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <utils/Panic.h> #include <utils/Panic.h>
#include <utils/Systrace.h> #include <utils/Systrace.h>
#include <utils/Slice.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>
@@ -157,8 +154,8 @@ using namespace GLUtils;
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
UTILS_NOINLINE UTILS_NOINLINE
OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* const platform, Driver* OpenGLDriver::create(OpenGLPlatform* const platform,
void* const /*sharedGLContext*/, const Platform::DriverConfig& driverConfig) noexcept { void* const sharedGLContext, const Platform::DriverConfig& driverConfig) noexcept {
assert_invariant(platform); assert_invariant(platform);
OpenGLPlatform* const ec = platform; OpenGLPlatform* const ec = platform;
@@ -225,7 +222,7 @@ OpenGLDriver* OpenGLDriver::create(OpenGLPlatform* const platform,
} }
#endif #endif
constexpr size_t defaultSize = FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U; size_t const defaultSize = FILAMENT_OPENGL_HANDLE_ARENA_SIZE_IN_MB * 1024U * 1024U;
Platform::DriverConfig validConfig{ driverConfig }; Platform::DriverConfig validConfig{ driverConfig };
validConfig.handleArenaSize = std::max(driverConfig.handleArenaSize, defaultSize); validConfig.handleArenaSize = std::max(driverConfig.handleArenaSize, defaultSize);
OpenGLDriver* const driver = new(std::nothrow) OpenGLDriver(ec, validConfig); OpenGLDriver* const driver = new(std::nothrow) OpenGLDriver(ec, validConfig);
@@ -280,6 +277,7 @@ OpenGLDriver::OpenGLDriver(OpenGLPlatform* platform, const Platform::DriverConfi
driverConfig.disableHandleUseAfterFreeCheck), driverConfig.disableHandleUseAfterFreeCheck),
mDriverConfig(driverConfig), mDriverConfig(driverConfig),
mCurrentPushConstants(new(std::nothrow) PushConstantBundle{}) { mCurrentPushConstants(new(std::nothrow) PushConstantBundle{}) {
// set a reasonable default value for our stream array // set a reasonable default value for our stream array
mTexturesWithStreamsAttached.reserve(8); mTexturesWithStreamsAttached.reserve(8);
mStreamsWithPendingAcquiredImage.reserve(8); mStreamsWithPendingAcquiredImage.reserve(8);
@@ -368,8 +366,8 @@ void OpenGLDriver::bindSampler(GLuint unit, GLuint sampler) noexcept {
mContext.bindSampler(unit, sampler); mContext.bindSampler(unit, sampler);
} }
void OpenGLDriver::setPushConstant(ShaderStage stage, uint8_t index, void OpenGLDriver::setPushConstant(backend::ShaderStage stage, uint8_t index,
PushConstantVariant value) { backend::PushConstantVariant value) {
assert_invariant(stage == ShaderStage::VERTEX || stage == ShaderStage::FRAGMENT); assert_invariant(stage == ShaderStage::VERTEX || stage == ShaderStage::FRAGMENT);
#if FILAMENT_ENABLE_MATDBG #if FILAMENT_ENABLE_MATDBG
@@ -378,7 +376,7 @@ void OpenGLDriver::setPushConstant(ShaderStage stage, uint8_t index,
} }
#endif #endif
Slice<std::pair<GLint, ConstantType>> constants; utils::Slice<std::pair<GLint, ConstantType>> constants;
if (stage == ShaderStage::VERTEX) { if (stage == ShaderStage::VERTEX) {
constants = mCurrentPushConstants->vertexConstants; constants = mCurrentPushConstants->vertexConstants;
} else if (stage == ShaderStage::FRAGMENT) { } else if (stage == ShaderStage::FRAGMENT) {
@@ -683,7 +681,7 @@ void OpenGLDriver::createBufferObjectR(Handle<HwBufferObject> boh,
bo->gl.buffer = malloc(byteCount); bo->gl.buffer = malloc(byteCount);
memset(bo->gl.buffer, 0, byteCount); memset(bo->gl.buffer, 0, byteCount);
} else { } else {
bo->gl.binding = getBufferBindingType(bindingType); bo->gl.binding = GLUtils::getBufferBindingType(bindingType);
glGenBuffers(1, &bo->gl.id); glGenBuffers(1, &bo->gl.id);
gl.bindBuffer(bo->gl.binding, bo->gl.id); gl.bindBuffer(bo->gl.binding, bo->gl.id);
glBufferData(bo->gl.binding, byteCount, nullptr, getBufferUsage(usage)); glBufferData(bo->gl.binding, byteCount, nullptr, getBufferUsage(usage));
@@ -760,7 +758,7 @@ void OpenGLDriver::createProgramR(Handle<HwProgram> ph, Program&& program) {
} }
UTILS_NOINLINE UTILS_NOINLINE
void OpenGLDriver::textureStorage(GLTexture* t, void OpenGLDriver::textureStorage(OpenGLDriver::GLTexture* t,
uint32_t width, uint32_t height, uint32_t depth, bool useProtectedMemory) noexcept { uint32_t width, uint32_t height, uint32_t depth, bool useProtectedMemory) noexcept {
auto& gl = mContext; auto& gl = mContext;
@@ -1146,7 +1144,7 @@ void OpenGLDriver::createTextureExternalImageR(Handle<HwTexture> th, SamplerType
} }
void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th, void OpenGLDriver::createTextureExternalImagePlaneR(Handle<HwTexture> th,
TextureFormat format, uint32_t width, uint32_t height, TextureUsage usage, backend::TextureFormat format, uint32_t width, uint32_t height, backend::TextureUsage usage,
void* image, uint32_t plane) { void* image, uint32_t plane) {
// not relevant for the OpenGL backend // not relevant for the OpenGL backend
} }
@@ -1462,7 +1460,7 @@ void OpenGLDriver::framebufferTexture(TargetBufferInfo const& binfo,
&& ((gl.ext.EXT_multisampled_render_to_texture && attachment == GL_COLOR_ATTACHMENT0) && ((gl.ext.EXT_multisampled_render_to_texture && attachment == GL_COLOR_ATTACHMENT0)
|| gl.ext.EXT_multisampled_render_to_texture2)) { || gl.ext.EXT_multisampled_render_to_texture2)) {
assert_invariant(rt->gl.samples > 1); assert_invariant(rt->gl.samples > 1);
// We have a multi-sample rendertarget, and we have EXT_multisampled_render_to_texture, // We have a multi-sample rendertarget and we have EXT_multisampled_render_to_texture,
// so, we can directly use a 1-sample texture as attachment, multi-sample resolve, // so, we can directly use a 1-sample texture as attachment, multi-sample resolve,
// will happen automagically and efficiently in the driver. // will happen automagically and efficiently in the driver.
// This extension only exists on OpenGL ES. // This extension only exists on OpenGL ES.
@@ -1662,9 +1660,9 @@ void OpenGLDriver::createRenderTargetR(Handle<HwRenderTarget> rth,
rt->gl.samples = samples; rt->gl.samples = samples;
rt->targets = targets; rt->targets = targets;
UTILS_UNUSED_IN_RELEASE vec2<uint32_t> tmin = { std::numeric_limits<uint32_t>::max() }; UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmin = { std::numeric_limits<uint32_t>::max() };
UTILS_UNUSED_IN_RELEASE vec2<uint32_t> tmax = { 0 }; UTILS_UNUSED_IN_RELEASE math::vec2<uint32_t> tmax = { 0 };
auto checkDimensions = [&tmin, &tmax](GLTexture const* t, uint8_t level) { auto checkDimensions = [&tmin, &tmax](GLTexture* t, uint8_t level) {
const auto twidth = std::max(1u, t->width >> level); const auto twidth = std::max(1u, t->width >> level);
const auto theight = std::max(1u, t->height >> level); const auto theight = std::max(1u, t->height >> level);
tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) }; tmin = { std::min(tmin.x, twidth), std::min(tmin.y, theight) };
@@ -2366,11 +2364,11 @@ bool OpenGLDriver::isStereoSupported() {
return false; return false;
} }
switch (mDriverConfig.stereoscopicType) { switch (mDriverConfig.stereoscopicType) {
case StereoscopicType::INSTANCED: case backend::StereoscopicType::INSTANCED:
return mContext.ext.EXT_clip_cull_distance; return mContext.ext.EXT_clip_cull_distance;
case StereoscopicType::MULTIVIEW: case backend::StereoscopicType::MULTIVIEW:
return mContext.ext.OVR_multiview2; return mContext.ext.OVR_multiview2;
case StereoscopicType::NONE: case backend::StereoscopicType::NONE:
return false; return false;
} }
} }
@@ -2383,7 +2381,7 @@ bool OpenGLDriver::isDepthStencilResolveSupported() {
return true; return true;
} }
bool OpenGLDriver::isDepthStencilBlitSupported(TextureFormat) { bool OpenGLDriver::isDepthStencilBlitSupported(TextureFormat format) {
return true; return true;
} }
@@ -2417,12 +2415,12 @@ FeatureLevel OpenGLDriver::getFeatureLevel() {
return mContext.getFeatureLevel(); return mContext.getFeatureLevel();
} }
float2 OpenGLDriver::getClipSpaceParams() { math::float2 OpenGLDriver::getClipSpaceParams() {
return mContext.ext.EXT_clip_control ? return mContext.ext.EXT_clip_control ?
// z-coordinate of virtual and physical clip-space is in [-w, 0] // z-coordinate of virtual and physical clip-space is in [-w, 0]
float2{ 1.0f, 0.0f } : math::float2{ 1.0f, 0.0f } :
// z-coordinate of virtual clip-space is in [-w,0], physical is in [-w, w] // z-coordinate of virtual clip-space is in [-w,0], physical is in [-w, w]
float2{ 2.0f, -1.0f }; math::float2{ 2.0f, -1.0f };
} }
uint8_t OpenGLDriver::getMaxDrawBuffers() { uint8_t OpenGLDriver::getMaxDrawBuffers() {
@@ -2486,7 +2484,7 @@ void OpenGLDriver::makeCurrent(Handle<HwSwapChain> schDraw, Handle<HwSwapChain>
// Updating driver objects // Updating driver objects
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, CString tag) { void OpenGLDriver::setDebugTag(HandleBase::HandleId handleId, utils::CString tag) {
mHandleAllocator.associateTagToHandle(handleId, std::move(tag)); mHandleAllocator.associateTagToHandle(handleId, std::move(tag));
} }
@@ -2662,7 +2660,7 @@ void OpenGLDriver::generateMipmaps(Handle<HwTexture> th) {
CHECK_GL_ERROR(utils::slog.e) CHECK_GL_ERROR(utils::slog.e)
} }
void OpenGLDriver::setTextureData(GLTexture const* t, uint32_t level, void OpenGLDriver::setTextureData(GLTexture* t, uint32_t level,
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
uint32_t width, uint32_t height, uint32_t depth, uint32_t width, uint32_t height, uint32_t depth,
PixelBufferDescriptor&& p) { PixelBufferDescriptor&& p) {
@@ -2771,7 +2769,7 @@ void OpenGLDriver::setTextureData(GLTexture const* t, uint32_t level,
CHECK_GL_ERROR(utils::slog.e) CHECK_GL_ERROR(utils::slog.e)
} }
void OpenGLDriver::setCompressedTextureData(GLTexture const* t, uint32_t level, void OpenGLDriver::setCompressedTextureData(GLTexture* t, uint32_t level,
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
uint32_t width, uint32_t height, uint32_t depth, uint32_t width, uint32_t height, uint32_t depth,
PixelBufferDescriptor&& p) { PixelBufferDescriptor&& p) {
@@ -3412,8 +3410,8 @@ void OpenGLDriver::readPixels(Handle<HwRenderTarget> src,
#endif #endif
} }
void OpenGLDriver::readBufferSubData(BufferObjectHandle boh, void OpenGLDriver::readBufferSubData(backend::BufferObjectHandle boh,
uint32_t offset, uint32_t size, BufferDescriptor&& p) { uint32_t offset, uint32_t size, backend::BufferDescriptor&& p) {
UTILS_UNUSED_IN_RELEASE auto& gl = mContext; UTILS_UNUSED_IN_RELEASE auto& gl = mContext;
assert_invariant(!gl.isES2()); assert_invariant(!gl.isES2());
@@ -3491,6 +3489,14 @@ 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);
// glFenceSync can return 0 in certain situations. For example, we've seen this happen on Web
// when the GL context has been lost.
// Unfortunately, there's not much we can do here. The fn callback will never execute, which
// could cause issues. If we've lost the WebGL context though, Filament is most likely shutting
// down anyway, so in practice this might not be a big problem.
if (!sync) {
return;
}
mGpuCommandCompleteOps.emplace_back(sync, fn); mGpuCommandCompleteOps.emplace_back(sync, fn);
CHECK_GL_ERROR(utils::slog.e) CHECK_GL_ERROR(utils::slog.e)
} }
@@ -3560,13 +3566,13 @@ void OpenGLDriver::beginFrame(
} }
} }
void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain>, CallbackHandler*, void OpenGLDriver::setFrameScheduledCallback(Handle<HwSwapChain> sch, CallbackHandler* handler,
FrameScheduledCallback&& /*callback*/, uint64_t /*flags*/) { FrameScheduledCallback&& callback, uint64_t flags) {
DEBUG_MARKER() DEBUG_MARKER()
} }
void OpenGLDriver::setFrameCompletedCallback(Handle<HwSwapChain>, void OpenGLDriver::setFrameCompletedCallback(Handle<HwSwapChain> sch,
CallbackHandler*, Invocable<void()>&& /*callback*/) { CallbackHandler* handler, utils::Invocable<void(void)>&& callback) {
DEBUG_MARKER() DEBUG_MARKER()
} }
@@ -3597,9 +3603,9 @@ void OpenGLDriver::endFrame(UTILS_UNUSED uint32_t frameId) {
} }
void OpenGLDriver::updateDescriptorSetBuffer( void OpenGLDriver::updateDescriptorSetBuffer(
DescriptorSetHandle dsh, backend::DescriptorSetHandle dsh,
descriptor_binding_t binding, backend::descriptor_binding_t binding,
BufferObjectHandle boh, backend::BufferObjectHandle boh,
uint32_t offset, uint32_t size) { uint32_t offset, uint32_t size) {
GLDescriptorSet* ds = handle_cast<GLDescriptorSet*>(dsh); GLDescriptorSet* ds = handle_cast<GLDescriptorSet*>(dsh);
GLBufferObject* bo = boh ? handle_cast<GLBufferObject*>(boh) : nullptr; GLBufferObject* bo = boh ? handle_cast<GLBufferObject*>(boh) : nullptr;
@@ -3607,9 +3613,9 @@ void OpenGLDriver::updateDescriptorSetBuffer(
} }
void OpenGLDriver::updateDescriptorSetTexture( void OpenGLDriver::updateDescriptorSetTexture(
DescriptorSetHandle dsh, backend::DescriptorSetHandle dsh,
descriptor_binding_t binding, backend::descriptor_binding_t binding,
TextureHandle th, backend::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; GLTexture* t = th ? handle_cast<GLTexture*>(th) : nullptr;
@@ -3642,7 +3648,7 @@ void OpenGLDriver::finish(int) {
UTILS_NOINLINE UTILS_NOINLINE
void OpenGLDriver::clearWithRasterPipe(TargetBufferFlags clearFlags, void OpenGLDriver::clearWithRasterPipe(TargetBufferFlags clearFlags,
float4 const& linearColor, GLfloat depth, GLint stencil) noexcept { math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept {
if (any(clearFlags & TargetBufferFlags::COLOR_ALL)) { if (any(clearFlags & TargetBufferFlags::COLOR_ALL)) {
mContext.colorMask(GL_TRUE); mContext.colorMask(GL_TRUE);
@@ -3965,9 +3971,9 @@ void OpenGLDriver::bindRenderPrimitive(Handle<HwRenderPrimitive> rph) {
} }
void OpenGLDriver::bindDescriptorSet( void OpenGLDriver::bindDescriptorSet(
DescriptorSetHandle dsh, backend::DescriptorSetHandle dsh,
descriptor_set_t set, backend::descriptor_set_t set,
DescriptorSetOffsetArray&& offsets) { backend::DescriptorSetOffsetArray&& offsets) {
if (UTILS_UNLIKELY(!dsh)) { if (UTILS_UNLIKELY(!dsh)) {
mBoundDescriptorSets[set].dsh = dsh; mBoundDescriptorSets[set].dsh = dsh;
@@ -3999,7 +4005,7 @@ void OpenGLDriver::bindDescriptorSet(
} }
} }
void OpenGLDriver::updateDescriptors(bitset8 invalidDescriptorSets) noexcept { void OpenGLDriver::updateDescriptors(utils::bitset8 invalidDescriptorSets) noexcept {
assert_invariant(mBoundProgram); assert_invariant(mBoundProgram);
auto const offsetOnly = mInvalidDescriptorSetBindingOffsets & ~mInvalidDescriptorSetBindings; auto const offsetOnly = mInvalidDescriptorSetBindingOffsets & ~mInvalidDescriptorSetBindings;
invalidDescriptorSets.forEachSetBit([this, offsetOnly, invalidDescriptorSets.forEachSetBit([this, offsetOnly,
@@ -4111,7 +4117,7 @@ void OpenGLDriver::draw(PipelineState state, Handle<HwRenderPrimitive> rph,
} }
} }
void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, uint3 workGroupCount) { void OpenGLDriver::dispatchCompute(Handle<HwProgram> program, math::uint3 workGroupCount) {
DEBUG_MARKER() DEBUG_MARKER()
getShaderCompilerService().tick(); getShaderCompilerService().tick();
+21 -30
View File
@@ -19,7 +19,6 @@
#include "DriverBase.h" #include "DriverBase.h"
#include "OpenGLContext.h" #include "OpenGLContext.h"
#include "OpenGLDriverBase.h"
#include "OpenGLTimerQuery.h" #include "OpenGLTimerQuery.h"
#include "GLBufferObject.h" #include "GLBufferObject.h"
#include "GLDescriptorSet.h" #include "GLDescriptorSet.h"
@@ -27,10 +26,11 @@
#include "GLTexture.h" #include "GLTexture.h"
#include "ShaderCompilerService.h" #include "ShaderCompilerService.h"
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/AcquiredImage.h> #include <backend/AcquiredImage.h>
#include <backend/DriverEnums.h> #include <backend/DriverEnums.h>
#include <backend/Handle.h> #include <backend/Handle.h>
#include <backend/PipelineState.h>
#include <backend/Platform.h> #include <backend/Platform.h>
#include <backend/Program.h> #include <backend/Program.h>
#include <backend/TargetBufferInfo.h> #include <backend/TargetBufferInfo.h>
@@ -41,7 +41,6 @@
#include <utils/bitset.h> #include <utils/bitset.h>
#include <utils/FixedCapacityVector.h> #include <utils/FixedCapacityVector.h>
#include <utils/compiler.h> #include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/debug.h> #include <utils/debug.h>
#include <math/vec4.h> #include <math/vec4.h>
@@ -75,14 +74,14 @@ class OpenGLProgram;
class TimerQueryFactoryInterface; class TimerQueryFactoryInterface;
struct PushConstantBundle; struct PushConstantBundle;
class OpenGLDriver final : public OpenGLDriverBase { class OpenGLDriver final : public DriverBase {
inline explicit OpenGLDriver(OpenGLPlatform* platform, inline explicit OpenGLDriver(OpenGLPlatform* platform,
const Platform::DriverConfig& driverConfig) noexcept; const Platform::DriverConfig& driverConfig) noexcept;
~OpenGLDriver() noexcept override; ~OpenGLDriver() noexcept final;
Dispatcher getDispatcher() const noexcept override; Dispatcher getDispatcher() const noexcept final;
public: public:
static OpenGLDriver* create(OpenGLPlatform* platform, void* sharedGLContext, static Driver* create(OpenGLPlatform* platform, void* sharedGLContext,
const Platform::DriverConfig& driverConfig) noexcept; const Platform::DriverConfig& driverConfig) noexcept;
class DebugMarker { class DebugMarker {
@@ -185,7 +184,7 @@ public:
std::condition_variable cond; std::condition_variable cond;
FenceStatus status{ FenceStatus::TIMEOUT_EXPIRED }; FenceStatus status{ FenceStatus::TIMEOUT_EXPIRED };
}; };
std::shared_ptr<State> state{ std::make_shared<State>() }; std::shared_ptr<State> state{ std::make_shared<GLFence::State>() };
}; };
OpenGLDriver(OpenGLDriver const&) = delete; OpenGLDriver(OpenGLDriver const&) = delete;
@@ -204,21 +203,13 @@ private:
return mShaderCompilerService; return mShaderCompilerService;
} }
ShaderModel getShaderModel() const noexcept override; ShaderModel getShaderModel() const noexcept final;
ShaderLanguage getShaderLanguage() const noexcept override; ShaderLanguage getShaderLanguage() const noexcept final;
/* /*
* OpenGLDriver interface * Driver interface
*/ */
utils::CString getVendorString() const noexcept override {
return utils::CString{ mContext.state.vendor };
}
utils::CString getRendererString() const noexcept override {
return utils::CString{ mContext.state.renderer };
}
template<typename T> template<typename T>
friend class ConcreteDispatcher; friend class ConcreteDispatcher;
@@ -245,21 +236,21 @@ private:
} }
template<typename D, typename B, typename ... ARGS> template<typename D, typename B, typename ... ARGS>
std::enable_if_t<std::is_base_of_v<B, D>, D>* typename std::enable_if<std::is_base_of<B, D>::value, D>::type*
construct(Handle<B> const& handle, ARGS&& ... args) { construct(Handle<B> const& handle, ARGS&& ... args) {
return mHandleAllocator.destroyAndConstruct<D, B>(handle, std::forward<ARGS>(args) ...); return mHandleAllocator.destroyAndConstruct<D, B>(handle, std::forward<ARGS>(args) ...);
} }
template<typename B, typename D, template<typename B, typename D,
typename = std::enable_if_t<std::is_base_of_v<B, D>, D>> typename = typename std::enable_if<std::is_base_of<B, D>::value, D>::type>
void destruct(Handle<B>& handle, D const* p) noexcept { void destruct(Handle<B>& handle, D const* p) noexcept {
return mHandleAllocator.deallocate(handle, p); return mHandleAllocator.deallocate(handle, p);
} }
template<typename Dp, typename B> template<typename Dp, typename B>
std::enable_if_t< typename std::enable_if_t<
std::is_pointer_v<Dp> && std::is_pointer_v<Dp> &&
std::is_base_of_v<B, std::remove_pointer_t<Dp>>, Dp> std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
handle_cast(Handle<B>& handle) { handle_cast(Handle<B>& handle) {
return mHandleAllocator.handle_cast<Dp, B>(handle); return mHandleAllocator.handle_cast<Dp, B>(handle);
} }
@@ -270,9 +261,9 @@ private:
} }
template<typename Dp, typename B> template<typename Dp, typename B>
std::enable_if_t< inline typename std::enable_if_t<
std::is_pointer_v<Dp> && std::is_pointer_v<Dp> &&
std::is_base_of_v<B, std::remove_pointer_t<Dp>>, Dp> std::is_base_of_v<B, typename std::remove_pointer_t<Dp>>, Dp>
handle_cast(Handle<B> const& handle) { handle_cast(Handle<B> const& handle) {
return mHandleAllocator.handle_cast<Dp, B>(handle); return mHandleAllocator.handle_cast<Dp, B>(handle);
} }
@@ -297,13 +288,13 @@ private:
void setStencilState(StencilState ss) noexcept; void setStencilState(StencilState ss) noexcept;
void setTextureData(GLTexture const* t, void setTextureData(GLTexture* t,
uint32_t level, uint32_t level,
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
uint32_t width, uint32_t height, uint32_t depth, uint32_t width, uint32_t height, uint32_t depth,
PixelBufferDescriptor&& p); PixelBufferDescriptor&& p);
void setCompressedTextureData(GLTexture const* t, void setCompressedTextureData(GLTexture* t,
uint32_t level, uint32_t level,
uint32_t xoffset, uint32_t yoffset, uint32_t zoffset, uint32_t xoffset, uint32_t yoffset, uint32_t zoffset,
uint32_t width, uint32_t height, uint32_t depth, uint32_t width, uint32_t height, uint32_t depth,
@@ -312,7 +303,7 @@ private:
void renderBufferStorage(GLuint rbo, GLenum internalformat, uint32_t width, void renderBufferStorage(GLuint rbo, GLenum internalformat, uint32_t width,
uint32_t height, uint8_t samples) const noexcept; uint32_t height, uint8_t samples) const noexcept;
void textureStorage(GLTexture* t, uint32_t width, uint32_t height, void textureStorage(OpenGLDriver::GLTexture* t, uint32_t width, uint32_t height,
uint32_t depth, bool useProtectedMemory) noexcept; uint32_t depth, bool useProtectedMemory) noexcept;
/* State tracking GL wrappers... */ /* State tracking GL wrappers... */
@@ -344,9 +335,9 @@ private:
void updateDescriptors(utils::bitset8 invalidDescriptorSets) noexcept; void updateDescriptors(utils::bitset8 invalidDescriptorSets) noexcept;
struct { struct {
DescriptorSetHandle dsh; backend::DescriptorSetHandle dsh;
std::array<uint32_t, CONFIG_UNIFORM_BINDING_COUNT> offsets; std::array<uint32_t, CONFIG_UNIFORM_BINDING_COUNT> offsets;
} mBoundDescriptorSets[MAX_DESCRIPTOR_SET_COUNT] = {}; } mBoundDescriptorSets[MAX_DESCRIPTOR_SET_COUNT];
void clearWithRasterPipe(TargetBufferFlags clearFlags, void clearWithRasterPipe(TargetBufferFlags clearFlags,
math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept; math::float4 const& linearColor, GLfloat depth, GLint stencil) noexcept;
@@ -1,37 +0,0 @@
/*
* 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_OPENGL_OPENGLDRIVERBASE_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGLDRIVERBASE_H
#include "DriverBase.h"
#include <utils/CString.h>
namespace filament::backend {
class OpenGLDriverBase : public DriverBase {
protected:
~OpenGLDriverBase() override;
public:
virtual utils::CString getVendorString() const noexcept = 0;
virtual utils::CString getRendererString() const noexcept = 0;
};
} // filament::backend
#endif //TNT_FILAMENT_BACKEND_OPENGL_OPENGLDRIVERBASE_H
+2 -27
View File
@@ -16,7 +16,6 @@
#include <backend/platforms/OpenGLPlatform.h> #include <backend/platforms/OpenGLPlatform.h>
#include "OpenGLDriverBase.h"
#include "OpenGLDriverFactory.h" #include "OpenGLDriverFactory.h"
#include <backend/AcquiredImage.h> #include <backend/AcquiredImage.h>
@@ -24,45 +23,21 @@
#include <backend/Platform.h> #include <backend/Platform.h>
#include <utils/compiler.h> #include <utils/compiler.h>
#include <utils/Panic.h>
#include <utils/CString.h>
#include <utils/Invocable.h>
#include <utils/Invocable.h>
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
#include "OpenGLDriver.h"
namespace filament::backend { namespace filament::backend {
OpenGLDriverBase::~OpenGLDriverBase() = default;
Driver* OpenGLPlatform::createDefaultDriver(OpenGLPlatform* platform, Driver* OpenGLPlatform::createDefaultDriver(OpenGLPlatform* platform,
void* sharedContext, const DriverConfig& driverConfig) { void* sharedContext, const Platform::DriverConfig& driverConfig) {
return OpenGLDriverFactory::create(platform, sharedContext, driverConfig); return OpenGLDriverFactory::create(platform, sharedContext, driverConfig);
} }
OpenGLPlatform::~OpenGLPlatform() noexcept = default; OpenGLPlatform::~OpenGLPlatform() noexcept = default;
utils::CString OpenGLPlatform::getVendorString(Driver const* driver) {
auto const p = static_cast<OpenGLDriverBase const*>(driver);
#if UTILS_HAS_RTTI
FILAMENT_CHECK_POSTCONDITION(dynamic_cast<OpenGLDriverBase const*>(driver))
<< "Driver* has not been allocated with OpenGLPlatform";
#endif
return p->getVendorString();
}
utils::CString OpenGLPlatform::getRendererString(Driver const* driver) {
auto const p = static_cast<OpenGLDriverBase const*>(driver);
#if UTILS_HAS_RTTI
FILAMENT_CHECK_POSTCONDITION(dynamic_cast<OpenGLDriverBase const*>(driver))
<< "Driver* has not been allocated with OpenGLPlatform";
#endif
return p->getRendererString();
}
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)>) noexcept {
makeCurrent(getCurrentContextType(), drawSwapChain, readSwapChain); makeCurrent(getCurrentContextType(), drawSwapChain, readSwapChain);
@@ -297,7 +297,7 @@ Driver* PlatformEGL::createDriver(void* sharedContext, const DriverConfig& drive
clearGlError(); clearGlError();
// success!! // success!!
return createDefaultDriver(this, sharedContext, driverConfig); return OpenGLPlatform::createDefaultDriver(this, sharedContext, driverConfig);
error: error:
// if we're here, we've failed // if we're here, we've failed
@@ -551,7 +551,7 @@ Platform::SwapChain* PlatformEGL::createSwapChain(
return sc; return sc;
} }
void PlatformEGL::destroySwapChain(SwapChain* swapChain) noexcept { void PlatformEGL::destroySwapChain(Platform::SwapChain* swapChain) noexcept {
if (swapChain) { if (swapChain) {
SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain); SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain);
if (sc->sur != EGL_NO_SURFACE) { if (sc->sur != EGL_NO_SURFACE) {
@@ -564,7 +564,7 @@ void PlatformEGL::destroySwapChain(SwapChain* swapChain) noexcept {
} }
} }
bool PlatformEGL::isSwapChainProtected(SwapChain* swapChain) noexcept { bool PlatformEGL::isSwapChainProtected(Platform::SwapChain* swapChain) noexcept {
if (swapChain) { if (swapChain) {
SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain); SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain);
return bool(sc->flags & SWAP_CHAIN_CONFIG_PROTECTED_CONTENT); return bool(sc->flags & SWAP_CHAIN_CONFIG_PROTECTED_CONTENT);
@@ -585,10 +585,10 @@ bool PlatformEGL::makeCurrent(ContextType type,
return success == EGL_TRUE ? true : false; return success == EGL_TRUE ? true : false;
} }
void PlatformEGL::makeCurrent(SwapChain* drawSwapChain, void PlatformEGL::makeCurrent(Platform::SwapChain* drawSwapChain,
SwapChain* readSwapChain, Platform::SwapChain* readSwapChain,
Invocable<void()> preContextChange, utils::Invocable<void()> preContextChange,
Invocable<void(size_t index)> postContextChange) noexcept { utils::Invocable<void(size_t index)> postContextChange) noexcept {
assert_invariant(drawSwapChain); assert_invariant(drawSwapChain);
assert_invariant(readSwapChain); assert_invariant(readSwapChain);
@@ -647,7 +647,7 @@ void PlatformEGL::makeCurrent(SwapChain* drawSwapChain,
} }
} }
void PlatformEGL::commit(SwapChain* swapChain) noexcept { void PlatformEGL::commit(Platform::SwapChain* swapChain) noexcept {
if (swapChain) { if (swapChain) {
SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain); SwapChainEGL const* const sc = static_cast<SwapChainEGL const*>(swapChain);
if (sc->sur != EGL_NO_SURFACE) { if (sc->sur != EGL_NO_SURFACE) {
@@ -670,7 +670,7 @@ Platform::Fence* PlatformEGL::createFence() noexcept {
return f; return f;
} }
void PlatformEGL::destroyFence(Fence* fence) noexcept { void PlatformEGL::destroyFence(Platform::Fence* fence) noexcept {
#ifdef EGL_KHR_reusable_sync #ifdef EGL_KHR_reusable_sync
EGLSyncKHR sync = (EGLSyncKHR) fence; EGLSyncKHR sync = (EGLSyncKHR) fence;
if (sync != EGL_NO_SYNC_KHR) { if (sync != EGL_NO_SYNC_KHR) {
@@ -680,7 +680,7 @@ void PlatformEGL::destroyFence(Fence* fence) noexcept {
} }
FenceStatus PlatformEGL::waitFence( FenceStatus PlatformEGL::waitFence(
Fence* fence, uint64_t timeout) noexcept { Platform::Fence* fence, uint64_t timeout) noexcept {
#ifdef EGL_KHR_reusable_sync #ifdef EGL_KHR_reusable_sync
EGLSyncKHR sync = (EGLSyncKHR) fence; EGLSyncKHR sync = (EGLSyncKHR) fence;
if (sync != EGL_NO_SYNC_KHR) { if (sync != EGL_NO_SYNC_KHR) {
@@ -746,7 +746,7 @@ void PlatformEGL::initializeGlExtensions() noexcept {
ext.gl.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3"); ext.gl.OES_EGL_image_external_essl3 = glExtensions.has("GL_OES_EGL_image_external_essl3");
} }
EGLContext PlatformEGL::getContextForType(ContextType type) const noexcept { EGLContext PlatformEGL::getContextForType(OpenGLPlatform::ContextType type) const noexcept {
switch (type) { switch (type) {
case ContextType::NONE: case ContextType::NONE:
return EGL_NO_CONTEXT; return EGL_NO_CONTEXT;
+2 -13
View File
@@ -163,24 +163,13 @@ public:
return mProtectedMemorySupported; return mProtectedMemorySupported;
} }
inline bool isImageView2DOn3DImageSupported() const noexcept {
return mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
}
private: private:
VkPhysicalDeviceMemoryProperties mMemoryProperties = {}; VkPhysicalDeviceMemoryProperties mMemoryProperties = {};
VkPhysicalDeviceProperties2 mPhysicalDeviceProperties = { VkPhysicalDeviceProperties2 mPhysicalDeviceProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2
}; };
VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures = { VkPhysicalDeviceFeatures2 mPhysicalDeviceFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2
};
VkPhysicalDevicePortabilitySubsetFeaturesKHR mPortabilitySubsetFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
// By default, on platforms where we don't have portability subset, then this feature must
// exists. We only fill this struct only when portability subset is needed (i.e.
// non-conformant vulkan implementation).
.imageView2DOn3DImage = VK_TRUE,
}; };
bool mDebugMarkersSupported = false; bool mDebugMarkersSupported = false;
bool mDebugUtilsSupported = false; bool mDebugUtilsSupported = false;
+1 -1
View File
@@ -579,7 +579,7 @@ void VulkanDriver::createTextureExternalImageR(Handle<HwTexture> th, backend::Sa
auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(), auto texture = resource_ptr<VulkanTexture>::make(&mResourceManager, th, mPlatform->getDevice(),
mAllocator, &mResourceManager, &mCommands, data.first, data.second, metadata.format, mAllocator, &mResourceManager, &mCommands, data.first, data.second, metadata.format,
1, metadata.width, metadata.height, /*depth=*/1, usage, mStagePool); 1, metadata.width, metadata.height, usage, mStagePool);
texture.inc(); texture.inc();
} }
+4 -12
View File
@@ -128,15 +128,6 @@ fvkmemory::resource_ptr<VulkanTexture> initMsaaTexture(
return msTexture; return msTexture;
} }
VulkanAttachment createSwapchainAttachment(const fvkmemory::resource_ptr<VulkanTexture> texture) {
return VulkanAttachment {
.texture = texture,
.level = 0,
.layerCount = static_cast<uint8_t>(texture ? texture->getPrimaryViewRange().layerCount : 1),
.layer = 0,
};
}
} // anonymous namespace } // anonymous namespace
void VulkanDescriptorSet::acquire(fvkmemory::resource_ptr<VulkanTexture> texture) { void VulkanDescriptorSet::acquire(fvkmemory::resource_ptr<VulkanTexture> texture) {
@@ -283,21 +274,22 @@ void VulkanRenderTarget::bindToSwapChain(fvkmemory::resource_ptr<VulkanSwapChain
height = extent.height; height = extent.height;
mProtected = swapchain->isProtected(); mProtected = swapchain->isProtected();
VulkanAttachment color = createSwapchainAttachment(swapchain->getCurrentColor()); VulkanAttachment color = {};
color.texture = swapchain->getCurrentColor();
mInfo->attachments = {color}; mInfo->attachments = {color};
auto& fbkey = mInfo->fbkey; auto& fbkey = mInfo->fbkey;
auto& rpkey = mInfo->rpkey; auto& rpkey = mInfo->rpkey;
rpkey.colorFormat[0] = color.getFormat(); rpkey.colorFormat[0] = color.getFormat();
rpkey.viewCount = color.layerCount;
fbkey.width = width; fbkey.width = width;
fbkey.height = height; fbkey.height = height;
fbkey.color[0] = color.getImageView(); fbkey.color[0] = color.getImageView();
fbkey.resolve[0] = VK_NULL_HANDLE; fbkey.resolve[0] = VK_NULL_HANDLE;
if (swapchain->getDepth()) { if (swapchain->getDepth()) {
VulkanAttachment depth = createSwapchainAttachment(swapchain->getDepth()); VulkanAttachment depth = {};
depth.texture = swapchain->getDepth();
mInfo->attachments.push_back(depth); mInfo->attachments.push_back(depth);
mInfo->depthIndex = 1; mInfo->depthIndex = 1;
@@ -218,6 +218,12 @@ struct VulkanProgram : public HwProgram, fvkmemory::Resource {
mInfo->pushConstantDescription.write(cmdbuf, layout, stage, index, value); mInfo->pushConstantDescription.write(cmdbuf, layout, stage, index, value);
} }
#if FVK_ENABLED_DEBUG_SAMPLER_NAME
inline utils::FixedCapacityVector<std::string> const& getBindingToName() const {
return mInfo->bindingToName;
}
#endif
// TODO: handle compute shaders. // TODO: handle compute shaders.
// The expected order of shaders - from frontend to backend - is vertex, fragment, compute. // The expected order of shaders - from frontend to backend - is vertex, fragment, compute.
static constexpr uint8_t const MAX_SHADER_MODULES = 2; static constexpr uint8_t const MAX_SHADER_MODULES = 2;
@@ -40,8 +40,6 @@ VulkanSwapChain::VulkanSwapChain(VulkanPlatform* platform, VulkanContext const&
mFlushAndWaitOnResize(platform->getCustomization().flushAndWaitOnWindowResize), mFlushAndWaitOnResize(platform->getCustomization().flushAndWaitOnWindowResize),
mTransitionSwapChainImageLayoutForPresent( mTransitionSwapChainImageLayoutForPresent(
platform->getCustomization().transitionSwapChainImageLayoutForPresent), platform->getCustomization().transitionSwapChainImageLayoutForPresent),
mLayerCount(1),
mCurrentSwapIndex(0),
mAcquired(false), mAcquired(false),
mIsFirstRenderPass(true) { mIsFirstRenderPass(true) {
swapChain = mPlatform->createSwapChain(nativeWindow, flags, extent); swapChain = mPlatform->createSwapChain(nativeWindow, flags, extent);
@@ -78,18 +76,17 @@ void VulkanSwapChain::update() {
for (auto const color: bundle.colors) { for (auto const color: bundle.colors) {
auto colorTexture = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, auto colorTexture = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager,
device, mAllocator, mResourceManager, mCommands, color, VK_NULL_HANDLE, device, mAllocator, mResourceManager, mCommands, color, VK_NULL_HANDLE,
bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height, bundle.layerCount, colorUsage, bundle.colorFormat, 1, bundle.extent.width, bundle.extent.height, colorUsage,
mStagePool); mStagePool);
mColors.push_back(colorTexture); mColors.push_back(colorTexture);
} }
mDepth = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, device, mDepth = fvkmemory::resource_ptr<VulkanTexture>::construct(mResourceManager, device,
mAllocator, mResourceManager, mCommands, bundle.depth, VK_NULL_HANDLE, mAllocator, mResourceManager, mCommands, bundle.depth, VK_NULL_HANDLE,
bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height, bundle.layerCount, depthUsage, bundle.depthFormat, 1, bundle.extent.width, bundle.extent.height, depthUsage,
mStagePool); mStagePool);
mExtent = bundle.extent; mExtent = bundle.extent;
mLayerCount = bundle.layerCount;
} }
void VulkanSwapChain::present() { void VulkanSwapChain::present() {
@@ -100,7 +97,7 @@ void VulkanSwapChain::present() {
.baseMipLevel = 0, .baseMipLevel = 0,
.levelCount = 1, .levelCount = 1,
.baseArrayLayer = 0, .baseArrayLayer = 0,
.layerCount = mLayerCount, .layerCount = 1,
}; };
mColors[mCurrentSwapIndex]->transitionLayout(&commands, subresources, VulkanLayout::PRESENT); mColors[mCurrentSwapIndex]->transitionLayout(&commands, subresources, VulkanLayout::PRESENT);
} }
@@ -96,7 +96,6 @@ private:
utils::FixedCapacityVector<fvkmemory::resource_ptr<VulkanTexture>> mColors; utils::FixedCapacityVector<fvkmemory::resource_ptr<VulkanTexture>> mColors;
fvkmemory::resource_ptr<VulkanTexture> mDepth; fvkmemory::resource_ptr<VulkanTexture> mDepth;
VkExtent2D mExtent; VkExtent2D mExtent;
uint32_t mLayerCount;
uint32_t mCurrentSwapIndex; uint32_t mCurrentSwapIndex;
std::function<void(Platform::SwapChain* handle)> mExplicitImageReadyWait = nullptr; std::function<void(Platform::SwapChain* handle)> mExplicitImageReadyWait = nullptr;
bool mAcquired; bool mAcquired;
+12 -31
View File
@@ -144,16 +144,6 @@ inline VulkanLayout getDefaultLayoutImpl(VkImageUsageFlags vkusage) {
return getDefaultLayoutImpl(usage); return getDefaultLayoutImpl(usage);
} }
SamplerType getSamplerTypeFromDepth(uint32_t const depth) {
return depth > 1 ? SamplerType::SAMPLER_2D_ARRAY
: SamplerType::SAMPLER_2D;
}
uint8_t getLayerCountFromDepth(uint32_t const depth) {
return getLayerCount(getSamplerTypeFromDepth(depth), depth);
}
} // anonymous namespace } // anonymous namespace
VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator, VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
@@ -175,12 +165,12 @@ VulkanTextureState::VulkanTextureState(VkDevice device, VmaAllocator allocator,
VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator, VulkanTexture::VulkanTexture(VkDevice device, VmaAllocator allocator,
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image, fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image,
VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width, VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width,
uint32_t height, uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool) uint32_t height, TextureUsage tusage, VulkanStagePool& stagePool)
: HwTexture(getSamplerTypeFromDepth(depth), 1, samples, width, height, depth, TextureFormat::UNUSED, : HwTexture(SamplerType::SAMPLER_2D, 1, samples, width, height, 1, TextureFormat::UNUSED,
tusage), tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device, mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
allocator, commands, stagePool, format, fvkutils::getViewType(SamplerType::SAMPLER_2D), allocator, commands, stagePool, format, fvkutils::getViewType(SamplerType::SAMPLER_2D),
/*mipLevels=*/1, getLayerCountFromDepth(depth), getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) { 1, 1, getDefaultLayoutImpl(tusage), any(usage & TextureUsage::PROTECTED))) {
mState->mTextureImage = image; mState->mTextureImage = image;
mState->mTextureImageMemory = memory; mState->mTextureImageMemory = memory;
mPrimaryViewRange = mState->mFullViewRange; mPrimaryViewRange = mState->mFullViewRange;
@@ -193,6 +183,7 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
uint8_t levels, TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h, uint8_t levels, TextureFormat tformat, uint8_t samples, uint32_t w, uint32_t h,
uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool) uint32_t depth, TextureUsage tusage, VulkanStagePool& stagePool)
: HwTexture(target, levels, samples, w, h, depth, tformat, tusage), : HwTexture(target, levels, samples, w, h, depth, tformat, tusage),
mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device, mState(fvkmemory::resource_ptr<VulkanTextureState>::construct(resourceManager, device,
allocator, commands, stagePool, fvkutils::getVkFormat(tformat), allocator, commands, stagePool, fvkutils::getVkFormat(tformat),
fvkutils::getViewType(target), levels, getLayerCount(target, depth), fvkutils::getViewType(target), levels, getLayerCount(target, depth),
@@ -208,20 +199,11 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
.tiling = VK_IMAGE_TILING_OPTIMAL, .tiling = VK_IMAGE_TILING_OPTIMAL,
.usage = 0, .usage = 0,
}; };
if (target == SamplerType::SAMPLER_3D && any(tusage & TextureUsage::ALL_ATTACHMENTS)) { if (target == SamplerType::SAMPLER_CUBEMAP) {
if (context.isImageView2DOn3DImageSupported()) {
// Note that VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT is only meant to create 2D views of
// a 3D image in the case where the image is the render target. So, for example, it's
// not meant to allow for 2D views that can be used with a sampler.
imageInfo.flags = VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT;
} else {
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;
}
} else if (target == SamplerType::SAMPLER_CUBEMAP) {
imageInfo.arrayLayers = 6; imageInfo.arrayLayers = 6;
imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT; imageInfo.flags = VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT;
} else if (target == SamplerType::SAMPLER_2D_ARRAY) { }
if (target == SamplerType::SAMPLER_2D_ARRAY) {
imageInfo.arrayLayers = depth; imageInfo.arrayLayers = depth;
imageInfo.extent.depth = 1; imageInfo.extent.depth = 1;
// NOTE: We do not use VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT here because: // NOTE: We do not use VK_IMAGE_CREATE_2D_ARRAY_COMPATIBLE_BIT here because:
@@ -265,9 +247,9 @@ VulkanTexture::VulkanTexture(VkDevice device, VkPhysicalDevice physicalDevice,
#if FVK_ENABLED(FVK_DEBUG_TEXTURE) #if FVK_ENABLED(FVK_DEBUG_TEXTURE)
// Validate that the format is actually sampleable. // Validate that the format is actually sampleable.
VkFormatProperties props; VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(physicalDevice, mState->mVkFormat, &props); vkGetPhysicalDeviceFormatProperties(physicalDevice, state->mVkFormat, &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 " << mState->mVkFormat << " is not " FVK_LOGW << "Texture usage is SAMPLEABLE but format " << state->mVkFormat << " is not "
"sampleable with optimal tiling." << utils::io::endl; "sampleable with optimal tiling." << utils::io::endl;
} }
#endif #endif
@@ -649,16 +631,15 @@ bool VulkanTexture::transitionLayout(VkCommandBuffer cmdbuf, VkImageSubresourceR
if (hasTransitions) { if (hasTransitions) {
#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=" << state->mTextureImage << " (" << range.baseArrayLayer
<< "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << "," << "," << range.baseMipLevel << ")" << " count=(" << range.layerCount << ","
<< range.levelCount << ")" << " from=" << oldLayout << " to=" << newLayout << range.levelCount << ")" << " from=" << oldLayout << " to=" << newLayout
<< " format=" << mState->mVkFormat << " depth=" << " format=" << state->mVkFormat << " depth=" << isVkDepthFormat(state->mVkFormat)
<< fvkutils::isVkDepthFormat(mState->mVkFormat)
<< " slice-by-slice=" << transitionSliceBySlice << utils::io::endl; << " slice-by-slice=" << transitionSliceBySlice << utils::io::endl;
#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=" << state->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" << utils::io::endl;
+1 -1
View File
@@ -94,7 +94,7 @@ struct VulkanTexture : public HwTexture, fvkmemory::Resource {
// The texture will never destroy the given VkImage, but it does manages its subresources. // The texture will never destroy the given VkImage, but it does manages its subresources.
VulkanTexture(VkDevice device, VmaAllocator allocator, VulkanTexture(VkDevice device, VmaAllocator allocator,
fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image, fvkmemory::ResourceManager* resourceManager, VulkanCommands* commands, VkImage image,
VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, VkDeviceMemory memory, VkFormat format, uint8_t samples, uint32_t width, uint32_t height,
TextureUsage tusage, VulkanStagePool& stagePool); TextureUsage tusage, VulkanStagePool& stagePool);
// Constructor for creating a texture view for wrt specific mip range // Constructor for creating a texture view for wrt specific mip range
@@ -18,7 +18,6 @@
#include <backend/DriverEnums.h> #include <backend/DriverEnums.h>
#include "vulkan/VulkanContext.h"
#include "vulkan/platform/VulkanPlatformSwapChainImpl.h" #include "vulkan/platform/VulkanPlatformSwapChainImpl.h"
#include "vulkan/VulkanConstants.h" #include "vulkan/VulkanConstants.h"
#include "vulkan/VulkanDriver.h" #include "vulkan/VulkanDriver.h"
@@ -69,7 +68,7 @@ FixedCapacityVector<const char*> getEnabledLayers() {
constexpr size_t kMaxEnabledLayersCount = sizeof(DESIRED_LAYERS) / sizeof(DESIRED_LAYERS[0]); constexpr size_t kMaxEnabledLayersCount = sizeof(DESIRED_LAYERS) / sizeof(DESIRED_LAYERS[0]);
const FixedCapacityVector<VkLayerProperties> availableLayers const FixedCapacityVector<VkLayerProperties> availableLayers
= fvkutils::enumerate(vkEnumerateInstanceLayerProperties); = filament::backend::enumerate(vkEnumerateInstanceLayerProperties);
auto enabledLayers = FixedCapacityVector<const char*>::with_capacity(kMaxEnabledLayersCount); auto enabledLayers = FixedCapacityVector<const char*>::with_capacity(kMaxEnabledLayersCount);
for (auto const& desired: DESIRED_LAYERS) { for (auto const& desired: DESIRED_LAYERS) {
@@ -85,13 +84,6 @@ FixedCapacityVector<const char*> getEnabledLayers() {
} }
#endif // FVK_EANBLED(FVK_DEBUG_VALIDATION) #endif // FVK_EANBLED(FVK_DEBUG_VALIDATION)
template<typename StructA, typename StructB>
StructA* chainStruct(StructA* structA, StructB* structB) {
structB->pNext = const_cast<void*>(structA->pNext);
structA->pNext = (void*) structB;
return structA;
}
void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) { void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
// Print some driver or MoltenVK information if it is available. // Print some driver or MoltenVK information if it is available.
if (vkGetPhysicalDeviceProperties2) { if (vkGetPhysicalDeviceProperties2) {
@@ -100,8 +92,8 @@ void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
}; };
VkPhysicalDeviceProperties2 physicalDeviceProperties2 = { VkPhysicalDeviceProperties2 physicalDeviceProperties2 = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2,
.pNext = &driverProperties,
}; };
chainStruct(&physicalDeviceProperties2, &driverProperties);
vkGetPhysicalDeviceProperties2(device, &physicalDeviceProperties2); vkGetPhysicalDeviceProperties2(device, &physicalDeviceProperties2);
FVK_LOGI << "Vulkan device driver: " << driverProperties.driverName << " " FVK_LOGI << "Vulkan device driver: " << driverProperties.driverName << " "
<< driverProperties.driverInfo << utils::io::endl; << driverProperties.driverInfo << utils::io::endl;
@@ -151,7 +143,7 @@ void printDepthFormats(VkPhysicalDevice device) {
const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT const VkFormatFeatureFlags required = VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT
| VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT; | VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;
FVK_LOGI << "Sampleable depth formats: "; FVK_LOGI << "Sampleable depth formats: ";
for (VkFormat format : fvkutils::ALL_VK_FORMATS) { for (VkFormat format : ALL_VK_FORMATS) {
VkFormatProperties props; VkFormatProperties props;
vkGetPhysicalDeviceFormatProperties(device, format, &props); vkGetPhysicalDeviceFormatProperties(device, format, &props);
if ((props.optimalTilingFeatures & required) == required) { if ((props.optimalTilingFeatures & required) == required) {
@@ -202,7 +194,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS) #if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
VK_EXT_DEBUG_MARKER_EXTENSION_NAME, VK_EXT_DEBUG_MARKER_EXTENSION_NAME,
#endif #endif
// We only support external image for Android for now, but nothing bars us from // We only support external image for Android for now, but nothing bars us from
// supporting other platforms. // supporting other platforms.
#if defined(__ANDROID__) #if defined(__ANDROID__)
VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME, VK_KHR_EXTERNAL_MEMORY_EXTENSION_NAME,
@@ -239,9 +231,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
VkInstance createInstance(ExtensionSet const& requiredExts) { VkInstance createInstance(ExtensionSet const& requiredExts) {
VkInstance instance; VkInstance instance;
VkInstanceCreateInfo instanceCreateInfo = { VkInstanceCreateInfo instanceCreateInfo = {};
.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO,
};
bool validationFeaturesSupported = false; bool validationFeaturesSupported = false;
#if FVK_ENABLED(FVK_DEBUG_VALIDATION) #if FVK_ENABLED(FVK_DEBUG_VALIDATION)
@@ -249,7 +239,7 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
if (!enabledLayers.empty()) { if (!enabledLayers.empty()) {
// If layers are supported, Check if VK_EXT_validation_features is supported. // If layers are supported, Check if VK_EXT_validation_features is supported.
FixedCapacityVector<VkExtensionProperties> const availableValidationExts FixedCapacityVector<VkExtensionProperties> const availableValidationExts
= fvkutils::enumerate(vkEnumerateInstanceExtensionProperties, = filament::backend::enumerate(vkEnumerateInstanceExtensionProperties,
"VK_LAYER_KHRONOS_validation"); "VK_LAYER_KHRONOS_validation");
for (auto const& extProps: availableValidationExts) { for (auto const& extProps: availableValidationExts) {
if (!strcmp(extProps.extensionName, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)) { if (!strcmp(extProps.extensionName, VK_EXT_VALIDATION_FEATURES_EXTENSION_NAME)) {
@@ -292,6 +282,7 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
appInfo.pEngineName = "Filament"; appInfo.pEngineName = "Filament";
appInfo.apiVersion appInfo.apiVersion
= VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0); = VK_MAKE_API_VERSION(0, FVK_REQUIRED_VERSION_MAJOR, FVK_REQUIRED_VERSION_MINOR, 0);
instanceCreateInfo.sType = VK_STRUCTURE_TYPE_INSTANCE_CREATE_INFO;
instanceCreateInfo.pApplicationInfo = &appInfo; instanceCreateInfo.pApplicationInfo = &appInfo;
instanceCreateInfo.enabledExtensionCount = enabledExtensionCount; instanceCreateInfo.enabledExtensionCount = enabledExtensionCount;
instanceCreateInfo.ppEnabledExtensionNames = ppEnabledExtensions; instanceCreateInfo.ppEnabledExtensionNames = ppEnabledExtensions;
@@ -299,17 +290,16 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR; instanceCreateInfo.flags = VK_INSTANCE_CREATE_ENUMERATE_PORTABILITY_BIT_KHR;
} }
VkValidationFeaturesEXT features = { VkValidationFeaturesEXT features = {};
.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT,
};
VkValidationFeatureEnableEXT enables[] = { VkValidationFeatureEnableEXT enables[] = {
VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT, VK_VALIDATION_FEATURE_ENABLE_BEST_PRACTICES_EXT,
VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT, VK_VALIDATION_FEATURE_ENABLE_SYNCHRONIZATION_VALIDATION_EXT,
}; };
if (validationFeaturesSupported) { if (validationFeaturesSupported) {
features.sType = VK_STRUCTURE_TYPE_VALIDATION_FEATURES_EXT;
features.enabledValidationFeatureCount = sizeof(enables) / sizeof(enables[0]); features.enabledValidationFeatureCount = sizeof(enables) / sizeof(enables[0]);
features.pEnabledValidationFeatures = enables; features.pEnabledValidationFeatures = enables;
chainStruct(&instanceCreateInfo, &features); instanceCreateInfo.pNext = &features;
} }
VkResult result = vkCreateInstance(&instanceCreateInfo, VKALLOC, &instance); VkResult result = vkCreateInstance(&instanceCreateInfo, VKALLOC, &instance);
@@ -320,13 +310,11 @@ VkInstance createInstance(ExtensionSet const& requiredExts) {
VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice, VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
VkPhysicalDeviceFeatures2 const& features, uint32_t graphicsQueueFamilyIndex, VkPhysicalDeviceFeatures2 const& features, uint32_t graphicsQueueFamilyIndex,
uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions, uint32_t protectedGraphicsQueueFamilyIndex, ExtensionSet const& deviceExtensions) {
bool requestImageView2DOn3DImage) {
VkDevice device; VkDevice device;
float queuePriority[] = {1.0f}; VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
VkDeviceCreateInfo deviceCreateInfo = { const float queuePriority[] = {1.0f};
.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO, VkDeviceCreateInfo deviceCreateInfo = {};
};
FixedCapacityVector<const char*> requestExtensions; FixedCapacityVector<const char*> requestExtensions;
requestExtensions.reserve(deviceExtensions.size() + 1); requestExtensions.reserve(deviceExtensions.size() + 1);
@@ -335,7 +323,6 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
for (auto const& ext: deviceExtensions) { for (auto const& ext: deviceExtensions) {
requestExtensions.push_back(ext.data()); requestExtensions.push_back(ext.data());
} }
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO; deviceQueueCreateInfo[0].sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO;
deviceQueueCreateInfo[0].queueFamilyIndex = graphicsQueueFamilyIndex; deviceQueueCreateInfo[0].queueFamilyIndex = graphicsQueueFamilyIndex;
deviceQueueCreateInfo[0].queueCount = 1; deviceQueueCreateInfo[0].queueCount = 1;
@@ -347,6 +334,7 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
deviceQueueCreateInfo[1].queueCount = 1; deviceQueueCreateInfo[1].queueCount = 1;
deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority[0]; deviceQueueCreateInfo[1].pQueuePriorities = &queuePriority[0];
deviceCreateInfo.sType = VK_STRUCTURE_TYPE_DEVICE_CREATE_INFO;
bool const hasProtectedQueue = protectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX; bool const hasProtectedQueue = protectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX;
deviceCreateInfo.queueCreateInfoCount = hasProtectedQueue ? 2 : 1; deviceCreateInfo.queueCreateInfoCount = hasProtectedQueue ? 2 : 1;
deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo; deviceCreateInfo.pQueueCreateInfos = deviceQueueCreateInfo;
@@ -365,35 +353,42 @@ VkDevice createLogicalDevice(VkPhysicalDevice physicalDevice,
deviceCreateInfo.enabledExtensionCount = (uint32_t) requestExtensions.size(); deviceCreateInfo.enabledExtensionCount = (uint32_t) requestExtensions.size();
deviceCreateInfo.ppEnabledExtensionNames = requestExtensions.data(); deviceCreateInfo.ppEnabledExtensionNames = requestExtensions.data();
void* pNext = nullptr;
VkPhysicalDevicePortabilitySubsetFeaturesKHR portability = { VkPhysicalDevicePortabilitySubsetFeaturesKHR portability = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PORTABILITY_SUBSET_FEATURES_KHR,
.imageViewFormatSwizzle = VK_TRUE, .pNext = nullptr,
.imageView2DOn3DImage = requestImageView2DOn3DImage ? VK_TRUE : VK_FALSE, .imageViewFormatSwizzle = VK_TRUE,
.mutableComparisonSamplers = VK_TRUE, .mutableComparisonSamplers = VK_TRUE,
}; };
if (setContains(deviceExtensions, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) { if (setContains(deviceExtensions, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) {
chainStruct(&deviceCreateInfo, &portability); portability.pNext = pNext;
pNext = &portability;
} }
VkPhysicalDeviceMultiviewFeaturesKHR multiview = { VkPhysicalDeviceMultiviewFeaturesKHR multiview = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_MULTIVIEW_FEATURES_KHR,
.multiview = VK_TRUE, .pNext = nullptr,
.multiviewGeometryShader = VK_FALSE, .multiview = VK_TRUE,
.multiviewTessellationShader = VK_FALSE, .multiviewGeometryShader = VK_FALSE,
.multiviewTessellationShader = VK_FALSE
}; };
if (setContains(deviceExtensions, VK_KHR_MULTIVIEW_EXTENSION_NAME)) { if (setContains(deviceExtensions, VK_KHR_MULTIVIEW_EXTENSION_NAME)) {
chainStruct(&deviceCreateInfo, &multiview); multiview.pNext = pNext;
pNext = &multiview;
} }
VkPhysicalDeviceProtectedMemoryFeatures protectedMemory = { VkPhysicalDeviceProtectedMemoryFeatures protectedMemory = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
.protectedMemory = VK_TRUE,
}; };
if (hasProtectedQueue) { if (hasProtectedQueue) {
// Enable protected memory, if requested. // Enable protected memory, if requested.
chainStruct(&deviceCreateInfo, &protectedMemory); protectedMemory.protectedMemory = VK_TRUE;
protectedMemory.pNext = pNext;
pNext = &protectedMemory;
} }
deviceCreateInfo.pNext = pNext;
VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, VKALLOC, &device); VkResult result = vkCreateDevice(physicalDevice, &deviceCreateInfo, VKALLOC, &device);
FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS) FILAMENT_CHECK_POSTCONDITION(result == VK_SUCCESS)
<< "vkCreateDevice error=" << static_cast<int32_t>(result); << "vkCreateDevice error=" << static_cast<int32_t>(result);
@@ -506,7 +501,7 @@ VkPhysicalDevice selectPhysicalDevice(VkInstance instance,
// Does the device have any command queues that support graphics? // Does the device have any command queues that support graphics?
// In theory, we should also ensure that the device supports presentation of our // In theory, we should also ensure that the device supports presentation of our
// particular VkSurface, but we don't have a VkSurface yet, so we'll skip this requirement. // particular VkSurface, but we don't have a VkSurface yet, so we'll skip this requirement.
if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT) if (identifyGraphicsQueueFamilyIndex(candidateDevice, VK_QUEUE_GRAPHICS_BIT)
== INVALID_VK_INDEX) { == INVALID_VK_INDEX) {
continue; continue;
} }
@@ -726,11 +721,14 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
VkPhysicalDeviceProtectedMemoryFeatures queryProtectedMemoryFeatures = { VkPhysicalDeviceProtectedMemoryFeatures queryProtectedMemoryFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_FEATURES,
}; };
// Chain to the pNext linked list
queryProtectedMemoryFeatures.pNext = context.mPhysicalDeviceFeatures.pNext;
context.mPhysicalDeviceFeatures.pNext = &queryProtectedMemoryFeatures;
VkPhysicalDeviceProtectedMemoryProperties protectedMemoryProperties = { VkPhysicalDeviceProtectedMemoryProperties protectedMemoryProperties = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES, .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROTECTED_MEMORY_PROPERTIES,
}; };
chainStruct(&context.mPhysicalDeviceFeatures, &queryProtectedMemoryFeatures); protectedMemoryProperties.pNext = context.mPhysicalDeviceProperties.pNext;
chainStruct(&context.mPhysicalDeviceProperties, &protectedMemoryProperties); context.mPhysicalDeviceProperties.pNext = &protectedMemoryProperties;
// Initialize the following fields: physicalDeviceProperties, memoryProperties, // Initialize the following fields: physicalDeviceProperties, memoryProperties,
// physicalDeviceFeatures, graphicsQueueFamilyIndex. // physicalDeviceFeatures, graphicsQueueFamilyIndex.
@@ -740,17 +738,17 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
mImpl->mGraphicsQueueFamilyIndex mImpl->mGraphicsQueueFamilyIndex
= mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX = mImpl->mGraphicsQueueFamilyIndex == INVALID_VK_INDEX
? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice, ? identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
VK_QUEUE_GRAPHICS_BIT) VK_QUEUE_GRAPHICS_BIT)
: mImpl->mGraphicsQueueFamilyIndex; : mImpl->mGraphicsQueueFamilyIndex;
assert_invariant(mImpl->mGraphicsQueueFamilyIndex != INVALID_VK_INDEX); assert_invariant(mImpl->mGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
// We know we need to allocate the protected version of the VK objects // We know we need to allocate the protected version of the VK objects
context.mProtectedMemorySupported = context.mProtectedMemorySupported =
static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory); static_cast<bool>(queryProtectedMemoryFeatures.protectedMemory);
if (context.mProtectedMemorySupported) { if (context.mProtectedMemorySupported) {
mImpl->mProtectedGraphicsQueueFamilyIndex mImpl->mProtectedGraphicsQueueFamilyIndex
= identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice, = identifyGraphicsQueueFamilyIndex(mImpl->mPhysicalDevice,
(VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT)); (VK_QUEUE_GRAPHICS_BIT | VK_QUEUE_PROTECTED_BIT));
assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX); assert_invariant(mImpl->mProtectedGraphicsQueueFamilyIndex != INVALID_VK_INDEX);
} }
@@ -770,7 +768,7 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
// Applying the same logic to the protected queue index (Not sure about shared context and protection) // Applying the same logic to the protected queue index (Not sure about shared context and protection)
mImpl->mProtectedGraphicsQueueIndex mImpl->mProtectedGraphicsQueueIndex
= mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 : = mImpl->mProtectedGraphicsQueueIndex == INVALID_VK_INDEX ? 0 :
mImpl->mProtectedGraphicsQueueIndex; mImpl->mProtectedGraphicsQueueIndex;
ExtensionSet deviceExts; ExtensionSet deviceExts;
@@ -787,23 +785,11 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
} }
} }
bool requestPortabilitySubsetImageView2DOn3DImage = false; mImpl->mDevice
if (setContains(deviceExts, VK_KHR_PORTABILITY_SUBSET_EXTENSION_NAME)) { = mImpl->mDevice == VK_NULL_HANDLE ? createLogicalDevice(mImpl->mPhysicalDevice,
// We are on a non-conformant vulkan implementation so we need to ascertain if the features context.mPhysicalDeviceFeatures, mImpl->mGraphicsQueueFamilyIndex,
// we need are available. mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts)
chainStruct(&context.mPhysicalDeviceFeatures, &context.mPortabilitySubsetFeatures); : mImpl->mDevice;
vkGetPhysicalDeviceFeatures2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceFeatures);
requestPortabilitySubsetImageView2DOn3DImage =
context.mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
}
mImpl->mDevice =
mImpl->mDevice == VK_NULL_HANDLE
? createLogicalDevice(mImpl->mPhysicalDevice, context.mPhysicalDeviceFeatures,
mImpl->mGraphicsQueueFamilyIndex,
mImpl->mProtectedGraphicsQueueFamilyIndex, deviceExts,
requestPortabilitySubsetImageView2DOn3DImage)
: mImpl->mDevice;
assert_invariant(mImpl->mDevice != VK_NULL_HANDLE); assert_invariant(mImpl->mDevice != VK_NULL_HANDLE);
vkGetDeviceQueue(mImpl->mDevice, mImpl->mGraphicsQueueFamilyIndex, mImpl->mGraphicsQueueIndex, vkGetDeviceQueue(mImpl->mDevice, mImpl->mGraphicsQueueFamilyIndex, mImpl->mGraphicsQueueIndex,
@@ -820,16 +806,9 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
} }
// Store the extension support in the context // Store the extension support in the context
if (!mImpl->mSharedContext) { context.mDebugUtilsSupported = setContains(instExts, VK_EXT_DEBUG_UTILS_EXTENSION_NAME);
context.mDebugUtilsSupported = setContains(instExts, VK_EXT_DEBUG_UTILS_EXTENSION_NAME); context.mDebugMarkersSupported = setContains(deviceExts, VK_EXT_DEBUG_MARKER_EXTENSION_NAME);
context.mDebugMarkersSupported = setContains(deviceExts, VK_EXT_DEBUG_MARKER_EXTENSION_NAME); context.mMultiviewEnabled = setContains(deviceExts, VK_KHR_MULTIVIEW_EXTENSION_NAME);
context.mMultiviewEnabled = setContains(deviceExts, VK_KHR_MULTIVIEW_EXTENSION_NAME);
} else {
VulkanSharedContext const* scontext = (VulkanSharedContext const*) sharedContext;
context.mDebugUtilsSupported = scontext->debugUtilsSupported;
context.mDebugMarkersSupported = scontext->debugMarkersSupported;
context.mMultiviewEnabled = scontext->multiviewSupported;
}
// Check the availability of lazily allocated memory // Check the availability of lazily allocated memory
{ {
+1 -1
View File
@@ -214,7 +214,7 @@ bool operator<(const VkImageSubresourceRange& a, const VkImageSubresourceRange&
case filament::backend::VulkanLayout::VALUE: { \ case filament::backend::VulkanLayout::VALUE: { \
out << #VALUE; \ out << #VALUE; \
out << " [" \ out << " [" \
<< filament::backend::fvkutils::getVkLayout( \ << filament::backend::imgutil::getVkLayout( \
filament::backend::VulkanLayout::VALUE) \ filament::backend::VulkanLayout::VALUE) \
<< "]"; \ << "]"; \
break; \ break; \
-12
View File
@@ -17,7 +17,6 @@
#ifndef TNT_FILAMENT_ENGINE_H #ifndef TNT_FILAMENT_ENGINE_H
#define TNT_FILAMENT_ENGINE_H #define TNT_FILAMENT_ENGINE_H
#include <filament/FilamentAPI.h> #include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h> #include <backend/DriverEnums.h>
@@ -33,7 +32,6 @@
#include <stdint.h> #include <stdint.h>
#include <stddef.h> #include <stddef.h>
namespace utils { namespace utils {
class Entity; class Entity;
class EntityManager; class EntityManager;
@@ -42,10 +40,6 @@ class JobSystem;
namespace filament { namespace filament {
namespace backend {
class Driver;
} // backend
class BufferObject; class BufferObject;
class Camera; class Camera;
class ColorGrading; class ColorGrading;
@@ -189,7 +183,6 @@ public:
using DriverConfig = backend::Platform::DriverConfig; using DriverConfig = backend::Platform::DriverConfig;
using FeatureLevel = backend::FeatureLevel; using FeatureLevel = backend::FeatureLevel;
using StereoscopicType = backend::StereoscopicType; using StereoscopicType = backend::StereoscopicType;
using Driver = backend::Driver;
/** /**
* Config is used to define the memory footprint used by the engine, such as the * Config is used to define the memory footprint used by the engine, such as the
@@ -589,11 +582,6 @@ public:
static Engine* UTILS_NULLABLE getEngine(void* UTILS_NONNULL token); static Engine* UTILS_NULLABLE getEngine(void* UTILS_NONNULL token);
#endif #endif
/**
* @return the Driver instance used by this Engine.
* @see OpenGLPlatform
*/
backend::Driver const* UTILS_NONNULL getDriver() const noexcept;
/** /**
* Destroy the Engine instance and all associated resources. * Destroy the Engine instance and all associated resources.
+9 -20
View File
@@ -121,7 +121,7 @@ public:
/** inline helper to provide the name as a null-terminated string literal */ /** inline helper to provide the name as a null-terminated string literal */
template<typename T, typename = is_supported_parameter_t<T>> template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(StringLiteral const name, T const& value) { void setParameter(StringLiteral name, T const& value) {
setParameter<T>(name.data, name.size, value); setParameter<T>(name.data, name.size, value);
} }
@@ -148,14 +148,14 @@ public:
/** inline helper to provide the name as a null-terminated string literal */ /** inline helper to provide the name as a null-terminated string literal */
template<typename T, typename = is_supported_parameter_t<T>> template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(StringLiteral const name, const T* UTILS_NONNULL values, size_t const count) { void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) {
setParameter<T>(name.data, name.size, values, count); setParameter<T>(name.data, name.size, values, count);
} }
/** inline helper to provide the name as a null-terminated C string */ /** inline helper to provide the name as a null-terminated C string */
template<typename T, typename = is_supported_parameter_t<T>> template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(const char* UTILS_NONNULL name, void setParameter(const char* UTILS_NONNULL name,
const T* UTILS_NONNULL values, size_t const count) { const T* UTILS_NONNULL values, size_t count) {
setParameter<T>(name, strlen(name), values, count); setParameter<T>(name, strlen(name), values, count);
} }
@@ -176,7 +176,7 @@ public:
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler); Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler);
/** inline helper to provide the name as a null-terminated string literal */ /** inline helper to provide the name as a null-terminated string literal */
void setParameter(StringLiteral const name, void setParameter(StringLiteral name,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) { Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
setParameter(name.data, name.size, texture, sampler); setParameter(name.data, name.size, texture, sampler);
} }
@@ -202,12 +202,12 @@ public:
RgbType type, math::float3 color); RgbType type, math::float3 color);
/** inline helper to provide the name as a null-terminated string literal */ /** inline helper to provide the name as a null-terminated string literal */
void setParameter(StringLiteral const name, RgbType const type, math::float3 const color) { void setParameter(StringLiteral name, RgbType type, math::float3 color) {
setParameter(name.data, name.size, type, color); setParameter(name.data, name.size, type, color);
} }
/** inline helper to provide the name as a null-terminated C string */ /** inline helper to provide the name as a null-terminated C string */
void setParameter(const char* UTILS_NONNULL name, RgbType const type, math::float3 const color) { void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) {
setParameter(name, strlen(name), type, color); setParameter(name, strlen(name), type, color);
} }
@@ -226,12 +226,12 @@ public:
RgbaType type, math::float4 color); RgbaType type, math::float4 color);
/** inline helper to provide the name as a null-terminated string literal */ /** inline helper to provide the name as a null-terminated string literal */
void setParameter(StringLiteral const name, RgbaType const type, math::float4 const color) { void setParameter(StringLiteral name, RgbaType type, math::float4 color) {
setParameter(name.data, name.size, type, color); setParameter(name.data, name.size, type, color);
} }
/** inline helper to provide the name as a null-terminated C string */ /** inline helper to provide the name as a null-terminated C string */
void setParameter(const char* UTILS_NONNULL name, RgbaType const type, math::float4 const color) { void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) {
setParameter(name, strlen(name), type, color); setParameter(name, strlen(name), type, color);
} }
@@ -251,7 +251,7 @@ public:
/** inline helper to provide the name as a null-terminated C string */ /** inline helper to provide the name as a null-terminated C string */
template<typename T, typename = is_supported_parameter_t<T>> template<typename T, typename = is_supported_parameter_t<T>>
T getParameter(StringLiteral const name) const { T getParameter(StringLiteral name) const {
return getParameter<T>(name.data, name.size); return getParameter<T>(name.data, name.size);
} }
@@ -376,22 +376,11 @@ public:
*/ */
void setCullingMode(CullingMode culling) noexcept; void setCullingMode(CullingMode culling) noexcept;
/**
* Overrides the default triangle culling state that was set on the material separately for the
* color and shadow passes
*/
void setCullingMode(CullingMode colorPassCullingMode, CullingMode shadowPassCullingMode) noexcept;
/** /**
* Returns the face culling mode. * Returns the face culling mode.
*/ */
CullingMode getCullingMode() const noexcept; CullingMode getCullingMode() const noexcept;
/**
* Returns the face culling mode for the shadow passes.
*/
CullingMode getShadowCullingMode() const noexcept;
/** /**
* Overrides the default color-buffer write state that was set on the material. * Overrides the default color-buffer write state that was set on the material.
*/ */
-5
View File
@@ -141,11 +141,6 @@ public:
*/ */
void removeEntities(const utils::Entity* UTILS_NONNULL entities, size_t count); void removeEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
/**
* Remove all entities to the Scene.
*/
void removeAllEntities() noexcept;
/** /**
* Returns the total number of Entities in the Scene, whether alive or not. * Returns the total number of Entities in the Scene, whether alive or not.
* @return Total number of Entities in the Scene. * @return Total number of Entities in the Scene.
-4
View File
@@ -68,10 +68,6 @@ Engine* Engine::getEngine(void* token) {
} }
#endif #endif
Driver const* Engine::getDriver() const noexcept {
return std::addressof(downcast(this)->getDriver());
}
void Engine::destroy(Engine** pEngine) { void Engine::destroy(Engine** pEngine) {
if (pEngine) { if (pEngine) {
Engine* engine = *pEngine; Engine* engine = *pEngine;
+3 -32
View File
@@ -17,26 +17,6 @@
#include <filament/MaterialInstance.h> #include <filament/MaterialInstance.h>
#include "details/Material.h" #include "details/Material.h"
#include "details/MaterialInstance.h"
#include <filament/Color.h>
#include <filament/MaterialEnums.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <math/mat3.h>
#include <algorithm>
#include <string_view>
#include <stddef.h>
#include <stdint.h>
namespace filament { namespace filament {
@@ -105,7 +85,7 @@ void MaterialInstance::setParameter(const char* name, size_t nameLength, T const
template<> template<>
UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool const& v) { UTILS_PUBLIC void MaterialInstance::setParameter(const char* name, size_t const nameLength, bool const& v) {
// this kills tail-call optimization // this kills tail-call optimization
setParameter(name, nameLength, uint32_t(v)); setParameter(name, nameLength, (uint32_t)v);
} }
template<> template<>
@@ -145,8 +125,8 @@ template UTILS_PUBLIC void MaterialInstance::setParameter<mat4f> (const char*
// ------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------
template <typename T, typename> template <typename T, typename>
void MaterialInstance::setParameter(const char* name, size_t nameLength, const T* values, size_t count) { void MaterialInstance::setParameter(const char* name, size_t nameLength, const T* value, size_t count) {
downcast(this)->setParameterImpl({ name, nameLength }, values, count); downcast(this)->setParameterImpl({ name, nameLength }, value, count);
} }
template<> template<>
@@ -292,11 +272,6 @@ void MaterialInstance::setCullingMode(CullingMode const culling) noexcept {
downcast(this)->setCullingMode(culling); downcast(this)->setCullingMode(culling);
} }
void MaterialInstance::setCullingMode(CullingMode const colorPassCullingMode,
CullingMode const shadowPassCullingMode) noexcept {
downcast(this)->setCullingMode(colorPassCullingMode, shadowPassCullingMode);
}
void MaterialInstance::setColorWrite(bool const enable) noexcept { void MaterialInstance::setColorWrite(bool const enable) noexcept {
downcast(this)->setColorWrite(enable); downcast(this)->setColorWrite(enable);
} }
@@ -378,10 +353,6 @@ CullingMode MaterialInstance::getCullingMode() const noexcept {
return downcast(this)->getCullingMode(); return downcast(this)->getCullingMode();
} }
CullingMode MaterialInstance::getShadowCullingMode() const noexcept {
return downcast(this)->getShadowCullingMode();
}
bool MaterialInstance::isColorWriteEnabled() const noexcept { bool MaterialInstance::isColorWriteEnabled() const noexcept {
return downcast(this)->isColorWriteEnabled(); return downcast(this)->isColorWriteEnabled();
} }
+4 -11
View File
@@ -807,13 +807,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
cmd.key &= ~Z_BUCKET_MASK; cmd.key &= ~Z_BUCKET_MASK;
cmd.key |= makeField(distanceBits >> 22u, Z_BUCKET_MASK, Z_BUCKET_SHIFT); cmd.key |= makeField(distanceBits >> 22u, Z_BUCKET_MASK, Z_BUCKET_SHIFT);
} }
*curr = cmd;
// cancel command if both front and back faces are culled
curr->key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
} else if constexpr (isDepthPass) { } else if constexpr (isDepthPass) {
const CullingMode cullingMode = hasShadowing ? mi->getShadowCullingMode() : mi->getCullingMode();
const RasterState rs = ma->getRasterState(); const RasterState rs = ma->getRasterState();
const TransparencyMode mode = mi->getTransparencyMode(); const TransparencyMode mode = mi->getTransparencyMode();
const BlendingMode blendingMode = ma->getBlendingMode(); const BlendingMode blendingMode = ma->getBlendingMode();
@@ -822,7 +816,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
const bool isPickingVariant = Variant::isPickingVariant(variant); const bool isPickingVariant = Variant::isPickingVariant(variant);
cmd.key |= mi->getSortingKey(); // already all set-up for direct or'ing cmd.key |= mi->getSortingKey(); // already all set-up for direct or'ing
cmd.info.rasterState.culling = cullingMode; cmd.info.rasterState.culling = mi->getCullingMode();
// FIXME: should writeDepthForShadowCasters take precedence over mi->getDepthWrite()? // FIXME: should writeDepthForShadowCasters take precedence over mi->getDepthWrite()?
cmd.info.rasterState.depthWrite = (1 // only keep bit 0 cmd.info.rasterState.depthWrite = (1 // only keep bit 0
@@ -831,12 +825,11 @@ RenderPass::Command* RenderPass::generateCommandsImpl(CommandTypeFlags extraFlag
& !(filterTranslucentObjects & translucent) & !(filterTranslucentObjects & translucent)
& !(depthFilterAlphaMaskedObjects & rs.alphaToCoverage)) & !(depthFilterAlphaMaskedObjects & rs.alphaToCoverage))
| writeDepthForShadowCasters; | writeDepthForShadowCasters;
*curr = cmd;
// cancel command if both front and back faces are culled
curr->key |= select(cullingMode == CullingMode::FRONT_AND_BACK);
} }
*curr = cmd;
// cancel command if both front and back faces are culled
curr->key |= select(mi->getCullingMode() == CullingMode::FRONT_AND_BACK);
++curr; ++curr;
} }
} }
-4
View File
@@ -55,10 +55,6 @@ void Scene::removeEntities(const Entity* entities, size_t const count) {
downcast(this)->removeEntities(entities, count); downcast(this)->removeEntities(entities, count);
} }
void Scene::removeAllEntities() noexcept {
downcast(this)->removeAllEntities();
}
size_t Scene::getEntityCount() const noexcept { size_t Scene::getEntityCount() const noexcept {
return downcast(this)->getEntityCount(); return downcast(this)->getEntityCount();
} }
+57 -70
View File
@@ -25,9 +25,7 @@
#include "details/Fence.h" #include "details/Fence.h"
#include "details/IndexBuffer.h" #include "details/IndexBuffer.h"
#include "details/IndirectLight.h" #include "details/IndirectLight.h"
#include "details/InstanceBuffer.h"
#include "details/Material.h" #include "details/Material.h"
#include "details/MorphTargetBuffer.h"
#include "details/Renderer.h" #include "details/Renderer.h"
#include "details/Scene.h" #include "details/Scene.h"
#include "details/SkinningBuffer.h" #include "details/SkinningBuffer.h"
@@ -38,39 +36,28 @@
#include "details/VertexBuffer.h" #include "details/VertexBuffer.h"
#include "details/View.h" #include "details/View.h"
#include <filament/ColorGrading.h>
#include <filament/Engine.h> #include <filament/Engine.h>
#include <filament/MaterialEnums.h> #include <filament/MaterialEnums.h>
#include <private/filament/DescriptorSets.h> #include <private/filament/DescriptorSets.h>
#include <private/filament/EngineEnums.h> #include <private/filament/EngineEnums.h>
#include <private/filament/Variant.h>
#include <private/backend/PlatformFactory.h> #include <private/backend/PlatformFactory.h>
#include <backend/DriverEnums.h> #include <backend/DriverEnums.h>
#include <utils/Allocator.h>
#include <utils/CallStack.h>
#include <utils/compiler.h> #include <utils/compiler.h>
#include <utils/debug.h> #include <utils/debug.h>
#include <utils/Invocable.h> #include <utils/Invocable.h>
#include <utils/Log.h> #include <utils/Log.h>
#include <utils/ostream.h>
#include <utils/Panic.h> #include <utils/Panic.h>
#include <utils/PrivateImplementation-impl.h> #include <utils/PrivateImplementation-impl.h>
#include <utils/Systrace.h> #include <utils/Systrace.h>
#include <utils/ThreadUtils.h> #include <utils/ThreadUtils.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <algorithm> #include <algorithm>
#include <chrono>
#include <initializer_list> #include <initializer_list>
#include <memory> #include <memory>
#include <mutex>
#include <new>
#include <optional> #include <optional>
#include <thread> #include <thread>
#include <string_view> #include <string_view>
@@ -79,7 +66,6 @@
#include <stddef.h> #include <stddef.h>
#include <stdint.h> #include <stdint.h>
#include <stdlib.h>
#include <string.h> #include <string.h>
#include "generated/resources/materials.h" #include "generated/resources/materials.h"
@@ -115,7 +101,7 @@ Engine* FEngine::create(Builder const& builder) {
// Normally we launch a thread and create the context and Driver from there (see FEngine::loop). // Normally we launch a thread and create the context and Driver from there (see FEngine::loop).
// In the single-threaded case, we do so in the here and now. // In the single-threaded case, we do so in the here and now.
if constexpr (!UTILS_HAS_THREADING) { if (!UTILS_HAS_THREADING) {
Platform* platform = builder->mPlatform; Platform* platform = builder->mPlatform;
void* const sharedContext = builder->mSharedContext; void* const sharedContext = builder->mSharedContext;
@@ -158,7 +144,7 @@ Engine* FEngine::create(Builder const& builder) {
// now we can initialize the largest part of the engine // now we can initialize the largest part of the engine
instance->init(); instance->init();
if constexpr (!UTILS_HAS_THREADING) { if (!UTILS_HAS_THREADING) {
instance->execute(); instance->execute();
} }
@@ -177,7 +163,7 @@ void FEngine::create(Builder const& builder, Invocable<void(void*)>&& callback)
instance->mDriverThread = std::thread(&FEngine::loop, instance); instance->mDriverThread = std::thread(&FEngine::loop, instance);
// launch a thread to call the callback -- so it can't do any damage. // launch a thread to call the callback -- so it can't do any damage.
std::thread callbackThread = std::thread([instance, callback = std::move(callback)] { std::thread callbackThread = std::thread([instance, callback = std::move(callback)]() {
instance->mDriverBarrier.await(); instance->mDriverBarrier.await();
callback(instance); callback(instance);
}); });
@@ -210,7 +196,7 @@ FEngine* FEngine::getEngine(void* token) {
#endif #endif
// These must be static because only a pointer is copied to the render stream // these must be static because only a pointer is copied to the render stream
// Note that these coordinates are specified in OpenGL clip space. Other backends can transform // Note that these coordinates are specified in OpenGL clip space. Other backends can transform
// these in the vertex shader as needed. // these in the vertex shader as needed.
static constexpr float4 sFullScreenTriangleVertices[3] = { static constexpr float4 sFullScreenTriangleVertices[3] = {
@@ -220,7 +206,7 @@ static constexpr float4 sFullScreenTriangleVertices[3] = {
}; };
// these must be static because only a pointer is copied to the render stream // these must be static because only a pointer is copied to the render stream
static constexpr uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 }; static const uint16_t sFullScreenTriangleIndices[3] = { 0, 1, 2 };
FEngine::FEngine(Builder const& builder) : FEngine::FEngine(Builder const& builder) :
mBackend(builder->mBackend), mBackend(builder->mBackend),
@@ -230,6 +216,7 @@ FEngine::FEngine(Builder const& builder) :
mPostProcessManager(*this), mPostProcessManager(*this),
mEntityManager(EntityManager::get()), mEntityManager(EntityManager::get()),
mRenderableManager(*this), mRenderableManager(*this),
mTransformManager(),
mLightManager(*this), mLightManager(*this),
mCameraManager(*this), mCameraManager(*this),
mCommandBufferQueue( mCommandBufferQueue(
@@ -287,7 +274,7 @@ uint32_t FEngine::getJobSystemThreadPoolSize(Config const& config) noexcept {
} }
// 1 thread for the user, 1 thread for the backend // 1 thread for the user, 1 thread for the backend
int threadCount = int(std::thread::hardware_concurrency()) - 2; int threadCount = (int)std::thread::hardware_concurrency() - 2;
// make sure we have at least 1 thread though // make sure we have at least 1 thread though
threadCount = std::max(1, threadCount); threadCount = std::max(1, threadCount);
return threadCount; return threadCount;
@@ -360,8 +347,8 @@ void FEngine::init() {
} }
// initialize the dummy textures so that their contents are not undefined // initialize the dummy textures so that their contents are not undefined
static constexpr uint32_t zeroes[6] = {}; static const uint32_t zeroes[6] = {0};
static constexpr uint32_t ones = 0xffffffff; static const uint32_t ones = 0xffffffff;
mDefaultIblTexture = downcast(Texture::Builder() mDefaultIblTexture = downcast(Texture::Builder()
.width(1).height(1).levels(1) .width(1).height(1).levels(1)
@@ -373,7 +360,7 @@ void FEngine::init() {
{ zeroes, sizeof(zeroes), Texture::Format::RGBA, Texture::Type::UBYTE }); { zeroes, sizeof(zeroes), Texture::Format::RGBA, Texture::Type::UBYTE });
// 3 bands = 9 float3 // 3 bands = 9 float3
constexpr float sh[9 * 3] = { 0.0f }; const float sh[9 * 3] = { 0.0f };
mDefaultIbl = downcast(IndirectLight::Builder() mDefaultIbl = downcast(IndirectLight::Builder()
.irradiance(3, reinterpret_cast<const float3*>(sh)) .irradiance(3, reinterpret_cast<const float3*>(sh))
.build(*this)); .build(*this));
@@ -440,10 +427,10 @@ void FEngine::init() {
#endif #endif
break; break;
} }
mDefaultMaterial = downcast(defaultMaterialBuilder.build(*this)); mDefaultMaterial = downcast(defaultMaterialBuilder.build(*const_cast<FEngine*>(this)));
constexpr float3 dummyPositions[1] = {}; float3 dummyPositions[1] = {};
constexpr short4 dummyTangents[1] = {}; short4 dummyTangents[1] = {};
mDummyMorphTargetBuffer->setPositionsAt(*this, 0, dummyPositions, 1, 0); mDummyMorphTargetBuffer->setPositionsAt(*this, 0, dummyPositions, 1, 0);
mDummyMorphTargetBuffer->setTangentsAt(*this, 0, dummyTangents, 1, 0); mDummyMorphTargetBuffer->setTangentsAt(*this, 0, dummyTangents, 1, 0);
@@ -466,7 +453,7 @@ void FEngine::init() {
mPostProcessManager.init(); mPostProcessManager.init();
mDebugRegistry.registerProperty("d.shadowmap.debug_directional_shadowmap", mDebugRegistry.registerProperty("d.shadowmap.debug_directional_shadowmap",
&debug.shadowmap.debug_directional_shadowmap, [this] { &debug.shadowmap.debug_directional_shadowmap, [this]() {
mMaterials.forEach([this](FMaterial* material) { mMaterials.forEach([this](FMaterial* material) {
if (material->getMaterialDomain() == MaterialDomain::SURFACE) { if (material->getMaterialDomain() == MaterialDomain::SURFACE) {
@@ -482,7 +469,7 @@ void FEngine::init() {
}); });
mDebugRegistry.registerProperty("d.lighting.debug_froxel_visualization", mDebugRegistry.registerProperty("d.lighting.debug_froxel_visualization",
&debug.lighting.debug_froxel_visualization, [this] { &debug.lighting.debug_froxel_visualization, [this]() {
mMaterials.forEach([this](FMaterial* material) { mMaterials.forEach([this](FMaterial* material) {
if (material->getMaterialDomain() == MaterialDomain::SURFACE) { if (material->getMaterialDomain() == MaterialDomain::SURFACE) {
@@ -620,7 +607,7 @@ void FEngine::shutdown() {
// now wait for all pending commands to be executed and the thread to exit // now wait for all pending commands to be executed and the thread to exit
mCommandBufferQueue.requestExit(); mCommandBufferQueue.requestExit();
if constexpr (!UTILS_HAS_THREADING) { if (!UTILS_HAS_THREADING) {
execute(); execute();
getDriverApi().terminate(); getDriverApi().terminate();
} else { } else {
@@ -651,13 +638,13 @@ void FEngine::prepare() {
DriverApi& driver = getDriverApi(); DriverApi& driver = getDriverApi();
for (auto& materialInstanceList: mMaterialInstances) { for (auto& materialInstanceList: mMaterialInstances) {
materialInstanceList.second.forEach([&driver](FMaterialInstance const* item) { materialInstanceList.second.forEach([&driver](FMaterialInstance* item) {
item->commit(driver); item->commit(driver);
}); });
} }
mMaterials.forEach([](FMaterial* material) { mMaterials.forEach([](FMaterial* material) {
#if FILAMENT_ENABLE_MATDBG // NOLINT(*-include-cleaner) #if FILAMENT_ENABLE_MATDBG
material->checkProgramEdits(); material->checkProgramEdits();
#endif #endif
}); });
@@ -681,7 +668,7 @@ void FEngine::flushAndWait() {
flushAndWait(FENCE_WAIT_FOR_EVER); flushAndWait(FENCE_WAIT_FOR_EVER);
} }
bool FEngine::flushAndWait(uint64_t const timeout) { bool FEngine::flushAndWait(uint64_t timeout) {
FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused()) FILAMENT_CHECK_PRECONDITION(!mCommandBufferQueue.isPaused())
<< "Cannot call Engine::flushAndWait() when rendering thread is paused!"; << "Cannot call Engine::flushAndWait() when rendering thread is paused!";
@@ -762,7 +749,7 @@ int FEngine::loop() {
} }
#endif #endif
#if FILAMENT_ENABLE_FGVIEWER // NOLINT(*-include-cleaner) #if FILAMENT_ENABLE_FGVIEWER
#ifdef __ANDROID__ #ifdef __ANDROID__
const char* fgviewerPortString = "8085"; const char* fgviewerPortString = "8085";
#else #else
@@ -792,9 +779,9 @@ int FEngine::loop() {
return 0; return 0;
} }
void FEngine::flushCommandBuffer(CommandBufferQueue& commandBufferQueue) const { void FEngine::flushCommandBuffer(CommandBufferQueue& commandQueue) {
getDriver().purge(); getDriver().purge();
commandBufferQueue.flush(); commandQueue.flush();
} }
const FMaterial* FEngine::getSkyboxMaterial() const noexcept { const FMaterial* FEngine::getSkyboxMaterial() const noexcept {
@@ -815,7 +802,7 @@ const FMaterial* FEngine::getSkyboxMaterial() const noexcept {
*/ */
template<typename T, typename ... ARGS> template<typename T, typename ... ARGS>
T* FEngine::create(ResourceList<T>& list, inline T* FEngine::create(ResourceList<T>& list,
typename T::Builder const& builder, ARGS&& ... args) noexcept { typename T::Builder const& builder, ARGS&& ... args) noexcept {
T* p = mHeapAllocator.make<T>(*this, builder, std::forward<ARGS>(args)...); T* p = mHeapAllocator.make<T>(*this, builder, std::forward<ARGS>(args)...);
if (UTILS_LIKELY(p)) { if (UTILS_LIKELY(p)) {
@@ -893,7 +880,7 @@ FMaterialInstance* FEngine::createMaterialInstance(const FMaterial* material,
const FMaterialInstance* other, const char* name) noexcept { const FMaterialInstance* other, const char* name) noexcept {
FMaterialInstance* p = mHeapAllocator.make<FMaterialInstance>(*this, other, name); FMaterialInstance* p = mHeapAllocator.make<FMaterialInstance>(*this, other, name);
if (UTILS_LIKELY(p)) { if (UTILS_LIKELY(p)) {
auto const pos = mMaterialInstances.emplace(material, "MaterialInstance"); auto pos = mMaterialInstances.emplace(material, "MaterialInstance");
pos.first->second.insert(p); pos.first->second.insert(p);
} }
return p; return p;
@@ -971,7 +958,7 @@ FCamera* FEngine::createCamera(Entity const entity) noexcept {
} }
FCamera* FEngine::getCameraComponent(Entity const entity) noexcept { FCamera* FEngine::getCameraComponent(Entity const entity) noexcept {
auto const ci = mCameraManager.getInstance(entity); auto ci = mCameraManager.getInstance(entity);
return ci ? mCameraManager.getCamera(ci) : nullptr; return ci ? mCameraManager.getCamera(ci) : nullptr;
} }
@@ -1024,16 +1011,16 @@ void FEngine::cleanupResourceListLocked(Lock& lock, ResourceList<T>&& list) {
template<typename T> template<typename T>
UTILS_ALWAYS_INLINE UTILS_ALWAYS_INLINE
bool FEngine::isValid(const T* ptr, ResourceList<T> const& list) const { inline bool FEngine::isValid(const T* ptr, ResourceList<T> const& list) const {
auto& l = const_cast<ResourceList<T>&>(list); auto& l = const_cast<ResourceList<T>&>(list);
return l.find(ptr) != l.end(); return l.find(ptr) != l.end();
} }
template<typename T> template<typename T>
UTILS_ALWAYS_INLINE UTILS_ALWAYS_INLINE
bool FEngine::terminateAndDestroy(const T* p, ResourceList<T>& list) { inline bool FEngine::terminateAndDestroy(const T* ptr, ResourceList<T>& list) {
if (p == nullptr) return true; if (ptr == nullptr) return true;
bool const success = list.remove(p); bool const success = list.remove(ptr);
#if UTILS_HAS_RTTI #if UTILS_HAS_RTTI
auto typeName = CallStack::typeName<T>(); auto typeName = CallStack::typeName<T>();
@@ -1043,19 +1030,19 @@ bool FEngine::terminateAndDestroy(const T* p, ResourceList<T>& list) {
#endif #endif
if (ASSERT_PRECONDITION_NON_FATAL(success, if (ASSERT_PRECONDITION_NON_FATAL(success,
"Object %s at %p doesn't exist (double free?)", typeNameCStr, p)) { "Object %s at %p doesn't exist (double free?)", typeNameCStr, ptr)) {
const_cast<T*>(p)->terminate(*this); const_cast<T*>(ptr)->terminate(*this);
mHeapAllocator.destroy(const_cast<T*>(p)); mHeapAllocator.destroy(const_cast<T*>(ptr));
} }
return success; return success;
} }
template<typename T, typename Lock> template<typename T, typename Lock>
UTILS_ALWAYS_INLINE UTILS_ALWAYS_INLINE
bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* p, ResourceList<T>& list) { inline bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* ptr, ResourceList<T>& list) {
if (p == nullptr) return true; if (ptr == nullptr) return true;
lock.lock(); lock.lock();
bool const success = list.remove(p); bool const success = list.remove(ptr);
lock.unlock(); lock.unlock();
#if UTILS_HAS_RTTI #if UTILS_HAS_RTTI
@@ -1066,9 +1053,9 @@ bool FEngine::terminateAndDestroyLocked(Lock& lock, const T* p, ResourceList<T>&
#endif #endif
if (ASSERT_PRECONDITION_NON_FATAL(success, if (ASSERT_PRECONDITION_NON_FATAL(success,
"Object %s at %p doesn't exist (double free?)", typeNameCStr, p)) { "Object %s at %p doesn't exist (double free?)", typeNameCStr, ptr)) {
const_cast<T*>(p)->terminate(*this); const_cast<T*>(ptr)->terminate(*this);
mHeapAllocator.destroy(const_cast<T*>(p)); mHeapAllocator.destroy(const_cast<T*>(ptr));
} }
return success; return success;
} }
@@ -1161,11 +1148,11 @@ bool FEngine::destroy(const FInstanceBuffer* p){
} }
UTILS_NOINLINE UTILS_NOINLINE
bool FEngine::destroy(const FMaterial* p) { bool FEngine::destroy(const FMaterial* ptr) {
if (p == nullptr) return true; if (ptr == nullptr) return true;
bool const success = terminateAndDestroy(p, mMaterials); bool const success = terminateAndDestroy(ptr, mMaterials);
if (UTILS_LIKELY(success)) { if (UTILS_LIKELY(success)) {
auto const pos = mMaterialInstances.find(p); auto pos = mMaterialInstances.find(ptr);
if (UTILS_LIKELY(pos != mMaterialInstances.cend())) { if (UTILS_LIKELY(pos != mMaterialInstances.cend())) {
mMaterialInstances.erase(pos); mMaterialInstances.erase(pos);
} }
@@ -1174,8 +1161,8 @@ bool FEngine::destroy(const FMaterial* p) {
} }
UTILS_NOINLINE UTILS_NOINLINE
bool FEngine::destroy(const FMaterialInstance* p) { bool FEngine::destroy(const FMaterialInstance* ptr) {
if (p == nullptr) return true; if (ptr == nullptr) return true;
// Check that the material instance we're destroying is not in use in the RenderableManager // Check that the material instance we're destroying is not in use in the RenderableManager
// To do this, we currently need to inspect all render primitives in the RenderableManager // To do this, we currently need to inspect all render primitives in the RenderableManager
@@ -1191,13 +1178,13 @@ bool FEngine::destroy(const FMaterialInstance* p) {
for (size_t j = 0; j < primitiveCount; j++) { for (size_t j = 0; j < primitiveCount; j++) {
auto const* const mi = rcm.getMaterialInstanceAt(ri, 0, j); auto const* const mi = rcm.getMaterialInstanceAt(ri, 0, j);
if (features.engine.debug.assert_material_instance_in_use) { if (features.engine.debug.assert_material_instance_in_use) {
FILAMENT_CHECK_PRECONDITION(mi != p) FILAMENT_CHECK_PRECONDITION(mi != ptr)
<< "destroying MaterialInstance \"" << "destroying MaterialInstance \""
<< mi->getName() << "\" which is still in use by Renderable (entity=" << mi->getName() << "\" which is still in use by Renderable (entity="
<< entity.getId() << ", instance=" << entity.getId() << ", instance="
<< ri.asValue() << ", index=" << j << ")"; << ri.asValue() << ", index=" << j << ")";
} else { } else {
if (UTILS_UNLIKELY(mi == p)) { if (UTILS_UNLIKELY(mi == ptr)) {
slog.e << "destroying MaterialInstance \"" slog.e << "destroying MaterialInstance \""
<< mi->getName() << "\" which is still in use by Renderable (entity=" << mi->getName() << "\" which is still in use by Renderable (entity="
<< entity.getId() << ", instance=" << entity.getId() << ", instance="
@@ -1209,11 +1196,11 @@ bool FEngine::destroy(const FMaterialInstance* p) {
} }
} }
if (p->isDefaultInstance()) return false; if (ptr->isDefaultInstance()) return false;
auto const pos = mMaterialInstances.find(p->getMaterial()); auto pos = mMaterialInstances.find(ptr->getMaterial());
assert_invariant(pos != mMaterialInstances.cend()); assert_invariant(pos != mMaterialInstances.cend());
if (pos != mMaterialInstances.cend()) { if (pos != mMaterialInstances.cend()) {
return terminateAndDestroy(p, pos->second); return terminateAndDestroy(ptr, pos->second);
} }
// this shouldn't happen, this would be double-free // this shouldn't happen, this would be double-free
return false; return false;
@@ -1266,7 +1253,7 @@ bool FEngine::isValid(const FMaterial* m, const FMaterialInstance* p) const {
} }
// then find the material instance list for that material // then find the material instance list for that material
auto const it = mMaterialInstances.find(m); auto it = mMaterialInstances.find(m);
if (it == mMaterialInstances.end()) { if (it == mMaterialInstances.end()) {
// this could happen if this material has no material instances at all // this could happen if this material has no material instances at all
return false; return false;
@@ -1355,7 +1342,7 @@ void* FEngine::streamAlloc(size_t const size, size_t const alignment) noexcept {
bool FEngine::execute() { bool FEngine::execute() {
// wait until we get command buffers to be executed (or thread exit requested) // wait until we get command buffers to be executed (or thread exit requested)
auto const buffers = mCommandBufferQueue.waitForCommands(); auto buffers = mCommandBufferQueue.waitForCommands();
if (UTILS_UNLIKELY(buffers.empty())) { if (UTILS_UNLIKELY(buffers.empty())) {
return false; return false;
} }
@@ -1394,7 +1381,7 @@ Engine::FeatureLevel FEngine::getSupportedFeatureLevel() const noexcept {
Engine::FeatureLevel FEngine::setActiveFeatureLevel(FeatureLevel featureLevel) { Engine::FeatureLevel FEngine::setActiveFeatureLevel(FeatureLevel featureLevel) {
FILAMENT_CHECK_PRECONDITION(featureLevel <= getSupportedFeatureLevel()) FILAMENT_CHECK_PRECONDITION(featureLevel <= getSupportedFeatureLevel())
<< "Feature level " << unsigned(featureLevel) << " not supported"; << "Feature level " << (unsigned)featureLevel << " not supported";
FILAMENT_CHECK_PRECONDITION(mActiveFeatureLevel >= FeatureLevel::FEATURE_LEVEL_1) FILAMENT_CHECK_PRECONDITION(mActiveFeatureLevel >= FeatureLevel::FEATURE_LEVEL_1)
<< "Cannot adjust feature level beyond 0 at runtime"; << "Cannot adjust feature level beyond 0 at runtime";
return (mActiveFeatureLevel = std::max(mActiveFeatureLevel, featureLevel)); return (mActiveFeatureLevel = std::max(mActiveFeatureLevel, featureLevel));
@@ -1413,7 +1400,7 @@ void FEngine::unprotected() noexcept {
mUnprotectedDummySwapchain->makeCurrent(getDriverApi()); mUnprotectedDummySwapchain->makeCurrent(getDriverApi());
} }
bool FEngine::setFeatureFlag(char const* name, bool const value) const noexcept { bool FEngine::setFeatureFlag(char const* name, bool const value) noexcept {
auto* const p = getFeatureFlagPtr(name); auto* const p = getFeatureFlagPtr(name);
if (p) { if (p) {
*p = value; *p = value;
@@ -1484,7 +1471,7 @@ Engine::Builder& Engine::Builder::feature(char const* name, bool const value) no
} }
Engine::Builder& Engine::Builder::features(std::initializer_list<char const *> const list) noexcept { Engine::Builder& Engine::Builder::features(std::initializer_list<char const *> const list) noexcept {
for (auto const name : list) { for (auto name : list) {
if (name) { if (name) {
feature(name, true); feature(name, true);
} }
@@ -1513,15 +1500,15 @@ Engine::Config Engine::BuilderDetails::validateConfig(Config config) noexcept {
// Use at least the defaults set by the build system // Use at least the defaults set by the build system
config.minCommandBufferSizeMB = std::max( config.minCommandBufferSizeMB = std::max(
config.minCommandBufferSizeMB, config.minCommandBufferSizeMB,
uint32_t(FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB)); // NOLINT(*-include-cleaner) (uint32_t)FILAMENT_MIN_COMMAND_BUFFERS_SIZE_IN_MB);
config.perFrameCommandsSizeMB = std::max( config.perFrameCommandsSizeMB = std::max(
config.perFrameCommandsSizeMB, config.perFrameCommandsSizeMB,
uint32_t(FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB)); // NOLINT(*-include-cleaner) (uint32_t)FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB);
config.perRenderPassArenaSizeMB = std::max( config.perRenderPassArenaSizeMB = std::max(
config.perRenderPassArenaSizeMB, config.perRenderPassArenaSizeMB,
uint32_t(FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB)); // NOLINT(*-include-cleaner) (uint32_t)FILAMENT_PER_RENDER_PASS_ARENA_SIZE_IN_MB);
config.commandBufferSizeMB = std::max( config.commandBufferSizeMB = std::max(
config.commandBufferSizeMB, config.commandBufferSizeMB,
+8 -9
View File
@@ -61,8 +61,6 @@
#include <filament/Texture.h> #include <filament/Texture.h>
#include <filament/VertexBuffer.h> #include <filament/VertexBuffer.h>
#include <backend/DriverEnums.h>
#include <utils/Allocator.h> #include <utils/Allocator.h>
#include <utils/compiler.h> #include <utils/compiler.h>
#include <utils/CountDownLatch.h> #include <utils/CountDownLatch.h>
@@ -124,11 +122,12 @@ class ResourceAllocator;
*/ */
class FEngine : public Engine { class FEngine : public Engine {
public: public:
void* operator new(std::size_t const size) noexcept {
inline void* operator new(std::size_t const size) noexcept {
return utils::aligned_alloc(size, alignof(FEngine)); return utils::aligned_alloc(size, alignof(FEngine));
} }
void operator delete(void* p) noexcept { inline void operator delete(void* p) noexcept {
utils::aligned_free(p); utils::aligned_free(p);
} }
@@ -491,7 +490,7 @@ public:
backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; } backend::Handle<backend::HwTexture> getOneTextureArray() const { return mDummyOneTextureArray; }
backend::Handle<backend::HwTexture> getZeroTextureArray() const { return mDummyZeroTextureArray; } backend::Handle<backend::HwTexture> getZeroTextureArray() const { return mDummyZeroTextureArray; }
static constexpr size_t MiB = 1024u * 1024u; static constexpr const size_t MiB = 1024u * 1024u;
size_t getMinCommandBufferSize() const noexcept { return mConfig.minCommandBufferSizeMB * MiB; } size_t getMinCommandBufferSize() const noexcept { return mConfig.minCommandBufferSizeMB * MiB; }
size_t getCommandBufferSize() const noexcept { return mConfig.commandBufferSizeMB * MiB; } size_t getCommandBufferSize() const noexcept { return mConfig.commandBufferSizeMB * MiB; }
size_t getPerFrameCommandsSize() const noexcept { return mConfig.perFrameCommandsSizeMB * MiB; } size_t getPerFrameCommandsSize() const noexcept { return mConfig.perFrameCommandsSizeMB * MiB; }
@@ -511,15 +510,15 @@ public:
void resetBackendState() noexcept; void resetBackendState() noexcept;
#endif #endif
backend::Driver& getDriver() const noexcept { return *mDriver; }
private: private:
explicit FEngine(Builder const& builder); explicit FEngine(Builder const& builder);
void init(); void init();
void shutdown(); void shutdown();
int loop(); int loop();
void flushCommandBuffer(backend::CommandBufferQueue& commandBufferQueue) const; void flushCommandBuffer(backend::CommandBufferQueue& commandBufferQueue);
backend::Driver& getDriver() const noexcept { return *mDriver; }
template<typename T> template<typename T>
bool isValid(const T* ptr, ResourceList<T> const& list) const; bool isValid(const T* ptr, ResourceList<T> const& list) const;
@@ -730,7 +729,7 @@ public:
return { mFeatures.data(), mFeatures.size() }; return { mFeatures.data(), mFeatures.size() };
} }
bool setFeatureFlag(char const* name, bool value) const noexcept; bool setFeatureFlag(char const* name, bool value) noexcept;
std::optional<bool> getFeatureFlag(char const* name) const noexcept; std::optional<bool> getFeatureFlag(char const* name) const noexcept;
bool* getFeatureFlagPtr(std::string_view name, bool allowConstant = false) const noexcept; bool* getFeatureFlagPtr(std::string_view name, bool allowConstant = false) const noexcept;
}; };
+7 -7
View File
@@ -196,10 +196,10 @@ void FMaterialInstance::commit(DriverApi& driver) const {
for (auto const& [binding, p]: mTextureParameters) { for (auto const& [binding, p]: mTextureParameters) {
assert_invariant(p.texture); assert_invariant(p.texture);
// TODO: figure out a way to do this more efficiently (isValid() is a hashmap lookup) // TODO: figure out a way to do this more efficiently (isValid() is a hashmap lookup)
FEngine const& engine = mMaterial->getEngine(); FEngine& engine = mMaterial->getEngine();
FILAMENT_CHECK_PRECONDITION(engine.isValid(p.texture)) FILAMENT_CHECK_PRECONDITION(engine.isValid(p.texture))
<< "Invalid texture still bound to MaterialInstance: '" << getName() << "'\n"; << "Invalid texture still bound to MaterialInstance: '" << getName() << "'\n";
Handle<HwTexture> const handle = p.texture->getHwHandleForSampling(); Handle<HwTexture> handle = p.texture->getHwHandleForSampling();
assert_invariant(handle); assert_invariant(handle);
mDescriptorSet.setSampler(binding, handle, p.params); mDescriptorSet.setSampler(binding, handle, p.params);
} }
@@ -216,7 +216,7 @@ void FMaterialInstance::commit(DriverApi& driver) const {
void FMaterialInstance::setParameter(std::string_view const name, void FMaterialInstance::setParameter(std::string_view const name,
Handle<HwTexture> texture, SamplerParams const params) { Handle<HwTexture> texture, SamplerParams const params) {
auto const binding = mMaterial->getSamplerBinding(name); auto binding = mMaterial->getSamplerBinding(name);
mDescriptorSet.setSampler(binding, texture, params); mDescriptorSet.setSampler(binding, texture, params);
} }
@@ -243,7 +243,7 @@ void FMaterialInstance::setParameterImpl(std::string_view const name,
} }
#endif #endif
auto const binding = mMaterial->getSamplerBinding(name); auto binding = mMaterial->getSamplerBinding(name);
if (texture && texture->textureHandleCanMutate()) { if (texture && texture->textureHandleCanMutate()) {
mTextureParameters[binding] = { texture, sampler.getSamplerParams() }; mTextureParameters[binding] = { texture, sampler.getSamplerParams() };
} else { } else {
@@ -328,13 +328,13 @@ const char* FMaterialInstance::getName() const noexcept {
void FMaterialInstance::use(FEngine::DriverApi& driver) const { void FMaterialInstance::use(FEngine::DriverApi& driver) const {
if (UTILS_UNLIKELY(mMissingSamplerDescriptors.any())) { if (UTILS_UNLIKELY(mMissingSamplerDescriptors.any())) {
std::call_once(mMissingSamplersFlag, [this] { std::call_once(mMissingSamplersFlag, [this]() {
auto const& list = mMaterial->getSamplerInterfaceBlock().getSamplerInfoList(); auto const& list = mMaterial->getSamplerInterfaceBlock().getSamplerInfoList();
slog.w << "sampler parameters not set in MaterialInstance \"" slog.w << "sampler parameters not set in MaterialInstance \""
<< mName.c_str_safe() << "\" or Material \"" << mName.c_str_safe() << "\" or Material \""
<< mMaterial->getName().c_str_safe() << "\":\n"; << mMaterial->getName().c_str_safe() << "\":\n";
mMissingSamplerDescriptors.forEachSetBit([&list](descriptor_binding_t binding) { mMissingSamplerDescriptors.forEachSetBit([&list](descriptor_binding_t binding) {
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) { auto pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
return item.binding == binding; return item.binding == binding;
}); });
// just safety-check, should never fail // just safety-check, should never fail
@@ -368,7 +368,7 @@ void FMaterialInstance::fixMissingSamplers() const {
// here we need to set the samplers that are missing // here we need to set the samplers that are missing
auto const& list = mMaterial->getSamplerInterfaceBlock().getSamplerInfoList(); auto const& list = mMaterial->getSamplerInterfaceBlock().getSamplerInfoList();
missingSamplerDescriptors.forEachSetBit([this, &list](descriptor_binding_t binding) { missingSamplerDescriptors.forEachSetBit([this, &list](descriptor_binding_t binding) {
auto const pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) { auto pos = std::find_if(list.begin(), list.end(), [binding](const auto& item) {
return item.binding == binding; return item.binding == binding;
}); });
+2 -11
View File
@@ -94,8 +94,6 @@ public:
backend::CullingMode getCullingMode() const noexcept { return mCulling; } backend::CullingMode getCullingMode() const noexcept { return mCulling; }
backend::CullingMode getShadowCullingMode() const noexcept { return mShadowCulling; }
bool isColorWriteEnabled() const noexcept { return mColorWrite; } bool isColorWriteEnabled() const noexcept { return mColorWrite; }
bool isDepthWriteEnabled() const noexcept { return mDepthWrite; } bool isDepthWriteEnabled() const noexcept { return mDepthWrite; }
@@ -139,11 +137,6 @@ public:
void setCullingMode(CullingMode const culling) noexcept { mCulling = culling; } void setCullingMode(CullingMode const culling) noexcept { mCulling = culling; }
void setCullingMode(CullingMode const color, CullingMode const shadow) noexcept {
mCulling = color;
mShadowCulling = shadow;
}
void setColorWrite(bool const enable) noexcept { mColorWrite = enable; } void setColorWrite(bool const enable) noexcept { mColorWrite = enable; }
void setDepthWrite(bool const enable) noexcept { mDepthWrite = enable; } void setDepthWrite(bool const enable) noexcept { mDepthWrite = enable; }
@@ -278,9 +271,7 @@ private:
float mSpecularAntiAliasingThreshold = 0.0f; float mSpecularAntiAliasingThreshold = 0.0f;
backend::CullingMode mCulling : 2; backend::CullingMode mCulling : 2;
backend::CullingMode mShadowCulling : 2;
backend::RasterState::DepthFunc mDepthFunc : 3; backend::RasterState::DepthFunc mDepthFunc : 3;
bool mColorWrite : 1; bool mColorWrite : 1;
bool mDepthWrite : 1; bool mDepthWrite : 1;
bool mHasScissor : 1; bool mHasScissor : 1;
@@ -292,8 +283,8 @@ private:
// Scissor rectangle is specified as: Left Bottom Width Height. // Scissor rectangle is specified as: Left Bottom Width Height.
backend::Viewport mScissorRect = { 0, 0, backend::Viewport mScissorRect = { 0, 0,
uint32_t(std::numeric_limits<int32_t>::max()), (uint32_t)std::numeric_limits<int32_t>::max(),
uint32_t(std::numeric_limits<int32_t>::max()) (uint32_t)std::numeric_limits<int32_t>::max()
}; };
utils::CString mName; utils::CString mName;
-5
View File
@@ -546,11 +546,6 @@ void FScene::removeEntities(const Entity* entities, size_t const count) {
} }
} }
UTILS_NOINLINE
void FScene::removeAllEntities() noexcept {
mEntities.clear();
}
UTILS_NOINLINE UTILS_NOINLINE
size_t FScene::getRenderableCount() const noexcept { size_t FScene::getRenderableCount() const noexcept {
FEngine& engine = mEngine; FEngine& engine = mEngine;
-1
View File
@@ -199,7 +199,6 @@ private:
void addEntities(const utils::Entity* entities, size_t count); void addEntities(const utils::Entity* entities, size_t count);
void remove(utils::Entity entity); void remove(utils::Entity entity);
void removeEntities(const utils::Entity* entities, size_t count); void removeEntities(const utils::Entity* entities, size_t count);
void removeAllEntities() noexcept;
size_t getEntityCount() const noexcept { return mEntities.size(); } size_t getEntityCount() const noexcept { return mEntities.size(); }
size_t getRenderableCount() const noexcept; size_t getRenderableCount() const noexcept;
size_t getLightCount() const noexcept; size_t getLightCount() const noexcept;
+2 -2
View File
@@ -1,12 +1,12 @@
Pod::Spec.new do |spec| Pod::Spec.new do |spec|
spec.name = "Filament" spec.name = "Filament"
spec.version = "1.57.0" spec.version = "1.56.7"
spec.license = { :type => "Apache 2.0", :file => "LICENSE" } spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
spec.homepage = "https://google.github.io/filament" spec.homepage = "https://google.github.io/filament"
spec.authors = "Google LLC." 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.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.platform = :ios, "11.0"
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.57.0/filament-v1.57.0-ios.tgz" } spec.source = { :http => "https://github.com/google/filament/releases/download/v1.56.7/filament-v1.56.7-ios.tgz" }
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon. # Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
spec.pod_target_xcconfig = { spec.pod_target_xcconfig = {
@@ -28,7 +28,7 @@
namespace filament { namespace filament {
// update this when a new version of filament wouldn't work with older materials // update this when a new version of filament wouldn't work with older materials
static constexpr size_t MATERIAL_VERSION = 57; static constexpr size_t MATERIAL_VERSION = 56;
/** /**
* Supported shading models * Supported shading models
+9 -2
View File
@@ -704,12 +704,19 @@ FilamentApp::Window::Window(FilamentApp* filamentApp,
::prepareNativeWindow(mWindow); ::prepareNativeWindow(mWindow);
void* metalLayer = nullptr; void* metalLayer = nullptr;
if (config.backend == filament::Engine::Backend::METAL || config.backend == filament::Engine::Backend::VULKAN) { if (config.backend == filament::Engine::Backend::METAL) {
metalLayer = setUpMetalLayer(nativeWindow); metalLayer = setUpMetalLayer(nativeWindow);
// The swap chain on both native Metal and MoltenVK is a CAMetalLayer. // The swap chain on Metal is a CAMetalLayer.
nativeSwapChain = metalLayer; nativeSwapChain = metalLayer;
} }
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
if (config.backend == filament::Engine::Backend::VULKAN) {
// We request a Metal layer for rendering via MoltenVK.
setUpMetalLayer(nativeWindow);
}
#endif
#endif #endif
// Write back the active feature level. // Write back the active feature level.
+3 -11
View File
@@ -222,13 +222,8 @@ bool ApiHandler::handleGetApiShader(struct mg_connection* conn,
} }
void ApiHandler::addMaterial(MaterialRecord const* material) { void ApiHandler::addMaterial(MaterialRecord const* material) {
updateMaterial(material->key);
}
void ApiHandler::updateMaterial(uint32_t key) {
std::unique_lock const lock(mStatusMutex); std::unique_lock const lock(mStatusMutex);
mCurrentStatus++; snprintf(statusMaterialId, sizeof(statusMaterialId), "%8.8x", material->key);
snprintf(statusMaterialId, sizeof(statusMaterialId), "%8.8x", key);
mStatusCondition.notify_all(); mStatusCondition.notify_all();
} }
@@ -293,11 +288,8 @@ bool ApiHandler::handlePost(CivetServer* server, struct mg_connection* conn) {
sstream >> std::hex >> matid >> std::dec >> api >> shaderIndex; sstream >> std::hex >> matid >> std::dec >> api >> shaderIndex;
std::string const shader = sstream.str().substr(sstream.tellg()); std::string const shader = sstream.str().substr(sstream.tellg());
if (!mServer->handleEditCommand(matid, backend::Backend(api), shaderIndex, shader.c_str(), mServer->handleEditCommand(matid, backend::Backend(api), shaderIndex, shader.c_str(),
shader.size())) { shader.size());
return error(__LINE__, uri);
}
updateMaterial(matid);
mg_printf(conn, "HTTP/1.1 200 OK\r\nConnection: close"); mg_printf(conn, "HTTP/1.1 200 OK\r\nConnection: close");
return true; return true;
+1 -3
View File
@@ -55,8 +55,6 @@ private:
bool handleGetStatus(struct mg_connection* conn, struct mg_request_info const* request); bool handleGetStatus(struct mg_connection* conn, struct mg_request_info const* request);
MaterialRecord const* getMaterialRecord(struct mg_request_info const* request); MaterialRecord const* getMaterialRecord(struct mg_request_info const* request);
void updateMaterial(uint32_t key);
DebugServer* mServer; DebugServer* mServer;
std::mutex mStatusMutex; std::mutex mStatusMutex;
@@ -66,7 +64,7 @@ private:
// This variable is to implement a *hanging* effect for /api/status. The call to /api/status // This variable is to implement a *hanging* effect for /api/status. The call to /api/status
// will always block until statusMaterialId is updated again. The client is expected to keep // will always block until statusMaterialId is updated again. The client is expected to keep
// calling /api/status (a constant "pull" to simulate a push). // calling /api/status (a constant "pull" to simulate a push).
uint64_t mCurrentStatus = 0; std::atomic<uint64_t> mCurrentStatus = 0;
SourceFormatter mFormatter; SourceFormatter mFormatter;
}; };
+1 -25
View File
@@ -25,7 +25,6 @@
#include <utils/Log.h> #include <utils/Log.h>
#include <algorithm>
#include <sstream> #include <sstream>
#include <GlslangToSpv.h> #include <GlslangToSpv.h>
@@ -51,30 +50,10 @@ using namespace glslang;
using namespace utils; using namespace utils;
using std::ostream; using std::ostream;
using std::streampos;
using std::stringstream; using std::stringstream;
using std::streampos;
using std::vector; using std::vector;
namespace {
// This is to ensure that the edited material package have the same order of shaders as the output
// of the original material. We use the ordering in the front-end to simplify logic.
template<typename RecordType>
void sortRecords(std::vector<RecordType>& records) {
std::sort(records.begin(), records.end(), [](RecordType const& a, RecordType const& b) -> bool {
if (a.shaderModel != b.shaderModel) {
return a.shaderModel < b.shaderModel;
}
if (a.variant.key != b.variant.key) {
return a.variant.key < b.variant.key;
}
return a.stage < b.stage;
});
}
} // anonymous
// Tiny database of shader text that can import / export MaterialTextChunk and DictionaryTextChunk. // Tiny database of shader text that can import / export MaterialTextChunk and DictionaryTextChunk.
class ShaderIndex { class ShaderIndex {
public: public:
@@ -365,7 +344,6 @@ void ShaderIndex::writeChunks(ostream& stream) {
for (const auto& record : mShaderRecords) { for (const auto& record : mShaderRecords) {
lines.addText(record.shader); lines.addText(record.shader);
} }
sortRecords(mShaderRecords);
filamat::ChunkContainer cc; filamat::ChunkContainer cc;
const auto& dchunk = cc.push<DictionaryTextChunk>(std::move(lines), mDictTag); const auto& dchunk = cc.push<DictionaryTextChunk>(std::move(lines), mDictTag);
@@ -428,8 +406,6 @@ void BlobIndex::writeChunks(ostream& stream) {
} }
}; };
sortRecords(mShaderRecords);
// Apply SMOL-V compression and write out the results. // Apply SMOL-V compression and write out the results.
filamat::ChunkContainer cc; filamat::ChunkContainer cc;
cc.push<MaterialBinaryChunk>(std::move(mShaderRecords), ChunkType::MaterialSpirv); cc.push<MaterialBinaryChunk>(std::move(mShaderRecords), ChunkType::MaterialSpirv);
+1 -1
View File
@@ -34,7 +34,7 @@ std::string SourceFormatter::format(char const* source) {
while (fgets(output, 1024, fp) != NULL) {} while (fgets(output, 1024, fp) != NULL) {}
int status = pclose(fp); int status = pclose(fp);
if (!fp || WEXITSTATUS(status)) { if (!fp || !WEXITSTATUS(status)) {
std::call_once(mClangWarningFlag, []() { std::call_once(mClangWarningFlag, []() {
utils::slog.w << "[matdbg] unable to run clang-format to format shader file. " utils::slog.w << "[matdbg] unable to run clang-format to format shader file. "
<< "Please make sure it's installed." << utils::io::endl; << "Please make sure it's installed." << utils::io::endl;
+1 -20
View File
@@ -240,25 +240,6 @@ function(add_demo NAME)
endif() endif()
endfunction() endfunction()
function(add_demo2 NAME)
include_directories(${GENERATION_ROOT})
if (APPLE)
add_executable(${NAME} helper.h helper.mm ${NAME}.cpp)
target_link_libraries(${NAME} PRIVATE sample-resources)
target_compile_options(${NAME} PRIVATE ${COMPILER_FLAGS})
set_target_properties(${NAME} PROPERTIES FOLDER Samples)
# This is needed after XCode 15.3
target_link_libraries(${NAME} PUBLIC "-framework Cocoa -framework QuartzCore" sdl2)
set_target_properties(${NAME} PROPERTIES BUILD_WITH_INSTALL_RPATH TRUE)
set_target_properties(${NAME} PROPERTIES INSTALL_RPATH /usr/local/lib)
else()
add_demo(${NAME})
endif()
target_link_libraries(${NAME} PRIVATE gltfio)
endfunction()
if (NOT ANDROID) if (NOT ANDROID)
add_demo(animation) add_demo(animation)
add_demo(depthtesting) add_demo(depthtesting)
@@ -268,7 +249,7 @@ if (NOT ANDROID)
add_demo(heightfield) add_demo(heightfield)
add_demo(hellomorphing) add_demo(hellomorphing)
add_demo(hellopbr) add_demo(hellopbr)
add_demo2(hellotriangle) add_demo(hellotriangle)
add_demo(helloskinning) add_demo(helloskinning)
add_demo(helloskinningbuffer) add_demo(helloskinningbuffer)
add_demo(helloskinningbuffer_morebones) add_demo(helloskinningbuffer_morebones)
+167 -166
View File
@@ -1,191 +1,192 @@
#include <fstream> /*
#include <iostream> * 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 <filament/Camera.h> #include <filament/Camera.h>
#include <filament/Engine.h> #include <filament/Engine.h>
#include <filament/IndexBuffer.h> #include <filament/IndexBuffer.h>
#include <filament/LightManager.h> #include <filament/Material.h>
#include <filament/MaterialInstance.h>
#include <filament/RenderableManager.h> #include <filament/RenderableManager.h>
#include <filament/Renderer.h>
#include <filament/Scene.h> #include <filament/Scene.h>
#include <filament/Skybox.h> #include <filament/Skybox.h>
#include <filament/TransformManager.h>
#include <filament/VertexBuffer.h>
#include <filament/View.h> #include <filament/View.h>
#include <filament/Viewport.h>
#include <filamat/MaterialBuilder.h>
#include <utils/EntityManager.h> #include <utils/EntityManager.h>
#include <utils/Log.h>
#include <math/norm.h> #include <filamentapp/Config.h>
#include <filamentapp/FilamentApp.h>
#include <gltfio/AssetLoader.h> #include <getopt/getopt.h>
#include <gltfio/ResourceLoader.h>
#include <SDL.h> #include <cmath>
#include <SDL_syswm.h> #include <iostream>
#include <SDL_video.h>
#if defined(__linux__) #include "generated/resources/resources.h"
void* getNativeWindow(SDL_Window* sdlWindow) {
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
SDL_GetWindowWMInfo(sdlWindow, &wmi);
if (wmi.subsystem == SDL_SYSWM_X11) {
Window win = (Window) wmi.info.x11.window;
return (void*) win;
} else {
std::cout << "Unknown SDL subsystem";
}
return nullptr;
}
#elif defined(__APPLE__)
#include "helper.h"
#endif
SDL_Window* createSDLwindow() {
uint32_t windowFlags = SDL_WINDOW_SHOWN | SDL_WINDOW_RESIZABLE | SDL_WINDOW_ALLOW_HIGHDPI;
SDL_Window* win = SDL_CreateWindow("Hello World!", 100, 100, 600, 400, 0);
if (win == nullptr) {
std::cout << "SDL_CreateWindow Error: " << SDL_GetError() << std::endl;
SDL_Quit();
return nullptr;
}
return win;
}
using namespace filament; using namespace filament;
using namespace math; using utils::Entity;
using namespace utils; using utils::EntityManager;
int main() {
if (SDL_Init(SDL_INIT_VIDEO) < 0) {
std::cout << "SDL_Init Error: " << SDL_GetError() << std::endl;
return 1;
}
const static uint32_t indices[] = { 0, 1, 2, };
const static math::float3 vertices[] = { struct App {
{ -10, 0, -10 }, Config config;
{ -10, 0, 10 }, VertexBuffer* vb;
{ 10, 0, 10 }, IndexBuffer* ib;
Material* mat;
Camera* cam;
Entity camera;
Skybox* skybox;
Entity renderable;
};
struct Vertex {
filament::math::float2 position;
uint32_t color;
};
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},
};
static constexpr uint16_t TRIANGLE_INDICES[3] = { 0, 1, 2 };
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);
}
std::cout << usage;
}
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 }
};
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;
}
}
return optind;
}
int main(int argc, char** argv) {
App app{};
app.config.title = "hellotriangle";
app.config.featureLevel = backend::FeatureLevel::FEATURE_LEVEL_0;
handleCommandLineArguments(argc, argv, &app);
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);
}; };
short4 tbn = math::packSnorm16( auto cleanup = [&app](Engine* engine, View*, Scene*) {
mat3f::packTangentFrame( engine->destroy(app.skybox);
math::mat3f{ engine->destroy(app.renderable);
float3{ 1.0f, 0.0f, 0.0f }, engine->destroy(app.mat);
float3{ 0.0f, 0.0f, 1.0f }, float3{ 0.0f, 1.0f, 0.0f } }) engine->destroy(app.vb);
.xyzw); engine->destroy(app.ib);
engine->destroyCameraComponent(app.camera);
utils::EntityManager::get().destroy(app.camera);
};
const static math::short4 normals[]{ tbn, tbn, tbn }; FilamentApp::get().animate([&app](Engine* engine, View* view, double now) {
SDL_Window* window = createSDLwindow(); constexpr float ZOOM = 1.5f;
if (!window) { const uint32_t w = view->getViewport().width;
return 1; const uint32_t h = view->getViewport().height;
} const float aspect = (float) w / h;
Engine* engine = Engine::create(filament::backend::Backend::VULKAN); app.cam->setProjection(Camera::Projection::ORTHO,
SwapChain* swapChain = engine->createSwapChain(getNativeWindow(window)); -aspect * ZOOM, aspect * ZOOM,
Renderer* renderer = engine->createRenderer(); -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 }));
});
auto cameraEntity = EntityManager::get().create(); FilamentApp::get().run(app.config, setup, cleanup);
Camera* camera = engine->createCamera(cameraEntity);
View* view = engine->createView();
Scene* scene = engine->createScene();
view->setCamera(camera);
// Determine the current size of the window in physical pixels.
uint32_t w, h;
SDL_GL_GetDrawableSize(window, (int*) &w, (int*) &h);
camera->lookAt(float3(0, 50.5f, 0), float3(0, 0, 0), float3(1.f, 0, 0));
camera->setProjection(45.0, double(w) / h, 0.1, 50, Camera::Fov::VERTICAL);
view->setViewport({ 0, 0, w, h });
view->setScene(scene);
view->setPostProcessingEnabled(false);
VertexBuffer* vertexBuffer =
VertexBuffer::Builder()
.vertexCount(3)
.bufferCount(2)
.attribute(VertexAttribute::POSITION, 0, VertexBuffer::AttributeType::FLOAT3)
.attribute(VertexAttribute::TANGENTS, 1, VertexBuffer::AttributeType::SHORT4)
.normalized(VertexAttribute::TANGENTS)
.build(*engine);
vertexBuffer->setBufferAt(*engine, 0,
VertexBuffer::BufferDescriptor(vertices,
vertexBuffer->getVertexCount() * sizeof(vertices[0])));
vertexBuffer->setBufferAt(*engine, 1,
VertexBuffer::BufferDescriptor(normals,
vertexBuffer->getVertexCount() * sizeof(normals[0])));
IndexBuffer* indexBuffer = IndexBuffer::Builder().indexCount(3).build(*engine);
indexBuffer->setBuffer(*engine,
IndexBuffer::BufferDescriptor(indices,
indexBuffer->getIndexCount() * sizeof(uint32_t)));
filamat::MaterialBuilder::init();
filamat::MaterialBuilder builder;
builder.name("Material")
.material(" void material(inout MaterialInputs material) {\n"
" prepareMaterial(material);"
" material.baseColor.rgb = materialParams.baseColor;"
" }")
.parameter("baseColor", filament::backend::UniformType::FLOAT3)
.parameter("metallic", filament::backend::UniformType::FLOAT)
.parameter("roughness", filament::backend::UniformType::FLOAT)
.parameter("reflectance", filament::backend::UniformType::FLOAT)
.optimization(filamat::MaterialBuilder::Optimization::NONE)
.shading(filamat::MaterialBuilder::Shading::UNLIT)
.targetApi(filamat::MaterialBuilder::TargetApi::ALL)
.platform(filamat::MaterialBuilder::Platform::ALL);
filamat::Package package = builder.build(engine->getJobSystem());
Material* material =
Material::Builder().package(package.getData(), package.getSize()).build(*engine);
material->setDefaultParameter("baseColor", RgbType::LINEAR, float3{ 1, 0, 0 });
material->setDefaultParameter("metallic", 0.0f);
material->setDefaultParameter("roughness", 0.4f);
material->setDefaultParameter("reflectance", 0.5f);
MaterialInstance* materialInstance = material->createInstance();
Entity renderable = EntityManager::get().create();
// build a quad
RenderableManager::Builder(1)
.boundingBox({ { -1, -1, -1 }, { 1, 1, 1 } })
.material(0, materialInstance)
.geometry(0, RenderableManager::PrimitiveType::TRIANGLES, vertexBuffer, indexBuffer, 0,
3)
.culling(false)
.build(*engine, renderable);
scene->addEntity(renderable);
int i = 0;
while (i++ < 1) {
// beginFrame() returns false if we need to skip a frame
if (renderer->beginFrame(swapChain)) {
// for each View
renderer->render(view);
renderer->endFrame();
}
}
bool running = true;
SDL_Event event;
while (running) {
while (SDL_PollEvent(&event)) {
if (event.type == SDL_QUIT) {
running = false;
}
SDL_Delay(16);
}
}
engine->destroy(cameraEntity);
return 0; return 0;
} }
-10
View File
@@ -1,10 +0,0 @@
#ifndef HELLO_TRIANGLE_H
#define HELLO_TRIANGLE_H
#include <SDL.h>
#include <SDL_syswm.h>
#include <SDL_video.h>
void* getNativeWindow(SDL_Window* sdlWindow);
#endif
-39
View File
@@ -1,39 +0,0 @@
#include "helper.h"
#include <Cocoa/Cocoa.h>
#include <QuartzCore/QuartzCore.h>
#include <utils/Panic.h>
void* getNativeWindow(SDL_Window* sdlWindow) {
SDL_SysWMinfo wmi;
SDL_VERSION(&wmi.version);
FILAMENT_CHECK_POSTCONDITION(SDL_GetWindowWMInfo(sdlWindow, &wmi))
<< "SDL version unsupported!";
NSWindow* win = wmi.info.cocoa.window;
NSView* view = [win contentView];
[win setColorSpace:[NSColorSpace sRGBColorSpace]];
[view setWantsLayer:YES];
CAMetalLayer* metalLayer = [CAMetalLayer layer];
metalLayer.bounds = view.bounds;
// It's important to set the drawableSize to the actual backing pixels. When rendering
// full-screen, we can skip the macOS compositor if the size matches the display size.
metalLayer.drawableSize = [view convertSizeToBacking:view.bounds.size];
// In its implementation of vkGetPhysicalDeviceSurfaceCapabilitiesKHR, MoltenVK takes into
// consideration both the size (in points) of the bounds, and the contentsScale of the
// CAMetalLayer from which the Vulkan surface was created.
// See also https://github.com/KhronosGroup/MoltenVK/issues/428
metalLayer.contentsScale = view.window.backingScaleFactor;
// This is set to NO by default, but is also important to ensure we can bypass the compositor
// in full-screen mode
// See "Direct to Display" http://metalkit.org/2017/06/30/introducing-metal-2.html.
metalLayer.opaque = YES;
[view setLayer:metalLayer];
return metalLayer;
}
+8 -2
View File
@@ -205,11 +205,17 @@ void setup_window(Window& w, Engine* engine) {
void* nativeSwapChain = nativeWindow; void* nativeSwapChain = nativeWindow;
#if defined(__APPLE__) #if defined(__APPLE__)
void* metalLayer = nullptr; void* metalLayer = nullptr;
if (kBackend == filament::Engine::Backend::METAL || kBackend == filament::Engine::Backend::VULKAN) { if (kBackend == filament::Engine::Backend::METAL) {
metalLayer = setUpMetalLayer(nativeWindow); metalLayer = setUpMetalLayer(nativeWindow);
// The swap chain on both native Metal and MoltenVK is a CAMetalLayer. // The swap chain on Metal is a CAMetalLayer.
nativeSwapChain = metalLayer; nativeSwapChain = metalLayer;
} }
#if defined(FILAMENT_DRIVER_SUPPORTS_VULKAN)
if (kBackend == filament::Engine::Backend::VULKAN) {
// We request a Metal layer for rendering via MoltenVK.
setUpMetalLayer(nativeWindow);
}
#endif
#endif #endif
w.swapChain = engine->createSwapChain(nativeSwapChain); w.swapChain = engine->createSwapChain(nativeSwapChain);
+14 -25
View File
@@ -1,27 +1,3 @@
//------------------------------------------------------------------------------
// Common Helpers
//------------------------------------------------------------------------------
/**
* Index of the eye being rendered, starting at 0.
* @public-api
*/
int getEyeIndex() {
#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED)
return instance_index % CONFIG_STEREO_EYE_COUNT;
#elif defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW)
# if defined(TARGET_VULKAN_ENVIRONMENT)
return int(gl_ViewIndex);
# else
// gl_ViewID_OVR is of uint type, which needs an explicit conversion.
return int(gl_ViewID_OVR);
# endif // TARGET_VULKAN_ENVIRONMENT
#endif
return 0;
}
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Uniforms access // Uniforms access
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
@@ -48,7 +24,20 @@ highp mat4 getViewFromClipMatrix() {
/** @public-api */ /** @public-api */
highp mat4 getClipFromWorldMatrix() { highp mat4 getClipFromWorldMatrix() {
return frameUniforms.clipFromWorldMatrix[getEyeIndex()]; #if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED)
int eye = instance_index % CONFIG_STEREO_EYE_COUNT;
return frameUniforms.clipFromWorldMatrix[eye];
#elif defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW)
#if defined(TARGET_VULKAN_ENVIRONMENT)
return frameUniforms.clipFromWorldMatrix[gl_ViewIndex];
#else
return frameUniforms.clipFromWorldMatrix[gl_ViewID_OVR];
#endif // TARGET_VULKAN_ENVIRONMENT
#else
return frameUniforms.clipFromWorldMatrix[0];
#endif
} }
/** @public-api */ /** @public-api */
+21 -1
View File
@@ -235,7 +235,7 @@ vec4 getCustom7() { return mesh_custom7; }
#endif #endif
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
// Surface Helpers // Helpers
//------------------------------------------------------------------------------ //------------------------------------------------------------------------------
/** /**
@@ -275,3 +275,23 @@ vec4 computeWorldPosition() {
#error Unknown Vertex Domain #error Unknown Vertex Domain
#endif #endif
} }
/**
* Index of the eye being rendered, starting at 0.
* @public-api
*/
int getEyeIndex() {
#if defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_INSTANCED)
return instance_index % CONFIG_STEREO_EYE_COUNT;
#elif defined(VARIANT_HAS_STEREO) && defined(FILAMENT_STEREO_MULTIVIEW)
#if defined(TARGET_VULKAN_ENVIRONMENT)
return int(gl_ViewIndex);
#else
// gl_ViewID_OVR is of uint type, which needs an explicit conversion.
return int(gl_ViewID_OVR);
#endif // TARGET_VULKAN_ENVIRONMENT
#endif
return 0;
}
+1 -8
View File
@@ -661,7 +661,6 @@ class_<View>("View")
.function("getViewport", &View::getViewport) .function("getViewport", &View::getViewport)
.function("setVisibleLayers", &View::setVisibleLayers) .function("setVisibleLayers", &View::setVisibleLayers)
.function("setPostProcessingEnabled", &View::setPostProcessingEnabled) .function("setPostProcessingEnabled", &View::setPostProcessingEnabled)
.function("setDithering", &View::setDithering)
.function("_setAmbientOcclusionOptions", &View::setAmbientOcclusionOptions) .function("_setAmbientOcclusionOptions", &View::setAmbientOcclusionOptions)
.function("_setDepthOfFieldOptions", &View::setDepthOfFieldOptions) .function("_setDepthOfFieldOptions", &View::setDepthOfFieldOptions)
.function("_setMultiSampleAntiAliasingOptions", &View::setMultiSampleAntiAliasingOptions) .function("_setMultiSampleAntiAliasingOptions", &View::setMultiSampleAntiAliasingOptions)
@@ -1392,14 +1391,8 @@ class_<MaterialInstance>("MaterialInstance")
.function("isDoubleSided", &MaterialInstance::isDoubleSided) .function("isDoubleSided", &MaterialInstance::isDoubleSided)
.function("setTransparencyMode", &MaterialInstance::setTransparencyMode) .function("setTransparencyMode", &MaterialInstance::setTransparencyMode)
.function("getTransparencyMode", &MaterialInstance::getTransparencyMode) .function("getTransparencyMode", &MaterialInstance::getTransparencyMode)
.function("setCullingMode", EMBIND_LAMBDA(void, .function("setCullingMode", &MaterialInstance::setCullingMode)
(MaterialInstance* self, MaterialInstance::CullingMode mode), {
self->setCullingMode(mode); }), allow_raw_pointers())
.function("setCullingModeSeparate", EMBIND_LAMBDA(void,
(MaterialInstance* self, MaterialInstance::CullingMode color, MaterialInstance::CullingMode shadows), {
self->setCullingMode(color, shadows); }), allow_raw_pointers())
.function("getCullingMode", &MaterialInstance::getCullingMode) .function("getCullingMode", &MaterialInstance::getCullingMode)
.function("getShadowCullingMode", &MaterialInstance::getShadowCullingMode)
.function("setColorWrite", &MaterialInstance::setColorWrite) .function("setColorWrite", &MaterialInstance::setColorWrite)
.function("isColorWriteEnabled", &MaterialInstance::isColorWriteEnabled) .function("isColorWriteEnabled", &MaterialInstance::isColorWriteEnabled)
.function("setDepthWrite", &MaterialInstance::setDepthWrite) .function("setDepthWrite", &MaterialInstance::setDepthWrite)
+1 -1
View File
@@ -1,6 +1,6 @@
{ {
"name": "filament", "name": "filament",
"version": "1.57.0", "version": "1.56.7",
"description": "Real-time physically based rendering engine", "description": "Real-time physically based rendering engine",
"main": "filament.js", "main": "filament.js",
"module": "filament.js", "module": "filament.js",