Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
ea428a27d1 | ||
|
|
3bef718238 | ||
|
|
298e54c32a | ||
|
|
4c82f0259d | ||
|
|
d0c043c7ff | ||
|
|
20cbecfd7c | ||
|
|
194defdb1b |
@@ -31,7 +31,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation 'com.google.android.filament:filament-android:1.31.2'
|
||||
implementation 'com.google.android.filament:filament-android:1.31.3'
|
||||
}
|
||||
```
|
||||
|
||||
@@ -51,7 +51,7 @@ Here are all the libraries available in the group `com.google.android.filament`:
|
||||
iOS projects can use CocoaPods to install the latest release:
|
||||
|
||||
```
|
||||
pod 'Filament', '~> 1.31.2'
|
||||
pod 'Filament', '~> 1.31.3'
|
||||
```
|
||||
|
||||
### Snapshots
|
||||
|
||||
@@ -5,6 +5,11 @@ A new header is inserted each time a *tag* is created.
|
||||
|
||||
## main branch
|
||||
|
||||
## v1.31.3
|
||||
|
||||
- vulkan: fix memory leak in readPixels
|
||||
- engine: added support for draw-commands channels (stronger ordering of commands/renderables)
|
||||
|
||||
## v1.31.2
|
||||
|
||||
## v1.31.1
|
||||
|
||||
@@ -150,6 +150,13 @@ Java_com_google_android_filament_RenderableManager_nBuilderPriority(JNIEnv*, jcl
|
||||
builder->priority((uint8_t) priority);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nBuilderChannel(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jint channel) {
|
||||
RenderableManager::Builder *builder = (RenderableManager::Builder *) nativeBuilder;
|
||||
builder->channel((uint8_t) channel);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nBuilderCulling(JNIEnv*, jclass,
|
||||
jlong nativeBuilder, jboolean enabled) {
|
||||
@@ -339,6 +346,13 @@ Java_com_google_android_filament_RenderableManager_nSetPriority(JNIEnv*, jclass,
|
||||
rm->setPriority((RenderableManager::Instance) i, (uint8_t) priority);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetChannel(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jint channel) {
|
||||
RenderableManager *rm = (RenderableManager *) nativeRenderableManager;
|
||||
rm->setChannel((RenderableManager::Instance) i, (uint8_t) channel);
|
||||
}
|
||||
|
||||
extern "C" JNIEXPORT void JNICALL
|
||||
Java_com_google_android_filament_RenderableManager_nSetCulling(JNIEnv*, jclass,
|
||||
jlong nativeRenderableManager, jint i, jboolean enabled) {
|
||||
|
||||
@@ -257,23 +257,74 @@ public class RenderableManager {
|
||||
* Provides coarse-grained control over draw order.
|
||||
*
|
||||
* <p>In general Filament reserves the right to re-order renderables to allow for efficient
|
||||
* rendering. However clients can control ordering at a coarse level using <em>priority</em>.</p>
|
||||
* rendering. However clients can control ordering at a coarse level using \em priority.
|
||||
* The priority is applied separately for opaque and translucent objects, that is, opaque
|
||||
* objects are always drawn before translucent objects regardless of the priority.</p>
|
||||
*
|
||||
* <p>For example, this could be used to draw a semitransparent HUD, if a client wishes to
|
||||
* avoid using a separate View for the HUD. Note that priority is completely orthogonal to
|
||||
* {@link Builder#layerMask}, which merely controls visibility.</p>
|
||||
|
||||
* <p>The Skybox always using the lowest priority, so it's drawn last, which may improve
|
||||
* performance.</p>
|
||||
*
|
||||
* <p>The priority is clamped to the range [0..7], defaults to 4; 7 is lowest priority
|
||||
* (rendered last).</p>
|
||||
*
|
||||
* @see Builder#blendOrder
|
||||
*/
|
||||
|
||||
/**
|
||||
* Provides coarse-grained control over draw order.
|
||||
*
|
||||
* <p>In general Filament reserves the right to re-order renderables to allow for efficient
|
||||
* rendering. However clients can control ordering at a coarse level using priority.
|
||||
* The priority is applied separately for opaque and translucent objects, that is, opaque
|
||||
* objects are always drawn before translucent objects regardless of the priority.</p>
|
||||
*
|
||||
* <p>For example, this could be used to draw a semitransparent HUD, if a client wishes to
|
||||
* avoid using a separate View for the HUD. Note that priority is completely orthogonal to
|
||||
* {@link Builder#layerMask}, which merely controls visibility.</p>
|
||||
|
||||
* <p>The Skybox always using the lowest priority, so it's drawn last, which may improve
|
||||
* performance.</p>
|
||||
*
|
||||
* @param priority clamped to the range [0..7], defaults to 4; 7 is lowest priority
|
||||
* (rendered last).
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
* @see Builder#channel
|
||||
* @see Builder#blendOrder
|
||||
* @see #setPriority
|
||||
* @see #setBlendOrderAt
|
||||
*/
|
||||
@NonNull
|
||||
public Builder priority(@IntRange(from = 0, to = 7) int priority) {
|
||||
nBuilderPriority(mNativeBuilder, priority);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the channel this renderable is associated to. There can be 4 channels.
|
||||
* All renderables in a given channel are rendered together, regardless of anything else.
|
||||
* They are sorted as usual withing a channel.
|
||||
* Channels work similarly to priorities, except that they enforce the strongest ordering.
|
||||
*
|
||||
* @param channel clamped to the range [0..3], defaults to 0.
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
* @see Builder::blendOrder()
|
||||
* @see Builder::priority()
|
||||
* @see RenderableManager::setBlendOrderAt()
|
||||
*/
|
||||
@NonNull
|
||||
public Builder channel(@IntRange(from = 0, to = 3) int channel) {
|
||||
nBuilderChannel(mNativeBuilder, channel);
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Controls frustum culling, true by default.
|
||||
*
|
||||
@@ -655,6 +706,15 @@ public class RenderableManager {
|
||||
nSetPriority(mNativeObject, i, priority);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the channel of a renderable
|
||||
*
|
||||
* @see Builder#channel
|
||||
*/
|
||||
public void setChannel(@EntityInstance int i, @IntRange(from = 0, to = 3) int channel) {
|
||||
nSetChannel(mNativeObject, i, channel);
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes whether or not frustum culling is on.
|
||||
*
|
||||
@@ -876,6 +936,7 @@ public class RenderableManager {
|
||||
private static native void nBuilderBoundingBox(long nativeBuilder, float cx, float cy, float cz, float ex, float ey, float ez);
|
||||
private static native void nBuilderLayerMask(long nativeBuilder, int select, int value);
|
||||
private static native void nBuilderPriority(long nativeBuilder, int priority);
|
||||
private static native void nBuilderChannel(long nativeBuilder, int channel);
|
||||
private static native void nBuilderCulling(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderCastShadows(long nativeBuilder, boolean enabled);
|
||||
private static native void nBuilderReceiveShadows(long nativeBuilder, boolean enabled);
|
||||
@@ -898,6 +959,7 @@ public class RenderableManager {
|
||||
private static native void nSetAxisAlignedBoundingBox(long nativeRenderableManager, int i, float cx, float cy, float cz, float ex, float ey, float ez);
|
||||
private static native void nSetLayerMask(long nativeRenderableManager, int i, int select, int value);
|
||||
private static native void nSetPriority(long nativeRenderableManager, int i, int priority);
|
||||
private static native void nSetChannel(long nativeRenderableManager, int i, int channel);
|
||||
private static native void nSetCulling(long nativeRenderableManager, int i, boolean enabled);
|
||||
private static native void nSetLightChannel(long nativeRenderableManager, int i, int channel, boolean enable);
|
||||
private static native boolean nGetLightChannel(long nativeRenderableManager, int i, int channel);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
GROUP=com.google.android.filament
|
||||
VERSION_NAME=1.31.2
|
||||
VERSION_NAME=1.31.3
|
||||
|
||||
POM_DESCRIPTION=Real-time physically based rendering engine for Android.
|
||||
|
||||
|
||||
@@ -65,7 +65,38 @@ VKAPI_ATTR VkBool32 VKAPI_CALL debugUtilsCallback(VkDebugUtilsMessageSeverityFla
|
||||
utils::slog.e << utils::io::endl;
|
||||
return VK_FALSE;
|
||||
}
|
||||
|
||||
// These strings need to be allocated outside a function stack
|
||||
const std::string_view DESIRED_LAYERS[] = {
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
#if FILAMENT_VULKAN_DUMP_API
|
||||
"VK_LAYER_LUNARG_api_dump",
|
||||
#endif
|
||||
#if defined(ENABLE_RENDERDOC)
|
||||
"VK_LAYER_RENDERDOC_Capture",
|
||||
#endif
|
||||
};
|
||||
|
||||
FixedCapacityVector<const char*> getEnabledLayers() {
|
||||
constexpr size_t kMaxEnabledLayersCount = sizeof(DESIRED_LAYERS) / sizeof(DESIRED_LAYERS[0]);
|
||||
|
||||
const FixedCapacityVector<VkLayerProperties> availableLayers = filament::backend::enumerate(
|
||||
vkEnumerateInstanceLayerProperties);
|
||||
|
||||
auto enabledLayers = FixedCapacityVector<const char*>::with_capacity(kMaxEnabledLayersCount);
|
||||
for (const auto& desired : DESIRED_LAYERS) {
|
||||
for (const VkLayerProperties& layer : availableLayers) {
|
||||
const std::string_view availableLayer(layer.layerName);
|
||||
if (availableLayer == desired) {
|
||||
enabledLayers.push_back(desired.data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return enabledLayers;
|
||||
}
|
||||
|
||||
#endif // VK_ENABLE_VALIDATION
|
||||
|
||||
void printDeviceInfo(VkInstance instance, VkPhysicalDevice device) {
|
||||
// Print some driver or MoltenVK information if it is available.
|
||||
@@ -144,37 +175,6 @@ void printDepthFormats(VkPhysicalDevice device) {
|
||||
}
|
||||
}
|
||||
|
||||
// These strings need to be allocated outside a function stack
|
||||
const std::string_view DESIRED_LAYERS[] = {
|
||||
"VK_LAYER_KHRONOS_validation",
|
||||
#if FILAMENT_VULKAN_DUMP_API
|
||||
"VK_LAYER_LUNARG_api_dump",
|
||||
#endif
|
||||
#if defined(ENABLE_RENDERDOC)
|
||||
"VK_LAYER_RENDERDOC_Capture",
|
||||
#endif
|
||||
};
|
||||
|
||||
FixedCapacityVector<const char*> getEnabledLayers() {
|
||||
constexpr size_t kMaxEnabledLayersCount = sizeof(DESIRED_LAYERS) / sizeof(DESIRED_LAYERS[0]);
|
||||
|
||||
const FixedCapacityVector<VkLayerProperties> availableLayers = filament::backend::enumerate(
|
||||
vkEnumerateInstanceLayerProperties);
|
||||
|
||||
auto enabledLayers = FixedCapacityVector<const char*>::with_capacity(kMaxEnabledLayersCount);
|
||||
for (const auto& desired : DESIRED_LAYERS) {
|
||||
for (const VkLayerProperties& layer : availableLayers) {
|
||||
const std::string_view availableLayer(layer.layerName);
|
||||
if (availableLayer == desired) {
|
||||
enabledLayers.push_back(desired.data());
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return enabledLayers;
|
||||
}
|
||||
|
||||
struct InstanceExtensions {
|
||||
bool debugUtilsSupported = false;
|
||||
bool portabilityEnumerationSupported = false;
|
||||
|
||||
@@ -1453,11 +1453,8 @@ void VulkanDriver::readPixels(Handle<HwRenderTarget> src, uint32_t x, uint32_t y
|
||||
}
|
||||
|
||||
vkUnmapMemory(device, stagingMemory);
|
||||
|
||||
mDisposer.createDisposable((void*)stagingImage, [=] () {
|
||||
vkDestroyImage(device, stagingImage, nullptr);
|
||||
vkFreeMemory(device, stagingMemory, nullptr);
|
||||
});
|
||||
vkDestroyImage(device, stagingImage, nullptr);
|
||||
vkFreeMemory(device, stagingMemory, nullptr);
|
||||
|
||||
scheduleDestroy(std::move(pbd));
|
||||
}
|
||||
|
||||
@@ -206,20 +206,44 @@ public:
|
||||
*
|
||||
* In general Filament reserves the right to re-order renderables to allow for efficient
|
||||
* rendering. However clients can control ordering at a coarse level using \em priority.
|
||||
* The priority is applied separately for opaque and translucent objects, that is, opaque
|
||||
* objects are always drawn before translucent objects regardless of the priority.
|
||||
*
|
||||
* For example, this could be used to draw a semitransparent HUD, if a client wishes to
|
||||
* avoid using a separate View for the HUD. Note that priority is completely orthogonal to
|
||||
* For example, this could be used to draw a semitransparent HUD on top of everything,
|
||||
* without using a separate View. Note that priority is completely orthogonal to
|
||||
* Builder::layerMask, which merely controls visibility.
|
||||
*
|
||||
* The Skybox always using the lowest priority, so it's drawn last, which may improve
|
||||
* performance.
|
||||
*
|
||||
* @param priority clamped to the range [0..7], defaults to 4; 7 is lowest priority
|
||||
* (rendered last).
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
* @see Builder::blendOrder(), RenderableManager::setBlendOrderAt()
|
||||
* @see Builder::blendOrder()
|
||||
* @see Builder::channel()
|
||||
* @see RenderableManager::setPriority()
|
||||
* @see RenderableManager::setBlendOrderAt()
|
||||
*/
|
||||
Builder& priority(uint8_t priority) noexcept;
|
||||
|
||||
/**
|
||||
* Set the channel this renderable is associated to. There can be 4 channels.
|
||||
* All renderables in a given channel are rendered together, regardless of anything else.
|
||||
* They are sorted as usual withing a channel.
|
||||
* Channels work similarly to priorities, except that they enforce the strongest ordering.
|
||||
*
|
||||
* @param channel clamped to the range [0..3], defaults to 0.
|
||||
*
|
||||
* @return Builder reference for chaining calls.
|
||||
*
|
||||
* @see Builder::blendOrder()
|
||||
* @see Builder::priority()
|
||||
* @see RenderableManager::setBlendOrderAt()
|
||||
*/
|
||||
Builder& channel(uint8_t channel) noexcept;
|
||||
|
||||
/**
|
||||
* Controls frustum culling, true by default.
|
||||
*
|
||||
@@ -461,6 +485,13 @@ public:
|
||||
*/
|
||||
void setPriority(Instance instance, uint8_t priority) noexcept;
|
||||
|
||||
/**
|
||||
* Changes the channel a renderable is associated to.
|
||||
*
|
||||
* \see Builder::channel().
|
||||
*/
|
||||
void setChannel(Instance instance, uint8_t channel) noexcept;
|
||||
|
||||
/**
|
||||
* Changes whether or not frustum culling is on.
|
||||
*
|
||||
|
||||
@@ -148,15 +148,18 @@ void RenderPass::appendCommands(FEngine& engine, CommandTypeFlags const commandT
|
||||
}
|
||||
}
|
||||
|
||||
void RenderPass::appendCustomCommand(Pass pass, CustomCommand custom, uint32_t order,
|
||||
void RenderPass::appendCustomCommand(uint8_t channel, Pass pass, CustomCommand custom, uint32_t order,
|
||||
Executor::CustomCommandFn command) {
|
||||
|
||||
assert((uint64_t(order) << CUSTOM_ORDER_SHIFT) <= CUSTOM_ORDER_MASK);
|
||||
assert_invariant((uint64_t(order) << CUSTOM_ORDER_SHIFT) <= CUSTOM_ORDER_MASK);
|
||||
|
||||
uint32_t index = mCustomCommands.size();
|
||||
channel = std::min(channel, uint8_t(0x3));
|
||||
|
||||
uint32_t const index = mCustomCommands.size();
|
||||
mCustomCommands.push_back(std::move(command));
|
||||
|
||||
uint64_t cmd = uint64_t(pass);
|
||||
cmd |= uint64_t(channel) << CHANNEL_SHIFT;
|
||||
cmd |= uint64_t(custom);
|
||||
cmd |= uint64_t(order) << CUSTOM_ORDER_SHIFT;
|
||||
cmd |= uint64_t(index);
|
||||
@@ -508,6 +511,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
|
||||
const bool hasSkinningOrMorphing = soaVisibility[i].skinning || hasMorphing;
|
||||
|
||||
cmdColor.key = makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT);
|
||||
cmdColor.key |= makeField(soaVisibility[i].channel, CHANNEL_MASK, CHANNEL_SHIFT);
|
||||
cmdColor.primitive.index = (uint16_t)i;
|
||||
cmdColor.primitive.instanceCount = soaInstanceCount[i];
|
||||
|
||||
@@ -522,6 +526,7 @@ RenderPass::Command* RenderPass::generateCommandsImpl(uint32_t extraFlags,
|
||||
cmdDepth.key = uint64_t(Pass::DEPTH);
|
||||
cmdDepth.key |= uint64_t(CustomCommand::PASS);
|
||||
cmdDepth.key |= makeField(soaVisibility[i].priority, PRIORITY_MASK, PRIORITY_SHIFT);
|
||||
cmdDepth.key |= makeField(soaVisibility[i].channel, CHANNEL_MASK, CHANNEL_SHIFT);
|
||||
cmdDepth.key |= makeField(distanceBits >> 22u, Z_BUCKET_MASK, Z_BUCKET_SHIFT);
|
||||
cmdDepth.primitive.index = (uint16_t)i;
|
||||
cmdDepth.primitive.instanceCount = soaInstanceCount[i];
|
||||
|
||||
@@ -49,6 +49,8 @@ public:
|
||||
* Command key encoding
|
||||
* --------------------
|
||||
*
|
||||
* CC = Channel
|
||||
* PP = Pass
|
||||
* a = alpha masking
|
||||
* ppp = priority
|
||||
* t = two-pass transparency ordering
|
||||
@@ -58,45 +60,45 @@ public:
|
||||
* TODO: we need to add a "primitive id" in the low-bits of material-id, so that
|
||||
* auto-instancing can work better
|
||||
*
|
||||
* DEPTH command
|
||||
* | 6 | 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +------+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |000000|01|00|0|ppp|00|000000| Z-bucket | material-id |
|
||||
* +------+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | correctness | optimizations (truncation allowed) |
|
||||
* DEPTH command (b00)
|
||||
* | | | 2| 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |CC|00|00|01|00|0|ppp|00|000000| Z-bucket | material-id |
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | correctness | optimizations (truncation allowed) |
|
||||
*
|
||||
*
|
||||
* COLOR command
|
||||
* | 6 | 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +------+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |000001|01|00|a|ppp|00|000000| Z-bucket | material-id |
|
||||
* |000010|01|00|a|ppp|00|000000| Z-bucket | material-id | refraction
|
||||
* +------+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | correctness | optimizations (truncation allowed) |
|
||||
* COLOR (b01) and REFRACT (b10) commands
|
||||
* | | 2| 2| 2| 2|1| 3 | 2| 6 | 10 | 32 |
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* |CC|00|01|01|00|a|ppp|00|000000| Z-bucket | material-id |
|
||||
* |CC|00|10|01|00|a|ppp|00|000000| Z-bucket | material-id | refraction
|
||||
* +--+--+--+--+--+-+---+--+------+----------+--------------------------------+
|
||||
* | correctness | optimizations (truncation allowed) |
|
||||
*
|
||||
*
|
||||
* BLENDED command
|
||||
* | 6 | 2| 2|1| 3 | 2| 32 | 15 |1|
|
||||
* +------+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* |000011|01|00|0|ppp|00| ~distanceBits | blendOrder |t|
|
||||
* +------+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* | correctness |
|
||||
* BLENDED command (b11)
|
||||
* | 2| 2| 2| 2| 2|1| 3 | 2| 32 | 15 |1|
|
||||
* +--+--+--+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* |CC|00|11|01|00|0|ppp|00| ~distanceBits | blendOrder |t|
|
||||
* +--+--+--+--+--+-+---+--+--------------------------------+---------------+-+
|
||||
* | correctness |
|
||||
*
|
||||
*
|
||||
* pre-CUSTOM command
|
||||
* | 6 | 2| 2| 22 | 32 |
|
||||
* +------+--+--+----------------------+--------------------------------+
|
||||
* | pass |00|00| order | custom command index |
|
||||
* +------+--+--+----------------------+--------------------------------+
|
||||
* | correctness |
|
||||
* | 2| 2| 2| 2| 2| 22 | 32 |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* |CC|00|PP|00|00| order | custom command index |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* | correctness |
|
||||
*
|
||||
*
|
||||
* post-CUSTOM command
|
||||
* | 6 | 2| 2| 22 | 32 |
|
||||
* +------+--+--+----------------------+--------------------------------+
|
||||
* | pass |11|00| order | custom command index |
|
||||
* +------+--+--+----------------------+--------------------------------+
|
||||
* | correctness |
|
||||
* | 2| 2| 2| 2| 2| 22 | 32 |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* |CC|00|PP|11|00| order | custom command index |
|
||||
* +--+--+--+--+--+----------------------+--------------------------------+
|
||||
* | correctness |
|
||||
*
|
||||
*
|
||||
* SENTINEL command
|
||||
@@ -137,12 +139,15 @@ public:
|
||||
static constexpr uint64_t BLENDING_MASK = 0x0020000000000000llu;
|
||||
static constexpr unsigned BLENDING_SHIFT = 53;
|
||||
|
||||
static constexpr uint64_t PASS_MASK = 0xFC00000000000000llu;
|
||||
static constexpr unsigned PASS_SHIFT = 58;
|
||||
|
||||
static constexpr uint64_t CUSTOM_MASK = 0x0300000000000000llu;
|
||||
static constexpr unsigned CUSTOM_SHIFT = 56;
|
||||
|
||||
static constexpr uint64_t PASS_MASK = 0x0C00000000000000llu;
|
||||
static constexpr unsigned PASS_SHIFT = 58;
|
||||
|
||||
static constexpr uint64_t CHANNEL_MASK = 0xC000000000000000llu;
|
||||
static constexpr unsigned CHANNEL_SHIFT = 62;
|
||||
|
||||
static constexpr uint64_t CUSTOM_ORDER_MASK = 0x003FFFFF00000000llu;
|
||||
static constexpr unsigned CUSTOM_ORDER_SHIFT = 32;
|
||||
|
||||
@@ -373,7 +378,7 @@ public:
|
||||
}
|
||||
|
||||
// Appends a custom command.
|
||||
void appendCustomCommand(Pass pass, CustomCommand custom, uint32_t order,
|
||||
void appendCustomCommand(uint8_t channel, Pass pass, CustomCommand custom, uint32_t order,
|
||||
Executor::CustomCommandFn command);
|
||||
|
||||
|
||||
|
||||
@@ -52,6 +52,10 @@ void RenderableManager::setPriority(Instance instance, uint8_t priority) noexcep
|
||||
downcast(this)->setPriority(instance, priority);
|
||||
}
|
||||
|
||||
void RenderableManager::setChannel(Instance instance, uint8_t channel) noexcept{
|
||||
downcast(this)->setChannel(instance, channel);
|
||||
}
|
||||
|
||||
void RenderableManager::setCulling(Instance instance, bool enable) noexcept {
|
||||
downcast(this)->setCulling(instance, enable);
|
||||
}
|
||||
|
||||
@@ -51,7 +51,8 @@ struct RenderableManager::BuilderDetails {
|
||||
Box mAABB;
|
||||
uint8_t mLayerMask = 0x1;
|
||||
uint8_t mPriority = 0x4;
|
||||
uint8_t mChannels = 1;
|
||||
uint8_t mCommandChannel = 0x0;
|
||||
uint8_t mLightChannels = 1;
|
||||
uint16_t mInstanceCount = 1;
|
||||
bool mCulling : 1;
|
||||
bool mCastShadows : 1;
|
||||
@@ -135,6 +136,11 @@ RenderableManager::Builder& RenderableManager::Builder::priority(uint8_t priorit
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderableManager::Builder& RenderableManager::Builder::channel(uint8_t channel) noexcept {
|
||||
mImpl->mCommandChannel = std::min(channel, uint8_t(0x3));
|
||||
return *this;
|
||||
}
|
||||
|
||||
RenderableManager::Builder& RenderableManager::Builder::culling(bool enable) noexcept {
|
||||
mImpl->mCulling = enable;
|
||||
return *this;
|
||||
@@ -143,8 +149,8 @@ RenderableManager::Builder& RenderableManager::Builder::culling(bool enable) noe
|
||||
RenderableManager::Builder& RenderableManager::Builder::lightChannel(unsigned int channel, bool enable) noexcept {
|
||||
if (channel < 8) {
|
||||
const uint8_t mask = 1u << channel;
|
||||
mImpl->mChannels &= ~mask;
|
||||
mImpl->mChannels |= enable ? mask : 0u;
|
||||
mImpl->mLightChannels &= ~mask;
|
||||
mImpl->mLightChannels |= enable ? mask : 0u;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
@@ -338,13 +344,14 @@ void FRenderableManager::create(
|
||||
setAxisAlignedBoundingBox(ci, builder->mAABB);
|
||||
setLayerMask(ci, builder->mLayerMask);
|
||||
setPriority(ci, builder->mPriority);
|
||||
setChannel(ci, builder->mCommandChannel);
|
||||
setCastShadows(ci, builder->mCastShadows);
|
||||
setReceiveShadows(ci, builder->mReceiveShadows);
|
||||
setScreenSpaceContactShadows(ci, builder->mScreenSpaceContactShadows);
|
||||
setCulling(ci, builder->mCulling);
|
||||
setSkinning(ci, false);
|
||||
setMorphing(ci, builder->mMorphTargetCount);
|
||||
mManager[ci].channels = builder->mChannels;
|
||||
mManager[ci].channels = builder->mLightChannels;
|
||||
mManager[ci].instanceCount = builder->mInstanceCount;
|
||||
|
||||
const uint32_t boneCount = builder->mSkinningBoneCount;
|
||||
|
||||
@@ -54,6 +54,7 @@ public:
|
||||
// TODO: consider renaming, this pertains to material variants, not strictly visibility.
|
||||
struct Visibility {
|
||||
uint8_t priority : 3;
|
||||
uint8_t channel : 2;
|
||||
bool castShadows : 1;
|
||||
bool receiveShadows : 1;
|
||||
bool culling : 1;
|
||||
@@ -102,6 +103,9 @@ public:
|
||||
// The priority is clamped to the range [0..7]
|
||||
inline void setPriority(Instance instance, uint8_t priority) noexcept;
|
||||
|
||||
// The channel is clamped to the range [0..3]
|
||||
inline void setChannel(Instance instance, uint8_t channel) noexcept;
|
||||
|
||||
inline void setCastShadows(Instance instance, bool enable) noexcept;
|
||||
|
||||
inline void setLayerMask(Instance instance, uint8_t layerMask) noexcept;
|
||||
@@ -159,7 +163,7 @@ public:
|
||||
return mManager.getEntity(instance);
|
||||
}
|
||||
|
||||
inline size_t getLevelCount(Instance) const noexcept { return 1; }
|
||||
inline size_t getLevelCount(Instance) const noexcept { return 1u; }
|
||||
size_t getPrimitiveCount(Instance instance, uint8_t level) const noexcept;
|
||||
void setMaterialInstanceAt(Instance instance, uint8_t level,
|
||||
size_t primitiveIndex, FMaterialInstance const* materialInstance);
|
||||
@@ -283,7 +287,14 @@ void FRenderableManager::setLayerMask(Instance instance, uint8_t layerMask) noex
|
||||
void FRenderableManager::setPriority(Instance instance, uint8_t priority) noexcept {
|
||||
if (instance) {
|
||||
Visibility& visibility = mManager[instance].visibility;
|
||||
visibility.priority = priority;
|
||||
visibility.priority = std::min(priority, uint8_t(0x7));
|
||||
}
|
||||
}
|
||||
|
||||
void FRenderableManager::setChannel(Instance instance, uint8_t channel) noexcept {
|
||||
if (instance) {
|
||||
Visibility& visibility = mManager[instance].visibility;
|
||||
visibility.channel = std::min(channel, uint8_t(0x3));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -201,11 +201,7 @@ bool FRenderer::beginFrame(FSwapChain* swapChain, uint64_t vsyncSteadyClockTimeN
|
||||
mFrameId++;
|
||||
mViewRenderedCount = 0;
|
||||
|
||||
{ // scope for frame id trace
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "frame %u", mFrameId);
|
||||
SYSTRACE_NAME(buf);
|
||||
}
|
||||
SYSTRACE_FRAME_ID(mFrameId);
|
||||
|
||||
FEngine& engine = mEngine;
|
||||
FEngine::DriverApi& driver = engine.getDriverApi();
|
||||
@@ -913,7 +909,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
|
||||
if (colorGradingConfigForColor.asSubpass) {
|
||||
// append color grading subpass after all other passes
|
||||
pass.appendCustomCommand(
|
||||
pass.appendCustomCommand(3,
|
||||
RenderPass::Pass::BLENDED,
|
||||
RenderPass::CustomCommand::EPILOG,
|
||||
0, [&ppm, &driver, colorGradingConfigForColor]() {
|
||||
@@ -921,7 +917,7 @@ void FRenderer::renderJob(ArenaScope& arena, FView& view) {
|
||||
});
|
||||
} if (colorGradingConfig.customResolve) {
|
||||
// append custom resolve subpass after all other passes
|
||||
pass.appendCustomCommand(
|
||||
pass.appendCustomCommand(3,
|
||||
RenderPass::Pass::BLENDED,
|
||||
RenderPass::CustomCommand::EPILOG,
|
||||
0, [&ppm, &driver]() {
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
Pod::Spec.new do |spec|
|
||||
spec.name = "Filament"
|
||||
spec.version = "1.31.2"
|
||||
spec.version = "1.31.3"
|
||||
spec.license = { :type => "Apache 2.0", :file => "LICENSE" }
|
||||
spec.homepage = "https://google.github.io/filament"
|
||||
spec.authors = "Google LLC."
|
||||
spec.summary = "Filament is a real-time physically based rendering engine for Android, iOS, Windows, Linux, macOS, and WASM/WebGL."
|
||||
spec.platform = :ios, "11.0"
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.31.2/filament-v1.31.2-ios.tgz" }
|
||||
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.31.3/filament-v1.31.3-ios.tgz" }
|
||||
|
||||
# Fix linking error with Xcode 12; we do not yet support the simulator on Apple silicon.
|
||||
spec.pod_target_xcconfig = {
|
||||
|
||||
@@ -71,7 +71,6 @@ set(SRCS
|
||||
src/Profiler.cpp
|
||||
src/sstream.cpp
|
||||
src/string.cpp
|
||||
src/Systrace.cpp
|
||||
src/ThreadUtils.cpp
|
||||
)
|
||||
|
||||
@@ -80,6 +79,7 @@ if (WIN32)
|
||||
endif()
|
||||
if (ANDROID)
|
||||
list(APPEND SRCS src/android/ThermalManager.cpp)
|
||||
list(APPEND SRCS src/android/Systrace.cpp)
|
||||
endif()
|
||||
if (LINUX OR ANDROID)
|
||||
list(APPEND SRCS src/linux/Condition.cpp)
|
||||
@@ -88,6 +88,7 @@ if (LINUX OR ANDROID)
|
||||
endif()
|
||||
if (APPLE)
|
||||
list(APPEND SRCS src/darwin/Path.mm)
|
||||
list(APPEND SRCS src/darwin/Systrace.cpp)
|
||||
endif()
|
||||
|
||||
# ==================================================================================================
|
||||
|
||||
@@ -23,17 +23,6 @@
|
||||
#define SYSTRACE_TAG_FILAMENT (1<<1) // don't change, used in makefiles
|
||||
#define SYSTRACE_TAG_JOBSYSTEM (1<<2)
|
||||
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
|
||||
/*
|
||||
* The SYSTRACE_ macros use SYSTRACE_TAG as a the TAG, which should be defined
|
||||
* before this file is included. If not, the SYSTRACE_TAG_ALWAYS tag will be used.
|
||||
@@ -43,228 +32,22 @@
|
||||
#define SYSTRACE_TAG (SYSTRACE_TAG_ALWAYS)
|
||||
#endif
|
||||
|
||||
// enable tracing
|
||||
#define SYSTRACE_ENABLE() ::utils::details::Systrace::enable(SYSTRACE_TAG)
|
||||
// Systrace on Apple platforms is fragile and adds overhead, should only be enabled in dev builds.
|
||||
#ifndef FILAMENT_APPLE_SYSTRACE
|
||||
#define FILAMENT_APPLE_SYSTRACE 0
|
||||
#endif
|
||||
|
||||
// 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 ___tracer(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)
|
||||
|
||||
// SYSTRACE_CALL is an SYSTRACE_NAME that uses the current function name.
|
||||
#define SYSTRACE_CALL() SYSTRACE_NAME(__FUNCTION__)
|
||||
|
||||
#define SYSTRACE_NAME_BEGIN(name) \
|
||||
___tracer.traceBegin(SYSTRACE_TAG, name)
|
||||
|
||||
#define SYSTRACE_NAME_END() \
|
||||
___tracer.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) \
|
||||
___tracer.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) \
|
||||
___tracer.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) \
|
||||
___tracer.value(SYSTRACE_TAG, name, int32_t(val))
|
||||
|
||||
#define SYSTRACE_VALUE64(name, val) \
|
||||
___tracer.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);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
private:
|
||||
Systrace mTrace;
|
||||
const uint32_t mTag;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#else // !ANDROID
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
#if defined(__ANDROID__)
|
||||
#include <utils/android/Systrace.h>
|
||||
#elif defined(__APPLE__) && FILAMENT_APPLE_SYSTRACE
|
||||
#include <utils/darwin/Systrace.h>
|
||||
#else
|
||||
|
||||
#define SYSTRACE_ENABLE()
|
||||
#define SYSTRACE_DISABLE()
|
||||
#define SYSTRACE_CONTEXT()
|
||||
#define SYSTRACE_NAME(name)
|
||||
#define SYSTRACE_FRAME_ID(frame)
|
||||
#define SYSTRACE_NAME_BEGIN(name)
|
||||
#define SYSTRACE_NAME_END()
|
||||
#define SYSTRACE_CALL()
|
||||
|
||||
250
libs/utils/include/utils/android/Systrace.h
Normal file
250
libs/utils/include/utils/android/Systrace.h
Normal file
@@ -0,0 +1,250 @@
|
||||
/*
|
||||
* 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 ___tracer(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) \
|
||||
___tracer.traceBegin(SYSTRACE_TAG, name)
|
||||
|
||||
#define SYSTRACE_NAME_END() \
|
||||
___tracer.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) \
|
||||
___tracer.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) \
|
||||
___tracer.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) \
|
||||
___tracer.value(SYSTRACE_TAG, name, int32_t(val))
|
||||
|
||||
#define SYSTRACE_VALUE64(name, val) \
|
||||
___tracer.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);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
private:
|
||||
Systrace mTrace;
|
||||
const uint32_t mTag;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
|
||||
#endif // TNT_UTILS_ANDROID_SYSTRACE_H
|
||||
243
libs/utils/include/utils/darwin/Systrace.h
Normal file
243
libs/utils/include/utils/darwin/Systrace.h
Normal file
@@ -0,0 +1,243 @@
|
||||
/*
|
||||
* 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_DARWIN_SYSTRACE_H
|
||||
#define TNT_UTILS_DARWIN_SYSTRACE_H
|
||||
|
||||
#include <atomic>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <os/log.h>
|
||||
#include <os/signpost.h>
|
||||
|
||||
#include <utils/compiler.h>
|
||||
#include <stack>
|
||||
|
||||
// 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 ___tracer(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) \
|
||||
::utils::details::Systrace(SYSTRACE_TAG).frameId(SYSTRACE_TAG, frame)
|
||||
|
||||
extern thread_local std::stack<const char*> ___tracerSections;
|
||||
|
||||
// SYSTRACE_CALL is an SYSTRACE_NAME that uses the current function name.
|
||||
#define SYSTRACE_CALL() SYSTRACE_NAME(__PRETTY_FUNCTION__)
|
||||
|
||||
#define SYSTRACE_NAME_BEGIN(name) \
|
||||
___tracerSections.push(name) , \
|
||||
___tracer.traceBegin(SYSTRACE_TAG, name)
|
||||
|
||||
#define SYSTRACE_NAME_END() \
|
||||
___tracer.traceEnd(SYSTRACE_TAG, ___tracerSections.top()) , \
|
||||
___tracerSections.pop()
|
||||
|
||||
/**
|
||||
* 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) \
|
||||
___tracer.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) \
|
||||
___tracer.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) \
|
||||
___tracer.value(SYSTRACE_TAG, name, int32_t(val))
|
||||
|
||||
#define SYSTRACE_VALUE64(name, val) \
|
||||
___tracer.value(SYSTRACE_TAG, name, int64_t(val))
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
// No user serviceable code below...
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
// This is an alternative to os_signpost_emit_with_type that allows non-compile time strings (namely
|
||||
// for us, __FUNCTION__).
|
||||
// The trade-off is that this doesn't allow messages to have printf-style formatting.
|
||||
// It's fine to pass an empty string to __builtin_os_log_format_buffer_size and
|
||||
// __builtin_os_log_format, because they return the same value for strings without any format
|
||||
// specifiers.
|
||||
// This is fragile, so should only be used to assist debugging and never in production.
|
||||
#define APPLE_SIGNPOST_EMIT(log, type, spid, name, message) \
|
||||
if (os_signpost_enabled(log)) { \
|
||||
uint8_t _os_fmt_buf[__builtin_os_log_format_buffer_size("")]; \
|
||||
_os_signpost_emit_with_name_impl( \
|
||||
&__dso_handle, log, type, spid, \
|
||||
name, message, \
|
||||
(uint8_t *)__builtin_os_log_format(_os_fmt_buf, ""), \
|
||||
(uint32_t)sizeof(_os_fmt_buf)); \
|
||||
}
|
||||
|
||||
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)) {
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.systraceLog, OS_SIGNPOST_INTERVAL_BEGIN,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, name, name)
|
||||
}
|
||||
}
|
||||
|
||||
inline void traceEnd(uint32_t tag, const char* name) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.systraceLog, OS_SIGNPOST_INTERVAL_END,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, name, "")
|
||||
}
|
||||
}
|
||||
|
||||
inline void asyncBegin(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
inline void asyncEnd(uint32_t tag, const char* name, int32_t cookie) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t value) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "%s - %d", name, value);
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.systraceLog, OS_SIGNPOST_EVENT,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, name, buf)
|
||||
}
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t value) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
char buf[64];
|
||||
snprintf(buf, 64, "%s - %lld", name, value);
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.systraceLog, OS_SIGNPOST_EVENT,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, name, buf)
|
||||
}
|
||||
}
|
||||
|
||||
inline void frameId(uint32_t tag, uint32_t frame) noexcept {
|
||||
if (tag && UTILS_UNLIKELY(mIsTracingEnabled)) {
|
||||
char buf[64]; \
|
||||
snprintf(buf, 64, "frame %u", frame); \
|
||||
APPLE_SIGNPOST_EMIT(sGlobalState.frameIdLog, OS_SIGNPOST_EVENT,
|
||||
OS_SIGNPOST_ID_EXCLUSIVE, "frame", buf)
|
||||
}
|
||||
}
|
||||
|
||||
private:
|
||||
friend class ScopedTrace;
|
||||
|
||||
struct GlobalState {
|
||||
std::atomic<uint32_t> isTracingEnabled;
|
||||
|
||||
os_log_t systraceLog;
|
||||
os_log_t frameIdLog;
|
||||
};
|
||||
|
||||
static GlobalState sGlobalState;
|
||||
|
||||
void init(uint32_t tag) noexcept;
|
||||
|
||||
// cached values for faster access, no need to be initialized
|
||||
bool mIsTracingEnabled;
|
||||
|
||||
static void setup() noexcept;
|
||||
static void init_once() noexcept;
|
||||
static bool isTracingEnabled(uint32_t tag) 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), mName(name), mTag(tag) {
|
||||
mTrace.traceBegin(tag, name);
|
||||
}
|
||||
|
||||
inline ~ScopedTrace() noexcept {
|
||||
mTrace.traceEnd(mTag, mName);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int32_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
inline void value(uint32_t tag, const char* name, int64_t v) noexcept {
|
||||
mTrace.value(tag, name, v);
|
||||
}
|
||||
|
||||
private:
|
||||
Systrace mTrace;
|
||||
const char* mName;
|
||||
const uint32_t mTag;
|
||||
};
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
|
||||
#endif // TNT_UTILS_DARWIN_SYSTRACE_H
|
||||
@@ -17,8 +17,6 @@
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
|
||||
#include <cinttypes>
|
||||
|
||||
#include <string.h>
|
||||
@@ -219,5 +217,3 @@ void Systrace::int64_body(int fd, int pid, const char* name, int64_t value) noex
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
|
||||
#endif // ANDROID
|
||||
73
libs/utils/src/darwin/Systrace.cpp
Normal file
73
libs/utils/src/darwin/Systrace.cpp
Normal file
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* 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.
|
||||
*/
|
||||
|
||||
#include <utils/Systrace.h>
|
||||
#include <utils/Log.h>
|
||||
|
||||
#if FILAMENT_APPLE_SYSTRACE
|
||||
|
||||
#include <pthread.h>
|
||||
|
||||
static pthread_once_t atrace_once_control = PTHREAD_ONCE_INIT;
|
||||
|
||||
thread_local std::stack<const char*> ___tracerSections;
|
||||
|
||||
namespace utils {
|
||||
namespace details {
|
||||
|
||||
Systrace::GlobalState Systrace::sGlobalState = {};
|
||||
|
||||
void Systrace::init_once() noexcept {
|
||||
GlobalState& s = sGlobalState;
|
||||
|
||||
s.systraceLog = os_log_create("com.google.filament", "systrace");
|
||||
s.frameIdLog = os_log_create("com.google.filament", "frameId");
|
||||
}
|
||||
|
||||
void Systrace::setup() noexcept {
|
||||
pthread_once(&atrace_once_control, init_once);
|
||||
}
|
||||
|
||||
void Systrace::enable(uint32_t tags) noexcept {
|
||||
setup();
|
||||
sGlobalState.isTracingEnabled.fetch_or(tags, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
void Systrace::disable(uint32_t tags) noexcept {
|
||||
sGlobalState.isTracingEnabled.fetch_and(~tags, std::memory_order_relaxed);
|
||||
}
|
||||
|
||||
// unfortunately, this generates quite a bit of code because reading a global is not
|
||||
// trivial. For this reason, we do not inline this method.
|
||||
bool Systrace::isTracingEnabled(uint32_t tag) noexcept {
|
||||
if (tag) {
|
||||
setup();
|
||||
return bool((sGlobalState.isTracingEnabled.load(std::memory_order_relaxed) | SYSTRACE_TAG_ALWAYS) & tag);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// ------------------------------------------------------------------------------------------------
|
||||
|
||||
void Systrace::init(uint32_t tag) noexcept {
|
||||
// must be called first
|
||||
mIsTracingEnabled = isTracingEnabled(tag);
|
||||
}
|
||||
|
||||
} // namespace details
|
||||
} // namespace utils
|
||||
|
||||
#endif // FILAMENT_APPLE_SYSTRACE
|
||||
@@ -896,6 +896,9 @@ class_<RenderableBuilder>("RenderableManager$Builder")
|
||||
.BUILDER_FUNCTION("priority", RenderableBuilder, (RenderableBuilder* builder, uint8_t value), {
|
||||
return &builder->priority(value); })
|
||||
|
||||
.BUILDER_FUNCTION("channel", RenderableBuilder, (RenderableBuilder* builder, uint8_t value), {
|
||||
return &builder->channel(value); })
|
||||
|
||||
.BUILDER_FUNCTION("culling", RenderableBuilder, (RenderableBuilder* builder, bool enable), {
|
||||
return &builder->culling(enable); })
|
||||
|
||||
@@ -965,6 +968,7 @@ class_<RenderableManager>("RenderableManager")
|
||||
.function("setAxisAlignedBoundingBox", &RenderableManager::setAxisAlignedBoundingBox)
|
||||
.function("setLayerMask", &RenderableManager::setLayerMask)
|
||||
.function("setPriority", &RenderableManager::setPriority)
|
||||
.function("setChannel", &RenderableManager::setChannel)
|
||||
.function("setCastShadows", &RenderableManager::setCastShadows)
|
||||
.function("setReceiveShadows", &RenderableManager::setReceiveShadows)
|
||||
.function("isShadowCaster", &RenderableManager::isShadowCaster)
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "filament",
|
||||
"version": "1.31.2",
|
||||
"version": "1.31.3",
|
||||
"description": "Real-time physically based rendering engine",
|
||||
"main": "filament.js",
|
||||
"module": "filament.js",
|
||||
|
||||
Reference in New Issue
Block a user