update macos/ios to Filament v1.51.2

This commit is contained in:
Nick Fisher
2024-04-20 13:46:58 +08:00
parent 15882891e2
commit ea04e94c1f
156 changed files with 5394 additions and 5884 deletions

View File

@@ -23,7 +23,6 @@
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -113,7 +112,7 @@ public:
/**
* Helper to create a BufferDescriptor that uses a KNOWN method pointer w/ object passed
* by pointer as the callback. e.g.:
* auto bd = BufferDescriptor::make(buffer, size, &Foo::method, foo);
* auto bd = BufferDescriptor::make<Foo, &Foo::method>(buffer, size, foo);
*
* @param buffer Memory address of the CPU buffer to reference
* @param size Size of the CPU buffer in bytes
@@ -121,12 +120,12 @@ public:
* @return a new BufferDescriptor
*/
template<typename T, void(T::*method)(void const*, size_t)>
static BufferDescriptor make(
void const* buffer, size_t size, T* data, CallbackHandler* handler = nullptr) noexcept {
static BufferDescriptor make(void const* buffer, size_t size, T* data,
CallbackHandler* handler = nullptr) noexcept {
return {
buffer, size,
handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s);
(static_cast<T*>(u)->*method)(b, s);
}, data
};
}
@@ -145,14 +144,14 @@ public:
* @return a new BufferDescriptor
*/
template<typename T>
static BufferDescriptor make(
void const* buffer, size_t size, T&& functor, CallbackHandler* handler = nullptr) noexcept {
static BufferDescriptor make(void const* buffer, size_t size, T&& functor,
CallbackHandler* handler = nullptr) noexcept {
return {
buffer, size,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
T* const that = static_cast<T*>(u);
that->operator()(b, s);
delete that;
},
new T(std::forward<T>(functor))
};
@@ -201,7 +200,7 @@ public:
return mUser;
}
//! CPU mempry-buffer virtual address
//! CPU memory-buffer virtual address
void* buffer = nullptr;
//! CPU memory-buffer size in bytes

View File

@@ -17,8 +17,6 @@
#ifndef TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#define TNT_FILAMENT_BACKEND_CALLBACKHANDLER_H
#include <utils/compiler.h>
namespace filament::backend {
/**

View File

@@ -28,7 +28,8 @@
#include <math/vec4.h>
#include <array> // FIXME: STL headers are not allowed in public headers
#include <array> // FIXME: STL headers are not allowed in public headers
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <stddef.h>
#include <stdint.h>
@@ -77,6 +78,18 @@ static constexpr uint64_t SWAP_CHAIN_CONFIG_APPLE_CVPIXELBUFFER = 0x8;
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_SRGB_COLORSPACE = 0x10;
/**
* Indicates that the SwapChain should also contain a stencil component.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER = 0x20;
static constexpr uint64_t SWAP_CHAIN_HAS_STENCIL_BUFFER = SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER;
/**
* The SwapChain contains protected content. Currently only supported by OpenGLPlatform and
* only when OpenGLPlatform::isProtectedContextSupported() is true.
*/
static constexpr uint64_t SWAP_CHAIN_CONFIG_PROTECTED_CONTENT = 0x40;
static constexpr size_t MAX_VERTEX_ATTRIBUTE_COUNT = 16; // This is guaranteed by OpenGL ES.
static constexpr size_t MAX_SAMPLER_COUNT = 62; // Maximum needed at feature level 3.
@@ -123,6 +136,12 @@ enum class Backend : uint8_t {
NOOP = 4, //!< Selects the no-op driver for testing purposes.
};
enum class TimerQueryResult : int8_t {
ERROR = -1, // an error occurred, result won't be available
NOT_READY = 0, // result to ready yet
AVAILABLE = 1, // result is available
};
static constexpr const char* backendToString(Backend backend) {
switch (backend) {
case Backend::NOOP:
@@ -138,6 +157,30 @@ static constexpr const char* backendToString(Backend backend) {
}
}
/**
* Defines the shader language. Similar to the above backend enum, but the OpenGL backend can select
* between two shader languages: ESSL 1.0 and ESSL 3.0.
*/
enum class ShaderLanguage {
ESSL1 = 0,
ESSL3 = 1,
SPIRV = 2,
MSL = 3,
};
static constexpr const char* shaderLanguageToString(ShaderLanguage shaderLanguage) {
switch (shaderLanguage) {
case ShaderLanguage::ESSL1:
return "ESSL 1.0";
case ShaderLanguage::ESSL3:
return "ESSL 3.0";
case ShaderLanguage::SPIRV:
return "SPIR-V";
case ShaderLanguage::MSL:
return "MSL";
}
}
/**
* Bitmask for selecting render buffers
*/
@@ -198,6 +241,7 @@ struct Viewport {
int32_t top() const noexcept { return bottom + int32_t(height); }
};
/**
* Specifies the mapping of the near and far clipping plane to window coordinates.
*/
@@ -628,14 +672,17 @@ enum class TextureFormat : uint16_t {
};
//! Bitmask describing the intended Texture Usage
enum class TextureUsage : uint8_t {
NONE = 0x0,
COLOR_ATTACHMENT = 0x1, //!< Texture can be used as a color attachment
DEPTH_ATTACHMENT = 0x2, //!< Texture can be used as a depth attachment
STENCIL_ATTACHMENT = 0x4, //!< Texture can be used as a stencil attachment
UPLOADABLE = 0x8, //!< Data can be uploaded into this texture (default)
SAMPLEABLE = 0x10, //!< Texture can be sampled (default)
SUBPASS_INPUT = 0x20, //!< Texture can be used as a subpass input
enum class TextureUsage : uint16_t {
NONE = 0x0000,
COLOR_ATTACHMENT = 0x0001, //!< Texture can be used as a color attachment
DEPTH_ATTACHMENT = 0x0002, //!< Texture can be used as a depth attachment
STENCIL_ATTACHMENT = 0x0004, //!< Texture can be used as a stencil attachment
UPLOADABLE = 0x0008, //!< Data can be uploaded into this texture (default)
SAMPLEABLE = 0x0010, //!< Texture can be sampled (default)
SUBPASS_INPUT = 0x0020, //!< Texture can be used as a subpass input
BLIT_SRC = 0x0040, //!< Texture can be used the source of a blit()
BLIT_DST = 0x0080, //!< Texture can be used the destination of a blit()
PROTECTED = 0x0100, //!< Texture can be used the destination of a blit()
DEFAULT = UPLOADABLE | SAMPLEABLE //!< Default texture usage
};
@@ -663,6 +710,17 @@ static constexpr bool isDepthFormat(TextureFormat format) noexcept {
}
}
static constexpr bool isStencilFormat(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::STENCIL8:
case TextureFormat::DEPTH24_STENCIL8:
case TextureFormat::DEPTH32F_STENCIL8:
return true;
default:
return false;
}
}
static constexpr bool isUnsignedIntFormat(TextureFormat format) {
switch (format) {
case TextureFormat::R8UI:
@@ -1128,11 +1186,27 @@ struct StencilState {
//! Stencil operations for front-facing polygons
StencilOperations front = {
.stencilFunc = StencilFunction::A, .ref = 0, .readMask = 0xff, .writeMask = 0xff };
.stencilFunc = StencilFunction::A,
.stencilOpStencilFail = StencilOperation::KEEP,
.padding0 = 0,
.stencilOpDepthFail = StencilOperation::KEEP,
.stencilOpDepthStencilPass = StencilOperation::KEEP,
.padding1 = 0,
.ref = 0,
.readMask = 0xff,
.writeMask = 0xff };
//! Stencil operations for back-facing polygons
StencilOperations back = {
.stencilFunc = StencilFunction::A, .ref = 0, .readMask = 0xff, .writeMask = 0xff };
.stencilFunc = StencilFunction::A,
.stencilOpStencilFail = StencilOperation::KEEP,
.padding0 = 0,
.stencilOpDepthFail = StencilOperation::KEEP,
.stencilOpDepthStencilPass = StencilOperation::KEEP,
.padding1 = 0,
.ref = 0,
.readMask = 0xff,
.writeMask = 0xff };
//! Whether stencil-buffer writes are enabled
bool stencilWrite = false;
@@ -1151,8 +1225,8 @@ using FrameScheduledCallback = void(*)(PresentCallable callable, void* user);
enum class Workaround : uint16_t {
// The EASU pass must split because shader compiler flattens early-exit branch
SPLIT_EASU,
// Backend allows feedback loop with ancillary buffers (depth/stencil) as long as they're read-only for
// the whole render pass.
// Backend allows feedback loop with ancillary buffers (depth/stencil) as long as they're
// read-only for the whole render pass.
ALLOW_READ_ONLY_ANCILLARY_FEEDBACK_LOOP,
// for some uniform arrays, it's needed to do an initialization to avoid crash on adreno gpu
ADRENO_UNIFORM_ARRAY_CRASH,
@@ -1168,6 +1242,14 @@ enum class Workaround : uint16_t {
DISABLE_THREAD_AFFINITY
};
//! The type of technique for stereoscopic rendering
enum class StereoscopicType : uint8_t {
// Stereoscopic rendering is performed using instanced rendering technique.
INSTANCED,
// Stereoscopic rendering is performed using the multiview feature from the graphics backend.
MULTIVIEW,
};
} // namespace filament::backend
template<> struct utils::EnableBitMaskOperators<filament::backend::ShaderStageFlags>

View File

@@ -17,16 +17,14 @@
#ifndef TNT_FILAMENT_BACKEND_HANDLE_H
#define TNT_FILAMENT_BACKEND_HANDLE_H
#include <utils/compiler.h>
#if !defined(NDEBUG)
#include <utils/Log.h>
#include <utils/ostream.h>
#endif
#include <utils/debug.h>
#include <stdint.h>
#include <type_traits> // FIXME: STL headers are not allowed in public headers
#include <limits>
#include <type_traits>
#include <stdint.h>
namespace filament::backend {
@@ -41,6 +39,7 @@ struct HwStream;
struct HwSwapChain;
struct HwTexture;
struct HwTimerQuery;
struct HwVertexBufferInfo;
struct HwVertexBuffer;
/*
@@ -54,7 +53,7 @@ struct HwVertexBuffer;
class HandleBase {
public:
using HandleId = uint32_t;
static constexpr const HandleId nullid = HandleId{ std::numeric_limits<HandleId>::max() };
static constexpr const HandleId nullid = HandleId{ UINT32_MAX };
constexpr HandleBase() noexcept: object(nullid) {}
@@ -64,14 +63,6 @@ public:
// clear the handle, this doesn't free associated resources
void clear() noexcept { object = nullid; }
// compare handles
bool operator==(const HandleBase& rhs) const noexcept { return object == rhs.object; }
bool operator!=(const HandleBase& rhs) const noexcept { return object != rhs.object; }
bool operator<(const HandleBase& rhs) const noexcept { return object < rhs.object; }
bool operator<=(const HandleBase& rhs) const noexcept { return object <= rhs.object; }
bool operator>(const HandleBase& rhs) const noexcept { return object > rhs.object; }
bool operator>=(const HandleBase& rhs) const noexcept { return object >= rhs.object; }
// get this handle's handleId
HandleId getId() const noexcept { return object; }
@@ -103,6 +94,14 @@ struct Handle : public HandleBase {
explicit Handle(HandleId id) noexcept : HandleBase(id) { }
// compare handles of the same type
bool operator==(const Handle& rhs) const noexcept { return getId() == rhs.getId(); }
bool operator!=(const Handle& rhs) const noexcept { return getId() != rhs.getId(); }
bool operator<(const Handle& rhs) const noexcept { return getId() < rhs.getId(); }
bool operator<=(const Handle& rhs) const noexcept { return getId() <= rhs.getId(); }
bool operator>(const Handle& rhs) const noexcept { return getId() > rhs.getId(); }
bool operator>=(const Handle& rhs) const noexcept { return getId() >= rhs.getId(); }
// type-safe Handle cast
template<typename B, typename = std::enable_if_t<std::is_base_of<T, B>::value> >
Handle(Handle<B> const& base) noexcept : HandleBase(base) { } // NOLINT(hicpp-explicit-conversions,google-explicit-constructor)
@@ -116,18 +115,19 @@ private:
// Types used by the command stream
// (we use this renaming because the macro-system doesn't deal well with "<" and ">")
using BufferObjectHandle = Handle<HwBufferObject>;
using FenceHandle = Handle<HwFence>;
using IndexBufferHandle = Handle<HwIndexBuffer>;
using ProgramHandle = Handle<HwProgram>;
using RenderPrimitiveHandle = Handle<HwRenderPrimitive>;
using RenderTargetHandle = Handle<HwRenderTarget>;
using SamplerGroupHandle = Handle<HwSamplerGroup>;
using StreamHandle = Handle<HwStream>;
using SwapChainHandle = Handle<HwSwapChain>;
using TextureHandle = Handle<HwTexture>;
using TimerQueryHandle = Handle<HwTimerQuery>;
using VertexBufferHandle = Handle<HwVertexBuffer>;
using BufferObjectHandle = Handle<HwBufferObject>;
using FenceHandle = Handle<HwFence>;
using IndexBufferHandle = Handle<HwIndexBuffer>;
using ProgramHandle = Handle<HwProgram>;
using RenderPrimitiveHandle = Handle<HwRenderPrimitive>;
using RenderTargetHandle = Handle<HwRenderTarget>;
using SamplerGroupHandle = Handle<HwSamplerGroup>;
using StreamHandle = Handle<HwStream>;
using SwapChainHandle = Handle<HwSwapChain>;
using TextureHandle = Handle<HwTexture>;
using TimerQueryHandle = Handle<HwTimerQuery>;
using VertexBufferHandle = Handle<HwVertexBuffer>;
using VertexBufferInfoHandle = Handle<HwVertexBufferInfo>;
} // namespace filament::backend

View File

@@ -20,7 +20,7 @@
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <limits>
#include <utils/ostream.h>
#include <stdint.h>
@@ -29,14 +29,13 @@ namespace filament::backend {
//! \privatesection
struct PipelineState {
Handle<HwProgram> program;
RasterState rasterState;
StencilState stencilState;
PolygonOffset polygonOffset;
Viewport scissor{ 0, 0,
(uint32_t)std::numeric_limits<int32_t>::max(),
(uint32_t)std::numeric_limits<int32_t>::max()
};
Handle<HwProgram> program; // 4
Handle<HwVertexBufferInfo> vertexBufferInfo; // 4
RasterState rasterState; // 4
StencilState stencilState; // 12
PolygonOffset polygonOffset; // 8
PrimitiveType primitiveType = PrimitiveType::TRIANGLES; // 1
uint8_t padding[3] = {}; // 3
};
} // namespace filament::backend

View File

@@ -24,6 +24,7 @@
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
@@ -141,7 +142,7 @@ public:
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type, alignment, left, top, stride,
handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data };
(static_cast<T*>(u)->*method)(b, s); }, data };
}
template<typename T, void(T::*method)(void const*, size_t)>
@@ -149,7 +150,7 @@ public:
PixelDataFormat format, PixelDataType type, T* data,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type, handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data };
(static_cast<T*>(u)->*method)(b, s); }, data };
}
template<typename T, void(T::*method)(void const*, size_t)>
@@ -157,7 +158,7 @@ public:
backend::CompressedPixelDataType format, uint32_t imageSize, T* data,
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, imageSize, handler, [](void* b, size_t s, void* u) {
(*static_cast<T**>(u)->*method)(b, s); }, data
(static_cast<T*>(u)->*method)(b, s); }, data
};
}
@@ -168,9 +169,9 @@ public:
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type, alignment, left, top, stride,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
T* const that = static_cast<T*>(u);
that->operator()(b, s);
delete that;
}, new T(std::forward<T>(functor))
};
}
@@ -181,9 +182,9 @@ public:
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, type,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
T* const that = static_cast<T*>(u);
that->operator()(b, s);
delete that;
}, new T(std::forward<T>(functor))
};
}
@@ -194,9 +195,9 @@ public:
CallbackHandler* handler = nullptr) noexcept {
return { buffer, size, format, imageSize,
handler, [](void* b, size_t s, void* u) {
T& that = *static_cast<T*>(u);
that(b, s);
delete &that;
T* const that = static_cast<T*>(u);
that->operator()(b, s);
delete that;
}, new T(std::forward<T>(functor))
};
}

View File

@@ -19,11 +19,12 @@
#ifndef TNT_FILAMENT_BACKEND_PLATFORM_H
#define TNT_FILAMENT_BACKEND_PLATFORM_H
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class Driver;
@@ -41,11 +42,29 @@ public:
struct Stream {};
struct DriverConfig {
/*
* size of handle arena in bytes. Setting to 0 indicates default value is to be used.
/**
* Size of handle arena in bytes. Setting to 0 indicates default value is to be used.
* Driver clamps to valid values.
*/
size_t handleArenaSize = 0;
/**
* This number of most-recently destroyed textures will be tracked for use-after-free.
* Throws an exception when a texture is freed but still bound to a SamplerGroup and used in
* a draw call. 0 disables completely. Currently only respected by the Metal backend.
*/
size_t textureUseAfterFreePoolSize = 0;
/**
* Set to `true` to forcibly disable parallel shader compilation in the backend.
* Currently only honored by the GL and Metal backends.
*/
bool disableParallelShaderCompile = false;
/**
* Disable backend handles use-after-free checks.
*/
bool disableHandleUseAfterFreeCheck = false;
};
Platform() noexcept;
@@ -71,7 +90,7 @@ public:
*
* @return nullptr on failure, or a pointer to the newly created driver.
*/
virtual backend::Driver* createDriver(void* sharedContext,
virtual backend::Driver* UTILS_NULLABLE createDriver(void* UTILS_NULLABLE sharedContext,
const DriverConfig& driverConfig) noexcept = 0;
/**
@@ -89,7 +108,8 @@ public:
* cache.
*/
using InsertBlobFunc = utils::Invocable<
void(const void* key, size_t keySize, const void* value, size_t valueSize)>;
void(const void* UTILS_NONNULL key, size_t keySize,
const void* UTILS_NONNULL value, size_t valueSize)>;
/*
* RetrieveBlobFunc is an Invocable to an application-provided function that a
@@ -97,7 +117,8 @@ public:
* cache.
*/
using RetrieveBlobFunc = utils::Invocable<
size_t(const void* key, size_t keySize, void* value, size_t valueSize)>;
size_t(const void* UTILS_NONNULL key, size_t keySize,
void* UTILS_NONNULL value, size_t valueSize)>;
/**
* Sets the callback functions that the backend can use to interact with caching functionality
@@ -107,6 +128,7 @@ public:
* Platform. The <insert> and <retrieve> Invocables may be called at any time and
* from any thread from the time at which setBlobFunc is called until the time that Platform
* is destroyed. Concurrent calls to these functions from different threads is also allowed.
* Either function can be null.
*
* @param insertBlob an Invocable that inserts a new value into the cache and associates
* it with the given key
@@ -116,9 +138,21 @@ public:
void setBlobFunc(InsertBlobFunc&& insertBlob, RetrieveBlobFunc&& retrieveBlob) noexcept;
/**
* @return true if setBlobFunc was called.
* @return true if insertBlob is valid.
*/
bool hasBlobFunc() const noexcept;
bool hasInsertBlobFunc() const noexcept;
/**
* @return true if retrieveBlob is valid.
*/
bool hasRetrieveBlobFunc() const noexcept;
/**
* @return true if either of insertBlob or retrieveBlob are valid.
*/
bool hasBlobFunc() const noexcept {
return hasInsertBlobFunc() || hasRetrieveBlobFunc();
}
/**
* To insert a new binary value into the cache and associate it with a given
@@ -137,7 +171,8 @@ public:
* @param value pointer to the beginning of the value data that is to be inserted
* @param valueSize specifies the size in byte of the data pointed to by <value>
*/
void insertBlob(const void* key, size_t keySize, const void* value, size_t valueSize);
void insertBlob(const void* UTILS_NONNULL key, size_t keySize,
const void* UTILS_NONNULL value, size_t valueSize);
/**
* To retrieve the binary value associated with a given key from the cache, a
@@ -156,11 +191,43 @@ public:
* @return If the cache contains a value associated with the given key then the
* size of that binary value in bytes is returned. Otherwise 0 is returned.
*/
size_t retrieveBlob(const void* key, size_t keySize, void* value, size_t valueSize);
size_t retrieveBlob(const void* UTILS_NONNULL key, size_t keySize,
void* UTILS_NONNULL value, size_t valueSize);
using DebugUpdateStatFunc = utils::Invocable<void(const char* UTILS_NONNULL key, uint64_t value)>;
/**
* Sets the callback function that the backend can use to update backend-specific statistics
* to aid with debugging. This callback is guaranteed to be called on the Filament driver
* thread.
*
* @param debugUpdateStat an Invocable that updates debug statistics
*/
void setDebugUpdateStatFunc(DebugUpdateStatFunc&& debugUpdateStat) noexcept;
/**
* @return true if debugUpdateStat is valid.
*/
bool hasDebugUpdateStatFunc() const noexcept;
/**
* To track backend-specific statistics, the backend implementation can call the
* application-provided callback function debugUpdateStatFunc to associate or update a value
* with a given key. It is possible for this function to be called multiple times with the
* same key, in which case newer values should overwrite older values.
*
* This function is guaranteed to be called only on a single thread, the Filament driver
* thread.
*
* @param key a null-terminated C-string with the key of the debug statistic
* @param value the updated value of key
*/
void debugUpdateStat(const char* UTILS_NONNULL key, uint64_t value);
private:
InsertBlobFunc mInsertBlob;
RetrieveBlobFunc mRetrieveBlob;
DebugUpdateStatFunc mDebugUpdateStat;
};
} // namespace filament

View File

@@ -21,8 +21,7 @@
#include <utils/compiler.h>
namespace filament {
namespace backend {
namespace filament::backend {
/**
* A PresentCallable is a callable object that, when called, schedules a frame for presentation on
@@ -98,7 +97,6 @@ private:
*/
using FrameFinishedCallback UTILS_DEPRECATED = void(*)(PresentCallable callable, void* user);
} // namespace backend
} // namespace filament
} // namespace filament::backend
#endif // TNT_FILAMENT_BACKEND_PRESENTCALLABLE

View File

@@ -17,17 +17,19 @@
#ifndef TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
#define TNT_FILAMENT_BACKEND_PRIVATE_PROGRAM_H
#include <utils/compiler.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/Invocable.h>
#include <utils/Log.h>
#include <utils/ostream.h>
#include <backend/DriverEnums.h>
#include <array>
#include <variant>
#include <array> // FIXME: STL headers are not allowed in public headers
#include <utility> // FIXME: STL headers are not allowed in public headers
#include <variant> // FIXME: STL headers are not allowed in public headers
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -114,6 +116,8 @@ public:
Program& cacheId(uint64_t cacheId) noexcept;
Program& multiview(bool multiview) noexcept;
ShaderSource const& getShadersSource() const noexcept { return mShadersSource; }
ShaderSource& getShadersSource() noexcept { return mShadersSource; }
@@ -141,6 +145,8 @@ public:
uint64_t getCacheId() const noexcept { return mCacheId; }
bool isMultiview() const noexcept { return mMultiview; }
CompilerPriorityQueue getPriorityQueue() const noexcept { return mPriorityQueue; }
private:
@@ -156,6 +162,11 @@ private:
utils::FixedCapacityVector<std::pair<utils::CString, uint8_t>> mAttributes;
std::array<UniformInfo, Program::UNIFORM_BINDING_COUNT> mBindingUniformInfo;
CompilerPriorityQueue mPriorityQueue = CompilerPriorityQueue::HIGH;
// Indicates the current engine was initialized with multiview stereo, and the variant for this
// program contains STE flag. This will be referred later for the OpenGL shader compiler to
// determine whether shader code replacement for the num_views should be performed.
// This variable could be promoted as a more generic variable later if other similar needs occur.
bool mMultiview = false;
};
} // namespace filament::backend

View File

@@ -24,9 +24,6 @@
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
struct UTILS_PUBLIC SamplerDescriptor {

View File

@@ -17,9 +17,11 @@
#ifndef TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#define TNT_FILAMENT_BACKEND_TARGETBUFFERINFO_H
#include <backend/DriverEnums.h>
#include <backend/Handle.h>
#include <utils/ostream.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
@@ -30,6 +32,10 @@ struct TargetBufferInfo {
// texture to be used as render target
Handle<HwTexture> handle;
// starting layer index for multiview. This value is only used when the `layerCount` for the
// render target is greater than 1.
uint8_t baseViewIndex = 0;
// level to be used
uint8_t level = 0;
@@ -78,7 +84,7 @@ public:
// this is here for backward compatibility
MRT(Handle<HwTexture> handle, uint8_t level, uint16_t layer) noexcept
: mInfos{{ handle, level, layer }} {
: mInfos{{ handle, 0, level, layer }} {
}
};

View File

@@ -18,8 +18,15 @@
#define TNT_FILAMENT_BACKEND_PRIVATE_OPENGLPLATFORM_H
#include <backend/AcquiredImage.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class Driver;
@@ -38,8 +45,8 @@ protected:
* Derived classes can use this to instantiate the default OpenGLDriver backend.
* This is typically called from your implementation of createDriver()
*/
static Driver* createDefaultDriver(OpenGLPlatform* platform,
void* sharedContext, const DriverConfig& driverConfig);
static Driver* UTILS_NULLABLE createDefaultDriver(OpenGLPlatform* UTILS_NONNULL platform,
void* UTILS_NULLABLE sharedContext, const DriverConfig& driverConfig);
~OpenGLPlatform() noexcept override;
@@ -57,6 +64,22 @@ public:
*/
virtual void terminate() noexcept = 0;
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
*/
virtual bool isSRGBSwapChainSupported() const noexcept;
/**
* Return whether protected contexts are supported by this backend.
* If protected context are supported, the SWAP_CHAIN_CONFIG_PROTECTED_CONTENT flag can be
* used when creating a SwapChain.
* The default implementation returns false.
*/
virtual bool isProtectedContextSupported() const noexcept;
/**
* Called by the driver to create a SwapChain for this driver.
*
@@ -66,15 +89,8 @@ public:
* @return The driver's SwapChain object.
*
*/
virtual SwapChain* createSwapChain(void* nativeWindow, uint64_t flags) noexcept = 0;
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
*/
virtual bool isSRGBSwapChainSupported() const noexcept;
virtual SwapChain* UTILS_NULLABLE createSwapChain(
void* UTILS_NULLABLE nativeWindow, uint64_t flags) noexcept = 0;
/**
* Called by the driver create a headless SwapChain.
@@ -87,13 +103,14 @@ public:
* TODO: we need a more generic way of passing construction parameters
* A void* might be enough.
*/
virtual SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
virtual SwapChain* UTILS_NULLABLE createSwapChain(
uint32_t width, uint32_t height, uint64_t flags) noexcept = 0;
/**
* Called by the driver to destroys the SwapChain
* @param swapChain SwapChain to be destroyed.
*/
virtual void destroySwapChain(SwapChain* swapChain) noexcept = 0;
virtual void destroySwapChain(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
/**
* Returns the set of buffers that must be preserved up to the call to commit().
@@ -106,28 +123,80 @@ public:
* @return buffer that must be preserved
* @see commit()
*/
virtual TargetBufferFlags getPreservedFlags(SwapChain* swapChain) noexcept;
virtual TargetBufferFlags getPreservedFlags(SwapChain* UTILS_NONNULL swapChain) noexcept;
/**
* Returns true if the swapchain is protected
*/
virtual bool isSwapChainProtected(Platform::SwapChain* UTILS_NONNULL swapChain) noexcept;
/**
* Called by the driver to establish the default FBO. The default implementation returns 0.
* @return a GLuint casted to a uint32_t that is an OpenGL framebuffer object.
*
* This method can be called either on the regular or protected OpenGL contexts and can return
* a different or identical name, since these names exist in different namespaces.
*
* @return a GLuint casted to a uint32_t that is an OpenGL framebuffer object.
*/
virtual uint32_t createDefaultRenderTarget() noexcept;
virtual uint32_t getDefaultFramebufferObject() noexcept;
/**
* Type of contexts available
*/
enum class ContextType {
NONE, //!< No current context
UNPROTECTED, //!< current context is unprotected
PROTECTED //!< current context supports protected content
};
/**
* Returns the type of the context currently in use. This value is updated by makeCurrent()
* and therefore can be cached between calls. ContextType::PROTECTED can only be returned
* if isProtectedContextSupported() is true.
* @return ContextType
*/
virtual ContextType getCurrentContextType() const noexcept;
/**
* Binds the requested context to the current thread and drawSwapChain to the default FBO
* returned by getDefaultFramebufferObject().
*
* @param type type of context to bind to the current thread.
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
* @return true on success, false on error.
*/
virtual bool makeCurrent(ContextType type,
SwapChain* UTILS_NONNULL drawSwapChain,
SwapChain* UTILS_NONNULL readSwapChain) noexcept = 0;
/**
* Called by the driver to make the OpenGL context active on the calling thread and bind
* the drawSwapChain to the default render target (FBO) created with createDefaultRenderTarget.
* the drawSwapChain to the default FBO returned by getDefaultFramebufferObject().
* The context used is either the default context or the protected context. When a context
* change is necessary, the preContextChange and postContextChange callbacks are called,
* before and after the context change respectively. postContextChange is given the index
* of the new context (0 for default and 1 for protected).
* The default implementation just calls makeCurrent(getCurrentContextType(), SwapChain*, SwapChain*).
*
* @param drawSwapChain SwapChain to draw to. It must be bound to the default FBO.
* @param readSwapChain SwapChain to read from (for operation like `glBlitFramebuffer`)
* @param preContextChange called before the context changes
* @param postContextChange called after the context changes
*/
virtual void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept = 0;
virtual void makeCurrent(
SwapChain* UTILS_NONNULL drawSwapChain,
SwapChain* UTILS_NONNULL readSwapChain,
utils::Invocable<void()> preContextChange,
utils::Invocable<void(size_t index)> postContextChange) noexcept;
/**
* Called by the driver once the current frame finishes drawing. Typically, this should present
* the drawSwapChain. This is for example where `eglMakeCurrent()` would be called.
* @param swapChain the SwapChain to present.
*/
virtual void commit(SwapChain* swapChain) noexcept = 0;
virtual void commit(SwapChain* UTILS_NONNULL swapChain) noexcept = 0;
/**
* Set the time the next committed buffer should be presented to the user at.
@@ -152,14 +221,14 @@ public:
*
* @return A Fence object. The default implementation returns nullptr.
*/
virtual Fence* createFence() noexcept;
virtual Fence* UTILS_NULLABLE createFence() noexcept;
/**
* Destroys a Fence object. The default implementation does nothing.
*
* @param fence Fence to destroy.
*/
virtual void destroyFence(Fence* fence) noexcept;
virtual void destroyFence(Fence* UTILS_NONNULL fence) noexcept;
/**
* Waits on a Fence.
@@ -169,7 +238,7 @@ public:
* @return Whether the fence signaled or timed out. See backend::FenceStatus.
* The default implementation always return backend::FenceStatus::ERROR.
*/
virtual backend::FenceStatus waitFence(Fence* fence, uint64_t timeout) noexcept;
virtual backend::FenceStatus waitFence(Fence* UTILS_NONNULL fence, uint64_t timeout) noexcept;
// --------------------------------------------------------------------------------------------
@@ -183,13 +252,13 @@ public:
* @param nativeStream The native stream, this parameter depends on the concrete implementation.
* @return A new Stream object.
*/
virtual Stream* createStream(void* nativeStream) noexcept;
virtual Stream* UTILS_NULLABLE createStream(void* UTILS_NULLABLE nativeStream) noexcept;
/**
* Destroys a Stream.
* @param stream Stream to destroy.
*/
virtual void destroyStream(Stream* stream) noexcept;
virtual void destroyStream(Stream* UTILS_NONNULL stream) noexcept;
/**
* The specified stream takes ownership of the texture (tname) object
@@ -199,20 +268,21 @@ public:
* @param stream Stream to take ownership of the texture
* @param tname GL texture id to "bind" to the Stream.
*/
virtual void attach(Stream* stream, intptr_t tname) noexcept;
virtual void attach(Stream* UTILS_NONNULL stream, intptr_t tname) noexcept;
/**
* Destroys the texture associated to the stream
* @param stream Stream to detach from its texture
*/
virtual void detach(Stream* stream) noexcept;
virtual void detach(Stream* UTILS_NONNULL stream) noexcept;
/**
* Updates the content of the texture attached to the stream.
* @param stream Stream to update
* @param timestamp Output parameter: Timestamp of the image bound to the texture.
*/
virtual void updateTexImage(Stream* stream, int64_t* timestamp) noexcept;
virtual void updateTexImage(Stream* UTILS_NONNULL stream,
int64_t* UTILS_NONNULL timestamp) noexcept;
// --------------------------------------------------------------------------------------------
@@ -225,13 +295,13 @@ public:
* implementation could just return { 0, GL_TEXTURE_2D } at this point. The actual
* values can be delayed until setExternalImage.
*/
virtual ExternalTexture *createExternalImageTexture() noexcept;
virtual ExternalTexture* UTILS_NULLABLE createExternalImageTexture() noexcept;
/**
* Destroys an external texture handle and associated data.
* @param texture a pointer to the handle to destroy.
*/
virtual void destroyExternalImage(ExternalTexture* texture) noexcept;
virtual void destroyExternalImage(ExternalTexture* UTILS_NONNULL texture) noexcept;
// called on the application thread to allow Filament to take ownership of the image
@@ -244,7 +314,7 @@ public:
* @param externalImage A token representing the platform's external image.
* @see destroyExternalImage
*/
virtual void retainExternalImage(void* externalImage) noexcept;
virtual void retainExternalImage(void* UTILS_NONNULL externalImage) noexcept;
/**
* Called to bind the platform-specific externalImage to an ExternalTexture.
@@ -258,7 +328,8 @@ public:
* @param texture an in/out pointer to ExternalTexture, id and target can be updated if necessary.
* @return true on success, false on error.
*/
virtual bool setExternalImage(void* externalImage, ExternalTexture* texture) noexcept;
virtual bool setExternalImage(void* UTILS_NONNULL externalImage,
ExternalTexture* UTILS_NONNULL texture) noexcept;
/**
* The method allows platforms to convert a user-supplied external image object into a new type

View File

@@ -17,11 +17,10 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_COCOA_GL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <stdint.h>
namespace filament::backend {
@@ -58,7 +57,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;
void destroyExternalImage(ExternalTexture* texture) noexcept override;

View File

@@ -30,7 +30,7 @@ struct PlatformCocoaTouchGLImpl;
class PlatformCocoaTouchGL : public OpenGLPlatform {
public:
PlatformCocoaTouchGL();
~PlatformCocoaTouchGL() noexcept;
~PlatformCocoaTouchGL() noexcept override;
// --------------------------------------------------------------------------------------------
// Platform Interface
@@ -45,7 +45,7 @@ public:
void terminate() noexcept override;
uint32_t createDefaultRenderTarget() noexcept override;
uint32_t getDefaultFramebufferObject() noexcept override;
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
@@ -53,7 +53,7 @@ public:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
OpenGLPlatform::ExternalTexture* createExternalImageTexture() noexcept override;

View File

@@ -17,18 +17,23 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_H
#include <stdint.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
#include <EGL/eglplatform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/DriverEnums.h>
#include <utils/Invocable.h>
#include <initializer_list>
#include <utility>
#include <vector>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
/**
@@ -38,12 +43,11 @@ class PlatformEGL : public OpenGLPlatform {
public:
PlatformEGL() noexcept;
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
void releaseContext() noexcept override;
// Return true if we're on an OpenGL platform (as opposed to OpenGL ES). false by default.
virtual bool isOpenGL() const noexcept;
protected:
// --------------------------------------------------------------------------------------------
// Helper for EGL configs and attributes parameters
@@ -83,13 +87,30 @@ protected:
// --------------------------------------------------------------------------------------------
// OpenGLPlatform Interface
bool isExtraContextSupported() const noexcept override;
void createContext(bool shared) override;
void releaseContext() noexcept override;
void terminate() noexcept override;
bool isProtectedContextSupported() const noexcept override;
bool isSRGBSwapChainSupported() const noexcept override;
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool isSwapChainProtected(SwapChain* swapChain) noexcept override;
ContextType getCurrentContextType() const noexcept override;
bool makeCurrent(ContextType type,
SwapChain* drawSwapChain,
SwapChain* readSwapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain,
utils::Invocable<void()> preContextChange,
utils::Invocable<void(size_t index)> postContextChange) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
bool canCreateFence() noexcept override;
@@ -116,16 +137,28 @@ protected:
static void clearGlError() noexcept;
/**
* Always use this instead of eglMakeCurrent().
* Always use this instead of eglMakeCurrent(), as it tracks some state.
*/
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept;
EGLContext getContextForType(ContextType type) const noexcept;
// makes the draw and read surface current without changing the current context
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept {
return egl.makeCurrent(drawSurface, readSurface);
}
// makes context current and set draw and read surfaces to EGL_NO_SURFACE
EGLBoolean makeCurrent(EGLContext context) noexcept {
return egl.makeCurrent(context, mEGLDummySurface, mEGLDummySurface);
}
// TODO: this should probably use getters instead.
EGLDisplay mEGLDisplay = EGL_NO_DISPLAY;
EGLContext mEGLContext = EGL_NO_CONTEXT;
EGLSurface mCurrentDrawSurface = EGL_NO_SURFACE;
EGLSurface mCurrentReadSurface = EGL_NO_SURFACE;
EGLContext mEGLContextProtected = EGL_NO_CONTEXT;
EGLSurface mEGLDummySurface = EGL_NO_SURFACE;
ContextType mCurrentContextType = ContextType::NONE;
// mEGLConfig is valid only if ext.egl.KHR_no_config_context is false
EGLConfig mEGLConfig = EGL_NO_CONFIG_KHR;
Config mContextAttribs;
std::vector<EGLContext> mAdditionalContexts;
@@ -141,13 +174,38 @@ protected:
bool KHR_gl_colorspace = false;
bool KHR_no_config_context = false;
bool KHR_surfaceless_context = false;
bool EXT_protected_content = false;
} egl;
} ext;
struct SwapChainEGL : public Platform::SwapChain {
EGLSurface sur = EGL_NO_SURFACE;
Config attribs{};
EGLNativeWindowType nativeWindow{};
EGLConfig config{};
uint64_t flags{};
};
void initializeGlExtensions() noexcept;
protected:
EGLConfig findSwapChainConfig(uint64_t flags, bool window, bool pbuffer) const;
private:
EGLConfig findSwapChainConfig(uint64_t flags) const;
class EGL {
EGLDisplay& mEGLDisplay;
EGLSurface mCurrentDrawSurface = EGL_NO_SURFACE;
EGLSurface mCurrentReadSurface = EGL_NO_SURFACE;
EGLContext mCurrentContext = EGL_NO_CONTEXT;
public:
explicit EGL(EGLDisplay& dpy) : mEGLDisplay(dpy) {}
EGLBoolean makeCurrent(EGLContext context,
EGLSurface drawSurface, EGLSurface readSurface) noexcept;
EGLBoolean makeCurrent(EGLSurface drawSurface, EGLSurface readSurface) noexcept {
return makeCurrent(mCurrentContext, drawSurface, readSurface);
}
} egl{ mEGLDisplay };
};
} // namespace filament::backend

View File

@@ -17,8 +17,14 @@
#ifndef TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#define TNT_FILAMENT_BACKEND_OPENGL_OPENGL_PLATFORM_EGL_ANDROID_H
#include <backend/AcquiredImage.h>
#include <backend/Platform.h>
#include <backend/platforms/OpenGLPlatform.h>
#include <backend/platforms/PlatformEGL.h>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
class ExternalStreamManagerAndroid;

View File

@@ -30,6 +30,9 @@ public:
Driver* createDriver(void* sharedContext,
const Platform::DriverConfig& driverConfig) noexcept override;
protected:
bool isOpenGL() const noexcept override;
};
} // namespace filament

View File

@@ -51,7 +51,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
private:

View File

@@ -53,7 +53,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
protected:

View File

@@ -46,7 +46,7 @@ protected:
SwapChain* createSwapChain(void* nativewindow, uint64_t flags) noexcept override;
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags) noexcept override;
void destroySwapChain(SwapChain* swapChain) noexcept override;
void makeCurrent(SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
bool makeCurrent(ContextType type, SwapChain* drawSwapChain, SwapChain* readSwapChain) noexcept override;
void commit(SwapChain* swapChain) noexcept override;
};

View File

@@ -20,12 +20,18 @@
#include <backend/Platform.h>
#include <bluevk/BlueVK.h>
#include <utils/CString.h>
#include <utils/FixedCapacityVector.h>
#include <utils/PrivateImplementation.h>
#include <string_view>
#include <tuple>
#include <unordered_set>
#include <stddef.h>
#include <stdint.h>
namespace filament::backend {
using SwapChain = Platform::SwapChain;
@@ -89,36 +95,44 @@ public:
// ----------------------------------------------------
// ---------- Platform Customization options ----------
/**
* The client preference can be stored within the struct. We allow for two specification of
* preference:
* 1) A substring to match against `VkPhysicalDeviceProperties.deviceName`.
* 2) Index of the device in the list as returned by vkEnumeratePhysicalDevices.
*/
struct GPUPreference {
std::string deviceName;
int8_t index = -1;
struct Customization {
/**
* The client can specify the GPU (i.e. VkDevice) for the platform. We allow the
* following preferences:
* 1) A substring to match against `VkPhysicalDeviceProperties.deviceName`. Empty string
* by default.
* 2) Index of the device in the list as returned by
* `vkEnumeratePhysicalDevices`. -1 by default to indicate no preference.
*/
struct GPUPreference {
utils::CString deviceName;
int8_t index = -1;
} gpu;
/**
* Whether the platform supports sRGB swapchain. Default is true.
*/
bool isSRGBSwapChainSupported = true;
/**
* When the platform window is resized, we will flush and wait on the command queues
* before recreating the swapchain. Default is true.
*/
bool flushAndWaitOnWindowResize = true;
};
/**
* Client can provide a preference over the GPU to use in the vulkan instance
* @return `GPUPreference` struct that indicates the client's preference
* Client can override to indicate customized behavior or parameter for their platform.
* @return `Customization` struct that indicates the client's platform
* customizations.
*/
virtual GPUPreference getPreferredGPU() noexcept {
virtual Customization getCustomization() const noexcept {
return {};
}
// -------- End platform customization options --------
// ----------------------------------------------------
/**
* Returns whether the platform supports sRGB swapchain. This is true by default, and the client
* needs to override this method to specify otherwise.
* @return Whether the platform supports sRGB swapchain.
*/
virtual bool isSRGBSwapChainSupported() const {
return true;
}
/**
* Get the images handles and format of the memory backing the swapchain. This should be called
* after createSwapChain() or after recreateIfResized().

View File

@@ -127,7 +127,7 @@ public:
protected:
// Looks at platform and target API, then decides on shader models and output formats.
void prepare(bool vulkanSemantics);
void prepare(bool vulkanSemantics, filament::backend::FeatureLevel featureLevel);
using ShaderModel = filament::backend::ShaderModel;
Platform mPlatform = Platform::DESKTOP;
@@ -135,11 +135,13 @@ protected:
Optimization mOptimization = Optimization::PERFORMANCE;
bool mPrintShaders = false;
bool mGenerateDebugInfo = false;
bool mIncludeEssl1 = true;
utils::bitset32 mShaderModels;
struct CodeGenParams {
ShaderModel shaderModel;
TargetApi targetApi;
TargetLanguage targetLanguage;
filament::backend::FeatureLevel featureLevel;
};
std::vector<CodeGenParams> mCodeGenPermutations;
@@ -241,6 +243,7 @@ public:
using Precision = filament::backend::Precision;
using CullingMode = filament::backend::CullingMode;
using FeatureLevel = filament::backend::FeatureLevel;
using StereoscopicType = filament::backend::StereoscopicType;
enum class VariableQualifier : uint8_t {
OUT
@@ -270,6 +273,9 @@ public:
MaterialBuilder& noSamplerValidation(bool enabled) noexcept;
//! Enable generation of ESSL 1.0 code in FL0 materials.
MaterialBuilder& includeEssl1(bool enabled) noexcept;
//! Set the name of this material.
MaterialBuilder& name(const char* name) noexcept;
@@ -306,12 +312,8 @@ public:
*/
MaterialBuilder& parameter(const char* name, SamplerType samplerType,
SamplerFormat format = SamplerFormat::FLOAT,
ParameterPrecision precision = ParameterPrecision::DEFAULT) noexcept;
/// @copydoc parameter(SamplerType, SamplerFormat, ParameterPrecision, const char*)
MaterialBuilder& parameter(const char* name, SamplerType samplerType,
ParameterPrecision precision) noexcept;
ParameterPrecision precision = ParameterPrecision::DEFAULT,
bool multisample = false) noexcept;
MaterialBuilder& buffer(filament::BufferInterfaceBlock bib) noexcept;
@@ -408,7 +410,8 @@ public:
/**
* Set the blending mode of the post-lighting color for this material.
* Only OPAQUE, TRANSPARENT and ADD are supported, the default is TRANSPARENT.
* This setting requires the material property "postLightingColor" to be set.
* This setting requires the material properties "postLightingColor" and
* "postLightingMixFactor" to be set.
*/
MaterialBuilder& postLightingBlending(BlendingMode blending) noexcept;
@@ -520,6 +523,12 @@ public:
//! Specifies how transparent objects should be rendered (default is DEFAULT).
MaterialBuilder& transparencyMode(TransparencyMode mode) noexcept;
//! Specify the stereoscopic type (default is INSTANCED)
MaterialBuilder& stereoscopicType(StereoscopicType stereoscopicType) noexcept;
//! Specify the number of eyes for stereoscopic rendering
MaterialBuilder& stereoscopicEyeCount(uint8_t eyeCount) noexcept;
/**
* Enable / disable custom surface shading. Custom surface shading requires the LIT
* shading model. In addition, the following function must be defined in the fragment
@@ -617,8 +626,8 @@ public:
Parameter() noexcept: parameterType(INVALID) {}
// Sampler
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p)
: name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER) { }
Parameter(const char* paramName, SamplerType t, SamplerFormat f, ParameterPrecision p, bool ms)
: name(paramName), size(1), precision(p), samplerType(t), format(f), parameterType(SAMPLER), multisample(ms) { }
// Uniform
Parameter(const char* paramName, UniformType t, size_t typeSize, ParameterPrecision p)
@@ -635,6 +644,7 @@ public:
SamplerType samplerType;
SubpassType subpassType;
SamplerFormat format;
bool multisample;
enum {
INVALID,
UNIFORM,
@@ -690,8 +700,8 @@ public:
std::string peek(filament::backend::ShaderStage type,
const CodeGenParams& params, const PropertyList& properties) noexcept;
// Returns true if any of the parameter samplers is of type samplerExternal
bool hasExternalSampler() const noexcept;
// Returns true if any of the parameter samplers matches the specified type.
bool hasSamplerType(SamplerType samplerType) const noexcept;
static constexpr size_t MAX_PARAMETERS_COUNT = 48;
static constexpr size_t MAX_SUBPASS_COUNT = 1;
@@ -754,7 +764,7 @@ private:
MaterialBuilder::PropertyList& allProperties,
CodeGenParams const& semanticCodeGenParams) noexcept;
bool runSemanticAnalysis(MaterialInfo const& info,
bool runSemanticAnalysis(MaterialInfo* inOutInfo,
CodeGenParams const& semanticCodeGenParams) noexcept;
bool checkLiteRequirements() noexcept;
@@ -827,6 +837,8 @@ private:
Interpolation mInterpolation = Interpolation::SMOOTH;
VertexDomain mVertexDomain = VertexDomain::OBJECT;
TransparencyMode mTransparencyMode = TransparencyMode::DEFAULT;
StereoscopicType mStereoscopicType = StereoscopicType::INSTANCED;
uint8_t mStereoscopicEyeCount = 2;
filament::AttributeBitset mRequiredAttributes;

View File

@@ -88,12 +88,23 @@ public:
*/
class EquirectangularToCubemap {
public:
struct Config {
bool mirror = true; //!< mirror the source horizontally
};
/**
* Creates a EquirectangularToCubemap processor.
* Creates a EquirectangularToCubemap processor using the default Config
* @param context IBLPrefilterContext to use
*/
explicit EquirectangularToCubemap(IBLPrefilterContext& context);
/**
* Creates a EquirectangularToCubemap processor using the provided Config
* @param context IBLPrefilterContext to use
*/
EquirectangularToCubemap(IBLPrefilterContext& context, Config const& config);
/**
* Destroys all GPU resources created during initialization.
*/
@@ -125,6 +136,7 @@ public:
private:
IBLPrefilterContext& mContext;
filament::Material* mEquirectMaterial = nullptr;
Config mConfig{};
};
/**

View File

@@ -21,10 +21,14 @@
#include <utils/compiler.h>
#include <limits>
#include <math/mat3.h>
#include <math/mat4.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <float.h>
#include <stddef.h>
namespace filament {
@@ -70,7 +74,7 @@ public:
* @return This bounding box
*/
Box& set(const math::float3& min, const math::float3& max) noexcept {
// float3 ctor needed for visual studio
// float3 ctor needed for Visual Studio
center = (max + min) * math::float3(0.5f);
halfExtent = (max - min) * math::float3(0.5f);
return *this;
@@ -130,17 +134,17 @@ public:
struct UTILS_PUBLIC Aabb {
/** min coordinates */
math::float3 min = std::numeric_limits<float>::max();
math::float3 min = FLT_MAX;
/** max coordinates */
math::float3 max = std::numeric_limits<float>::lowest();
math::float3 max = -FLT_MAX;
/**
* Computes the center of the box.
* @return (max + min)/2
*/
math::float3 center() const noexcept {
// float3 ctor needed for visual studio
// float3 ctor needed for Visual Studio
return (max + min) * math::float3(0.5f);
}
@@ -149,7 +153,7 @@ struct UTILS_PUBLIC Aabb {
* @return (max - min)/2
*/
math::float3 extent() const noexcept {
// float3 ctor needed for visual studio
// float3 ctor needed for Visual Studio
return (max - min) * math::float3(0.5f);
}
@@ -170,6 +174,8 @@ struct UTILS_PUBLIC Aabb {
value_type const* data() const { return vertices; }
value_type * data() { return vertices; }
size_t size() const { return 8; }
value_type const& operator[](size_t i) const noexcept { return vertices[i]; }
value_type& operator[](size_t i) noexcept { return vertices[i]; }
value_type vertices[8];
};
@@ -196,12 +202,14 @@ struct UTILS_PUBLIC Aabb {
* @return the maximum signed distance to the box. Negative if p is in the box
*/
float contains(math::float3 p) const noexcept {
// we don't use std::max to avoid a dependency on <algorithm>
auto const maximum = [](auto a, auto b) { return a > b ? a : b; };
float d = min.x - p.x;
d = std::max(d, min.y - p.y);
d = std::max(d, min.z - p.z);
d = std::max(d, p.x - max.x);
d = std::max(d, p.y - max.y);
d = std::max(d, p.z - max.z);
d = maximum(d, min.y - p.y);
d = maximum(d, min.z - p.z);
d = maximum(d, p.x - max.x);
d = maximum(d, p.y - max.y);
d = maximum(d, p.z - max.z);
return d;
}

View File

@@ -22,11 +22,13 @@
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/BufferDescriptor.h>
#include <utils/compiler.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
class FBufferObject;
@@ -82,8 +84,7 @@ public:
*
* @param engine Reference to the filament::Engine to associate this BufferObject with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
@@ -91,7 +92,7 @@ public:
*
* @see IndexBuffer::setBuffer
*/
BufferObject* build(Engine& engine);
BufferObject* UTILS_NONNULL build(Engine& engine);
private:
friend class FBufferObject;
};
@@ -110,6 +111,10 @@ public:
* @return The maximum capacity of the BufferObject.
*/
size_t getByteCount() const noexcept;
protected:
// prevent heap allocation
~BufferObject() = default;
};
} // namespace filament

View File

@@ -26,6 +26,12 @@
#include <math/mathfwd.h>
#include <math/vec2.h>
#include <math/vec4.h>
#include <math/mat4.h>
#include <math.h>
#include <stdint.h>
#include <stddef.h>
namespace utils {
class Entity;
@@ -172,6 +178,30 @@ public:
HORIZONTAL //!< the field-of-view angle is defined on the horizontal axis
};
/** Returns the projection matrix from the field-of-view.
*
* @param fovInDegrees full field-of-view in degrees. 0 < \p fov < 180.
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
* @param near distance in world units from the camera to the near plane. \p near > 0.
* @param far distance in world units from the camera to the far plane. \p far > \p near.
* @param direction direction of the \p fovInDegrees parameter.
*
* @see Fov.
*/
static math::mat4 projection(Fov direction, double fovInDegrees,
double aspect, double near, double far = INFINITY);
/** Returns the projection matrix from the focal length.
*
* @param focalLengthInMillimeters lens's focal length in millimeters. \p focalLength > 0.
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
* @param near distance in world units from the camera to the near plane. \p near > 0.
* @param far distance in world units from the camera to the far plane. \p far > \p near.
*/
static math::mat4 projection(double focalLengthInMillimeters,
double aspect, double near, double far = INFINITY);
/** Sets the projection matrix from a frustum defined by six planes.
*
* @param projection type of #Projection to use.
@@ -209,7 +239,8 @@ public:
double bottom, double top,
double near, double far);
/** Sets the projection matrix from the field-of-view.
/** Utility to set the projection matrix from the field-of-view.
*
* @param fovInDegrees full field-of-view in degrees. 0 < \p fov < 180.
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
@@ -222,7 +253,7 @@ public:
void setProjection(double fovInDegrees, double aspect, double near, double far,
Fov direction = Fov::VERTICAL);
/** Sets the projection matrix from the focal length.
/** Utility to set the projection matrix from the focal length.
*
* @param focalLengthInMillimeters lens's focal length in millimeters. \p focalLength > 0.
* @param aspect aspect ratio \f$ \frac{width}{height} \f$. \p aspect > 0.
@@ -232,13 +263,8 @@ public:
void setLensProjection(double focalLengthInMillimeters,
double aspect, double near, double far);
/** Sets a custom projection matrix.
*
* The projection matrix must be of one of the following form:
* a 0 tx 0 a 0 0 tx
* 0 b ty 0 0 b 0 ty
* 0 0 tz c 0 0 c tz
* 0 0 -1 0 0 0 0 1
*
* The projection matrix must define an NDC system that must match the OpenGL convention,
* that is all 3 axis are mapped to [-1, 1].
@@ -249,31 +275,7 @@ public:
*/
void setCustomProjection(math::mat4 const& projection, double near, double far) noexcept;
/** Sets a custom projection matrix for each eye.
*
* The projectionForCulling, near, and far parameters establish a "culling frustum" which must
* encompass anything either eye can see.
*
* @param projection an array of projection matrices, only the first
* CONFIG_STEREOSCOPIC_EYES (2) are read
* @param count size of the projection matrix array to set, must be
* >= CONFIG_STEREOSCOPIC_EYES (2)
* @param projectionForCulling custom projection matrix for culling, must encompass both eyes
* @param near distance in world units from the camera to the culling near plane. \p near > 0.
* @param far distance in world units from the camera to the culling far plane. \p far > \p
* near.
* @see setCustomProjection
*/
void setCustomEyeProjection(math::mat4 const* projection, size_t count,
math::mat4 const& projectionForCulling, double near, double far);
/** Sets the projection matrix.
*
* The projection matrices must be of one of the following form:
* a 0 tx 0 a 0 0 tx
* 0 b ty 0 0 b 0 ty
* 0 0 tz c 0 0 c tz
* 0 0 -1 0 0 0 0 1
*
* The projection matrices must define an NDC system that must match the OpenGL convention,
* that is all 3 axis are mapped to [-1, 1].
@@ -286,6 +288,27 @@ public:
void setCustomProjection(math::mat4 const& projection, math::mat4 const& projectionForCulling,
double near, double far) noexcept;
/** Sets a custom projection matrix for each eye.
*
* The projectionForCulling, near, and far parameters establish a "culling frustum" which must
* encompass anything any eye can see. All projection matrices must be set simultaneously. The
* number of stereoscopic eyes is controlled by the stereoscopicEyeCount setting inside of
* Engine::Config.
*
* @param projection an array of projection matrices, only the first config.stereoscopicEyeCount
* are read
* @param count size of the projection matrix array to set, must be
* >= config.stereoscopicEyeCount
* @param projectionForCulling custom projection matrix for culling, must encompass both eyes
* @param near distance in world units from the camera to the culling near plane. \p near > 0.
* @param far distance in world units from the camera to the culling far plane. \p far > \p
* near.
* @see setCustomProjection
* @see Engine::Config::stereoscopicEyeCount
*/
void setCustomEyeProjection(math::mat4 const* UTILS_NONNULL projection, size_t count,
math::mat4 const& projectionForCulling, double near, double far);
/** Sets an additional matrix that scales the projection matrix.
*
* This is useful to adjust the aspect ratio of the camera independent from its projection.
@@ -342,8 +365,8 @@ public:
* The projection matrix used for rendering always has its far plane set to infinity. This
* is why it may differ from the matrix set through setProjection() or setLensProjection().
*
* @param eyeId the index of the eye to return the projection matrix for, must be <
* CONFIG_STEREOSCOPIC_EYES (2)
* @param eyeId the index of the eye to return the projection matrix for, must be
* < config.stereoscopicEyeCount
* @return The projection matrix used for rendering
*
* @see setProjection, setLensProjection, setCustomProjection, getCullingProjectionMatrix,
@@ -401,7 +424,7 @@ public:
* This method is not intended to be called every frame. Instead, to update the position of the
* head, use Camera::setModelMatrix.
*
* @param eyeId the index of the eye to set, must be < CONFIG_STEREOSCOPIC_EYES (2)
* @param eyeId the index of the eye to set, must be < config.stereoscopicEyeCount
* @param model the model matrix for an individual eye
*/
void setEyeModelMatrix(uint8_t eyeId, math::mat4 const& model);
@@ -524,33 +547,6 @@ public:
*
* \param p the projection matrix to inverse
* \returns the inverse of the projection matrix \p p
*
* \warning the projection matrix to invert must have one of the form below:
* - perspective projection
*
* \f$
* \left(
* \begin{array}{cccc}
* a & 0 & tx & 0 \\
* 0 & b & ty & 0 \\
* 0 & 0 & tz & c \\
* 0 & 0 & -1 & 0 \\
* \end{array}
* \right)
* \f$
*
* - orthographic projection
*
* \f$
* \left(
* \begin{array}{cccc}
* a & 0 & 0 & tx \\
* 0 & b & 0 & ty \\
* 0 & 0 & c & tz \\
* 0 & 0 & 0 & 1 \\
* \end{array}
* \right)
* \f$
*/
static math::mat4 inverseProjection(const math::mat4& p) noexcept;
@@ -577,6 +573,10 @@ public:
* @return effective full field of view in degrees
*/
static double computeEffectiveFov(double fovInDegrees, double focusDistance) noexcept;
protected:
// prevent heap allocation
~Camera() = default;
};
} // namespace filament

View File

@@ -24,6 +24,9 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
//! RGB color in linear space

View File

@@ -26,6 +26,9 @@
#include <math/mathfwd.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
class Engine;
@@ -200,7 +203,7 @@ public:
*
* @return This Builder, for chaining calls
*/
Builder& toneMapper(const ToneMapper* toneMapper) noexcept;
Builder& toneMapper(ToneMapper const* UTILS_NULLABLE toneMapper) noexcept;
/**
* Selects the tone mapping operator to apply to the HDR color buffer as the last
@@ -470,14 +473,17 @@ public:
*
* @param engine Reference to the filament::Engine to associate this ColorGrading with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*/
ColorGrading* build(Engine& engine);
ColorGrading* UTILS_NONNULL build(Engine& engine);
private:
friend class FColorGrading;
};
protected:
// prevent heap allocation
~ColorGrading() = default;
};
} // namespace filament

View File

@@ -18,7 +18,6 @@
#define TNT_FILAMENT_COLOR_SPACE_H
#include <math/vec2.h>
#include <math/vec3.h>
namespace filament::color {

View File

@@ -25,7 +25,7 @@
#include <math/mathfwd.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
@@ -39,27 +39,12 @@ namespace filament {
class UTILS_PUBLIC DebugRegistry : public FilamentAPI {
public:
/**
* Type of a property
*/
enum Type {
BOOL, INT, FLOAT, FLOAT2, FLOAT3, FLOAT4
};
/**
* Information about a property
*/
struct Property {
const char* name; //!< property name
Type type; //!< property type
};
/**
* Queries whether a property exists
* @param name The name of the property to query
* @return true if the property exists, false otherwise
*/
bool hasProperty(const char* name) const noexcept;
bool hasProperty(const char* UTILS_NONNULL name) const noexcept;
/**
* Queries the address of a property's data from its name
@@ -67,15 +52,30 @@ public:
* @return Address of the data of the \p name property
* @{
*/
void* getPropertyAddress(const char* name) noexcept;
void* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name);
void const* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) const noexcept;
template<typename T>
inline T* getPropertyAddress(const char* name) noexcept {
inline T* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) {
return static_cast<T*>(getPropertyAddress(name));
}
template<typename T>
inline bool getPropertyAddress(const char* name, T** p) noexcept {
inline T const* UTILS_NULLABLE getPropertyAddress(const char* UTILS_NONNULL name) const noexcept {
return static_cast<T*>(getPropertyAddress(name));
}
template<typename T>
inline bool getPropertyAddress(const char* UTILS_NONNULL name,
T* UTILS_NULLABLE* UTILS_NONNULL p) {
*p = getPropertyAddress<T>(name);
return *p != nullptr;
}
template<typename T>
inline bool getPropertyAddress(const char* UTILS_NONNULL name,
T* const UTILS_NULLABLE* UTILS_NONNULL p) const noexcept {
*p = getPropertyAddress<T>(name);
return *p != nullptr;
}
@@ -88,12 +88,12 @@ public:
* @return true if the operation was successful, false otherwise.
* @{
*/
bool setProperty(const char* name, bool v) noexcept;
bool setProperty(const char* name, int v) noexcept;
bool setProperty(const char* name, float v) noexcept;
bool setProperty(const char* name, math::float2 v) noexcept;
bool setProperty(const char* name, math::float3 v) noexcept;
bool setProperty(const char* name, math::float4 v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, bool v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, int v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, float v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, math::float2 v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, math::float3 v) noexcept;
bool setProperty(const char* UTILS_NONNULL name, math::float4 v) noexcept;
/** @}*/
/**
@@ -103,20 +103,20 @@ public:
* @return true if the call was successful and \p v was updated
* @{
*/
bool getProperty(const char* name, bool* v) const noexcept;
bool getProperty(const char* name, int* v) const noexcept;
bool getProperty(const char* name, float* v) const noexcept;
bool getProperty(const char* name, math::float2* v) const noexcept;
bool getProperty(const char* name, math::float3* v) const noexcept;
bool getProperty(const char* name, math::float4* v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, bool* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, int* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, float* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, math::float2* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, math::float3* UTILS_NONNULL v) const noexcept;
bool getProperty(const char* UTILS_NONNULL name, math::float4* UTILS_NONNULL v) const noexcept;
/** @}*/
struct DataSource {
void const* data;
void const* UTILS_NULLABLE data;
size_t count;
};
DataSource getDataSource(const char* name) const noexcept;
DataSource getDataSource(const char* UTILS_NONNULL name) const noexcept;
struct FrameHistory {
using duration_ms = float;
@@ -129,6 +129,10 @@ public:
float pid_i = 0.0f;
float pid_d = 0.0f;
};
protected:
// prevent heap allocation
~DebugRegistry() = default;
};

View File

@@ -19,9 +19,14 @@
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/Platform.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stdint.h>
#include <stddef.h>
namespace utils {
class Entity;
@@ -172,10 +177,12 @@ public:
using Platform = backend::Platform;
using Backend = backend::Backend;
using DriverConfig = backend::Platform::DriverConfig;
using FeatureLevel = backend::FeatureLevel;
using StereoscopicType = backend::StereoscopicType;
/**
* Config is used to define the memory footprint used by the engine, such as the
* command buffer size. Config can be used to customize engine requirements based
* command buffer size. Config can be used to customize engine requirements based
* on the applications needs.
*
* .perRenderPassArenaSizeMB (default: 3 MiB)
@@ -267,11 +274,77 @@ public:
* This value does not affect the application's memory usage.
*/
uint32_t perFrameCommandsSizeMB = FILAMENT_PER_FRAME_COMMANDS_SIZE_IN_MB;
/**
* Number of threads to use in Engine's JobSystem.
*
* Engine uses a utils::JobSystem to carry out paralleization of Engine workloads. This
* value sets the number of threads allocated for JobSystem. Configuring this value can be
* helpful in CPU-constrained environments where too many threads can cause contention of
* CPU and reduce performance.
*
* The default value is 0, which implies that the Engine will use a heuristic to determine
* the number of threads to use.
*/
uint32_t jobSystemThreadCount = 0;
/*
* Number of most-recently destroyed textures to track for use-after-free.
*
* This will cause the backend to throw an exception when a texture is freed but still bound
* to a SamplerGroup and used in a draw call. 0 disables completely.
*
* Currently only respected by the Metal backend.
*/
size_t textureUseAfterFreePoolSize = 0;
/**
* Set to `true` to forcibly disable parallel shader compilation in the backend.
* Currently only honored by the GL and Metal backends.
*/
bool disableParallelShaderCompile = false;
/*
* The type of technique for stereoscopic rendering.
*
* This setting determines the algorithm used when stereoscopic rendering is enabled. This
* decision applies to the entire Engine for the lifetime of the Engine. E.g., multiple
* Views created from the Engine must use the same stereoscopic type.
*
* Each view can enable stereoscopic rendering via the StereoscopicOptions::enable flag.
*
* @see View::setStereoscopicOptions
*/
StereoscopicType stereoscopicType = StereoscopicType::INSTANCED;
/*
* The number of eyes to render when stereoscopic rendering is enabled. Supported values are
* between 1 and Engine::getMaxStereoscopicEyes() (inclusive).
*
* @see View::setStereoscopicOptions
* @see Engine::getMaxStereoscopicEyes
*/
uint8_t stereoscopicEyeCount = 2;
/*
* @deprecated This value is no longer used.
*/
uint32_t resourceAllocatorCacheSizeMB = 64;
/*
* This value determines for how many frames are texture entries kept in the cache.
*/
uint32_t resourceAllocatorCacheMaxAge = 2;
/*
* Disable backend handles use-after-free checks.
*/
bool disableHandleUseAfterFreeCheck = false;
};
#if UTILS_HAS_THREADING
using CreateCallback = void(void* user, void* token);
using CreateCallback = void(void* UTILS_NULLABLE user, void* UTILS_NONNULL token);
#endif
/**
@@ -310,7 +383,7 @@ public:
*
* @return A reference to this Builder for chaining calls.
*/
Builder& platform(Platform* platform) noexcept;
Builder& platform(Platform* UTILS_NULLABLE platform) noexcept;
/**
* @param config A pointer to optional parameters to specify memory size
@@ -318,7 +391,7 @@ public:
*
* @return A reference to this Builder for chaining calls.
*/
Builder& config(const Config* config) noexcept;
Builder& config(const Config* UTILS_NULLABLE config) noexcept;
/**
* @param sharedContext A platform-dependant context used as a shared context
@@ -326,7 +399,21 @@ public:
*
* @return A reference to this Builder for chaining calls.
*/
Builder& sharedContext(void* sharedContext) noexcept;
Builder& sharedContext(void* UTILS_NULLABLE sharedContext) noexcept;
/**
* @param featureLevel The feature level at which initialize Filament.
* @return A reference to this Builder for chaining calls.
*/
Builder& featureLevel(FeatureLevel featureLevel) noexcept;
/**
* Warning: This is an experimental API. See Engine::setPaused(bool) for caveats.
*
* @param paused Whether to start the rendering thread paused.
* @return A reference to this Builder for chaining calls.
*/
Builder& paused(bool paused) noexcept;
#if UTILS_HAS_THREADING
/**
@@ -335,7 +422,7 @@ public:
* @param callback Callback called once the engine is initialized and it is safe to
* call Engine::getEngine().
*/
void build(utils::Invocable<void(void* token)>&& callback) const;
void build(utils::Invocable<void(void* UTILS_NONNULL token)>&& callback) const;
#endif
/**
@@ -350,16 +437,17 @@ public:
* allocate the command buffer. If exceptions are disabled, this condition if
* fatal and this function will abort.
*/
Engine* build() const;
Engine* UTILS_NULLABLE build() const;
};
/**
* Backward compatibility helper to create an Engine.
* @see Builder
*/
static inline Engine* create(Backend backend = Backend::DEFAULT,
Platform* platform = nullptr, void* sharedContext = nullptr,
const Config* config = nullptr) {
static inline Engine* UTILS_NULLABLE create(Backend backend = Backend::DEFAULT,
Platform* UTILS_NULLABLE platform = nullptr,
void* UTILS_NULLABLE sharedContext = nullptr,
const Config* UTILS_NULLABLE config = nullptr) {
return Engine::Builder()
.backend(backend)
.platform(platform)
@@ -374,16 +462,18 @@ public:
* Backward compatibility helper to create an Engine asynchronously.
* @see Builder
*/
static inline void createAsync(CreateCallback callback, void* user,
static inline void createAsync(CreateCallback callback,
void* UTILS_NULLABLE user,
Backend backend = Backend::DEFAULT,
Platform* platform = nullptr, void* sharedContext = nullptr,
const Config* config = nullptr) {
Platform* UTILS_NULLABLE platform = nullptr,
void* UTILS_NULLABLE sharedContext = nullptr,
const Config* UTILS_NULLABLE config = nullptr) {
Engine::Builder()
.backend(backend)
.platform(platform)
.sharedContext(sharedContext)
.config(config)
.build([callback, user](void* token) {
.build([callback, user](void* UTILS_NONNULL token) {
callback(user, token);
});
}
@@ -400,7 +490,7 @@ public:
* allocate the command buffer. If exceptions are disabled, this condition if fatal and
* this function will abort.
*/
static Engine* getEngine(void* token);
static Engine* UTILS_NULLABLE getEngine(void* UTILS_NONNULL token);
#endif
@@ -430,7 +520,7 @@ public:
* \remark
* This method is thread-safe.
*/
static void destroy(Engine** engine);
static void destroy(Engine* UTILS_NULLABLE* UTILS_NULLABLE engine);
/**
* Destroy the Engine instance and all associated resources.
@@ -457,10 +547,7 @@ public:
* \remark
* This method is thread-safe.
*/
static void destroy(Engine* engine);
using FeatureLevel = backend::FeatureLevel;
static void destroy(Engine* UTILS_NULLABLE engine);
/**
* Query the feature level supported by the selected backend.
@@ -473,17 +560,23 @@ public:
FeatureLevel getSupportedFeatureLevel() const noexcept;
/**
* Activate all features of a given feature level. By default FeatureLevel::FEATURE_LEVEL_1 is
* active. The selected feature level must not be higher than the value returned by
* getActiveFeatureLevel() and it's not possible lower the active feature level.
* Activate all features of a given feature level. If an explicit feature level is not specified
* at Engine initialization time via Builder::featureLevel, the default feature level is
* FeatureLevel::FEATURE_LEVEL_0 on devices not compatible with GLES 3.0; otherwise, the default
* is FeatureLevel::FEATURE_LEVEL_1. The selected feature level must not be higher than the
* value returned by getActiveFeatureLevel() and it's not possible lower the active feature
* level. Additionally, it is not possible to modify the feature level at all if the Engine was
* initialized at FeatureLevel::FEATURE_LEVEL_0.
*
* @param featureLevel the feature level to activate. If featureLevel is lower than
* getActiveFeatureLevel(), the current (higher) feature level is kept.
* If featureLevel is higher than getSupportedFeatureLevel(), an exception
* is thrown, or the program is terminated if exceptions are disabled.
* getActiveFeatureLevel(), the current (higher) feature level is kept. If
* featureLevel is higher than getSupportedFeatureLevel(), or if the engine
* was initialized at feature level 0, an exception is thrown, or the
* program is terminated if exceptions are disabled.
*
* @return the active feature level.
*
* @see Builder::featureLevel
* @see getSupportedFeatureLevel
* @see getActiveFeatureLevel
*/
@@ -514,12 +607,35 @@ public:
size_t getMaxAutomaticInstances() const noexcept;
/**
* Queries the device and platform for instanced stereo rendering support.
* Queries the device and platform for support of the given stereoscopic type.
*
* @return true if stereo rendering is supported, false otherwise
* @return true if the given stereo rendering is supported, false otherwise
* @see View::setStereoscopicOptions
*/
bool isStereoSupported() const noexcept;
bool isStereoSupported(StereoscopicType stereoscopicType) const noexcept;
/**
* Retrieves the configuration settings of this Engine.
*
* This method returns the configuration object that was supplied to the Engine's
* Builder::config method during the creation of this Engine. If the Builder::config method was
* not explicitly called (or called with nullptr), this method returns the default configuration
* settings.
*
* @return a Config object with this Engine's configuration
* @see Builder::config
*/
const Config& getConfig() const noexcept;
/**
* Returns the maximum number of stereoscopic eyes supported by Filament. The actual number of
* eyes rendered is set at Engine creation time with the Engine::Config::stereoscopicEyeCount
* setting.
*
* @return the max number of stereoscopic eyes supported
* @see Engine::Config::stereoscopicEyeCount
*/
static size_t getMaxStereoscopicEyes() noexcept;
/**
* @return EntityManager used by filament
@@ -579,11 +695,11 @@ public:
* `ANativeWindow*`.
* @param flags One or more configuration flags as defined in `SwapChain`.
*
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
* @return A pointer to the newly created SwapChain.
*
* @see Renderer.beginFrame()
*/
SwapChain* createSwapChain(void* nativeWindow, uint64_t flags = 0) noexcept;
SwapChain* UTILS_NONNULL createSwapChain(void* UTILS_NULLABLE nativeWindow, uint64_t flags = 0) noexcept;
/**
@@ -593,42 +709,42 @@ public:
* @param height Height of the drawing buffer in pixels.
* @param flags One or more configuration flags as defined in `SwapChain`.
*
* @return A pointer to the newly created SwapChain or nullptr if it couldn't be created.
* @return A pointer to the newly created SwapChain.
*
* @see Renderer.beginFrame()
*/
SwapChain* createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
SwapChain* UTILS_NONNULL createSwapChain(uint32_t width, uint32_t height, uint64_t flags = 0) noexcept;
/**
* Creates a renderer associated to this engine.
*
* A Renderer is intended to map to a *window* on screen.
*
* @return A pointer to the newly created Renderer or nullptr if it couldn't be created.
* @return A pointer to the newly created Renderer.
*/
Renderer* createRenderer() noexcept;
Renderer* UTILS_NONNULL createRenderer() noexcept;
/**
* Creates a View.
*
* @return A pointer to the newly created View or nullptr if it couldn't be created.
* @return A pointer to the newly created View.
*/
View* createView() noexcept;
View* UTILS_NONNULL createView() noexcept;
/**
* Creates a Scene.
*
* @return A pointer to the newly created Scene or nullptr if it couldn't be created.
* @return A pointer to the newly created Scene.
*/
Scene* createScene() noexcept;
Scene* UTILS_NONNULL createScene() noexcept;
/**
* Creates a Camera component.
*
* @param entity Entity to add the camera component to.
* @return A pointer to the newly created Camera or nullptr if it couldn't be created.
* @return A pointer to the newly created Camera.
*/
Camera* createCamera(utils::Entity entity) noexcept;
Camera* UTILS_NONNULL createCamera(utils::Entity entity) noexcept;
/**
* Returns the Camera component of the given entity.
@@ -638,7 +754,7 @@ public:
* have a Camera component. The pointer is valid until destroyCameraComponent()
* is called or the entity itself is destroyed.
*/
Camera* getCameraComponent(utils::Entity entity) noexcept;
Camera* UTILS_NULLABLE getCameraComponent(utils::Entity entity) noexcept;
/**
* Destroys the Camera component associated with the given entity.
@@ -650,17 +766,17 @@ public:
/**
* Creates a Fence.
*
* @return A pointer to the newly created Fence or nullptr if it couldn't be created.
* @return A pointer to the newly created Fence.
*/
Fence* createFence() noexcept;
Fence* UTILS_NONNULL createFence() noexcept;
bool destroy(const BufferObject* p); //!< Destroys a BufferObject object.
bool destroy(const VertexBuffer* p); //!< Destroys an VertexBuffer object.
bool destroy(const Fence* p); //!< Destroys a Fence object.
bool destroy(const IndexBuffer* p); //!< Destroys an IndexBuffer object.
bool destroy(const SkinningBuffer* p); //!< Destroys a SkinningBuffer object.
bool destroy(const MorphTargetBuffer* p); //!< Destroys a MorphTargetBuffer object.
bool destroy(const IndirectLight* p); //!< Destroys an IndirectLight object.
bool destroy(const BufferObject* UTILS_NULLABLE p); //!< Destroys a BufferObject object.
bool destroy(const VertexBuffer* UTILS_NULLABLE p); //!< Destroys an VertexBuffer object.
bool destroy(const Fence* UTILS_NULLABLE p); //!< Destroys a Fence object.
bool destroy(const IndexBuffer* UTILS_NULLABLE p); //!< Destroys an IndexBuffer object.
bool destroy(const SkinningBuffer* UTILS_NULLABLE p); //!< Destroys a SkinningBuffer object.
bool destroy(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Destroys a MorphTargetBuffer object.
bool destroy(const IndirectLight* UTILS_NULLABLE p); //!< Destroys an IndirectLight object.
/**
* Destroys a Material object
@@ -670,38 +786,38 @@ public:
* @exception utils::PreConditionPanic is thrown if some MaterialInstances remain.
* no-op if exceptions are disabled and some MaterialInstances remain.
*/
bool destroy(const Material* p);
bool destroy(const MaterialInstance* p); //!< Destroys a MaterialInstance object.
bool destroy(const Renderer* p); //!< Destroys a Renderer object.
bool destroy(const Scene* p); //!< Destroys a Scene object.
bool destroy(const Skybox* p); //!< Destroys a SkyBox object.
bool destroy(const ColorGrading* p); //!< Destroys a ColorGrading object.
bool destroy(const SwapChain* p); //!< Destroys a SwapChain object.
bool destroy(const Stream* p); //!< Destroys a Stream object.
bool destroy(const Texture* p); //!< Destroys a Texture object.
bool destroy(const RenderTarget* p); //!< Destroys a RenderTarget object.
bool destroy(const View* p); //!< Destroys a View object.
bool destroy(const InstanceBuffer* p); //!< Destroys an InstanceBuffer object.
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
bool destroy(const Material* UTILS_NULLABLE p);
bool destroy(const MaterialInstance* UTILS_NULLABLE p); //!< Destroys a MaterialInstance object.
bool destroy(const Renderer* UTILS_NULLABLE p); //!< Destroys a Renderer object.
bool destroy(const Scene* UTILS_NULLABLE p); //!< Destroys a Scene object.
bool destroy(const Skybox* UTILS_NULLABLE p); //!< Destroys a SkyBox object.
bool destroy(const ColorGrading* UTILS_NULLABLE p); //!< Destroys a ColorGrading object.
bool destroy(const SwapChain* UTILS_NULLABLE p); //!< Destroys a SwapChain object.
bool destroy(const Stream* UTILS_NULLABLE p); //!< Destroys a Stream object.
bool destroy(const Texture* UTILS_NULLABLE p); //!< Destroys a Texture object.
bool destroy(const RenderTarget* UTILS_NULLABLE p); //!< Destroys a RenderTarget object.
bool destroy(const View* UTILS_NULLABLE p); //!< Destroys a View object.
bool destroy(const InstanceBuffer* UTILS_NULLABLE p); //!< Destroys an InstanceBuffer object.
void destroy(utils::Entity e); //!< Destroys all filament-known components from this entity
bool isValid(const BufferObject* p); //!< Tells whether a BufferObject object is valid
bool isValid(const VertexBuffer* p); //!< Tells whether an VertexBuffer object is valid
bool isValid(const Fence* p); //!< Tells whether a Fence object is valid
bool isValid(const IndexBuffer* p); //!< Tells whether an IndexBuffer object is valid
bool isValid(const SkinningBuffer* p); //!< Tells whether a SkinningBuffer object is valid
bool isValid(const MorphTargetBuffer* p); //!< Tells whether a MorphTargetBuffer object is valid
bool isValid(const IndirectLight* p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Material* p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Renderer* p); //!< Tells whether a Renderer object is valid
bool isValid(const Scene* p); //!< Tells whether a Scene object is valid
bool isValid(const Skybox* p); //!< Tells whether a SkyBox object is valid
bool isValid(const ColorGrading* p); //!< Tells whether a ColorGrading object is valid
bool isValid(const SwapChain* p); //!< Tells whether a SwapChain object is valid
bool isValid(const Stream* p); //!< Tells whether a Stream object is valid
bool isValid(const Texture* p); //!< Tells whether a Texture object is valid
bool isValid(const RenderTarget* p); //!< Tells whether a RenderTarget object is valid
bool isValid(const View* p); //!< Tells whether a View object is valid
bool isValid(const InstanceBuffer* p); //!< Tells whether an InstanceBuffer object is valid
bool isValid(const BufferObject* UTILS_NULLABLE p); //!< Tells whether a BufferObject object is valid
bool isValid(const VertexBuffer* UTILS_NULLABLE p); //!< Tells whether an VertexBuffer object is valid
bool isValid(const Fence* UTILS_NULLABLE p); //!< Tells whether a Fence object is valid
bool isValid(const IndexBuffer* UTILS_NULLABLE p); //!< Tells whether an IndexBuffer object is valid
bool isValid(const SkinningBuffer* UTILS_NULLABLE p); //!< Tells whether a SkinningBuffer object is valid
bool isValid(const MorphTargetBuffer* UTILS_NULLABLE p); //!< Tells whether a MorphTargetBuffer object is valid
bool isValid(const IndirectLight* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Material* UTILS_NULLABLE p); //!< Tells whether an IndirectLight object is valid
bool isValid(const Renderer* UTILS_NULLABLE p); //!< Tells whether a Renderer object is valid
bool isValid(const Scene* UTILS_NULLABLE p); //!< Tells whether a Scene object is valid
bool isValid(const Skybox* UTILS_NULLABLE p); //!< Tells whether a SkyBox object is valid
bool isValid(const ColorGrading* UTILS_NULLABLE p); //!< Tells whether a ColorGrading object is valid
bool isValid(const SwapChain* UTILS_NULLABLE p); //!< Tells whether a SwapChain object is valid
bool isValid(const Stream* UTILS_NULLABLE p); //!< Tells whether a Stream object is valid
bool isValid(const Texture* UTILS_NULLABLE p); //!< Tells whether a Texture object is valid
bool isValid(const RenderTarget* UTILS_NULLABLE p); //!< Tells whether a RenderTarget object is valid
bool isValid(const View* UTILS_NULLABLE p); //!< Tells whether a View object is valid
bool isValid(const InstanceBuffer* UTILS_NULLABLE p); //!< Tells whether an InstanceBuffer object is valid
/**
* Kicks the hardware thread (e.g. the OpenGL, Vulkan or Metal thread) and blocks until
@@ -724,6 +840,21 @@ public:
*/
void flush();
/**
* Pause or resume rendering thread.
*
* <p>Warning: This is an experimental API. In particular, note the following caveats.
*
* <ul><li>
* Buffer callbacks will never be called as long as the rendering thread is paused.
* Do not rely on a buffer callback to unpause the thread.
* </li><li>
* While the rendering thread is paused, rendering commands will continue to be queued until the
* buffer limit is reached. When the limit is reached, the program will abort.
* </li></ul>
*/
void setPaused(bool paused);
/**
* Drains the user callback message queue and immediately execute all pending callbacks.
*
@@ -741,7 +872,7 @@ public:
*
* @return A pointer to the default Material instance (a singleton).
*/
const Material* getDefaultMaterial() const noexcept;
Material const* UTILS_NONNULL getDefaultMaterial() const noexcept;
/**
* Returns the resolved backend.
@@ -772,7 +903,7 @@ public:
* @return A pointer to the Platform object that was provided to Engine::create, or the
* Filament-created one.
*/
Platform* getPlatform() const noexcept;
Platform* UTILS_NULLABLE getPlatform() const noexcept;
/**
* Allocate a small amount of memory directly in the command stream. The allocated memory is
@@ -785,7 +916,7 @@ public:
* @note there is no need to destroy this buffer, it will be freed automatically when
* the current command buffer is executed.
*/
void* streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
void* UTILS_NULLABLE streamAlloc(size_t size, size_t alignment = alignof(double)) noexcept;
/**
* Invokes one iteration of the render loop, used only on single-threaded platforms.
@@ -804,14 +935,14 @@ public:
#if defined(__EMSCRIPTEN__)
/**
* WebGL only: Tells the driver to reset any internal state tracking if necessary.
*
* This is only useful when integrating an external renderer into Filament on platforms
*
* This is only useful when integrating an external renderer into Filament on platforms
* like WebGL, where share contexts do not exist. Filament keeps track of the GL
* state it has set (like which texture is bound), and does not re-set that state if
* it does not think it needs to. However, if an external renderer has set different
* state in the mean time, Filament will use that new state unknowingly.
*
* If you are in this situation, call this function - ideally only once per frame,
*
* If you are in this situation, call this function - ideally only once per frame,
* immediately after calling Engine::execute().
*/
void resetBackendState() noexcept;

View File

@@ -25,6 +25,8 @@
#include <utils/compiler.h>
#include <stdint.h>
namespace filament {
/**
@@ -74,7 +76,11 @@ public:
* @return FenceStatus::CONDITION_SATISFIED on success,
* FenceStatus::ERROR otherwise.
*/
static FenceStatus waitAndDestroy(Fence* fence, Mode mode = Mode::FLUSH);
static FenceStatus waitAndDestroy(Fence* UTILS_NONNULL fence, Mode mode = Mode::FLUSH);
protected:
// prevent heap allocation
~Fence() = default;
};
} // namespace filament

View File

@@ -49,8 +49,6 @@ public:
// prevent heap allocation
static void *operator new (size_t) = delete;
static void *operator new[] (size_t) = delete;
static void operator delete (void*) = delete;
static void operator delete[](void*) = delete;
};
template<typename T>

View File

@@ -23,9 +23,12 @@
#include <math/mat4.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <utils/unwindows.h> // Because we define NEAR and FAR in the Plane enum.
#include <stdint.h>
namespace filament {
class Box;
@@ -76,14 +79,14 @@ public:
* @param planes six plane equations encoded as in getNormalizedPlane() in
* left, right, bottom, top, far, near order
*/
void getNormalizedPlanes(math::float4 planes[6]) const noexcept;
void getNormalizedPlanes(math::float4 planes[UTILS_NONNULL 6]) const noexcept;
/**
* Returns all six frustum planes in left, right, bottom, top, far, near order
* @return six plane equations encoded as in getNormalizedPlane() in
* left, right, bottom, top, far, near order
*/
math::float4 const* getNormalizedPlanes() const noexcept { return mPlanes; }
math::float4 const* UTILS_NONNULL getNormalizedPlanes() const noexcept { return mPlanes; }
/**
* Returns whether a box intersects the frustum (i.e. is visible)

View File

@@ -27,6 +27,7 @@
#include <utils/compiler.h>
#include <stdint.h>
#include <stddef.h>
namespace filament {
@@ -88,8 +89,7 @@ public:
*
* @param engine Reference to the filament::Engine to associate this IndexBuffer with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
@@ -97,7 +97,7 @@ public:
*
* @see IndexBuffer::setBuffer
*/
IndexBuffer* build(Engine& engine);
IndexBuffer* UTILS_NONNULL build(Engine& engine);
private:
friend class FIndexBuffer;
};
@@ -118,6 +118,10 @@ public:
* @return The number of indices the IndexBuffer holds.
*/
size_t getIndexCount() const noexcept;
protected:
// prevent heap allocation
~IndexBuffer() = default;
};
} // namespace filament

View File

@@ -25,6 +25,8 @@
#include <math/mathfwd.h>
#include <stdint.h>
namespace filament {
class Engine;
@@ -114,7 +116,7 @@ public:
* @return This Builder, for chaining calls.
*
*/
Builder& reflections(Texture const* cubemap) noexcept;
Builder& reflections(Texture const* UTILS_NULLABLE cubemap) noexcept;
/**
* Sets the irradiance as Spherical Harmonics.
@@ -160,7 +162,7 @@ public:
* Because the coefficients are pre-scaled, `sh[0]` is the environment's
* average irradiance.
*/
Builder& irradiance(uint8_t bands, math::float3 const* sh) noexcept;
Builder& irradiance(uint8_t bands, math::float3 const* UTILS_NONNULL sh) noexcept;
/**
* Sets the irradiance from the radiance expressed as Spherical Harmonics.
@@ -192,7 +194,7 @@ public:
*
* @return This Builder, for chaining calls.
*/
Builder& radiance(uint8_t bands, math::float3 const* sh) noexcept;
Builder& radiance(uint8_t bands, math::float3 const* UTILS_NONNULL sh) noexcept;
/**
* Sets the irradiance as a cubemap.
@@ -211,7 +213,7 @@ public:
*
* @see irradiance(uint8_t bands, math::float3 const* sh)
*/
Builder& irradiance(Texture const* cubemap) noexcept;
Builder& irradiance(Texture const* UTILS_NULLABLE cubemap) noexcept;
/**
* (optional) Environment intensity.
@@ -247,7 +249,7 @@ public:
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
IndirectLight* build(Engine& engine);
IndirectLight* UTILS_NONNULL build(Engine& engine);
private:
friend class FIndirectLight;
@@ -284,12 +286,12 @@ public:
/**
* Returns the associated reflection map, or null if it does not exist.
*/
Texture const* getReflectionsTexture() const noexcept;
Texture const* UTILS_NULLABLE getReflectionsTexture() const noexcept;
/**
* Returns the associated irradiance map, or null if it does not exist.
*/
Texture const* getIrradianceTexture() const noexcept;
Texture const* UTILS_NULLABLE getIrradianceTexture() const noexcept;
/**
* Helper to estimate the direction of the dominant light in the environment represented by
@@ -312,7 +314,7 @@ public:
* @see LightManager::Builder::direction()
* @see getColorEstimate()
*/
static math::float3 getDirectionEstimate(const math::float3 sh[9]) noexcept;
static math::float3 getDirectionEstimate(const math::float3 sh[UTILS_NONNULL 9]) noexcept;
/**
* Helper to estimate the color and relative intensity of the environment represented by
@@ -332,7 +334,8 @@ public:
* @see LightManager::Builder::intensity()
* @see getDirectionEstimate, getIntensity, setIntensity
*/
static math::float4 getColorEstimate(const math::float3 sh[9], math::float3 direction) noexcept;
static math::float4 getColorEstimate(const math::float3 sh[UTILS_NONNULL 9],
math::float3 direction) noexcept;
/** @deprecated use static versions instead */
@@ -342,6 +345,10 @@ public:
/** @deprecated use static versions instead */
UTILS_DEPRECATED
math::float4 getColorEstimate(math::float3 direction) const noexcept;
protected:
// prevent heap allocation
~IndirectLight() = default;
};
} // namespace filament

View File

@@ -18,11 +18,14 @@
#define TNT_FILAMENT_INSTANCEBUFFER_H
#include <filament/FilamentAPI.h>
#include <filament/Engine.h>
#include <utils/compiler.h>
#include <math/mathfwd.h>
#include <stddef.h>
namespace filament {
/**
@@ -45,7 +48,7 @@ public:
* >= 1 and <= \c Engine::getMaxAutomaticInstances()
* @see Engine::getMaxAutomaticInstances
*/
Builder(size_t instanceCount) noexcept;
explicit Builder(size_t instanceCount) noexcept;
Builder(Builder const& rhs) noexcept;
Builder(Builder&& rhs) noexcept;
@@ -65,12 +68,12 @@ public:
* @param localTransforms an array of math::mat4f with length instanceCount, must remain
* valid until after build() is called
*/
Builder& localTransforms(math::mat4f const* localTransforms) noexcept;
Builder& localTransforms(math::mat4f const* UTILS_NULLABLE localTransforms) noexcept;
/**
* Creates the InstanceBuffer object and returns a pointer to it.
*/
InstanceBuffer* build(Engine& engine);
InstanceBuffer* UTILS_NONNULL build(Engine& engine);
private:
friend class FInstanceBuffer;
@@ -90,7 +93,12 @@ public:
* @param count the number of local transforms
* @param offset index of the first instance to set local transforms
*/
void setLocalTransforms(math::mat4f const* localTransforms, size_t count, size_t offset = 0);
void setLocalTransforms(math::mat4f const* UTILS_NONNULL localTransforms,
size_t count, size_t offset = 0);
protected:
// prevent heap allocation
~InstanceBuffer() = default;
};
} // namespace filament

View File

@@ -27,6 +27,9 @@
#include <math/mathfwd.h>
#include <math/quat.h>
#include <stdint.h>
#include <stddef.h>
namespace utils {
class Entity;
} // namespace utils
@@ -143,20 +146,13 @@ public:
using Instance = utils::EntityInstance<LightManager>;
/**
* Returns the number of component in the LightManager, not that component are not
* Returns the number of component in the LightManager, note that component are not
* guaranteed to be active. Use the EntityManager::isAlive() before use if needed.
*
* @return number of component in the LightManager
*/
size_t getComponentCount() const noexcept;
/**
* Returns the list of Entity for all components. Use getComponentCount() to know the size
* of the list.
* @return a pointer to Entity
*/
utils::Entity const* getEntities() const noexcept;
/**
* Returns whether a particular Entity is associated with a component of this LightManager
* @param e An Entity.
@@ -164,6 +160,24 @@ public:
*/
bool hasComponent(utils::Entity e) const noexcept;
/**
* @return true if the this manager has no components
*/
bool empty() const noexcept;
/**
* Retrieve the `Entity` of the component from its `Instance`.
* @param i Instance of the component obtained from getInstance()
* @return
*/
utils::Entity getEntity(Instance i) const noexcept;
/**
* Retrieve the Entities of all the components of this manager.
* @return A list, in no particular order, of all the entities managed by this manager.
*/
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
/**
* Gets an Instance representing the Light component associated with the given Entity.
* @param e An Entity.
@@ -380,7 +394,7 @@ public:
* positions into
* @param cascades the number of shadow cascades, at most 4
*/
static void computeUniformSplits(float* splitPositions, uint8_t cascades);
static void computeUniformSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades);
/**
* Utility method to compute ShadowOptions::cascadeSplitPositions according to a logarithmic
@@ -392,7 +406,7 @@ public:
* @param near the camera near plane
* @param far the camera far plane
*/
static void computeLogSplits(float* splitPositions, uint8_t cascades,
static void computeLogSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades,
float near, float far);
/**
@@ -412,7 +426,7 @@ public:
* @param lambda a float in the range [0, 1] that interpolates between log and
* uniform split schemes
*/
static void computePracticalSplits(float* splitPositions, uint8_t cascades,
static void computePracticalSplits(float* UTILS_NONNULL splitPositions, uint8_t cascades,
float near, float far, float lambda);
};
@@ -953,19 +967,9 @@ public:
*/
bool isShadowCaster(Instance i) const noexcept;
/**
* Helper to process all components with a given function
* @tparam F a void(Entity entity, Instance instance)
* @param func a function of type F
*/
template<typename F>
void forEachComponent(F func) noexcept {
utils::Entity const* const pEntity = getEntities();
for (size_t i = 0, c = getComponentCount(); i < c; i++) {
// Instance 0 is the invalid instance
func(pEntity[i], Instance(i + 1));
}
}
protected:
// prevent heap allocation
~LightManager() = default;
};
} // namespace filament

View File

@@ -30,7 +30,12 @@
#include <math/mathfwd.h>
#include <type_traits>
#include <utility>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
namespace utils {
class CString;
@@ -50,11 +55,11 @@ class UTILS_PUBLIC Material : public FilamentAPI {
struct BuilderDetails;
public:
using BlendingMode = BlendingMode;
using Shading = Shading;
using Interpolation = Interpolation;
using VertexDomain = VertexDomain;
using TransparencyMode = TransparencyMode;
using BlendingMode = filament::BlendingMode;
using Shading = filament::Shading;
using Interpolation = filament::Interpolation;
using VertexDomain = filament::VertexDomain;
using TransparencyMode = filament::TransparencyMode;
using ParameterType = backend::UniformType;
using Precision = backend::Precision;
@@ -69,7 +74,7 @@ public:
*/
struct ParameterInfo {
//! Name of the parameter.
const char* name;
const char* UTILS_NONNULL name;
//! Whether the parameter is a sampler (texture).
bool isSampler;
//! Whether the parameter is a subpass type.
@@ -105,7 +110,7 @@ public:
* @param payload Pointer to the material data, must stay valid until build() is called.
* @param size Size of the material data pointed to by "payload" in bytes.
*/
Builder& package(const void* payload, size_t size);
Builder& package(const void* UTILS_NONNULL payload, size_t size);
template<typename T>
using is_supported_constant_parameter_t = typename std::enable_if<
@@ -127,11 +132,11 @@ public:
* in the material definition.
*/
template<typename T, typename = is_supported_constant_parameter_t<T>>
Builder& constant(const char* name, size_t nameLength, T value);
Builder& constant(const char* UTILS_NONNULL name, size_t nameLength, T value);
/** inline helper to provide the constant name as a null-terminated C string */
template<typename T, typename = is_supported_constant_parameter_t<T>>
inline Builder& constant(const char* name, T value) {
inline Builder& constant(const char* UTILS_NONNULL name, T value) {
return constant(name, strlen(name), value);
}
@@ -147,7 +152,7 @@ public:
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
Material* build(Engine& engine);
Material* UTILS_NULLABLE build(Engine& engine);
private:
friend class FMaterial;
};
@@ -193,22 +198,22 @@ public:
*/
void compile(CompilerPriorityQueue priority,
UserVariantFilterMask variants,
backend::CallbackHandler* handler = nullptr,
utils::Invocable<void(Material*)>&& callback = {}) noexcept;
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept;
inline void compile(CompilerPriorityQueue priority,
UserVariantFilterBit variants,
backend::CallbackHandler* handler = nullptr,
utils::Invocable<void(Material*)>&& callback = {}) noexcept {
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept {
compile(priority, UserVariantFilterMask(variants), handler,
std::forward<utils::Invocable<void(Material*)>>(callback));
std::forward<utils::Invocable<void(Material* UTILS_NONNULL)>>(callback));
}
inline void compile(CompilerPriorityQueue priority,
backend::CallbackHandler* handler = nullptr,
utils::Invocable<void(Material*)>&& callback = {}) noexcept {
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
utils::Invocable<void(Material* UTILS_NONNULL)>&& callback = {}) noexcept {
compile(priority, UserVariantFilterBit::ALL, handler,
std::forward<utils::Invocable<void(Material*)>>(callback));
std::forward<utils::Invocable<void(Material* UTILS_NONNULL)>>(callback));
}
/**
@@ -220,13 +225,13 @@ public:
*
* @return A pointer to the new instance.
*/
MaterialInstance* createInstance(const char* name = nullptr) const noexcept;
MaterialInstance* UTILS_NONNULL createInstance(const char* UTILS_NULLABLE name = nullptr) const noexcept;
//! Returns the name of this material as a null-terminated string.
const char* getName() const noexcept;
const char* UTILS_NONNULL getName() const noexcept;
//! Returns the shading model of this material.
Shading getShading() const noexcept;
Shading getShading() const noexcept;
//! Returns the interpolation mode of this material. This affects how variables are interpolated.
Interpolation getInterpolation() const noexcept;
@@ -237,6 +242,9 @@ public:
//! Returns the vertex domain of this material.
VertexDomain getVertexDomain() const noexcept;
//! Returns the material's supported variants
UserVariantFilterMask getSupportedVariants() const noexcept;
//! Returns the material domain of this material.
//! The material domain determines how the material is used.
MaterialDomain getMaterialDomain() const noexcept;
@@ -291,6 +299,9 @@ public:
//! Returns the reflection mode used by this material.
ReflectionMode getReflectionMode() const noexcept;
//! Returns the minimum required feature level for this material.
backend::FeatureLevel getFeatureLevel() const noexcept;
/**
* Returns the number of parameters declared by this material.
* The returned value can be 0.
@@ -306,13 +317,13 @@ public:
*
* @return The number of parameters written to the parameters pointer.
*/
size_t getParameters(ParameterInfo* parameters, size_t count) const noexcept;
size_t getParameters(ParameterInfo* UTILS_NONNULL parameters, size_t count) const noexcept;
//! Indicates whether a parameter of the given name exists on this material.
bool hasParameter(const char* name) const noexcept;
bool hasParameter(const char* UTILS_NONNULL name) const noexcept;
//! Indicates whether an existing parameter is a sampler or not.
bool isSampler(const char* name) const noexcept;
bool isSampler(const char* UTILS_NONNULL name) const noexcept;
/**
* Sets the value of the given parameter on this material's default instance.
@@ -323,7 +334,7 @@ public:
* @see getDefaultInstance()
*/
template <typename T>
void setDefaultParameter(const char* name, T value) noexcept {
void setDefaultParameter(const char* UTILS_NONNULL name, T value) noexcept {
getDefaultInstance()->setParameter(name, value);
}
@@ -336,8 +347,8 @@ public:
*
* @see getDefaultInstance()
*/
void setDefaultParameter(const char* name, Texture const* texture,
TextureSampler const& sampler) noexcept {
void setDefaultParameter(const char* UTILS_NONNULL name,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) noexcept {
getDefaultInstance()->setParameter(name, texture, sampler);
}
@@ -350,7 +361,7 @@ public:
*
* @see getDefaultInstance()
*/
void setDefaultParameter(const char* name, RgbType type, math::float3 color) noexcept {
void setDefaultParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) noexcept {
getDefaultInstance()->setParameter(name, type, color);
}
@@ -363,15 +374,19 @@ public:
*
* @see getDefaultInstance()
*/
void setDefaultParameter(const char* name, RgbaType type, math::float4 color) noexcept {
void setDefaultParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) noexcept {
getDefaultInstance()->setParameter(name, type, color);
}
//! Returns this material's default instance.
MaterialInstance* getDefaultInstance() noexcept;
MaterialInstance* UTILS_NONNULL getDefaultInstance() noexcept;
//! Returns this material's default instance.
MaterialInstance const* getDefaultInstance() const noexcept;
MaterialInstance const* UTILS_NONNULL getDefaultInstance() const noexcept;
protected:
// prevent heap allocation
~Material() = default;
};
} // namespace filament

View File

@@ -42,6 +42,7 @@ enum UTILS_PUBLIC ChunkType : uint64_t {
MaterialSib = charTo64bitNum("MAT_SIB "),
MaterialSubpass = charTo64bitNum("MAT_SUB "),
MaterialGlsl = charTo64bitNum("MAT_GLSL"),
MaterialEssl1 = charTo64bitNum("MAT_ESS1"),
MaterialSpirv = charTo64bitNum("MAT_SPIR"),
MaterialMetal = charTo64bitNum("MAT_METL"),
MaterialShaderModels = charTo64bitNum("MAT_SMDL"),
@@ -66,6 +67,7 @@ enum UTILS_PUBLIC ChunkType : uint64_t {
MaterialSpecularAntiAliasingThreshold = charTo64bitNum("MAT_STHR"),
MaterialClearCoatIorChange = charTo64bitNum("MAT_CIOR"),
MaterialDomain = charTo64bitNum("MAT_DOMN"),
MaterialVariantFilterMask = charTo64bitNum("MAT_VFLT"),
MaterialRefraction = charTo64bitNum("MAT_REFM"),
MaterialRefractionType = charTo64bitNum("MAT_REFT"),
MaterialReflectionMode = charTo64bitNum("MAT_REFL"),

View File

@@ -28,7 +28,7 @@
namespace filament {
// update this when a new version of filament wouldn't work with older materials
static constexpr size_t MATERIAL_VERSION = 43;
static constexpr size_t MATERIAL_VERSION = 51;
/**
* Supported shading models
@@ -201,7 +201,7 @@ enum class ReflectionMode : uint8_t {
// can't really use std::underlying_type<AttributeIndex>::type because the driver takes a uint32_t
using AttributeBitset = utils::bitset32;
static constexpr size_t MATERIAL_PROPERTIES_COUNT = 26;
static constexpr size_t MATERIAL_PROPERTIES_COUNT = 27;
enum class Property : uint8_t {
BASE_COLOR, //!< float4, all shading models
ROUGHNESS, //!< float, lit shading models only
@@ -223,6 +223,7 @@ enum class Property : uint8_t {
EMISSIVE, //!< float4, all shading models
NORMAL, //!< float3, all shading models only, except unlit
POST_LIGHTING_COLOR, //!< float4, all shading models
POST_LIGHTING_MIX_FACTOR,//!< float, all shading models
CLIP_SPACE_TRANSFORM, //!< mat4, vertex shader only
ABSORPTION, //!< float3, how much light is absorbed by the material
TRANSMISSION, //!< float, how much light is refracted through the material

View File

@@ -28,6 +28,12 @@
#include <math/mathfwd.h>
#include <type_traits>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
namespace filament {
class Material;
@@ -41,7 +47,7 @@ class UTILS_PUBLIC MaterialInstance : public FilamentAPI {
using StringLiteralHelper = const char[N];
struct StringLiteral {
const char* data;
const char* UTILS_NONNULL data;
size_t size;
template<size_t N>
StringLiteral(StringLiteralHelper<N> const& s) noexcept // NOLINT(google-explicit-constructor)
@@ -89,17 +95,18 @@ public:
* @param name A name for the new MaterialInstance or nullptr to use the template's name
* @return A new MaterialInstance
*/
static MaterialInstance* duplicate(MaterialInstance const* other, const char* name = nullptr) noexcept;
static MaterialInstance* UTILS_NONNULL duplicate(MaterialInstance const* UTILS_NONNULL other,
const char* UTILS_NULLABLE name = nullptr) noexcept;
/**
* @return the Material associated with this instance
*/
Material const* getMaterial() const noexcept;
Material const* UTILS_NONNULL getMaterial() const noexcept;
/**
* @return the name associated with this instance
*/
const char* getName() const noexcept;
const char* UTILS_NONNULL getName() const noexcept;
/**
* Set a uniform by name
@@ -110,7 +117,7 @@ public:
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(const char* name, size_t nameLength, T const& value);
void setParameter(const char* UTILS_NONNULL name, size_t nameLength, T const& value);
/** inline helper to provide the name as a null-terminated string literal */
template<typename T, typename = is_supported_parameter_t<T>>
@@ -120,7 +127,7 @@ public:
/** inline helper to provide the name as a null-terminated C string */
template<typename T, typename = is_supported_parameter_t<T>>
inline void setParameter(const char* name, T const& value) {
inline void setParameter(const char* UTILS_NONNULL name, T const& value) {
setParameter<T>(name, strlen(name), value);
}
@@ -135,17 +142,19 @@ public:
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
template<typename T, typename = is_supported_parameter_t<T>>
void setParameter(const char* name, size_t nameLength, const T* values, size_t count);
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
const T* UTILS_NONNULL values, size_t count);
/** inline helper to provide the name as a null-terminated string literal */
template<typename T, typename = is_supported_parameter_t<T>>
inline void setParameter(StringLiteral name, const T* values, size_t count) {
inline void setParameter(StringLiteral name, const T* UTILS_NONNULL values, size_t count) {
setParameter<T>(name.data, name.size, values, count);
}
/** inline helper to provide the name as a null-terminated C string */
template<typename T, typename = is_supported_parameter_t<T>>
inline void setParameter(const char* name, const T* values, size_t count) {
inline void setParameter(const char* UTILS_NONNULL name,
const T* UTILS_NONNULL values, size_t count) {
setParameter<T>(name, strlen(name), values, count);
}
@@ -162,18 +171,18 @@ public:
* @param sampler Sampler parameters.
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
void setParameter(const char* name, size_t nameLength,
Texture const* texture, TextureSampler const& sampler);
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler);
/** inline helper to provide the name as a null-terminated string literal */
inline void setParameter(StringLiteral name,
Texture const* texture, TextureSampler const& sampler) {
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
setParameter(name.data, name.size, texture, sampler);
}
/** inline helper to provide the name as a null-terminated C string */
inline void setParameter(const char* name,
Texture const* texture, TextureSampler const& sampler) {
inline void setParameter(const char* UTILS_NONNULL name,
Texture const* UTILS_NULLABLE texture, TextureSampler const& sampler) {
setParameter(name, strlen(name), texture, sampler);
}
@@ -188,7 +197,8 @@ public:
* @param color Array of read, green, blue channels values.
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
void setParameter(const char* name, size_t nameLength, RgbType type, math::float3 color);
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
RgbType type, math::float3 color);
/** inline helper to provide the name as a null-terminated string literal */
inline void setParameter(StringLiteral name, RgbType type, math::float3 color) {
@@ -196,7 +206,7 @@ public:
}
/** inline helper to provide the name as a null-terminated C string */
inline void setParameter(const char* name, RgbType type, math::float3 color) {
inline void setParameter(const char* UTILS_NONNULL name, RgbType type, math::float3 color) {
setParameter(name, strlen(name), type, color);
}
@@ -211,7 +221,8 @@ public:
* @param color Array of read, green, blue and alpha channels values.
* @throws utils::PreConditionPanic if name doesn't exist or no-op if exceptions are disabled.
*/
void setParameter(const char* name, size_t nameLength, RgbaType type, math::float4 color);
void setParameter(const char* UTILS_NONNULL name, size_t nameLength,
RgbaType type, math::float4 color);
/** inline helper to provide the name as a null-terminated string literal */
inline void setParameter(StringLiteral name, RgbaType type, math::float4 color) {
@@ -219,7 +230,7 @@ public:
}
/** inline helper to provide the name as a null-terminated C string */
inline void setParameter(const char* name, RgbaType type, math::float4 color) {
inline void setParameter(const char* UTILS_NONNULL name, RgbaType type, math::float4 color) {
setParameter(name, strlen(name), type, color);
}
@@ -479,6 +490,10 @@ public:
*/
void setStencilWriteMask(uint8_t writeMask,
StencilFace face = StencilFace::FRONT_AND_BACK) noexcept;
protected:
// prevent heap allocation
~MaterialInstance() = default;
};
} // namespace filament

View File

@@ -21,8 +21,11 @@
#include <filament/Engine.h>
#include <utils/compiler.h>
#include <math/mathfwd.h>
#include <stddef.h>
namespace filament {
@@ -65,14 +68,13 @@ public:
*
* @param engine Reference to the filament::Engine to associate this MorphTargetBuffer with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
MorphTargetBuffer* build(Engine& engine);
MorphTargetBuffer* UTILS_NONNULL build(Engine& engine);
private:
friend class FMorphTargetBuffer;
};
@@ -92,7 +94,7 @@ public:
* @see setTangentsAt
*/
void setPositionsAt(Engine& engine, size_t targetIndex,
math::float3 const* positions, size_t count, size_t offset = 0);
math::float3 const* UTILS_NONNULL positions, size_t count, size_t offset = 0);
/**
* Updates positions for the given morph target.
@@ -107,7 +109,7 @@ public:
* @see setTangentsAt
*/
void setPositionsAt(Engine& engine, size_t targetIndex,
math::float4 const* positions, size_t count, size_t offset = 0);
math::float4 const* UTILS_NONNULL positions, size_t count, size_t offset = 0);
/**
* Updates tangents for the given morph target.
@@ -123,7 +125,7 @@ public:
* @see setPositionsAt
*/
void setTangentsAt(Engine& engine, size_t targetIndex,
math::short4 const* tangents, size_t count, size_t offset = 0);
math::short4 const* UTILS_NONNULL tangents, size_t count, size_t offset = 0);
/**
* Returns the vertex count of this MorphTargetBuffer.
@@ -136,6 +138,10 @@ public:
* @return The number of targets the MorphTargetBuffer holds.
*/
size_t getCount() const noexcept;
protected:
// prevent heap allocation
~MorphTargetBuffer() = default;
};
} // namespace filament

View File

@@ -19,10 +19,13 @@
#include <filament/Color.h>
#include <stdint.h>
#include <math/vec2.h>
#include <math/vec3.h>
#include <math.h>
#include <stdint.h>
namespace filament {
class Texture;
@@ -114,8 +117,6 @@ struct DynamicResolutionOptions {
* blendMode: Whether the bloom effect is purely additive (false) or mixed with the original
* image (true).
*
* anamorphism: Bloom's aspect ratio (x/y), for artistic purposes.
*
* threshold: When enabled, a threshold at 1.0 is applied on the source image, this is
* useful for artistic reasons and is usually needed when a dirt texture is used.
*
@@ -134,7 +135,6 @@ struct BloomOptions {
float dirtStrength = 0.2f; //!< strength of the dirt texture %codegen_skip_json% %codegen_skip_javascript%
float strength = 0.10f; //!< bloom's strength between 0.0 and 1.0
uint32_t resolution = 384; //!< resolution of vertical axis (2^levels to 2048)
float anamorphism = 1.0f; //!< bloom x/y aspect-ratio (1/32 to 32)
uint8_t levels = 6; //!< number of blur levels (1 to 11)
BlendMode blendMode = BlendMode::ADD; //!< how the bloom effect is applied
bool threshold = true; //!< whether to threshold the source
@@ -296,6 +296,7 @@ struct DepthOfFieldOptions {
MEDIAN
};
float cocScale = 1.0f; //!< circle of confusion scale factor (amount of blur)
float cocAspectRatio = 1.0f; //!< width/height aspect ratio of the circle of confusion (simulate anamorphic lenses)
float maxApertureDiameter = 0.01f; //!< maximum aperture diameter in meters (zero to disable rotation)
bool enabled = false; //!< enable or disable depth of field effect
Filter filter = Filter::MEDIAN; //!< filter to use for filling gaps in the kernel
@@ -404,7 +405,7 @@ struct AmbientOcclusionOptions {
};
/**
* Options for Temporal Multi-Sample Anti-aliasing (MSAA)
* Options for Multi-Sample Anti-aliasing (MSAA)
* @see setMultiSampleAntiAliasingOptions()
*/
struct MultiSampleAntiAliasingOptions {
@@ -427,12 +428,53 @@ struct MultiSampleAntiAliasingOptions {
/**
* Options for Temporal Anti-aliasing (TAA)
* Most TAA parameters are extremely costly to change, as they will trigger the TAA post-process
* shaders to be recompiled. These options should be changed or set during initialization.
* `filterWidth`, `feedback` and `jitterPattern`, however, can be changed at any time.
*
* `feedback` of 0.1 effectively accumulates a maximum of 19 samples in steady state.
* see "A Survey of Temporal Antialiasing Techniques" by Lei Yang and all for more information.
*
* @see setTemporalAntiAliasingOptions()
*/
struct TemporalAntiAliasingOptions {
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0 (sharper, aliased) and 1 (smoother)
float feedback = 0.04f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
float filterWidth = 1.0f; //!< reconstruction filter width typically between 0.2 (sharper, aliased) and 1.5 (smoother)
float feedback = 0.12f; //!< history feedback, between 0 (maximum temporal AA) and 1 (no temporal AA).
float lodBias = -1.0f; //!< texturing lod bias (typically -1 or -2)
float sharpness = 0.0f; //!< post-TAA sharpen, especially useful when upscaling is true.
bool enabled = false; //!< enables or disables temporal anti-aliasing
bool upscaling = false; //!< 4x TAA upscaling. Disables Dynamic Resolution. [BETA]
enum class BoxType : uint8_t {
AABB, //!< use an AABB neighborhood
VARIANCE, //!< use the variance of the neighborhood (not recommended)
AABB_VARIANCE //!< use both AABB and variance
};
enum class BoxClipping : uint8_t {
ACCURATE, //!< Accurate box clipping
CLAMP, //!< clamping
NONE //!< no rejections (use for debugging)
};
enum class JitterPattern : uint8_t {
RGSS_X4, //! 4-samples, rotated grid sampling
UNIFORM_HELIX_X4, //! 4-samples, uniform grid in helix sequence
HALTON_23_X8, //! 8-samples of halton 2,3
HALTON_23_X16, //! 16-samples of halton 2,3
HALTON_23_X32 //! 32-samples of halton 2,3
};
bool filterHistory = true; //!< whether to filter the history buffer
bool filterInput = true; //!< whether to apply the reconstruction filter to the input
bool useYCoCg = false; //!< whether to use the YcoCg color-space for history rejection
BoxType boxType = BoxType::AABB; //!< type of color gamut box
BoxClipping boxClipping = BoxClipping::ACCURATE; //!< clipping algorithm
JitterPattern jitterPattern = JitterPattern::HALTON_23_X16; //! Jitter Pattern
float varianceGamma = 1.0f; //! High values increases ghosting artefact, lower values increases jittering, range [0.75, 1.25]
bool preventFlickering = false; //!< adjust the feedback dynamically to reduce flickering
bool historyReprojection = true; //!< whether to apply history reprojection (debug option)
};
/**
@@ -482,7 +524,8 @@ enum class ShadowType : uint8_t {
PCF, //!< percentage-closer filtered shadows (default)
VSM, //!< variance shadows
DPCF, //!< PCF with contact hardening simulation
PCSS //!< PCF with soft shadows and contact hardening
PCSS, //!< PCF with soft shadows and contact hardening
PCFd, // for debugging only, don't use.
};
/**

View File

@@ -24,7 +24,10 @@
#include <backend/DriverEnums.h>
#include <backend/TargetBufferInfo.h>
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -103,7 +106,7 @@ public:
* @param texture The associated texture object.
* @return A reference to this Builder for chaining calls.
*/
Builder& texture(AttachmentPoint attachment, Texture* texture) noexcept;
Builder& texture(AttachmentPoint attachment, Texture* UTILS_NULLABLE texture) noexcept;
/**
* Sets the mipmap level for a given attachment point.
@@ -135,10 +138,9 @@ public:
/**
* Creates the RenderTarget object and returns a pointer to it.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*/
RenderTarget* build(Engine& engine);
RenderTarget* UTILS_NONNULL build(Engine& engine);
private:
friend class FRenderTarget;
@@ -149,7 +151,7 @@ public:
* @param attachment Attachment point
* @return A Texture object or nullptr if no texture is set for this attachment point
*/
Texture* getTexture(AttachmentPoint attachment) const noexcept;
Texture* UTILS_NULLABLE getTexture(AttachmentPoint attachment) const noexcept;
/**
* Returns the mipmap level set on the given attachment point
@@ -180,6 +182,10 @@ public:
* @return Number of color attachments usable in a render target.
*/
uint8_t getSupportedColorAttachmentsCount() const noexcept;
protected:
// prevent heap allocation
~RenderTarget() = default;
};
} // namespace filament

View File

@@ -26,11 +26,18 @@
#include <utils/compiler.h>
#include <utils/EntityInstance.h>
#include <utils/FixedCapacityVector.h>
#include <math/mathfwd.h>
#include <math/vec3.h>
#include <math/vec4.h>
#include <type_traits>
#include <float.h>
#include <stddef.h>
#include <stdint.h>
namespace utils {
class Entity;
} // namespace utils
@@ -101,6 +108,29 @@ public:
*/
Instance getInstance(utils::Entity e) const noexcept;
/**
* @return the number of Components
*/
size_t getComponentCount() const noexcept;
/**
* @return true if the this manager has no components
*/
bool empty() const noexcept;
/**
* Retrieve the `Entity` of the component from its `Instance`.
* @param i Instance of the component obtained from getInstance()
* @return
*/
utils::Entity getEntity(Instance i) const noexcept;
/**
* Retrieve the Entities of all the components of this manager.
* @return A list, in no particular order, of all the entities managed by this manager.
*/
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
/**
* The transformation associated with a skinning joint.
*
@@ -126,6 +156,15 @@ public:
*/
static constexpr uint8_t DEFAULT_CHANNEL = 2u;
/**
* Type of geometry for a Renderable
*/
enum class GeometryType : uint8_t {
DYNAMIC, //!< dynamic gemoetry has no restriction
STATIC_BOUNDS, //!< bounds and world space transform are immutable
STATIC //!< skinning/morphing not allowed and Vertex/IndexBuffer immutables
};
/**
* Creates a builder for renderable components.
*
@@ -160,9 +199,30 @@ public:
* @param maxIndex specifies the maximum index contained in the index buffer
* @param count number of indices to read (for triangles, this should be a multiple of 3)
*/
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices, size_t offset, size_t count) noexcept; //!< \overload
Builder& geometry(size_t index, PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices) noexcept; //!< \overload
Builder& geometry(size_t index, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices,
size_t offset, size_t minIndex, size_t maxIndex, size_t count) noexcept;
Builder& geometry(size_t index, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices,
size_t offset, size_t count) noexcept; //!< \overload
Builder& geometry(size_t index, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices) noexcept; //!< \overload
/**
* Specify the type of geometry for this renderable. DYNAMIC geometry has no restriction,
* STATIC_BOUNDS geometry means that both the bounds and the world-space transform of the
* the renderable are immutable.
* STATIC geometry has the same restrictions as STATIC_BOUNDS, but in addition disallows
* skinning, morphing and changing the VertexBuffer or IndexBuffer in any way.
* @param enable whether this renderable has static bounds. false by default.
*/
Builder& geometryType(GeometryType type) noexcept;
/**
* Binds a material instance to the specified primitive.
@@ -179,7 +239,8 @@ public:
*
* @see Engine::setActiveFeatureLevel
*/
Builder& material(size_t index, MaterialInstance const* materialInstance) noexcept;
Builder& material(size_t index,
MaterialInstance const* UTILS_NONNULL materialInstance) noexcept;
/**
* The axis-aligned bounding box of the renderable.
@@ -327,7 +388,8 @@ public:
* @param count 0 to disable, otherwise the number of bone transforms (up to 255)
* @param offset offset in the SkinningBuffer
*/
Builder& skinning(SkinningBuffer* skinningBuffer, size_t count, size_t offset) noexcept;
Builder& skinning(SkinningBuffer* UTILS_NONNULL skinningBuffer,
size_t count, size_t offset) noexcept;
/**
@@ -345,10 +407,63 @@ public:
* @param boneCount 0 to disable, otherwise the number of bone transforms (up to 255)
* @param transforms the initial set of transforms (one for each bone)
*/
Builder& skinning(size_t boneCount, math::mat4f const* transforms) noexcept;
Builder& skinning(size_t boneCount, Bone const* bones) noexcept; //!< \overload
Builder& skinning(size_t boneCount, math::mat4f const* UTILS_NONNULL transforms) noexcept;
Builder& skinning(size_t boneCount, Bone const* UTILS_NONNULL bones) noexcept; //!< \overload
Builder& skinning(size_t boneCount) noexcept; //!< \overload
/**
* Define bone indices and weights "pairs" for vertex skinning as a float2.
* The unsigned int(pair.x) defines index of the bone and pair.y is the bone weight.
* The pairs substitute \c BONE_INDICES and the \c BONE_WEIGHTS defined in the VertexBuffer.
* Both ways of indices and weights definition must not be combined in one primitive.
* Number of pairs per vertex bonesPerVertex is not limited to 4 bones.
* Vertex buffer used for \c primitiveIndex must be set for advance skinning.
* All bone weights of one vertex should sum to one. Otherwise they will be normalized.
* Data must be rectangular and number of bone pairs must be same for all vertices of this
* primitive.
* The data is arranged sequentially, all bone pairs for the first vertex, then for the
* second vertex, and so on.
*
* @param primitiveIndex zero-based index of the primitive, must be less than the primitive
* count passed to Builder constructor
* @param indicesAndWeights pairs of bone index and bone weight for all vertices
* sequentially
* @param count number of all pairs, must be a multiple of vertexCount of the primitive
* count = vertexCount * bonesPerVertex
* @param bonesPerVertex number of bone pairs, same for all vertices of the primitive
*
* @return Builder reference for chaining calls.
*
* @see VertexBuffer:Builder:advancedSkinning
*/
Builder& boneIndicesAndWeights(size_t primitiveIndex,
math::float2 const* UTILS_NONNULL indicesAndWeights,
size_t count, size_t bonesPerVertex) noexcept;
/**
* Define bone indices and weights "pairs" for vertex skinning as a float2.
* The unsigned int(pair.x) defines index of the bone and pair.y is the bone weight.
* The pairs substitute \c BONE_INDICES and the \c BONE_WEIGHTS defined in the VertexBuffer.
* Both ways of indices and weights definition must not be combined in one primitive.
* Number of pairs is not limited to 4 bones per vertex.
* Vertex buffer used for \c primitiveIndex must be set for advance skinning.
* All bone weights of one vertex should sum to one. Otherwise they will be normalized.
* Data doesn't have to be rectangular and number of pairs per vertices of primitive can be
* variable.
* The vector of the vertices contains the vectors of the pairs
*
* @param primitiveIndex zero-based index of the primitive, must be less than the primitive
* count passed to Builder constructor
* @param indicesAndWeightsVectors pairs of bone index and bone weight for all vertices of
* the primitive sequentially
*
* @return Builder reference for chaining calls.
*
* @see VertexBuffer:Builder:advancedSkinning
*/
Builder& boneIndicesAndWeights(size_t primitiveIndex,
utils::FixedCapacityVector<
utils::FixedCapacityVector<math::float2>> indicesAndWeightsVector) noexcept;
/**
* Controls if the renderable has vertex morphing targets, zero by default. This is
* required to enable GPU morphing.
@@ -386,10 +501,11 @@ public:
* @param count number of vertices in the morph target buffer to read, must equal the geometry's count (for triangles, this should be a multiple of 3)
*/
Builder& morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count) noexcept;
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer,
size_t offset, size_t count) noexcept;
inline Builder& morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer) noexcept;
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept;
/**
* Sets the drawing order for blended primitives. The drawing order is either global or
@@ -456,7 +572,8 @@ public:
* the result of Engine::getMaxAutomaticInstances().
* @param instanceBuffer an InstanceBuffer containing at least instanceCount transforms
*/
Builder& instances(size_t instanceCount, InstanceBuffer* instanceBuffer) noexcept;
Builder& instances(size_t instanceCount,
InstanceBuffer* UTILS_NONNULL instanceBuffer) noexcept;
/**
* Adds the Renderable component to an entity.
@@ -483,18 +600,16 @@ public:
friend class FRenderPrimitive;
friend class FRenderableManager;
struct Entry {
VertexBuffer* vertices = nullptr;
IndexBuffer* indices = nullptr;
VertexBuffer* UTILS_NULLABLE vertices = nullptr;
IndexBuffer* UTILS_NULLABLE indices = nullptr;
size_t offset = 0;
size_t minIndex = 0;
size_t maxIndex = 0;
size_t count = 0;
MaterialInstance const* materialInstance = nullptr;
MaterialInstance const* UTILS_NULLABLE materialInstance = nullptr;
PrimitiveType type = PrimitiveType::TRIANGLES;
uint16_t blendOrder = 0;
bool globalBlendOrderEnabled = false;
struct {
MorphTargetBuffer* buffer = nullptr;
MorphTargetBuffer* UTILS_NULLABLE buffer = nullptr;
size_t offset = 0;
size_t count = 0;
} morphing;
@@ -508,11 +623,12 @@ public:
/**
* Changes the bounding box used for frustum culling.
* The renderable must not have staticGeometry enabled.
*
* \see Builder::boundingBox()
* \see RenderableManager::getAxisAlignedBoundingBox()
*/
void setAxisAlignedBoundingBox(Instance instance, const Box& aabb) noexcept;
void setAxisAlignedBoundingBox(Instance instance, const Box& aabb);
/**
* Changes the visibility bits.
@@ -612,8 +728,11 @@ public:
* Updates the bone transforms in the range [offset, offset + boneCount).
* The bones must be pre-allocated using Builder::skinning().
*/
void setBones(Instance instance, Bone const* transforms, size_t boneCount = 1, size_t offset = 0);
void setBones(Instance instance, math::mat4f const* transforms, size_t boneCount = 1, size_t offset = 0); //!< \overload
void setBones(Instance instance, Bone const* UTILS_NONNULL transforms,
size_t boneCount = 1, size_t offset = 0);
void setBones(Instance instance, math::mat4f const* UTILS_NONNULL transforms,
size_t boneCount = 1, size_t offset = 0); //!< \overload
/**
* Associates a region of a SkinningBuffer to a renderable instance
@@ -626,7 +745,7 @@ public:
* @param count Size of the region in bones, must be smaller or equal to 256.
* @param offset Start offset of the region in bones
*/
void setSkinningBuffer(Instance instance, SkinningBuffer* skinningBuffer,
void setSkinningBuffer(Instance instance, SkinningBuffer* UTILS_NONNULL skinningBuffer,
size_t count, size_t offset);
/**
@@ -641,24 +760,25 @@ public:
* @param offset Index of the first morph target weight to set at instance.
*/
void setMorphWeights(Instance instance,
float const* weights, size_t count, size_t offset = 0);
float const* UTILS_NONNULL weights, size_t count, size_t offset = 0);
/**
* Associates a MorphTargetBuffer to the given primitive.
*/
void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer, size_t offset, size_t count);
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer, size_t offset, size_t count);
/**
* Utility method to change a MorphTargetBuffer to the given primitive
*/
inline void setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer);
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer);
/**
* Get a MorphTargetBuffer to the given primitive or null if it doesn't exist.
*/
MorphTargetBuffer* getMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex) const noexcept;
MorphTargetBuffer* UTILS_NULLABLE getMorphTargetBufferAt(Instance instance,
uint8_t level, size_t primitiveIndex) const noexcept;
/**
* Gets the number of morphing in the given entity.
@@ -700,20 +820,22 @@ public:
* @see Engine::setActiveFeatureLevel
*/
void setMaterialInstanceAt(Instance instance,
size_t primitiveIndex, MaterialInstance const* materialInstance);
size_t primitiveIndex, MaterialInstance const* UTILS_NONNULL materialInstance);
/**
* Retrieves the material instance that is bound to the given primitive.
*/
MaterialInstance* getMaterialInstanceAt(Instance instance, size_t primitiveIndex) const noexcept;
MaterialInstance* UTILS_NULLABLE getMaterialInstanceAt(
Instance instance, size_t primitiveIndex) const noexcept;
/**
* Changes the geometry for the given primitive.
*
* \see Builder::geometry()
*/
void setGeometryAt(Instance instance, size_t primitiveIndex,
PrimitiveType type, VertexBuffer* vertices, IndexBuffer* indices,
void setGeometryAt(Instance instance, size_t primitiveIndex, PrimitiveType type,
VertexBuffer* UTILS_NONNULL vertices,
IndexBuffer* UTILS_NONNULL indices,
size_t offset, size_t count) noexcept;
/**
@@ -774,27 +896,37 @@ public:
template<typename VECTOR, typename INDEX,
typename = typename is_supported_vector_type<VECTOR>::type,
typename = typename is_supported_index_type<INDEX>::type>
static Box computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
static Box computeAABB(
VECTOR const* UTILS_NONNULL vertices,
INDEX const* UTILS_NONNULL indices, size_t count,
size_t stride = sizeof(VECTOR)) noexcept;
protected:
// prevent heap allocation
~RenderableManager() = default;
};
RenderableManager::Builder& RenderableManager::Builder::morphing(uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer) noexcept {
RenderableManager::Builder& RenderableManager::Builder::morphing(
uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) noexcept {
return morphing(level, primitiveIndex, morphTargetBuffer, 0,
morphTargetBuffer->getVertexCount());
}
void RenderableManager::setMorphTargetBufferAt(Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* morphTargetBuffer) {
void RenderableManager::setMorphTargetBufferAt(
Instance instance, uint8_t level, size_t primitiveIndex,
MorphTargetBuffer* UTILS_NONNULL morphTargetBuffer) {
setMorphTargetBufferAt(instance, level, primitiveIndex, morphTargetBuffer, 0,
morphTargetBuffer->getVertexCount());
}
template<typename VECTOR, typename INDEX, typename, typename>
Box RenderableManager::computeAABB(VECTOR const* vertices, INDEX const* indices, size_t count,
size_t stride) noexcept {
math::float3 bmin(std::numeric_limits<float>::max());
math::float3 bmax(std::numeric_limits<float>::lowest());
Box RenderableManager::computeAABB(
VECTOR const* UTILS_NONNULL vertices,
INDEX const* UTILS_NONNULL indices,
size_t count, size_t stride) noexcept {
math::float3 bmin(FLT_MAX);
math::float3 bmax(-FLT_MAX);
for (size_t i = 0; i < count; ++i) {
VECTOR const* p = reinterpret_cast<VECTOR const*>(
(char const*)vertices + indices[i] * stride);

View File

@@ -23,9 +23,6 @@
#include <utils/compiler.h>
#include <backend/PresentCallable.h>
#include <backend/DriverEnums.h>
#include <math/vec4.h>
#include <stdint.h>
@@ -173,19 +170,25 @@ public:
*/
void setClearOptions(const ClearOptions& options);
/**
* Returns the ClearOptions currently set.
* @return A reference to a ClearOptions structure.
*/
ClearOptions const& getClearOptions() const noexcept;
/**
* Get the Engine that created this Renderer.
*
* @return A pointer to the Engine instance this Renderer is associated to.
*/
Engine* getEngine() noexcept;
Engine* UTILS_NONNULL getEngine() noexcept;
/**
* Get the Engine that created this Renderer.
*
* @return A constant pointer to the Engine instance this Renderer is associated to.
*/
inline Engine const* getEngine() const noexcept {
inline Engine const* UTILS_NONNULL getEngine() const noexcept {
return const_cast<Renderer *>(this)->getEngine();
}
@@ -261,7 +264,7 @@ public:
* @see
* endFrame()
*/
bool beginFrame(SwapChain* swapChain,
bool beginFrame(SwapChain* UTILS_NONNULL swapChain,
uint64_t vsyncSteadyClockTimeNano = 0u);
/**
@@ -332,7 +335,7 @@ public:
* beginFrame(), endFrame(), View
*
*/
void render(View const* view);
void render(View const* UTILS_NONNULL view);
/**
* Copy the currently rendered view to the indicated swap chain, using the
@@ -347,7 +350,7 @@ public:
* copyFrame() should be called after a frame is rendered using render()
* but before endFrame() is called.
*/
void copyFrame(SwapChain* dstSwapChain, Viewport const& dstViewport,
void copyFrame(SwapChain* UTILS_NONNULL dstSwapChain, Viewport const& dstViewport,
Viewport const& srcViewport, uint32_t flags = 0);
/**
@@ -487,7 +490,7 @@ public:
* readPixels() is intended for debugging and testing. It will impact performance significantly.
*
*/
void readPixels(RenderTarget* renderTarget,
void readPixels(RenderTarget* UTILS_NONNULL renderTarget,
uint32_t xoffset, uint32_t yoffset, uint32_t width, uint32_t height,
backend::PixelBufferDescriptor&& buffer);
@@ -514,7 +517,7 @@ public:
* However, internally, renderStandaloneView() is highly multi-threaded to both improve
* performance in mitigate the call's latency.
*/
void renderStandaloneView(View const* view);
void renderStandaloneView(View const* UTILS_NONNULL view);
/**
@@ -573,6 +576,10 @@ public:
* getUserTime()
*/
void resetUserTime();
protected:
// prevent heap allocation
~Renderer() = default;
};
} // namespace filament

View File

@@ -24,6 +24,8 @@
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stddef.h>
namespace utils {
class Entity;
} // namespace utils
@@ -73,14 +75,14 @@ public:
*
* @param skybox The Skybox to use to fill untouched pixels, or nullptr to unset the Skybox.
*/
void setSkybox(Skybox* skybox) noexcept;
void setSkybox(Skybox* UTILS_NULLABLE skybox) noexcept;
/**
* Returns the Skybox associated with the Scene.
*
* @return The associated Skybox, or nullptr if there is none.
*/
Skybox* getSkybox() const noexcept;
Skybox* UTILS_NULLABLE getSkybox() const noexcept;
/**
* Set the IndirectLight to use when rendering the Scene.
@@ -91,7 +93,7 @@ public:
* @param ibl The IndirectLight to use when rendering the Scene or nullptr to unset.
* @see getIndirectLight
*/
void setIndirectLight(IndirectLight* ibl) noexcept;
void setIndirectLight(IndirectLight* UTILS_NULLABLE ibl) noexcept;
/**
* Get the IndirectLight or nullptr if none is set.
@@ -99,7 +101,7 @@ public:
* @return the the IndirectLight or nullptr if none is set
* @see setIndirectLight
*/
IndirectLight* getIndirectLight() const noexcept;
IndirectLight* UTILS_NULLABLE getIndirectLight() const noexcept;
/**
* Adds an Entity to the Scene.
@@ -118,7 +120,7 @@ public:
* @param entities Array containing entities to add to the scene.
* @param count Size of the entity array.
*/
void addEntities(const utils::Entity* entities, size_t count);
void addEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
/**
* Removes the Renderable from the Scene.
@@ -137,19 +139,25 @@ public:
* @param entities Array containing entities to remove from the scene.
* @param count Size of the entity array.
*/
void removeEntities(const utils::Entity* entities, size_t count);
void removeEntities(const utils::Entity* UTILS_NONNULL entities, size_t count);
/**
* Returns the number of Renderable objects in the Scene.
* Returns the total number of Entities in the Scene, whether alive or not.
* @return Total number of Entities in the Scene.
*/
size_t getEntityCount() const noexcept;
/**
* Returns the number of active (alive) Renderable objects in the Scene.
*
* @return number of Renderable objects in the Scene.
* @return The number of active (alive) Renderable objects in the Scene.
*/
size_t getRenderableCount() const noexcept;
/**
* Returns the total number of Light objects in the Scene.
* Returns the number of active (alive) Light objects in the Scene.
*
* @return The total number of Light objects in the Scene.
* @return The number of active (alive) Light objects in the Scene.
*/
size_t getLightCount() const noexcept;
@@ -168,6 +176,10 @@ public:
* @param functor User provided functor called for each entity in the scene
*/
void forEach(utils::Invocable<void(utils::Entity entity)>&& functor) const noexcept;
protected:
// prevent heap allocation
~Scene() = default;
};
} // namespace filament

View File

@@ -26,7 +26,7 @@
#include <math/mathfwd.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -74,8 +74,7 @@ public:
*
* @param engine Reference to the filament::Engine to associate this SkinningBuffer with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
@@ -83,7 +82,7 @@ public:
*
* @see SkinningBuffer::setBones
*/
SkinningBuffer* build(Engine& engine);
SkinningBuffer* UTILS_NONNULL build(Engine& engine);
private:
friend class FSkinningBuffer;
};
@@ -96,7 +95,7 @@ public:
* @param offset offset in elements (not bytes) in the SkinningBuffer (not in transforms)
* @see RenderableManager::setSkinningBuffer
*/
void setBones(Engine& engine, RenderableManager::Bone const* transforms,
void setBones(Engine& engine, RenderableManager::Bone const* UTILS_NONNULL transforms,
size_t count, size_t offset = 0);
/**
@@ -107,7 +106,7 @@ public:
* @param offset offset in elements (not bytes) in the SkinningBuffer (not in transforms)
* @see RenderableManager::setSkinningBuffer
*/
void setBones(Engine& engine, math::mat4f const* transforms,
void setBones(Engine& engine, math::mat4f const* UTILS_NONNULL transforms,
size_t count, size_t offset = 0);
/**
@@ -115,6 +114,10 @@ public:
* @return The number of bones the SkinningBuffer holds.
*/
size_t getBoneCount() const noexcept;
protected:
// prevent heap allocation
~SkinningBuffer() = default;
};
} // namespace filament

View File

@@ -23,9 +23,10 @@
#include <utils/compiler.h>
#include <stdint.h>
#include <math/mathfwd.h>
#include <stdint.h>
namespace filament {
class FSkybox;
@@ -91,7 +92,7 @@ public:
*
* @see Texture
*/
Builder& environment(Texture* cubemap) noexcept;
Builder& environment(Texture* UTILS_NONNULL cubemap) noexcept;
/**
* Indicates whether the sun should be rendered. The sun can only be
@@ -135,9 +136,9 @@ public:
*
* @param engine Reference to the filament::Engine to associate this Skybox with.
*
* @return pointer to the newly created object, or nullptr if the light couldn't be created.
* @return pointer to the newly created object.
*/
Skybox* build(Engine& engine);
Skybox* UTILS_NONNULL build(Engine& engine);
private:
friend class FSkybox;
@@ -171,9 +172,13 @@ public:
float getIntensity() const noexcept;
/**
* @return the associated texture, or null if it does not exist
* @return the associated texture
*/
Texture const* getTexture() const noexcept;
Texture const* UTILS_NONNULL getTexture() const noexcept;
protected:
// prevent heap allocation
~Skybox() = default;
};
} // namespace filament

View File

@@ -20,12 +20,12 @@
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/PixelBufferDescriptor.h>
#include <backend/CallbackHandler.h>
#include <utils/compiler.h>
#include <stdint.h>
namespace filament {
class FStream;
@@ -114,7 +114,7 @@ public:
*
* @return This Builder, for chaining calls.
*/
Builder& stream(void* stream) noexcept;
Builder& stream(void* UTILS_NULLABLE stream) noexcept;
/**
*
@@ -141,9 +141,9 @@ public:
*
* @param engine Reference to the filament::Engine to associate this Stream with.
*
* @return pointer to the newly created object, or nullptr if the stream couldn't be created.
* @return pointer to the newly created object.
*/
Stream* build(Engine& engine);
Stream* UTILS_NONNULL build(Engine& engine);
private:
friend class FStream;
@@ -171,11 +171,12 @@ public:
*
* @param image Pointer to AHardwareBuffer, casted to void* since this is a public header.
* @param callback This is triggered by Filament when it wishes to release the image.
* It callback tales two arguments: the AHardwareBuffer and the userdata.
* The callback tales two arguments: the AHardwareBuffer and the userdata.
* @param userdata Optional closure data. Filament will pass this into the callback when it
* releases the image.
*/
void setAcquiredImage(void* image, Callback callback, void* userdata) noexcept;
void setAcquiredImage(void* UTILS_NONNULL image,
Callback UTILS_NONNULL callback, void* UTILS_NULLABLE userdata) noexcept;
/**
* @see setAcquiredImage(void*, Callback, void*)
@@ -187,7 +188,9 @@ public:
* @param userdata Optional closure data. Filament will pass this into the callback when it
* releases the image.
*/
void setAcquiredImage(void* image, backend::CallbackHandler* handler, Callback callback, void* userdata) noexcept;
void setAcquiredImage(void* UTILS_NONNULL image,
backend::CallbackHandler* UTILS_NULLABLE handler,
Callback UTILS_NONNULL callback, void* UTILS_NULLABLE userdata) noexcept;
/**
* Updates the size of the incoming stream. Whether this value is used is
@@ -207,6 +210,10 @@ public:
* @return timestamp in nanosecond.
*/
int64_t getTimestamp() const noexcept;
protected:
// prevent heap allocation
~Stream() = default;
};
} // namespace filament

View File

@@ -21,11 +21,12 @@
#include <backend/CallbackHandler.h>
#include <backend/DriverEnums.h>
#include <backend/PresentCallable.h>
#include <utils/compiler.h>
#include <utils/Invocable.h>
#include <stdint.h>
namespace filament {
class Engine;
@@ -151,7 +152,7 @@ class Engine;
class UTILS_PUBLIC SwapChain : public FilamentAPI {
public:
using FrameScheduledCallback = backend::FrameScheduledCallback;
using FrameCompletedCallback = utils::Invocable<void(SwapChain*)>;
using FrameCompletedCallback = utils::Invocable<void(SwapChain* UTILS_NONNULL)>;
/**
* Requests a SwapChain with an alpha channel.
@@ -202,15 +203,55 @@ public:
static constexpr uint64_t CONFIG_SRGB_COLORSPACE = backend::SWAP_CHAIN_CONFIG_SRGB_COLORSPACE;
/**
* Return whether createSwapChain supports the SWAP_CHAIN_CONFIG_SRGB_COLORSPACE flag.
* Indicates that this SwapChain should allocate a stencil buffer in addition to a depth buffer.
*
* This flag is necessary when using View::setStencilBufferEnabled and rendering directly into
* the SwapChain (when post-processing is disabled).
*
* The specific format of the stencil buffer depends on platform support. The following pixel
* formats are tried, in order of preference:
*
* Depth only (without CONFIG_HAS_STENCIL_BUFFER):
* - DEPTH32F
* - DEPTH24
*
* Depth + stencil (with CONFIG_HAS_STENCIL_BUFFER):
* - DEPTH32F_STENCIL8
* - DEPTH24F_STENCIL8
*
* Note that enabling the stencil buffer may hinder depth precision and should only be used if
* necessary.
*
* @see View.setStencilBufferEnabled
* @see View.setPostProcessingEnabled
*/
static constexpr uint64_t CONFIG_HAS_STENCIL_BUFFER = backend::SWAP_CHAIN_CONFIG_HAS_STENCIL_BUFFER;
/**
* The SwapChain contains protected content. Only supported when isProtectedContentSupported()
* is true.
*/
static constexpr uint64_t CONFIG_PROTECTED_CONTENT = backend::SWAP_CHAIN_CONFIG_PROTECTED_CONTENT;
/**
* Return whether createSwapChain supports the CONFIG_PROTECTED_CONTENT flag.
* The default implementation returns false.
*
* @param engine A pointer to the filament Engine
* @return true if SWAP_CHAIN_CONFIG_SRGB_COLORSPACE is supported, false otherwise.
* @return true if CONFIG_PROTECTED_CONTENT is supported, false otherwise.
*/
static bool isProtectedContentSupported(Engine& engine) noexcept;
/**
* Return whether createSwapChain supports the CONFIG_SRGB_COLORSPACE flag.
* The default implementation returns false.
*
* @param engine A pointer to the filament Engine
* @return true if CONFIG_SRGB_COLORSPACE is supported, false otherwise.
*/
static bool isSRGBSwapChainSupported(Engine& engine) noexcept;
void* getNativeWindow() const noexcept;
void* UTILS_NULLABLE getNativeWindow() const noexcept;
/**
* FrameScheduledCallback is a callback function that notifies an application when Filament has
@@ -227,6 +268,16 @@ public:
* automatically schedule itself for presentation. Instead, the application must call the
* PresentCallable passed to the FrameScheduledCallback.
*
* There may be only one FrameScheduledCallback set per SwapChain. A call to
* SwapChain::setFrameScheduledCallback will overwrite any previous FrameScheduledCallbacks set
* on the same SwapChain.
*
* If your application delays the call to the PresentCallable by, for example, calling it on a
* separate thread, you must ensure all PresentCallables have been called before shutting down
* the Filament Engine. You can do this by issuing an Engine::flushAndWait before calling
* Engine::shutdown. This is necessary to ensure the Filament Engine has had a chance to clean
* up all memory related to frame presentation.
*
* @param callback A callback, or nullptr to unset.
* @param user An optional pointer to user data passed to the callback function.
*
@@ -237,7 +288,18 @@ public:
*
* @see PresentCallable
*/
void setFrameScheduledCallback(FrameScheduledCallback callback, void* user = nullptr);
void setFrameScheduledCallback(FrameScheduledCallback UTILS_NULLABLE callback,
void* UTILS_NULLABLE user = nullptr);
/**
* Returns the SwapChain::FrameScheduledCallback that was previously set with
* SwapChain::setFrameScheduledCallback, or nullptr if one is not set.
*
* @return the previously-set FrameScheduledCallback, or nullptr
*
* @see SwapChain::setFrameCompletedCallback
*/
UTILS_NULLABLE FrameScheduledCallback getFrameScheduledCallback() const noexcept;
/**
* FrameCompletedCallback is a callback function that notifies an application when a frame's
@@ -258,9 +320,13 @@ public:
*
* @see CallbackHandler
*/
void setFrameCompletedCallback(backend::CallbackHandler* handler = nullptr,
void setFrameCompletedCallback(backend::CallbackHandler* UTILS_NULLABLE handler = nullptr,
FrameCompletedCallback&& callback = {}) noexcept;
protected:
// prevent heap allocation
~SwapChain() = default;
};
} // namespace filament

View File

@@ -20,12 +20,16 @@
#define TNT_FILAMENT_TEXTURE_H
#include <filament/FilamentAPI.h>
#include <backend/DriverEnums.h>
#include <backend/PixelBufferDescriptor.h>
#include <utils/compiler.h>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace filament {
@@ -84,6 +88,9 @@ public:
/** @return whether a backend supports a particular format. */
static bool isTextureFormatSupported(Engine& engine, InternalFormat format) noexcept;
/** @return whether this backend supports protected textures. */
static bool isProtectedTexturesSupported(Engine& engine) noexcept;
/** @return whether a backend supports texture swizzling. */
static bool isTextureSwizzleSupported(Engine& engine) noexcept;
@@ -200,14 +207,13 @@ public:
*
* @param engine Reference to the filament::Engine to associate this Texture with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
Texture* build(Engine& engine);
Texture* UTILS_NONNULL build(Engine& engine);
/* no user serviceable parts below */
@@ -396,7 +402,7 @@ public:
* @see Builder::sampler()
*
*/
void setExternalImage(Engine& engine, void* image) noexcept;
void setExternalImage(Engine& engine, void* UTILS_NONNULL image) noexcept;
/**
* Specify the external image and plane to associate with this Texture. Typically the external
@@ -427,7 +433,7 @@ public:
* kCVPixelFormatType_420YpCbCr8BiPlanarFullRange images. On platforms
* other than iOS, this method is a no-op.
*/
void setExternalImage(Engine& engine, void* image, size_t plane) noexcept;
void setExternalImage(Engine& engine, void* UTILS_NONNULL image, size_t plane) noexcept;
/**
* Specify the external stream to associate with this Texture. Typically the external
@@ -446,16 +452,17 @@ public:
* @see Builder::sampler(), Stream
*
*/
void setExternalStream(Engine& engine, Stream* stream) noexcept;
void setExternalStream(Engine& engine, Stream* UTILS_NULLABLE stream) noexcept;
/**
* Generates all the mipmap levels automatically. This requires the texture to have a
* color-renderable format.
* color-renderable format and usage set to BLIT_SRC | BLIT_DST. If unspecified,
* usage bits are set automatically.
*
* @param engine Engine this texture is associated to.
*
* @attention \p engine must be the instance passed to Builder::build()
* @attention This Texture instance must NOT use Sampler::SAMPLER_CUBEMAP or it has no effect
* @attention This Texture instance must NOT use SamplerType::SAMPLER_3D or it has no effect
*/
void generateMipmaps(Engine& engine) const noexcept;
@@ -495,7 +502,7 @@ public:
*/
void generatePrefilterMipmap(Engine& engine,
PixelBufferDescriptor&& buffer, const FaceOffsets& faceOffsets,
PrefilterOptions const* options = nullptr);
PrefilterOptions const* UTILS_NULLABLE options = nullptr);
/** @deprecated */
@@ -541,6 +548,10 @@ public:
return *this;
}
};
protected:
// prevent heap allocation
~Texture() = default;
};
} // namespace filament

View File

@@ -25,6 +25,8 @@
#include <math.h>
#include <stdint.h>
namespace filament {
/**

View File

@@ -21,6 +21,8 @@
#include <math/mathfwd.h>
#include <cstdint>
namespace filament {
/**
@@ -37,10 +39,12 @@ namespace filament {
*
* - Configurable tone mapping operators
* - GenericToneMapper
* - AgXToneMapper
* - Fixed-aesthetic tone mapping operators
* - ACESToneMapper
* - ACESLegacyToneMapper
* - FilmicToneMapper
* - PBRNeutralToneMapper
* - Debug/validation tone mapping operators
* - LinearToneMapper
* - DisplayRangeToneMapper
@@ -115,6 +119,41 @@ struct UTILS_PUBLIC FilmicToneMapper final : public ToneMapper {
math::float3 operator()(math::float3 x) const noexcept override;
};
/**
* Khronos PBR Neutral tone mapping operator. This tone mapper was designed
* to preserve the appearance of materials across lighting conditions while
* avoiding artifacts in the highlights in high dynamic range conditions.
*/
struct UTILS_PUBLIC PBRNeutralToneMapper final : public ToneMapper {
PBRNeutralToneMapper() noexcept;
~PBRNeutralToneMapper() noexcept final;
math::float3 operator()(math::float3 x) const noexcept override;
};
/**
* AgX tone mapping operator.
*/
struct UTILS_PUBLIC AgxToneMapper final : public ToneMapper {
enum class AgxLook : uint8_t {
NONE = 0, //!< Base contrast with no look applied
PUNCHY, //!< A punchy and more chroma laden look for sRGB displays
GOLDEN //!< A golden tinted, slightly washed look for BT.1886 displays
};
/**
* Builds a new AgX tone mapper.
*
* @param look an optional creative adjustment to contrast and saturation
*/
explicit AgxToneMapper(AgxLook look = AgxLook::NONE) noexcept;
~AgxToneMapper() noexcept final;
math::float3 operator()(math::float3 x) const noexcept override;
AgxLook look;
};
/**
* Generic tone mapping operator that gives control over the tone mapping
* curve. This operator can be used to control the aesthetics of the final
@@ -159,9 +198,6 @@ struct UTILS_PUBLIC GenericToneMapper final : public ToneMapper {
/** Returns the contrast of the curve as a strictly positive value. */
float getContrast() const noexcept;
/** Returns how fast scene referred values map to output white as a value between 0.0 and 1.0. */
float getShoulder() const noexcept;
/** Returns the middle gray point for input values as a value between 0.0 and 1.0. */
float getMidGrayIn() const noexcept;

View File

@@ -26,6 +26,7 @@
#include <iterator>
#include <stddef.h>
namespace utils {
class Entity;
@@ -118,6 +119,29 @@ public:
*/
Instance getInstance(utils::Entity e) const noexcept;
/**
* @return the number of Components
*/
size_t getComponentCount() const noexcept;
/**
* @return true if the this manager has no components
*/
bool empty() const noexcept;
/**
* Retrieve the `Entity` of the component from its `Instance`.
* @param i Instance of the component obtained from getInstance()
* @return
*/
utils::Entity getEntity(Instance i) const noexcept;
/**
* Retrieve the Entities of all the components of this manager.
* @return A list, in no particular order, of all the entities managed by this manager.
*/
utils::Entity const* UTILS_NONNULL getEntities() const noexcept;
/**
* Enables or disable the accurate translation mode. Disabled by default.
*
@@ -200,7 +224,7 @@ public:
* @param count The maximum number of children to retrieve.
* @return The number of children written to the pointer.
*/
size_t getChildren(Instance i, utils::Entity* children, size_t count) const noexcept;
size_t getChildren(Instance i, utils::Entity* UTILS_NONNULL children, size_t count) const noexcept;
/**
* Returns an iterator to the Instance of the first child of the given parent.
@@ -261,7 +285,7 @@ public:
* returns the value set by setTransform().
* @see setTransform()
*/
const math::mat4 getTransformAccurate(Instance ci) const noexcept;
math::mat4 getTransformAccurate(Instance ci) const noexcept;
/**
* Return the world transform of a transform component.
@@ -279,7 +303,7 @@ public:
* composition of this component's local transform with its parent's world transform.
* @see setTransform()
*/
const math::mat4 getWorldTransformAccurate(Instance ci) const noexcept;
math::mat4 getWorldTransformAccurate(Instance ci) const noexcept;
/**
* Opens a local transform transaction. During a transaction, getWorldTransform() can
@@ -308,6 +332,10 @@ public:
* @see openLocalTransformTransaction(), setTransform()
*/
void commitLocalTransformTransaction() noexcept;
protected:
// prevent heap allocation
~TransformManager() = default;
};
} // namespace filament

View File

@@ -27,6 +27,9 @@
#include <utils/compiler.h>
#include <stddef.h>
#include <stdint.h>
namespace filament {
class FVertexBuffer;
@@ -142,19 +145,31 @@ public:
*/
Builder& normalized(VertexAttribute attribute, bool normalize = true) noexcept;
/**
* Sets advanced skinning mode. Bone data, indices and weights will be
* set in RenderableManager:Builder:boneIndicesAndWeights methods.
* Works with or without buffer objects.
*
* @param enabled If true, enables advanced skinning mode. False by default.
*
* @return A reference to this Builder for chaining calls.
*
* @see RenderableManager:Builder:boneIndicesAndWeights
*/
Builder& advancedSkinning(bool enabled) noexcept;
/**
* Creates the VertexBuffer object and returns a pointer to it.
*
* @param engine Reference to the filament::Engine to associate this VertexBuffer with.
*
* @return pointer to the newly created object or nullptr if exceptions are disabled and
* an error occurred.
* @return pointer to the newly created object.
*
* @exception utils::PostConditionPanic if a runtime error occurred, such as running out of
* memory or other resources.
* @exception utils::PreConditionPanic if a parameter to a builder function was invalid.
*/
VertexBuffer* build(Engine& engine);
VertexBuffer* UTILS_NONNULL build(Engine& engine);
private:
friend class FVertexBuffer;
@@ -193,7 +208,12 @@ public:
* and Builder::bufferCount() - 1.
* @param bufferObject The handle to the GPU data that will be used in this buffer slot.
*/
void setBufferObjectAt(Engine& engine, uint8_t bufferIndex, BufferObject const* bufferObject);
void setBufferObjectAt(Engine& engine, uint8_t bufferIndex,
BufferObject const* UTILS_NONNULL bufferObject);
protected:
// prevent heap allocation
~VertexBuffer() = default;
};
} // namespace filament

View File

@@ -19,17 +19,19 @@
#ifndef TNT_FILAMENT_VIEW_H
#define TNT_FILAMENT_VIEW_H
#include <filament/Color.h>
#include <filament/FilamentAPI.h>
#include <filament/Options.h>
#include <backend/DriverEnums.h>
#include <utils/compiler.h>
#include <utils/Entity.h>
#include <math/mathfwd.h>
#include <utility>
#include <stddef.h>
#include <stdint.h>
namespace filament {
namespace backend {
@@ -66,32 +68,32 @@ class Viewport;
*/
class UTILS_PUBLIC View : public FilamentAPI {
public:
using QualityLevel = QualityLevel;
using BlendMode = BlendMode;
using AntiAliasing = AntiAliasing;
using Dithering = Dithering;
using ShadowType = ShadowType;
using QualityLevel = filament::QualityLevel;
using BlendMode = filament::BlendMode;
using AntiAliasing = filament::AntiAliasing;
using Dithering = filament::Dithering;
using ShadowType = filament::ShadowType;
using DynamicResolutionOptions = DynamicResolutionOptions;
using BloomOptions = BloomOptions;
using FogOptions = FogOptions;
using DepthOfFieldOptions = DepthOfFieldOptions;
using VignetteOptions = VignetteOptions;
using RenderQuality = RenderQuality;
using AmbientOcclusionOptions = AmbientOcclusionOptions;
using TemporalAntiAliasingOptions = TemporalAntiAliasingOptions;
using MultiSampleAntiAliasingOptions = MultiSampleAntiAliasingOptions;
using VsmShadowOptions = VsmShadowOptions;
using SoftShadowOptions = SoftShadowOptions;
using ScreenSpaceReflectionsOptions = ScreenSpaceReflectionsOptions;
using GuardBandOptions = GuardBandOptions;
using StereoscopicOptions = StereoscopicOptions;
using DynamicResolutionOptions = filament::DynamicResolutionOptions;
using BloomOptions = filament::BloomOptions;
using FogOptions = filament::FogOptions;
using DepthOfFieldOptions = filament::DepthOfFieldOptions;
using VignetteOptions = filament::VignetteOptions;
using RenderQuality = filament::RenderQuality;
using AmbientOcclusionOptions = filament::AmbientOcclusionOptions;
using TemporalAntiAliasingOptions = filament::TemporalAntiAliasingOptions;
using MultiSampleAntiAliasingOptions = filament::MultiSampleAntiAliasingOptions;
using VsmShadowOptions = filament::VsmShadowOptions;
using SoftShadowOptions = filament::SoftShadowOptions;
using ScreenSpaceReflectionsOptions = filament::ScreenSpaceReflectionsOptions;
using GuardBandOptions = filament::GuardBandOptions;
using StereoscopicOptions = filament::StereoscopicOptions;
/**
* Sets the View's name. Only useful for debugging.
* @param name Pointer to the View's name. The string is copied.
*/
void setName(const char* name) noexcept;
void setName(const char* UTILS_NONNULL name) noexcept;
/**
* Returns the View's name
@@ -100,7 +102,7 @@ public:
*
* @attention Do *not* free the pointer or modify its content.
*/
const char* getName() const noexcept;
const char* UTILS_NULLABLE getName() const noexcept;
/**
* Set this View instance's Scene.
@@ -116,19 +118,19 @@ public:
* There is no reference-counting.
* Make sure to dissociate a Scene from all Views before destroying it.
*/
void setScene(Scene* scene);
void setScene(Scene* UTILS_NULLABLE scene);
/**
* Returns the Scene currently associated with this View.
* @return A pointer to the Scene associated to this View. nullptr if no Scene is set.
*/
Scene* getScene() noexcept;
Scene* UTILS_NULLABLE getScene() noexcept;
/**
* Returns the Scene currently associated with this View.
* @return A pointer to the Scene associated to this View. nullptr if no Scene is set.
*/
Scene const* getScene() const noexcept {
Scene const* UTILS_NULLABLE getScene() const noexcept {
return const_cast<View*>(this)->getScene();
}
@@ -143,7 +145,7 @@ public:
*
* @param renderTarget Render target associated with view, or nullptr for the swap chain.
*/
void setRenderTarget(RenderTarget* renderTarget) noexcept;
void setRenderTarget(RenderTarget* UTILS_NULLABLE renderTarget) noexcept;
/**
* Gets the offscreen render target associated with this view.
@@ -152,7 +154,7 @@ public:
*
* @see setRenderTarget
*/
RenderTarget* getRenderTarget() const noexcept;
RenderTarget* UTILS_NULLABLE getRenderTarget() const noexcept;
/**
* Sets the rectangular region to render to.
@@ -185,7 +187,7 @@ public:
* There is no reference-counting.
* Make sure to dissociate a Camera from all Views before destroying it.
*/
void setCamera(Camera* camera) noexcept;
void setCamera(Camera* UTILS_NONNULL camera) noexcept;
/**
* Returns the Camera currently associated with this View.
@@ -402,13 +404,13 @@ public:
* There is no reference-counting.
* Make sure to dissociate a ColorGrading from all Views before destroying it.
*/
void setColorGrading(ColorGrading* colorGrading) noexcept;
void setColorGrading(ColorGrading* UTILS_NULLABLE colorGrading) noexcept;
/**
* Returns the color grading transforms currently associated to this view.
* @return A pointer to the ColorGrading associated to this View.
*/
const ColorGrading* getColorGrading() const noexcept;
const ColorGrading* UTILS_NULLABLE getColorGrading() const noexcept;
/**
* Sets ambient occlusion options.
@@ -662,7 +664,8 @@ public:
* Material's stencil comparison function and reference value. Fragments that don't pass the
* stencil test are then discarded.
*
* Post-processing must be enabled in order to use the stencil buffer.
* If post-processing is disabled, then the SwapChain must have the CONFIG_HAS_STENCIL_BUFFER
* flag set in order to use the stencil buffer.
*
* A renderable's priority (see RenderableManager::setPriority) is useful to control the order
* in which primitives are drawn.
@@ -690,11 +693,12 @@ public:
* - punctual lights
*
* Stereo rendering depends on device and platform support. To check if stereo rendering is
* supported, use Engine::isStereoSupported().
* supported, use Engine::isStereoSupported(). If stereo rendering is not supported, then the
* stereoscopic options have no effect.
*
* @param options The stereoscopic options to use on this view
*/
void setStereoscopicOptions(StereoscopicOptions const& options);
void setStereoscopicOptions(StereoscopicOptions const& options) noexcept;
/**
* Returns the stereoscopic options associated with this View.
@@ -712,10 +716,10 @@ public:
bool isFrustumCullingEnabled() const noexcept;
//! debugging: sets the Camera used for rendering. It may be different from the culling camera.
void setDebugCamera(Camera* camera) noexcept;
void setDebugCamera(Camera* UTILS_NULLABLE camera) noexcept;
//! debugging: returns a Camera from the point of view of *the* dominant directional light used for shadowing.
Camera const* getDirectionalLightCamera() const noexcept;
Camera const* UTILS_NULLABLE getDirectionalShadowCamera() const noexcept;
/** Result of a picking query */
@@ -744,11 +748,12 @@ public:
/** User data for PickingQueryResultCallback */
struct PickingQuery {
// note: this is enough to store a std::function<> -- just saying...
void* storage[4];
void* UTILS_NULLABLE storage[4];
};
/** callback type used for picking queries. */
using PickingQueryResultCallback = void(*)(PickingQueryResult const& result, PickingQuery* pq);
using PickingQueryResultCallback =
void(*)(PickingQueryResult const& result, PickingQuery* UTILS_NONNULL pq);
/**
* Helper for creating a picking query from Foo::method, by pointer.
@@ -762,10 +767,10 @@ public:
* @param handler Handler to dispatch the callback or nullptr for the default handler.
*/
template<typename T, void(T::*method)(PickingQueryResult const&)>
void pick(uint32_t x, uint32_t y, T* instance, backend::CallbackHandler* handler = nullptr) noexcept {
void pick(uint32_t x, uint32_t y, T* UTILS_NONNULL instance,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr) noexcept {
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
void* user = pq->storage;
(*static_cast<T**>(user)->*method)(result);
(static_cast<T*>(pq->storage[0])->*method)(result);
}, handler);
query.storage[0] = instance;
}
@@ -782,11 +787,11 @@ public:
* @param handler Handler to dispatch the callback or nullptr for the default handler.
*/
template<typename T, void(T::*method)(PickingQueryResult const&)>
void pick(uint32_t x, uint32_t y, T instance, backend::CallbackHandler* handler = nullptr) noexcept {
void pick(uint32_t x, uint32_t y, T instance,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr) noexcept {
static_assert(sizeof(instance) <= sizeof(PickingQuery::storage), "user data too large");
PickingQuery& query = pick(x, y, [](PickingQueryResult const& result, PickingQuery* pq) {
void* user = pq->storage;
T* that = static_cast<T*>(user);
T* const that = static_cast<T*>(reinterpret_cast<void*>(pq->storage));
(that->*method)(result);
that->~T();
}, handler);
@@ -803,15 +808,15 @@ public:
* @param handler Handler to dispatch the callback or nullptr for the default handler.
*/
template<typename T>
void pick(uint32_t x, uint32_t y, T functor, backend::CallbackHandler* handler = nullptr) noexcept {
void pick(uint32_t x, uint32_t y, T functor,
backend::CallbackHandler* UTILS_NULLABLE handler = nullptr) noexcept {
static_assert(sizeof(functor) <= sizeof(PickingQuery::storage), "functor too large");
PickingQuery& query = pick(x, y, handler,
(PickingQueryResultCallback)[](PickingQueryResult const& result, PickingQuery* pq) {
void* user = pq->storage;
T& that = *static_cast<T*>(user);
that(result);
that.~T();
});
T* const that = static_cast<T*>(reinterpret_cast<void*>(pq->storage));
that->operator()(result);
that->~T();
});
new(query.storage) T(std::move(functor));
}
@@ -830,8 +835,9 @@ public:
* 8*sizeof(void*) bytes of user data. This user data is later accessible
* in the PickingQueryResultCallback callback 3rd parameter.
*/
PickingQuery& pick(uint32_t x, uint32_t y, backend::CallbackHandler* handler,
PickingQueryResultCallback callback) noexcept;
PickingQuery& pick(uint32_t x, uint32_t y,
backend::CallbackHandler* UTILS_NULLABLE handler,
PickingQueryResultCallback UTILS_NONNULL callback) noexcept;
/**
* Set the value of material global variables. There are up-to four such variable each of
@@ -893,6 +899,10 @@ public:
*/
UTILS_DEPRECATED
AmbientOcclusion getAmbientOcclusion() const noexcept;
protected:
// prevent heap allocation
~View() = default;
};
} // namespace filament

View File

@@ -23,9 +23,6 @@
#include <utils/compiler.h>
#include <math/scalar.h>
#include <math/mathfwd.h>
#include <stddef.h>
#include <stdint.h>

View File

@@ -21,6 +21,8 @@
#include <math/vec3.h>
#include <math/vec4.h>
#include <variant>
namespace filament {
namespace geometry {
@@ -106,16 +108,24 @@ public:
* - http://people.compute.dtu.dk/jerf/code/hairy/
*/
FRISVAD = 4,
/**
* Flat Shading
*
* **Requires**: `positions + indices` <br/>
* **Note**: Will remesh
*/
FLAT_SHADING = 5
};
/**
* This enum specifies the auxiliary attributes of each vertex that can be provided as input.
* These attributes do not affect the computation of the tangent space, but they will be
* properly mapped when a remeshing is carried out.
*/
enum class AuxAttribute : uint8_t {
UV1 = 0x0,
COLORS = 0x1,
JOINTS = 0x2,
WEIGHTS = 0x3,
};
using InData = std::variant<filament::math::float2 const*, filament::math::float3 const*,
filament::math::float4 const*, filament::math::ushort3 const*,
filament::math::ushort4 const*>;
/**
* Use this class to provide input to the TangentSpaceMesh computation. **Important**:
* Computation of the tangent space is intended to be synchronous (working on the same thread).
@@ -170,6 +180,16 @@ public:
*/
Builder& uvs(filament::math::float2 const* uvs, size_t stride = 0) noexcept;
/**
* Sets "auxiliary" attributes that will be properly mapped when remeshed.
*
* @param attribute The attribute of the data to be stored
* @param data The data to be store
* @param stride The stride for iterating through `attribute`
* @return Builder
*/
Builder& aux(AuxAttribute attribute, InData data, size_t stride = 0) noexcept;
/**
* @param positions The input positions
* @param stride The stride for iterating through `positions`
@@ -177,10 +197,30 @@ public:
*/
Builder& positions(filament::math::float3 const* positions, size_t stride = 0) noexcept;
/**
* @param triangleCount The input number of triangles
* @return Builder
*/
Builder& triangleCount(size_t triangleCount) noexcept;
/**
* @param triangles The triangles in 32-bit indices
* @return Builder
*/
Builder& triangles(filament::math::uint3 const* triangles) noexcept;
/**
* @param triangles The triangles in 16-bit indices
* @return Builder
*/
Builder& triangles(filament::math::ushort3 const* triangles) noexcept;
/**
* The Client can provide an algorithm hint to produce the tangents.
*
* @param algorithm The algorithm hint.
* @return Builder
*/
Builder& algorithm(Algorithm algorithm) noexcept;
/**
@@ -199,7 +239,7 @@ public:
};
/**
* Destory the mesh object
* Destroy the mesh object
* @param mesh A pointer to a TangentSpaceMesh ready to be destroyed
*/
static void destroy(TangentSpaceMesh* mesh) noexcept;
@@ -284,6 +324,24 @@ public:
*/
void getQuats(filament::math::quath* out, size_t stride = 0) const noexcept;
/**
* Get output auxiliary attributes.
* Assumes the `out` param is at least of getVertexCount() length (while accounting for
* `stride`).
*
* @param out Client-allocated array that will be used for copying out attribute as T
* @param stride Stride for iterating through `out`
*/
template<typename T>
using is_supported_aux_t =
typename std::enable_if<std::is_same<filament::math::float2, T>::value ||
std::is_same<filament::math::float3, T>::value ||
std::is_same<filament::math::float4, T>::value ||
std::is_same<filament::math::ushort3, T>::value ||
std::is_same<filament::math::ushort4, T>::value>::type;
template<typename T, typename = is_supported_aux_t<T>>
void getAux(AuxAttribute attribute, T* out, size_t stride = 0) const noexcept;
/**
* Get number of output triangles.
* The number of output triangles is the same as the number of input triangles. However, when a
@@ -315,9 +373,9 @@ public:
void getTriangles(filament::math::ushort3* out) const;
/**
* @return The algorithm used to compute the output mesh.
* @return Whether the TBN algorithm remeshed the input.
*/
Algorithm getAlgorithm() const noexcept;
bool remeshed() const noexcept;
private:
~TangentSpaceMesh() noexcept;

View File

@@ -97,8 +97,8 @@ struct AssetConfiguration {
*
* // Load buffers and textures from disk.
* ResourceLoader resourceLoader({engine, ".", true});
* resourceLoader.addTextureProvider("image/png", decoder)
* resourceLoader.addTextureProvider("image/jpeg", decoder)
* resourceLoader.addTextureProvider("image/png", decoder);
* resourceLoader.addTextureProvider("image/jpeg", decoder);
* resourceLoader.loadResources(asset);
*
* // Free the glTF hierarchy as it is no longer needed.
@@ -197,7 +197,7 @@ public:
* This cannot be called after FilamentAsset::releaseSourceData().
* See also AssetLoader::createInstancedAsset().
*/
FilamentInstance* createInstance(FilamentAsset* primary);
FilamentInstance* createInstance(FilamentAsset* asset);
/**
* Allows clients to enable diagnostic shading on newly-loaded assets.

View File

@@ -69,9 +69,12 @@ class UTILS_PUBLIC ResourceLoader {
public:
using BufferDescriptor = filament::backend::BufferDescriptor;
ResourceLoader(const ResourceConfiguration& config);
explicit ResourceLoader(const ResourceConfiguration& config);
~ResourceLoader();
void setConfiguration(const ResourceConfiguration& config);
/**
* Feeds the binary content of an external resource into the loader's URI cache.
*
@@ -90,7 +93,8 @@ public:
/**
* Register a plugin that can consume PNG / JPEG content and produce filament::Texture objects.
*
* Destruction of the given provider is the client's responsibility.
* Destruction of the given provider is the client's responsibility and must be done after the
* destruction of this ResourceLoader.
*/
void addTextureProvider(const char* mimeType, TextureProvider* provider);
@@ -153,8 +157,6 @@ public:
private:
bool loadResources(FFilamentAsset* asset, bool async);
void normalizeSkinningWeights(FFilamentAsset* asset) const;
AssetPool* mPool;
struct Impl;
Impl* pImpl;
};

View File

@@ -58,7 +58,8 @@ public:
/* compound assignment products by a scalar
*/
constexpr QUATERNION<T>& operator*=(T v) {
template<typename U, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
constexpr QUATERNION<T>& operator*=(U v) {
QUATERNION<T>& lhs = static_cast<QUATERNION<T>&>(*this);
for (size_t i = 0; i < QUATERNION<T>::size(); i++) {
lhs[i] *= v;
@@ -66,7 +67,8 @@ public:
return lhs;
}
constexpr QUATERNION<T>& operator/=(T v) {
template<typename U, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
constexpr QUATERNION<T>& operator/=(U v) {
QUATERNION<T>& lhs = static_cast<QUATERNION<T>&>(*this);
for (size_t i = 0; i < QUATERNION<T>::size(); i++) {
lhs[i] /= v;
@@ -85,28 +87,29 @@ public:
/* The operators below handle operation between quaternions of the same size
* but of a different element type.
*/
template<typename RT>
friend inline
constexpr QUATERNION<T> MATH_PURE operator*(const QUATERNION<T>& q, const QUATERNION<RT>& r) {
template<typename U>
friend inline constexpr
QUATERNION<arithmetic_result_t<T, U>> MATH_PURE operator*(
const QUATERNION<T>& q, const QUATERNION<U>& r) {
// could be written as:
// return QUATERNION<T>(
// q.w*r.w - dot(q.xyz, r.xyz),
// q.w*r.xyz + r.w*q.xyz + cross(q.xyz, r.xyz));
return QUATERNION<T>(
return {
q.w * r.w - q.x * r.x - q.y * r.y - q.z * r.z,
q.w * r.x + q.x * r.w + q.y * r.z - q.z * r.y,
q.w * r.y - q.x * r.z + q.y * r.w + q.z * r.x,
q.w * r.z + q.x * r.y - q.y * r.x + q.z * r.w);
q.w * r.z + q.x * r.y - q.y * r.x + q.z * r.w
};
}
template<typename RT>
friend inline
constexpr TVec3<T> MATH_PURE operator*(const QUATERNION<T>& q, const TVec3<RT>& v) {
template<typename U>
friend inline constexpr
TVec3<arithmetic_result_t<T, U>> MATH_PURE operator*(const QUATERNION<T>& q, const TVec3<U>& v) {
// note: if q is known to be a unit quaternion, then this simplifies to:
// TVec3<T> t = 2 * cross(q.xyz, v)
// return v + (q.w * t) + cross(q.xyz, t)
return imaginary(q * QUATERNION<T>(v, 0) * inverse(q));
return imaginary(q * QUATERNION<U>(v, 0) * inverse(q));
}
@@ -122,22 +125,25 @@ public:
* q.w*r.z + q.x*r.y - q.y*r.x + q.z*r.w);
*
*/
friend inline
constexpr QUATERNION<T> MATH_PURE operator*(QUATERNION<T> q, T scalar) {
template<typename U, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
friend inline constexpr
QUATERNION<arithmetic_result_t<T, U>> MATH_PURE operator*(QUATERNION<T> q, U scalar) {
// don't pass q by reference because we need a copy anyway
return q *= scalar;
return QUATERNION<arithmetic_result_t<T, U>>(q *= scalar);
}
friend inline
constexpr QUATERNION<T> MATH_PURE operator*(T scalar, QUATERNION<T> q) {
template<typename U, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
friend inline constexpr
QUATERNION<arithmetic_result_t<T, U>> MATH_PURE operator*(U scalar, QUATERNION<T> q) {
// don't pass q by reference because we need a copy anyway
return q *= scalar;
return QUATERNION<arithmetic_result_t<T, U>>(q *= scalar);
}
friend inline
constexpr QUATERNION<T> MATH_PURE operator/(QUATERNION<T> q, T scalar) {
template<typename U, typename = std::enable_if_t<std::is_arithmetic_v<U>>>
friend inline constexpr
QUATERNION<arithmetic_result_t<T, U>> MATH_PURE operator/(QUATERNION<T> q, U scalar) {
// don't pass q by reference because we need a copy anyway
return q /= scalar;
return QUATERNION<arithmetic_result_t<T, U>>(q /= scalar);
}
};
@@ -160,9 +166,10 @@ public:
* (the first one, BASE<T> being known).
*/
template<typename RT>
friend inline
constexpr T MATH_PURE dot(const QUATERNION<T>& p, const QUATERNION<RT>& q) {
template<typename U>
friend inline constexpr
arithmetic_result_t<T, U> MATH_PURE dot(
const QUATERNION<T>& p, const QUATERNION<U>& q) {
return p.x * q.x +
p.y * q.y +
p.z * q.z +
@@ -196,7 +203,7 @@ public:
friend inline
constexpr QUATERNION<T> MATH_PURE inverse(const QUATERNION<T>& q) {
return conj(q) * (1 / dot(q, q));
return conj(q) * (T(1) / dot(q, q));
}
friend inline
@@ -214,8 +221,10 @@ public:
return QUATERNION<T>(q.xyz, 0);
}
friend inline
constexpr QUATERNION<T> MATH_PURE cross(const QUATERNION<T>& p, const QUATERNION<T>& q) {
template<typename U>
friend inline constexpr
QUATERNION<arithmetic_result_t<T, U>> MATH_PURE cross(
const QUATERNION<T>& p, const QUATERNION<U>& q) {
return unreal(p * q);
}

View File

@@ -17,15 +17,21 @@
#ifndef TNT_MATH_MAT3_H
#define TNT_MATH_MAT3_H
#include <math/TMatHelpers.h>
#include <math/compiler.h>
#include <math/quat.h>
#include <math/vec3.h>
#include <math/TMatHelpers.h>
#include <math/TVecHelpers.h>
#include <limits.h>
#include <stdint.h>
#include <sys/types.h>
#include <cmath>
#include <assert.h>
#include <stddef.h>
namespace filament {
namespace math {
// -------------------------------------------------------------------------------------
@@ -289,6 +295,14 @@ public:
return matrix::cof(m);
}
/*
* Returns a matrix representing the pose of a virtual camera looking towards -Z in its
* local Y-up coordinate system. "up" defines where the Y axis of the camera's local coordinate
* system is.
*/
template<typename A, typename B>
static TMat33 lookTo(const TVec3<A>& direction, const TVec3<B>& up) noexcept;
/**
* Packs the tangent frame represented by the specified matrix into a quaternion.
* Reflection is preserved by encoding it as the sign of the w component in the
@@ -406,6 +420,29 @@ constexpr TMat33<T>::TMat33(const TQuaternion<U>& q) noexcept : m_value{} {
m_value[2] = col_type(xz + yw, yz - xw, 1 - xx - yy); // NOLINT
}
template<typename T>
constexpr T dot_tolerance() noexcept;
template<>
constexpr float dot_tolerance<float>() noexcept { return 0.999f; }
template<>
constexpr double dot_tolerance<double>() noexcept { return 0.9999; }
template<typename T>
template<typename A, typename B>
TMat33<T> TMat33<T>::lookTo(const TVec3<A>& direction, const TVec3<B>& up) noexcept {
auto const z_axis = direction;
auto norm_up = up;
if (std::abs(dot(z_axis, norm_up)) > dot_tolerance< arithmetic_result_t<A, B> >()) {
// Fix up vector if we're degenerate (looking straight up, basically)
norm_up = { norm_up.z, norm_up.x, norm_up.y };
}
auto const x_axis = normalize(cross(z_axis, norm_up));
auto const y_axis = cross(x_axis, z_axis);
return { x_axis, y_axis, -z_axis };
}
//------------------------------------------------------------------------------
template<typename T>
constexpr TQuaternion<T> TMat33<T>::packTangentFrame(const TMat33<T>& m, size_t storageSize) noexcept {

View File

@@ -285,6 +285,9 @@ public:
template<typename A, typename B, typename C>
static TMat44 lookAt(const TVec3<A>& eye, const TVec3<B>& center, const TVec3<C>& up) noexcept;
template<typename A, typename B, typename C>
static TMat44 lookTo(const TVec3<A>& direction, const TVec3<B>& position, const TVec3<C>& up) noexcept;
template<typename A>
static constexpr TVec3<A> project(const TMat44& projectionMatrix, TVec3<A> vertice) noexcept{
TVec4<A> r = projectionMatrix * TVec4<A>{ vertice, 1 };
@@ -517,19 +520,19 @@ template<typename T>
template<typename A, typename B, typename C>
TMat44<T> TMat44<T>::lookAt(const TVec3<A>& eye, const TVec3<B>& center,
const TVec3<C>& up) noexcept {
TVec3<T> z_axis(normalize(center - eye));
TVec3<T> norm_up(normalize(up));
if (std::abs(dot(z_axis, norm_up)) > T(0.999)) {
// Fix up vector if we're degenerate (looking straight up, basically)
norm_up = { norm_up.z, norm_up.x, norm_up.y };
}
TVec3<T> x_axis(normalize(cross(z_axis, norm_up)));
TVec3<T> y_axis(cross(x_axis, z_axis));
return TMat44<T>(
TVec4<T>(x_axis, 0),
TVec4<T>(y_axis, 0),
TVec4<T>(-z_axis, 0),
TVec4<T>(eye, 1));
return lookTo(normalize(center - eye), eye, normalize(up));
}
template<typename T>
template<typename A, typename B, typename C>
TMat44<T> TMat44<T>::lookTo(const TVec3<A>& direction, const TVec3<B>& position,
const TVec3<C>& up) noexcept {
auto r = TMat33<T>::lookTo(direction, up);
return TMat44<T>{
TVec4<T>{ r[0], 0 },
TVec4<T>{ r[1], 0 },
TVec4<T>{ r[2], 0 },
TVec4<T>{ position, 1 } };
}
// ----------------------------------------------------------------------------------------

View File

@@ -171,27 +171,29 @@ typedef details::TQuaternion<double> quat;
typedef details::TQuaternion<float> quatf;
typedef details::TQuaternion<half> quath;
constexpr inline quat operator "" _i(long double v) {
// note: don't put a space between "" and _{i,j,k}, this is deprecated
constexpr inline quat operator ""_i(long double v) {
return { 0.0, double(v), 0.0, 0.0 };
}
constexpr inline quat operator "" _j(long double v) {
constexpr inline quat operator ""_j(long double v) {
return { 0.0, 0.0, double(v), 0.0 };
}
constexpr inline quat operator "" _k(long double v) {
constexpr inline quat operator ""_k(long double v) {
return { 0.0, 0.0, 0.0, double(v) };
}
constexpr inline quat operator "" _i(unsigned long long v) {
constexpr inline quat operator ""_i(unsigned long long v) {
return { 0.0, double(v), 0.0, 0.0 };
}
constexpr inline quat operator "" _j(unsigned long long v) {
constexpr inline quat operator ""_j(unsigned long long v) {
return { 0.0, 0.0, double(v), 0.0 };
}
constexpr inline quat operator "" _k(unsigned long long v) {
constexpr inline quat operator ""_k(unsigned long long v) {
return { 0.0, 0.0, 0.0, double(v) };
}

View File

@@ -17,12 +17,10 @@
#ifndef TNT_UTILS_ALLOCATOR_H
#define TNT_UTILS_ALLOCATOR_H
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/memalign.h>
#include <utils/Mutex.h>
#include <utils/SpinLock.h>
#include <atomic>
#include <cstddef>
@@ -31,6 +29,8 @@
#include <assert.h>
#include <stdlib.h>
#include <stdint.h>
#include <vector>
namespace utils {
@@ -44,14 +44,14 @@ static inline P* add(P* a, T b) noexcept {
template <typename P>
static inline P* align(P* p, size_t alignment) noexcept {
// alignment must be a power-of-two
assert(alignment && !(alignment & alignment-1));
assert_invariant(alignment && !(alignment & alignment-1));
return (P*)((uintptr_t(p) + alignment - 1) & ~(alignment - 1));
}
template <typename P>
static inline P* align(P* p, size_t alignment, size_t offset) noexcept {
P* const r = align(add(p, offset), alignment);
assert(r >= add(p, offset));
assert_invariant(r >= add(p, offset));
return r;
}
@@ -90,20 +90,19 @@ public:
// branch-less allocation
void* const p = pointermath::align(current(), alignment, extra);
void* const c = pointermath::add(p, size);
bool success = c <= end();
bool const success = c <= end();
set_current(success ? c : current());
return success ? p : nullptr;
}
// API specific to this allocator
void *getCurrent() UTILS_RESTRICT noexcept {
return current();
}
// free memory back to the specified point
void rewind(void* p) UTILS_RESTRICT noexcept {
assert(p>=mBegin && p<end());
assert_invariant(p >= mBegin && p < end());
set_current(p);
}
@@ -123,16 +122,21 @@ public:
void swap(LinearAllocator& rhs) noexcept;
void *base() noexcept { return mBegin; }
void const *base() const noexcept { return mBegin; }
void free(void*, size_t) UTILS_RESTRICT noexcept { }
private:
protected:
void* end() UTILS_RESTRICT noexcept { return pointermath::add(mBegin, mSize); }
void const* end() const UTILS_RESTRICT noexcept { return pointermath::add(mBegin, mSize); }
void* current() UTILS_RESTRICT noexcept { return pointermath::add(mBegin, mCur); }
void const* current() const UTILS_RESTRICT noexcept { return pointermath::add(mBegin, mCur); }
private:
void set_current(void* p) UTILS_RESTRICT noexcept {
mCur = uint32_t(uintptr_t(p) - uintptr_t(mBegin));
}
void* mBegin = nullptr;
uint32_t mSize = 0;
uint32_t mCur = 0;
@@ -153,9 +157,7 @@ public:
explicit HeapAllocator(const AREA&) { }
// our allocator concept
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t), size_t extra = 0) {
// this allocator doesn't support 'extra'
assert(extra == 0);
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t)) {
return aligned_alloc(size, alignment);
}
@@ -172,6 +174,50 @@ public:
void swap(HeapAllocator&) noexcept { }
};
/* ------------------------------------------------------------------------------------------------
* LinearAllocatorWithFallback
*
* This is a LinearAllocator that falls back to a HeapAllocator when allocation fail. The Heap
* allocator memory is freed only when the LinearAllocator is reset or destroyed.
* ------------------------------------------------------------------------------------------------
*/
class LinearAllocatorWithFallback : private LinearAllocator, private HeapAllocator {
std::vector<void*> mHeapAllocations;
public:
LinearAllocatorWithFallback(void* begin, void* end) noexcept
: LinearAllocator(begin, end) {
}
template <typename AREA>
explicit LinearAllocatorWithFallback(const AREA& area)
: LinearAllocatorWithFallback(area.begin(), area.end()) {
}
~LinearAllocatorWithFallback() noexcept {
LinearAllocatorWithFallback::reset();
}
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t));
void *getCurrent() noexcept {
return LinearAllocator::getCurrent();
}
void rewind(void* p) noexcept {
if (p >= LinearAllocator::base() && p < LinearAllocator::end()) {
LinearAllocator::rewind(p);
}
}
void reset() noexcept;
void free(void*, size_t) noexcept { }
bool isHeapAllocation(void* p) const noexcept {
return p < LinearAllocator::base() || p >= LinearAllocator::end();
}
};
// ------------------------------------------------------------------------------------------------
class FreeList {
@@ -187,13 +233,13 @@ public:
Node* const head = mHead;
mHead = head ? head->next : nullptr;
// this could indicate a use after free
assert(!mHead || mHead >= mBegin && mHead < mEnd);
assert_invariant(!mHead || mHead >= mBegin && mHead < mEnd);
return head;
}
void push(void* p) noexcept {
assert(p);
assert(p >= mBegin && p < mEnd);
assert_invariant(p);
assert_invariant(p >= mBegin && p < mEnd);
// TODO: assert this is one of our pointer (i.e.: it's address match one of ours)
Node* const head = static_cast<Node*>(p);
head->next = mHead;
@@ -204,11 +250,11 @@ public:
return mHead;
}
private:
struct Node {
Node* next;
};
private:
static Node* init(void* begin, void* end,
size_t elementSize, size_t alignment, size_t extra) noexcept;
@@ -226,20 +272,20 @@ public:
AtomicFreeList() noexcept = default;
AtomicFreeList(void* begin, void* end,
size_t elementSize, size_t alignment, size_t extra) noexcept;
AtomicFreeList(const FreeList& rhs) = delete;
AtomicFreeList& operator=(const FreeList& rhs) = delete;
AtomicFreeList(const AtomicFreeList& rhs) = delete;
AtomicFreeList& operator=(const AtomicFreeList& rhs) = delete;
void* pop() noexcept {
Node* const storage = mStorage;
Node* const pStorage = mStorage;
HeadPtr currentHead = mHead.load();
while (currentHead.offset >= 0) {
// The value of "next" we load here might already contain application data if another
// The value of "pNext" we load here might already contain application data if another
// thread raced ahead of us. But in that case, the computed "newHead" will be discarded
// since compare_exchange_weak fails. Then this thread will loop with the updated
// value of currentHead, and try again.
Node* const next = storage[currentHead.offset].next.load(std::memory_order_relaxed);
const HeadPtr newHead{ next ? int32_t(next - storage) : -1, currentHead.tag + 1 };
Node* const pNext = pStorage[currentHead.offset].next.load(std::memory_order_relaxed);
const HeadPtr newHead{ pNext ? int32_t(pNext - pStorage) : -1, currentHead.tag + 1 };
// In the rare case that the other thread that raced ahead of us already returned the
// same mHead we just loaded, but it now has a different "next" value, the tag field will not
// match, and compare_exchange_weak will fail and prevent that particular race condition.
@@ -247,18 +293,18 @@ public:
// This assert needs to occur after we have validated that there was no race condition
// Otherwise, next might already contain application data, if another thread
// raced ahead of us after we loaded mHead, but before we loaded mHead->next.
assert(!next || next >= storage);
assert_invariant(!pNext || pNext >= pStorage);
break;
}
}
void* p = (currentHead.offset >= 0) ? (storage + currentHead.offset) : nullptr;
assert(!p || p >= storage);
void* p = (currentHead.offset >= 0) ? (pStorage + currentHead.offset) : nullptr;
assert_invariant(!p || p >= pStorage);
return p;
}
void push(void* p) noexcept {
Node* const storage = mStorage;
assert(p && p >= storage);
assert_invariant(p && p >= storage);
Node* const node = static_cast<Node*>(p);
HeadPtr currentHead = mHead.load();
HeadPtr newHead = { int32_t(node - storage), currentHead.tag + 1 };
@@ -273,7 +319,6 @@ public:
return mStorage + mHead.load(std::memory_order_relaxed).offset;
}
private:
struct Node {
// This should be a regular (non-atomic) pointer, but this causes TSAN to complain
// about a data-race that exists but is benin. We always use this atomic<> in
@@ -304,6 +349,7 @@ private:
std::atomic<Node*> next;
};
private:
// This struct is using a 32-bit offset into the arena rather than
// a direct pointer, because together with the 32-bit tag, it needs to
// fit into 8 bytes. If it was any larger, it would not be possible to
@@ -326,14 +372,15 @@ template <
size_t OFFSET = 0,
typename FREELIST = FreeList>
class PoolAllocator {
static_assert(ELEMENT_SIZE >= sizeof(void*), "ELEMENT_SIZE must accommodate at least a pointer");
static_assert(ELEMENT_SIZE >= sizeof(typename FREELIST::Node),
"ELEMENT_SIZE must accommodate at least a FreeList::Node");
public:
// our allocator concept
void* alloc(size_t size = ELEMENT_SIZE,
size_t alignment = ALIGNMENT, size_t offset = OFFSET) noexcept {
assert(size <= ELEMENT_SIZE);
assert(alignment <= ALIGNMENT);
assert(offset == OFFSET);
assert_invariant(size <= ELEMENT_SIZE);
assert_invariant(alignment <= ALIGNMENT);
assert_invariant(offset == OFFSET);
return mFreeList.pop();
}
@@ -347,7 +394,11 @@ public:
: mFreeList(begin, end, ELEMENT_SIZE, ALIGNMENT, OFFSET) {
}
template <typename AREA>
PoolAllocator(void* begin, size_t size) noexcept
: PoolAllocator(begin, static_cast<char *>(begin) + size) {
}
template<typename AREA>
explicit PoolAllocator(const AREA& area) noexcept
: PoolAllocator(area.begin(), area.end()) {
}
@@ -373,6 +424,53 @@ private:
FREELIST mFreeList;
};
template <
size_t ELEMENT_SIZE,
size_t ALIGNMENT = alignof(std::max_align_t),
typename FREELIST = FreeList>
class PoolAllocatorWithFallback :
private PoolAllocator<ELEMENT_SIZE, ALIGNMENT, 0, FREELIST>,
private HeapAllocator {
using PoolAllocator = PoolAllocator<ELEMENT_SIZE, ALIGNMENT, 0, FREELIST>;
void* mBegin;
void* mEnd;
public:
PoolAllocatorWithFallback(void* begin, void* end) noexcept
: PoolAllocator(begin, end), mBegin(begin), mEnd(end) {
}
PoolAllocatorWithFallback(void* begin, size_t size) noexcept
: PoolAllocatorWithFallback(begin, static_cast<char*>(begin) + size) {
}
template<typename AREA>
explicit PoolAllocatorWithFallback(const AREA& area) noexcept
: PoolAllocatorWithFallback(area.begin(), area.end()) {
}
bool isHeapAllocation(void* p) const noexcept {
return p < mBegin || p >= mEnd;
}
// our allocator concept
void* alloc(size_t size = ELEMENT_SIZE, size_t alignment = ALIGNMENT) noexcept {
void* p = PoolAllocator::alloc(size, alignment);
if (UTILS_UNLIKELY(!p)) {
p = HeapAllocator::alloc(size, alignment);
}
assert_invariant(p);
return p;
}
void free(void* p, size_t size) noexcept {
if (UTILS_LIKELY(!isHeapAllocation(p))) {
PoolAllocator::free(p, size);
} else {
HeapAllocator::free(p);
}
}
};
#define UTILS_MAX(a,b) ((a) > (b) ? (a) : (b))
template <typename T, size_t OFFSET = 0>
@@ -478,7 +576,6 @@ struct NoLock {
void unlock() noexcept { }
};
using SpinLock = utils::SpinLock;
using Mutex = utils::Mutex;
} // namespace LockingPolicy
@@ -587,32 +684,54 @@ public:
mListener(name, mArea.data(), mArea.size()) {
}
template<typename ... ARGS>
void* alloc(size_t size, size_t alignment, size_t extra, ARGS&& ... args) noexcept {
std::lock_guard<LockingPolicy> guard(mLock);
void* p = mAllocator.alloc(size, alignment, extra, std::forward<ARGS>(args) ...);
mListener.onAlloc(p, size, alignment, extra);
return p;
}
// allocate memory from arena with given size and alignment
// (acceptable size/alignment may depend on the allocator provided)
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t), size_t extra = 0) noexcept {
void* alloc(size_t size, size_t alignment, size_t extra) noexcept {
std::lock_guard<LockingPolicy> guard(mLock);
void* p = mAllocator.alloc(size, alignment, extra);
mListener.onAlloc(p, size, alignment, extra);
return p;
}
void* alloc(size_t size, size_t alignment = alignof(std::max_align_t)) noexcept {
std::lock_guard<LockingPolicy> guard(mLock);
void* p = mAllocator.alloc(size, alignment);
mListener.onAlloc(p, size, alignment, 0);
return p;
}
// Allocate an array of trivially destructible objects
// for safety, we disable the object-based alloc method if the object type is not
// trivially destructible, since free() won't call the destructor and this is allocating
// an array.
template <typename T,
typename = typename std::enable_if<std::is_trivially_destructible<T>::value>::type>
T* alloc(size_t count, size_t alignment = alignof(T), size_t extra = 0) noexcept {
T* alloc(size_t count, size_t alignment, size_t extra) noexcept {
return (T*)alloc(count * sizeof(T), alignment, extra);
}
// return memory pointed by p to the arena
// (actual behaviour may depend on allocator provided)
void free(void* p) noexcept {
template <typename T,
typename = typename std::enable_if<std::is_trivially_destructible<T>::value>::type>
T* alloc(size_t count, size_t alignment = alignof(T)) noexcept {
return (T*)alloc(count * sizeof(T), alignment);
}
// some allocators require more parameters
template<typename ... ARGS>
void free(void* p, size_t size, ARGS&& ... args) noexcept {
if (p) {
std::lock_guard<LockingPolicy> guard(mLock);
mListener.onFree(p);
mAllocator.free(p);
mListener.onFree(p, size);
mAllocator.free(p, size, std::forward<ARGS>(args) ...);
}
}
@@ -625,6 +744,16 @@ public:
}
}
// return memory pointed by p to the arena
// (actual behaviour may depend on allocator provided)
void free(void* p) noexcept {
if (p) {
std::lock_guard<LockingPolicy> guard(mLock);
mListener.onFree(p);
mAllocator.free(p);
}
}
// some allocators don't have a free() call, but a single reset() or rewind() instead
void reset() noexcept {
std::lock_guard<LockingPolicy> guard(mLock);
@@ -722,6 +851,8 @@ class ArenaScope {
}
public:
using Arena = ARENA;
explicit ArenaScope(ARENA& allocator)
: mArena(allocator), mRewind(allocator.getCurrent()) {
}
@@ -773,7 +904,7 @@ public:
}
// use with caution
ARENA& getAllocator() noexcept { return mArena; }
ARENA& getArena() noexcept { return mArena; }
private:
ARENA& mArena;
@@ -800,7 +931,7 @@ public:
public:
// we don't make this explicit, so that we can initialize a vector using a STLAllocator
// from an Arena, avoiding to have to repeat the vector type.
// from an Arena, avoiding having to repeat the vector type.
STLAllocator(ARENA& arena) : mArena(arena) { } // NOLINT(google-explicit-constructor)
template<typename U>

View File

@@ -17,13 +17,10 @@
#ifndef TNT_UTILS_BITMASKENUM_H
#define TNT_UTILS_BITMASKENUM_H
#include <utils/compiler.h>
#include <type_traits> // for std::false_type
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
namespace utils {

View File

@@ -35,7 +35,7 @@ struct hashCStrings {
typedef size_t result_type;
result_type operator()(argument_type cstr) const noexcept {
size_t hash = 5381;
while (int c = *cstr++) {
while (int const c = *cstr++) {
hash = (hash * 33u) ^ size_t(c);
}
return hash;
@@ -192,8 +192,8 @@ private:
};
int compare(const CString& rhs) const noexcept {
size_type lhs_size = size();
size_type rhs_size = rhs.size();
size_type const lhs_size = size();
size_type const rhs_size = rhs.size();
if (lhs_size < rhs_size) return -1;
if (lhs_size > rhs_size) return 1;
return strncmp(data(), rhs.data(), size());
@@ -225,6 +225,28 @@ private:
template<typename T>
CString to_string(T value) noexcept;
// ------------------------------------------------------------------------------------------------
template <size_t N>
class UTILS_PUBLIC FixedSizeString {
public:
using value_type = char;
using pointer = value_type*;
using const_pointer = const value_type*;
static_assert(N > 0);
FixedSizeString() noexcept = default;
explicit FixedSizeString(const char* str) noexcept {
strncpy(mData, str, N - 1); // leave room for the null terminator
}
const_pointer c_str() const noexcept { return mData; }
pointer c_str() noexcept { return mData; }
private:
value_type mData[N] = {0};
};
} // namespace utils
#endif // TNT_UTILS_CSTRING_H

View File

@@ -22,7 +22,8 @@
#include <typeinfo>
#include <utils/CString.h>
#include <utils/Log.h>
#include <utils/compiler.h>
#include <utils/ostream.h>
namespace utils {

View File

@@ -23,7 +23,6 @@
#include <stdint.h>
namespace utils {
class UTILS_PUBLIC EntityInstanceBase {
@@ -77,7 +76,7 @@ public:
// return a value for this Instance (mostly needed for debugging
constexpr uint32_t asValue() const noexcept { return mInstance; }
// auto convert to Type so it can be used as an index
// auto convert to Type, so it can be used as an index
constexpr operator Type() const noexcept { return mInstance; } // NOLINT(google-explicit-constructor)
// conversion from Type so we can initialize from an index

View File

@@ -17,12 +17,13 @@
#ifndef TNT_UTILS_ENTITYMANAGER_H
#define TNT_UTILS_ENTITYMANAGER_H
#include <assert.h>
#include <stdint.h>
#include <utils/Entity.h>
#include <utils/compiler.h>
#include <assert.h>
#include <stddef.h>
#include <stdint.h>
#ifndef FILAMENT_UTILS_TRACK_ENTITIES
#define FILAMENT_UTILS_TRACK_ENTITIES false
#endif
@@ -44,23 +45,25 @@ public:
public:
virtual void onEntitiesDestroyed(size_t n, Entity const* entities) noexcept = 0;
protected:
~Listener() noexcept;
virtual ~Listener() noexcept;
};
// maximum number of entities that can exist at the same time
static size_t getMaxEntityCount() noexcept {
// because index 0 is reserved, we only have 2^GENERATION_SHIFT - 1 valid indices
return RAW_INDEX_COUNT - 1;
}
// create n entities. Thread safe.
// number of active Entities
size_t getEntityCount() const noexcept;
// Create n entities. Thread safe.
void create(size_t n, Entity* entities);
// destroys n entities. Thread safe.
void destroy(size_t n, Entity* entities) noexcept;
// create a new Entity. Thread safe.
// Create a new Entity. Thread safe.
// Return Entity.isNull() if the entity cannot be allocated.
Entity create() {
Entity e;
@@ -68,20 +71,20 @@ public:
return e;
}
// destroys an Entity. Thread safe.
// Destroys an Entity. Thread safe.
void destroy(Entity e) noexcept {
destroy(1, &e);
}
// return whether the given Entity has been destroyed (false) or not (true).
// Return whether the given Entity has been destroyed (false) or not (true).
// Thread safe.
bool isAlive(Entity e) const noexcept {
assert(getIndex(e) < RAW_INDEX_COUNT);
return (!e.isNull()) && (getGeneration(e) == mGens[getIndex(e)]);
}
// registers a listener to be called when an entity is destroyed. thread safe.
// if the listener is already register, this method has no effect.
// Registers a listener to be called when an entity is destroyed. Thread safe.
// If the listener is already registered, this method has no effect.
void registerListener(Listener* l) noexcept;
// unregisters a listener.
@@ -94,6 +97,7 @@ public:
uint8_t getGenerationForIndex(size_t index) const noexcept {
return mGens[index];
}
// singleton, can't be copied
EntityManager(const EntityManager& rhs) = delete;
EntityManager& operator=(const EntityManager& rhs) = delete;

View File

@@ -17,16 +17,18 @@
#ifndef TNT_UTILS_FIXEDCAPACITYVECTOR_H
#define TNT_UTILS_FIXEDCAPACITYVECTOR_H
#include <utils/compiler.h>
#include <utils/compressed_pair.h>
#include <utils/Panic.h>
#include <initializer_list>
#include <iterator>
#include <limits>
#include <memory>
#include <type_traits>
#include <utility>
#include <vector> // TODO: is this necessary?
#include <assert.h>
#include <stddef.h>
#include <stdint.h>

View File

@@ -24,7 +24,6 @@
#include <utils/SingleInstanceComponentManager.h>
#include <stddef.h>
#include <stdint.h>
namespace utils {
@@ -48,7 +47,7 @@ class EntityManager;
* printf("%s\n", names->getName(names->getInstance(myEntity));
* ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
*/
class UTILS_PUBLIC NameComponentManager : public SingleInstanceComponentManager<utils::CString> {
class UTILS_PUBLIC NameComponentManager : private SingleInstanceComponentManager<utils::CString> {
public:
using Instance = EntityInstance<NameComponentManager>;
@@ -75,15 +74,6 @@ public:
return { SingleInstanceComponentManager::getInstance(e) };
}
/*! \cond PRIVATE */
// these are implemented in SingleInstanceComponentManager<>, but we need to
// reimplement them in each manager, to ensure they are generated in an implementation file
// for backward binary compatibility reasons.
size_t getComponentCount() const noexcept;
Entity const* getEntities() const noexcept;
void gc(const EntityManager& em, size_t ratio = 4) noexcept;
/*! \endcond */
/**
* Adds a name component to the given entity if it doesn't already exist.
*/
@@ -105,6 +95,12 @@ public:
* @return pointer to the copy that was made during setName()
*/
const char* getName(Instance instance) const noexcept;
void gc(EntityManager& em) noexcept {
SingleInstanceComponentManager<utils::CString>::gc(em, [this](Entity e) {
removeComponent(e);
});
}
};
} // namespace utils

View File

@@ -17,11 +17,11 @@
#ifndef TNT_UTILS_PANIC_H
#define TNT_UTILS_PANIC_H
#include <string>
#include <utils/CallStack.h>
#include <utils/compiler.h>
#include <string>
#ifdef __EXCEPTIONS
# define UTILS_EXCEPTIONS 1
#else

View File

@@ -17,8 +17,6 @@
#ifndef UTILS_PRIVATEIMPLEMENTATION_H
#define UTILS_PRIVATEIMPLEMENTATION_H
#include <utils/compiler.h>
#include <stddef.h>
namespace utils {

View File

@@ -98,7 +98,7 @@ public:
return pos != map.end() ? pos->second : 0;
}
// returns the number of components (i.e. size of each arrays)
// Returns the number of components (i.e. size of each array)
size_t getComponentCount() const noexcept {
// The array as an extra dummy component at index 0, so the visible count is 1 less.
return mData.size() - 1;
@@ -108,11 +108,8 @@ public:
return getComponentCount() == 0;
}
// returns a pointer to the Entity array. This is basically the list
// of entities this component manager handles.
// The pointer becomes invalid when adding or removing a component.
Entity const* getEntities() const noexcept {
return begin<ENTITY_INDEX>();
utils::Entity const* getEntities() const noexcept {
return data<ENTITY_INDEX>() + 1;
}
Entity getEntity(Instance i) const noexcept {
@@ -128,14 +125,6 @@ public:
// This invalidates all pointers components.
inline Instance removeComponent(Entity e);
// trigger one round of garbage collection. this is intended to be called on a regular
// basis. This gc gives up after it cannot randomly free 'ratio' component in a row.
void gc(const EntityManager& em, size_t ratio = 4) noexcept {
gc(em, ratio, [this](Entity e) {
removeComponent(e);
});
}
// return the first instance
Instance begin() const noexcept { return 1u; }
@@ -234,24 +223,33 @@ protected:
}
}
template<typename REMOVE>
void gc(const EntityManager& em,
REMOVE&& removeComponent) noexcept {
gc(em, 4, std::forward<REMOVE>(removeComponent));
}
template<typename REMOVE>
void gc(const EntityManager& em, size_t ratio,
REMOVE removeComponent) noexcept {
Entity const* entities = getEntities();
REMOVE&& removeComponent) noexcept {
Entity const* const pEntities = begin<ENTITY_INDEX>();
size_t count = getComponentCount();
size_t aliveInARow = 0;
default_random_engine& rng = mRng;
UTILS_NOUNROLL
while (count && aliveInARow < ratio) {
assert_invariant(count == getComponentCount());
// note: using the modulo favorizes lower number
size_t i = rng() % count;
if (UTILS_LIKELY(em.isAlive(entities[i]))) {
size_t const i = rng() % count;
Entity const entity = pEntities[i];
assert_invariant(entity);
if (UTILS_LIKELY(em.isAlive(entity))) {
++aliveInARow;
continue;
}
removeComponent(entity);
aliveInARow = 0;
count--;
removeComponent(entities[i]);
}
}

View File

@@ -1,90 +0,0 @@
/*
* Copyright (C) 2019 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_UTILS_SPINLOCK_H
#define TNT_UTILS_SPINLOCK_H
#include <utils/compiler.h>
#include <utils/Mutex.h>
#include <atomic>
#include <type_traits>
#include <assert.h>
#include <stddef.h>
namespace utils {
namespace details {
class SpinLock {
std::atomic_flag mLock = ATOMIC_FLAG_INIT;
public:
void lock() noexcept {
UTILS_PREFETCHW(&mLock);
#ifdef __ARM_ACLE
// we signal an event on this CPU, so that the first yield() will be a no-op,
// and falls through the test_and_set(). This is more efficient than a while { }
// construct.
UTILS_SIGNAL_EVENT();
do {
yield();
} while (mLock.test_and_set(std::memory_order_acquire));
#else
goto start;
do {
yield();
start: ;
} while (mLock.test_and_set(std::memory_order_acquire));
#endif
}
void unlock() noexcept {
mLock.clear(std::memory_order_release);
#ifdef __ARM_ARCH_7A__
// on ARMv7a SEL is needed
UTILS_SIGNAL_EVENT();
// as well as a memory barrier is needed
__dsb(0xA); // ISHST = 0xA (b1010)
#else
// on ARMv8 we could avoid the call to SE, but we'd need to write the
// test_and_set() above by hand, so the WFE only happens without a STRX first.
UTILS_BROADCAST_EVENT();
#endif
}
private:
inline void yield() noexcept {
// on x86 call pause instruction, on ARM call WFE
UTILS_WAIT_FOR_EVENT();
}
};
} // namespace details
#if UTILS_HAS_SANITIZE_THREAD
// Active spins with atomics slow down execution too much under ThreadSanitizer.
using SpinLock = Mutex;
#elif defined(__ARM_ARCH_7A__)
// We've had problems with "wfe" on some ARM-V7 devices, causing spurious SIGILL
using SpinLock = Mutex;
#else
using SpinLock = details::SpinLock;
#endif
} // namespace utils
#endif // TNT_UTILS_SPINLOCK_H

View File

@@ -17,8 +17,10 @@
#ifndef TNT_UTILS_STRUCTUREOFARRAYS_H
#define TNT_UTILS_STRUCTUREOFARRAYS_H
#include <type_traits>
#include <utils/Allocator.h>
#include <utils/compiler.h>
#include <utils/debug.h>
#include <utils/Slice.h>
#include <stddef.h>
@@ -352,33 +354,55 @@ public:
return push_back_unsafe(std::forward<Elements>(args)...);
}
// in C++20 we could use a lambda with explicit template parameter instead
struct PushBackUnsafeClosure {
size_t last;
std::tuple<Elements...> args;
inline explicit PushBackUnsafeClosure(size_t last, Structure&& args)
: last(last), args(std::forward<Structure>(args)) {}
template<size_t I>
inline void operator()(TypeAt<I>* p) {
new(p + last) TypeAt<I>{ std::get<I>(args) };
}
};
template <std::size_t... Indices>
struct ElementIndices {};
template <std::size_t N, std::size_t... Indices>
struct BuildElementIndices : BuildElementIndices<N - 1, N - 1, Indices...> {};
template <std::size_t... Indices>
struct BuildElementIndices<0, Indices...> : ElementIndices<Indices...> {};
template<std::size_t... Indices>
void push_back_unsafe(Structure&& args, ElementIndices<Indices...>){
size_t last = mSize++;
// Fold expression on the comma operator
([&]{
new(std::get<Indices>(mArrays) + last) Elements{std::get<Indices>(args)};
}() , ...);
}
template<std::size_t... Indices>
void push_back_unsafe(Elements const& ... args, ElementIndices<Indices...>){
size_t last = mSize++;
// Fold expression on the comma operator
([&]{
new(std::get<Indices>(mArrays) + last) Elements{args};
}() , ...);
}
template<std::size_t... Indices>
void push_back_unsafe(Elements && ... args, ElementIndices<Indices...>){
size_t last = mSize++;
// Fold expression on the comma operator
([&]{
new(std::get<Indices>(mArrays) + last) Elements{std::forward<Elements>(args)};
}() , ...);
}
StructureOfArraysBase& push_back_unsafe(Structure&& args) noexcept {
for_each_index(mArrays,
PushBackUnsafeClosure{ mSize++, std::forward<Structure>(args) });
push_back_unsafe(std::forward<Structure>(args), BuildElementIndices<sizeof...(Elements)>{});
return *this;
}
StructureOfArraysBase& push_back_unsafe(Elements const& ... args) noexcept {
for_each_index(mArrays,
PushBackUnsafeClosure{ mSize++, { args... } });
push_back_unsafe(args..., BuildElementIndices<sizeof...(Elements)>{});
return *this;
}
StructureOfArraysBase& push_back_unsafe(Elements&& ... args) noexcept {
for_each_index(mArrays,
PushBackUnsafeClosure{ mSize++, { std::forward<Elements>(args)... }});
push_back_unsafe(std::forward<Elements>(args)..., BuildElementIndices<sizeof...(Elements)>{});
return *this;
}
@@ -533,7 +557,7 @@ private:
}
inline void resizeNoCheck(size_t needed) noexcept {
assert(mCapacity >= needed);
assert_invariant(mCapacity >= needed);
if (needed < mSize) {
// we shrink the arrays
destroy_each(needed, mSize);

View File

@@ -1,242 +0,0 @@
/*
* Copyright (C) 2023 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_UTILS_ANDROID_SYSTRACE_H
#define TNT_UTILS_ANDROID_SYSTRACE_H
#include <atomic>
#include <stdint.h>
#include <stdio.h>
#include <unistd.h>
#include <utils/compiler.h>
// enable tracing
#define SYSTRACE_ENABLE() ::utils::details::Systrace::enable(SYSTRACE_TAG)
// disable tracing
#define SYSTRACE_DISABLE() ::utils::details::Systrace::disable(SYSTRACE_TAG)
/**
* Creates a Systrace context in the current scope. needed for calling all other systrace
* commands below.
*/
#define SYSTRACE_CONTEXT() ::utils::details::Systrace ___trctx(SYSTRACE_TAG)
// SYSTRACE_NAME traces the beginning and end of the current scope. To trace
// the correct start and end times this macro should be declared first in the
// scope body.
// It also automatically creates a Systrace context
#define SYSTRACE_NAME(name) ::utils::details::ScopedTrace ___tracer(SYSTRACE_TAG, name)
// Denotes that a new frame has started processing.
#define SYSTRACE_FRAME_ID(frame) \
{ /* scope for frame id trace */ \
char buf[64]; \
snprintf(buf, 64, "frame %u", frame); \
SYSTRACE_NAME(buf); \
}
// SYSTRACE_CALL is an SYSTRACE_NAME that uses the current function name.
#define SYSTRACE_CALL() SYSTRACE_NAME(__FUNCTION__)
#define SYSTRACE_NAME_BEGIN(name) \
___trctx.traceBegin(SYSTRACE_TAG, name)
#define SYSTRACE_NAME_END() \
___trctx.traceEnd(SYSTRACE_TAG)
/**
* Trace the beginning of an asynchronous event. Unlike ATRACE_BEGIN/ATRACE_END
* contexts, asynchronous events do not need to be nested. The name describes
* the event, and the cookie provides a unique identifier for distinguishing
* simultaneous events. The name and cookie used to begin an event must be
* used to end it.
*/
#define SYSTRACE_ASYNC_BEGIN(name, cookie) \
___trctx.asyncBegin(SYSTRACE_TAG, name, cookie)
/**
* Trace the end of an asynchronous event.
* This should have a corresponding SYSTRACE_ASYNC_BEGIN.
*/
#define SYSTRACE_ASYNC_END(name, cookie) \
___trctx.asyncEnd(SYSTRACE_TAG, name, cookie)
/**
* Traces an integer counter value. name is used to identify the counter.
* This can be used to track how a value changes over time.
*/
#define SYSTRACE_VALUE32(name, val) \
___trctx.value(SYSTRACE_TAG, name, int32_t(val))
#define SYSTRACE_VALUE64(name, val) \
___trctx.value(SYSTRACE_TAG, name, int64_t(val))
// ------------------------------------------------------------------------------------------------
// No user serviceable code below...
// ------------------------------------------------------------------------------------------------
namespace utils {
namespace details {
class Systrace {
public:
enum tags {
NEVER = SYSTRACE_TAG_NEVER,
ALWAYS = SYSTRACE_TAG_ALWAYS,
FILAMENT = SYSTRACE_TAG_FILAMENT,
JOBSYSTEM = SYSTRACE_TAG_JOBSYSTEM
// we could define more TAGS here, as we need them.
};
explicit Systrace(uint32_t tag) noexcept {
if (tag) init(tag);
}
static void enable(uint32_t tags) noexcept;
static void disable(uint32_t tags) noexcept;
inline void traceBegin(uint32_t tag, const char* name) noexcept {
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
beginSection(this, name);
}
}
inline void traceEnd(uint32_t tag) noexcept {
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
endSection(this);
}
}
inline void asyncBegin(uint32_t tag, const char* name, int32_t cookie) noexcept {
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
beginAsyncSection(this, name, cookie);
}
}
inline void asyncEnd(uint32_t tag, const char* name, int32_t cookie) noexcept {
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
endAsyncSection(this, name, cookie);
}
}
inline void value(uint32_t tag, const char* name, int32_t value) noexcept {
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
setCounter(this, name, value);
}
}
inline void value(uint32_t tag, const char* name, int64_t value) noexcept {
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
setCounter(this, name, value);
}
}
private:
friend class ScopedTrace;
// whether tracing is supported at all by the platform
using ATrace_isEnabled_t = bool (*)();
using ATrace_beginSection_t = void (*)(const char* sectionName);
using ATrace_endSection_t = void (*)();
using ATrace_beginAsyncSection_t = void (*)(const char* sectionName, int32_t cookie);
using ATrace_endAsyncSection_t = void (*)(const char* sectionName, int32_t cookie);
using ATrace_setCounter_t = void (*)(const char* counterName, int64_t counterValue);
struct GlobalState {
bool isTracingAvailable;
std::atomic<uint32_t> isTracingEnabled;
int markerFd;
ATrace_isEnabled_t ATrace_isEnabled;
ATrace_beginSection_t ATrace_beginSection;
ATrace_endSection_t ATrace_endSection;
ATrace_beginAsyncSection_t ATrace_beginAsyncSection;
ATrace_endAsyncSection_t ATrace_endAsyncSection;
ATrace_setCounter_t ATrace_setCounter;
void (*beginSection)(Systrace* that, const char* name);
void (*endSection)(Systrace* that);
void (*beginAsyncSection)(Systrace* that, const char* name, int32_t cookie);
void (*endAsyncSection)(Systrace* that, const char* name, int32_t cookie);
void (*setCounter)(Systrace* that, const char* name, int64_t value);
};
static GlobalState sGlobalState;
// per-instance versions for better performance
ATrace_isEnabled_t ATrace_isEnabled;
ATrace_beginSection_t ATrace_beginSection;
ATrace_endSection_t ATrace_endSection;
ATrace_beginAsyncSection_t ATrace_beginAsyncSection;
ATrace_endAsyncSection_t ATrace_endAsyncSection;
ATrace_setCounter_t ATrace_setCounter;
void (*beginSection)(Systrace* that, const char* name);
void (*endSection)(Systrace* that);
void (*beginAsyncSection)(Systrace* that, const char* name, int32_t cookie);
void (*endAsyncSection)(Systrace* that, const char* name, int32_t cookie);
void (*setCounter)(Systrace* that, const char* name, int64_t value);
void init(uint32_t tag) noexcept;
// cached values for faster access, no need to be initialized
bool mIsTracingEnabled;
int mMarkerFd = -1;
pid_t mPid;
static void setup() noexcept;
static void init_once() noexcept;
static bool isTracingEnabled(uint32_t tag) noexcept;
static void begin_body(int fd, int pid, const char* name) noexcept;
static void end_body(int fd, int pid) noexcept;
static void async_begin_body(int fd, int pid, const char* name, int32_t cookie) noexcept;
static void async_end_body(int fd, int pid, const char* name, int32_t cookie) noexcept;
static void int64_body(int fd, int pid, const char* name, int64_t value) noexcept;
};
// ------------------------------------------------------------------------------------------------
class ScopedTrace {
public:
// we don't inline this because it's relatively heavy due to a global check
ScopedTrace(uint32_t tag, const char* name) noexcept: mTrace(tag), mTag(tag) {
mTrace.traceBegin(tag, name);
}
inline ~ScopedTrace() noexcept {
mTrace.traceEnd(mTag);
}
private:
Systrace mTrace;
const uint32_t mTag;
};
} // namespace details
} // namespace utils
#endif // TNT_UTILS_ANDROID_SYSTRACE_H

View File

@@ -1,60 +0,0 @@
/*
* Copyright (C) 2022 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_UTILS_ANDROID_THERMALMANAGER_H
#define TNT_UTILS_ANDROID_THERMALMANAGER_H
#include <utils/compiler.h>
#include <stdint.h>
struct AThermalManager;
namespace utils {
class ThermalManager {
public:
enum class ThermalStatus : int8_t {
ERROR = -1,
NONE,
LIGHT,
MODERATE,
SEVERE,
CRITICAL,
EMERGENCY,
SHUTDOWN
};
ThermalManager();
~ThermalManager();
// Movable
ThermalManager(ThermalManager&& rhs) noexcept;
ThermalManager& operator=(ThermalManager&& rhs) noexcept;
// not copiable
ThermalManager(ThermalManager const& rhs) = delete;
ThermalManager& operator=(ThermalManager const& rhs) = delete;
ThermalStatus getCurrentThermalStatus() const noexcept;
private:
AThermalManager* mThermalManager = nullptr;
};
} // namespace utils
#endif // TNT_UTILS_ANDROID_THERMALMANAGER_H

View File

@@ -179,6 +179,14 @@
# define UTILS_HAS_FEATURE_CXX_THREAD_LOCAL 0
#endif
#if defined(__clang__)
#define UTILS_NONNULL _Nonnull
#define UTILS_NULLABLE _Nullable
#else
#define UTILS_NONNULL
#define UTILS_NULLABLE
#endif
#if defined(_MSC_VER)
// MSVC does not support loop unrolling hints
# define UTILS_UNROLL

View File

@@ -1,123 +0,0 @@
/*
* Copyright (C) 2016 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_UTILS_LINUX_CONDITION_H
#define TNT_UTILS_LINUX_CONDITION_H
#include <atomic>
#include <chrono>
#include <condition_variable> // for cv_status
#include <limits>
#include <mutex> // for unique_lock
#include <utils/linux/Mutex.h>
#include <time.h>
namespace utils {
/*
* A very simple condition variable class that can be used as an (almost) drop-in replacement
* for std::condition_variable (doesn't have the timed wait() though).
* It is very low overhead as most of it is inlined.
*/
class Condition {
public:
Condition() noexcept = default;
Condition(const Condition&) = delete;
Condition& operator=(const Condition&) = delete;
void notify_all() noexcept {
pulse(std::numeric_limits<int>::max());
}
void notify_one() noexcept {
pulse(1);
}
void notify_n(size_t n) noexcept {
if (n > 0) pulse(n);
}
void wait(std::unique_lock<Mutex>& lock) noexcept {
wait_until(lock.mutex(), false, nullptr);
}
template <class P>
void wait(std::unique_lock<Mutex>& lock, P predicate) {
while (!predicate()) {
wait(lock);
}
}
template<typename D>
std::cv_status wait_until(std::unique_lock<Mutex>& lock,
const std::chrono::time_point<std::chrono::steady_clock, D>& timeout_time) noexcept {
// convert to nanoseconds
uint64_t ns = std::chrono::duration<uint64_t, std::nano>(timeout_time.time_since_epoch()).count();
using sec_t = decltype(timespec::tv_sec);
using nsec_t = decltype(timespec::tv_nsec);
timespec ts{ sec_t(ns / 1000000000), nsec_t(ns % 1000000000) };
return wait_until(lock.mutex(), false, &ts);
}
template<typename D>
std::cv_status wait_until(std::unique_lock<Mutex>& lock,
const std::chrono::time_point<std::chrono::system_clock, D>& timeout_time) noexcept {
// convert to nanoseconds
uint64_t ns = std::chrono::duration<uint64_t, std::nano>(timeout_time.time_since_epoch()).count();
using sec_t = decltype(timespec::tv_sec);
using nsec_t = decltype(timespec::tv_nsec);
timespec ts{ sec_t(ns / 1000000000), nsec_t(ns % 1000000000) };
return wait_until(lock.mutex(), true, &ts);
}
template<typename C, typename D, typename P>
bool wait_until(std::unique_lock<Mutex>& lock,
const std::chrono::time_point<C, D>& timeout_time, P predicate) noexcept {
while (!predicate()) {
if (wait_until(lock, timeout_time) == std::cv_status::timeout) {
return predicate();
}
}
return true;
}
template<typename R, typename Period>
std::cv_status wait_for(std::unique_lock<Mutex>& lock,
const std::chrono::duration<R, Period>& rel_time) noexcept {
return wait_until(lock, std::chrono::steady_clock::now() + rel_time);
}
template<typename R, typename Period, typename P>
bool wait_for(std::unique_lock<Mutex>& lock,
const std::chrono::duration<R, Period>& rel_time, P pred) noexcept {
return wait_until(lock, std::chrono::steady_clock::now() + rel_time, std::move(pred));
}
private:
std::atomic<uint32_t> mState = { 0 };
void pulse(int threadCount) noexcept;
std::cv_status wait_until(Mutex* lock,
bool realtimeClock, timespec* ts) noexcept;
};
} // namespace utils
#endif // TNT_UTILS_LINUX_CONDITION_H

View File

@@ -1,64 +0,0 @@
/*
* Copyright (C) 2016 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_UTILS_LINUX_MUTEX_H
#define TNT_UTILS_LINUX_MUTEX_H
#include <atomic>
#include <utils/compiler.h>
namespace utils {
/*
* A very simple mutex class that can be used as an (almost) drop-in replacement
* for std::mutex.
* It is very low overhead as most of it is inlined.
*/
class Mutex {
public:
constexpr Mutex() noexcept = default;
Mutex(const Mutex&) = delete;
Mutex& operator=(const Mutex&) = delete;
void lock() noexcept {
uint32_t old_state = UNLOCKED;
if (UTILS_UNLIKELY(!mState.compare_exchange_strong(old_state,
LOCKED, std::memory_order_acquire, std::memory_order_relaxed))) {
wait();
}
}
void unlock() noexcept {
if (UTILS_UNLIKELY(mState.exchange(UNLOCKED, std::memory_order_release) == LOCKED_CONTENDED)) {
wake();
}
}
private:
enum {
UNLOCKED = 0, LOCKED = 1, LOCKED_CONTENDED = 2
};
std::atomic<uint32_t> mState = { UNLOCKED };
void wait() noexcept;
void wake() noexcept;
};
} // namespace utils
#endif // TNT_UTILS_LINUX_MUTEX_H

View File

@@ -29,7 +29,7 @@ namespace utils::io {
struct ostream_;
class UTILS_PUBLIC ostream : protected utils::PrivateImplementation<ostream_> {
class UTILS_PUBLIC ostream : protected utils::PrivateImplementation<ostream_> {
friend struct ostream_;
public:
@@ -69,6 +69,13 @@ public:
ostream& dec() noexcept;
ostream& hex() noexcept;
/*! @cond PRIVATE */
// Sets a consumer of the log. The consumer is invoked on flush() and replaces the default.
// Thread safe and reentrant.
using ConsumerCallback = void(*)(void*, char const*);
void setConsumer(ConsumerCallback consumer, void* user) noexcept;
/*! @endcond */
protected:
ostream& print(const char* format, ...) noexcept;
@@ -85,6 +92,7 @@ protected:
std::pair<char*, size_t> grow(size_t s) noexcept;
void advance(ssize_t n) noexcept;
void reset() noexcept;
size_t length() const noexcept;
private:
void reserve(size_t newSize) noexcept;
@@ -104,7 +112,7 @@ private:
friend ostream& hex(ostream& s) noexcept;
friend ostream& dec(ostream& s) noexcept;
friend ostream& endl(ostream& s) noexcept;
friend ostream& flush(ostream& s) noexcept;
UTILS_PUBLIC friend ostream& flush(ostream& s) noexcept;
enum type {
SHORT, USHORT, CHAR, UCHAR, INT, UINT, LONG, ULONG, LONG_LONG, ULONG_LONG, FLOAT, DOUBLE,
@@ -132,8 +140,7 @@ inline ostream& operator<<(ostream& stream, const VECTOR<T>& v) {
inline ostream& hex(ostream& s) noexcept { return s.hex(); }
inline ostream& dec(ostream& s) noexcept { return s.dec(); }
inline ostream& endl(ostream& s) noexcept { s << '\n'; return s.flush(); }
inline ostream& flush(ostream& s) noexcept { return s.flush(); }
inline ostream& endl(ostream& s) noexcept { return flush(s << '\n'); }
} // namespace utils::io

View File

@@ -57,8 +57,10 @@ enum class ToneMapping : uint8_t {
ACES_LEGACY = 1,
ACES = 2,
FILMIC = 3,
GENERIC = 4,
DISPLAY_RANGE = 5,
AGX = 4,
GENERIC = 5,
PBR_NEUTRAL = 6,
DISPLAY_RANGE = 7,
};
using AmbientOcclusionOptions = filament::View::AmbientOcclusionOptions;
@@ -76,6 +78,7 @@ using TemporalAntiAliasingOptions = filament::View::TemporalAntiAliasingOptions;
using VignetteOptions = filament::View::VignetteOptions;
using VsmShadowOptions = filament::View::VsmShadowOptions;
using GuardBandOptions = filament::View::GuardBandOptions;
using StereoscopicOptions = filament::View::StereoscopicOptions;
using LightManager = filament::LightManager;
// These functions push all editable property values to their respective Filament objects.
@@ -114,8 +117,14 @@ struct GenericToneMapperSettings {
float midGrayIn = 0.18f;
float midGrayOut = 0.215f;
float hdrMax = 10.0f;
bool operator!=(const GenericToneMapperSettings &rhs) const { return !(rhs == *this); }
bool operator==(const GenericToneMapperSettings &rhs) const;
bool operator!=(const GenericToneMapperSettings& rhs) const { return !(rhs == *this); }
bool operator==(const GenericToneMapperSettings& rhs) const;
};
struct AgxToneMapperSettings {
AgxToneMapper::AgxLook look = AgxToneMapper::AgxLook::NONE;
bool operator!=(const AgxToneMapperSettings& rhs) const { return !(rhs == *this); }
bool operator==(const AgxToneMapperSettings& rhs) const;
};
struct ColorGradingSettings {
@@ -127,7 +136,7 @@ struct ColorGradingSettings {
filament::ColorGrading::QualityLevel quality = filament::ColorGrading::QualityLevel::MEDIUM;
ToneMapping toneMapping = ToneMapping::ACES_LEGACY;
bool padding0{};
bool padding1{};
AgxToneMapperSettings agxToneMapper;
color::ColorSpace colorspace = Rec709-sRGB-D65;
GenericToneMapperSettings genericToneMapper;
math::float4 shadows{1.0f, 1.0f, 1.0f, 0.0f};
@@ -185,6 +194,7 @@ struct ViewSettings {
VignetteOptions vignette;
VsmShadowOptions vsmShadowOptions;
GuardBandOptions guardBand;
StereoscopicOptions stereoscopicOptions;
// Custom View Options
ColorGradingSettings colorGrading;
@@ -224,6 +234,8 @@ struct ViewerOptions {
float cameraISO = 100.0f;
float cameraNear = 0.1f;
float cameraFar = 100.0f;
float cameraEyeOcularDistance = 0.0f;
float cameraEyeToeIn = 0.0f;
float groundShadowStrength = 0.75f;
bool groundPlaneEnabled = false;
bool skyboxEnabled = true;

View File

@@ -103,7 +103,7 @@ public:
*
* This removes all the asset entities from the Scene, but does not destroy them.
*/
void removeEntity();
void removeAsset();
/**
* Sets or changes the current scene's IBL to allow the UI manipulate it.
@@ -227,12 +227,10 @@ public:
*/
Settings& getSettings() { return mSettings; }
void stopAnimation() { mCurrentAnimation = 0; }
void stopAnimation() { mCurrentAnimation = -1; }
int getCurrentCamera() const { return mCurrentCamera; }
float getOcularDistance() const { return mOcularDistance; }
private:
using SceneMask = gltfio::NodeManager::SceneMask;
@@ -256,7 +254,7 @@ private:
std::function<void()> mCustomUI;
// Properties that can be changed from the UI.
int mCurrentAnimation = 1; // It is a 1-based index and 0 means not playing animation
int mCurrentAnimation = 0; // -1 means not playing animation and count means plays all of them (0-based index)
int mCurrentVariant = 0;
bool mEnableWireframe = false;
int mVsmMsaaSamplesLog2 = 1;
@@ -268,15 +266,12 @@ private:
SceneMask mVisibleScenes;
bool mShowingRestPose = false;
// Stereoscopic debugging
float mOcularDistance = 0.0f;
// 0 is the default "free camera". Additional cameras come from the gltf file (1-based index).
int mCurrentCamera = 0;
// Cross fade animation parameters.
float mCrossFadeDuration = 0.5f; // number of seconds to transition between animations
int mPreviousAnimation = 0; // one-based index of the previous animation
int mPreviousAnimation = -1; // zero-based index of the previous animation
double mCurrentStartTime = 0.0f; // start time of most recent cross-fade (seconds)
double mPreviousStartTime = 0.0f; // start time of previous cross-fade (seconds)
bool mResetAnimation = true; // set when building ImGui widgets, honored in applyAnimation

View File

@@ -8,5 +8,5 @@ GIZMO_PACKAGE:
GIZMO_GIZMO_OFFSET:
.int 0
GIZMO_GIZMO_SIZE:
.int 36180
.int 26876

View File

@@ -8,5 +8,5 @@ _GIZMO_PACKAGE:
_GIZMO_GIZMO_OFFSET:
.int 0
_GIZMO_GIZMO_SIZE:
.int 36180
.int 26876

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:86a501c75fa0fcc20442a4fedbfe7a4e11502de16c8c80001e51a3a7804dc557
size 36180
oid sha256:f51fc0e67176e28fdf75f351834fa1d36b0993be066d5685eef10aa30ae68b1b
size 26876

File diff suppressed because it is too large Load Diff

View File

@@ -8,5 +8,5 @@ IMAGE_PACKAGE:
IMAGE_IMAGE_OFFSET:
.int 0
IMAGE_IMAGE_SIZE:
.int 51248
.int 37409

View File

@@ -8,5 +8,5 @@ _IMAGE_PACKAGE:
_IMAGE_IMAGE_OFFSET:
.int 0
_IMAGE_IMAGE_SIZE:
.int 51248
.int 37409

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:8769c6c04cadfee474655affa993670b60515a1cae26e41002c3ac3191751b24
size 51248
oid sha256:e709d2481f88bf81153a316c0e118f03e89dc7fe99272091d6884ceaac4233ff
size 37409

File diff suppressed because it is too large Load Diff

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:47ca0627f9dcc3c6336584c465e88065f7f07c5605bcb7402c0108c37e099ac5
size 30032312
oid sha256:78b799b769ddf2e3cfe091f81a2a1b7252c9c974b0d8839b2de02eac8ca98e88
size 3039272

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:e2f525755974f4eac7c7f0d1a0a193b3500906e6a079c3c249f43fc93050f2e3
size 958048
oid sha256:7b23944a06b713b016c679d0b257d21b5afdc940cfd60bcc3f23f32df14d6c6f
size 908192

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:45c1a36d9e1aac908e02d7b2b012e091409bdd28e93bfe423215426680e07a57
size 211392
oid sha256:3f4f9540df738e6519183de4fc91a89e37e36f0124c58c40c62f237771c73d96
size 79976

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:7c6b2eba6dc2d06ea00d005cf236d6d642d432d2c6e068538da1d4c3f162f07e
size 976448
oid sha256:1700aa159e33a3de9f31f0178f1006530dafc31d1ca711ee9999ebce350602b1
size 601384

View File

@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:2cb772adfb95a6d891674b374da4a4f465c115e669457a3267d7f4ff6303fb13
size 49949568
oid sha256:407e8e491ab34435cd018f437929d8c54021c878361c2002ed9f1d367298e853
size 4018752

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