Compare commits

...

3 Commits

Author SHA1 Message Date
Anish Goyal
6e17c413b9 Fix race condition for cache prewarming (#9613)
Right now, if a material is destroyed just after creation, it's possible
for prewarm to attempt to use destroyed shader modules. This ensures
that the resources are kept until after any queued jobs have run.

While it is likely ideal to properly cancel the prewarm if the program
has been destroyed, this seems like a rare occurrence in practice.
2026-01-20 12:36:44 -08:00
rafadevai
e0bcec5ef3 VK: Add support for VK_KHR_global_priority (#9607)
Add support for application that want to change the
priority of GPU queues at a system level.
2026-01-20 12:36:39 -08:00
Powei Feng
61f3f7f4d8 Bump version to 1.68.5 2026-01-15 16:21:46 -08:00
10 changed files with 75 additions and 17 deletions

View File

@@ -31,7 +31,7 @@ repositories {
}
dependencies {
implementation 'com.google.android.filament:filament-android:1.68.4'
implementation 'com.google.android.filament:filament-android:1.68.5'
}
```
@@ -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:
```shell
pod 'Filament', '~> 1.68.4'
pod 'Filament', '~> 1.68.5'
```
## Documentation

View File

@@ -1,5 +1,5 @@
GROUP=com.google.android.filament
VERSION_NAME=1.68.4
VERSION_NAME=1.68.5
POM_DESCRIPTION=Real-time physically based rendering engine for Android.

View File

@@ -540,6 +540,11 @@ private:
* to be created from a 3d VkImage.
*/
bool imageView2Don3DImage;
/**
* Desired global priority value for all VkQueue at a system level.
*/
Platform::GpuContextPriority gpuContextPriority = Platform::GpuContextPriority::DEFAULT;
};
void createInstance(ExtensionSet const& requiredExts) noexcept;

View File

@@ -207,6 +207,10 @@ public:
isDynamicRenderingSupported();
}
inline bool isGlobalPrioritySupported() const noexcept {
return mGlobalPrioritySupported;
}
private:
VkPhysicalDeviceMemoryProperties mMemoryProperties = {};
VkPhysicalDeviceProperties2 mPhysicalDeviceProperties = {
@@ -240,6 +244,7 @@ private:
bool mPipelineCreationFeedbackSupported = false;
bool mProtectedMemorySupported = false;
bool mVertexInputDynamicStateSupported = false;
bool mGlobalPrioritySupported = false;
// These are options that can be enabled or disabled at an application level.
bool mAsyncPipelineCachePrewarmingEnabled = false;

View File

@@ -851,7 +851,7 @@ void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils
// Base case - build the pipeline without any external samplers.
mPipelineCache.asyncPrewarmCache(
*vprogram.get(),
vprogram,
mPipelineLayoutCache.getLayout(vkLayouts, vprogram),
stereoscopicType,
mStereoscopicEyeCount,
@@ -888,7 +888,7 @@ void VulkanDriver::createProgramR(Handle<HwProgram> ph, Program&& program, utils
}
mPipelineCache.asyncPrewarmCache(
*vprogram.get(),
vprogram,
mPipelineLayoutCache.getLayout(vkLayouts, vprogram),
stereoscopicType,
mStereoscopicEyeCount,

View File

@@ -126,14 +126,16 @@ void VulkanPipelineCache::bindPipeline(VulkanCommandBuffer* commands) {
}
}
void VulkanPipelineCache::asyncPrewarmCache(const VulkanProgram& program,
void VulkanPipelineCache::asyncPrewarmCache(
resource_ptr<VulkanProgram> vprogram,
VkPipelineLayout layout,
StereoscopicType stereoscopicType,
uint8_t stereoscopicViewCount, CompilerPriorityQueue priority) {
uint8_t stereoscopicViewCount,
CompilerPriorityQueue priority) {
PipelineKey key {
.shaders = {
program.getVertexShader(),
program.getFragmentShader(),
vprogram->getVertexShader(),
vprogram->getFragmentShader(),
},
// We're using dynamic rendering, so this should be empty.
.renderPass = VK_NULL_HANDLE,
@@ -175,7 +177,10 @@ void VulkanPipelineCache::asyncPrewarmCache(const VulkanProgram& program,
CallbackManager::Handle cmh = mCallbackManager.get();
auto token = std::make_shared<ProgramToken>();
mCompilerThreadPool.queue(priority, token, [this, key, dynamicOptions, cmh]() mutable {
// Note: we keep a ref to vprogram in this lambda so that the shader modules don't get
// destroyed before we call createPipeline(). This is rare enough that we are ok with
// occasionally creating pipelines for destroyed materials.
mCompilerThreadPool.queue(priority, token, [this, vprogram, key, dynamicOptions, cmh]() mutable {
VkPipeline pipeline = createPipeline(key, dynamicOptions);
mCallbackManager.put(cmh);
// We don't actually need this pipeline, we just wanted to force the driver to cache

View File

@@ -104,7 +104,7 @@ public:
// compiling the pipeline on the main thread at draw time. This is very dependent
// on the implementation of the driver on the current device; it's expected to work
// on devices with VK_EXT_vertex_input_dynamic_state and VK_KHR_dynamic_rendering.
void asyncPrewarmCache(const VulkanProgram& program, VkPipelineLayout layout,
void asyncPrewarmCache(resource_ptr<VulkanProgram> vprogram, VkPipelineLayout layout,
StereoscopicType stereoscopicType, uint8_t stereoscopicViewCount,
CompilerPriorityQueue priority);

View File

@@ -232,6 +232,7 @@ ExtensionSet getDeviceExtensions(VkPhysicalDevice device) {
VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME,
// Required for dynamic rendering, enable this too.
VK_KHR_DEPTH_STENCIL_RESOLVE_EXTENSION_NAME,
VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME,
#if FVK_ENABLED(FVK_DEBUG_SHADER_MODULE)
VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME,
@@ -485,6 +486,22 @@ bool hasUnifiedMemoryArchitecture(VkPhysicalDeviceMemoryProperties memoryPropert
return true;
}
VkQueueGlobalPriorityKHR getVkQueueGlobalPriority(
Platform::GpuContextPriority priority) {
switch (priority) {
case Platform::GpuContextPriority::LOW:
return VK_QUEUE_GLOBAL_PRIORITY_LOW_KHR;
case Platform::GpuContextPriority::MEDIUM:
return VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
case Platform::GpuContextPriority::HIGH:
return VK_QUEUE_GLOBAL_PRIORITY_HIGH_KHR;
case Platform::GpuContextPriority::REALTIME:
return VK_QUEUE_GLOBAL_PRIORITY_REALTIME_KHR;
case Platform::GpuContextPriority::DEFAULT:
return VK_QUEUE_GLOBAL_PRIORITY_MEDIUM_KHR;
}
}
}// anonymous namespace
using SwapChainPtr = VulkanPlatform::SwapChainPtr;
@@ -624,9 +641,6 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
}
}
// TODO: Add support of VK_KHR_global_priority with `driverConfig.gpuContextPriority`
// in VulkanPlatform::createDriver.
MiscDeviceFeatures requestedFeatures {};
if (setContains(deviceExts, VK_KHR_DYNAMIC_RENDERING_EXTENSION_NAME)) {
@@ -639,6 +653,10 @@ Driver* VulkanPlatform::createDriver(void* sharedContext,
context.mPortabilitySubsetFeatures.imageView2DOn3DImage == VK_TRUE;
}
if (context.mGlobalPrioritySupported) {
requestedFeatures.gpuContextPriority = driverConfig.gpuContextPriority;
}
if (mImpl->mDevice == VK_NULL_HANDLE) {
createLogicalDeviceAndQueues(deviceExts, context.mPhysicalDeviceFeatures.features,
context.mPhysicalDeviceVk11Features, context.mProtectedMemorySupported,
@@ -927,6 +945,13 @@ void VulkanPlatform::queryAndSetDeviceFeatures(Platform::DriverConfig const& dri
chainStruct(&context.mPhysicalDeviceFeatures, &context.mPortabilitySubsetFeatures);
}
VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR globalPriorityFeatures = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR,
};
if (setContains(deviceExts, VK_KHR_GLOBAL_PRIORITY_EXTENSION_NAME)) {
chainStruct(&context.mPhysicalDeviceFeatures, &globalPriorityFeatures);
}
// Initialize the following fields: physicalDeviceProperties, memoryProperties,
// physicalDeviceFeatures.
vkGetPhysicalDeviceProperties2(mImpl->mPhysicalDevice, &context.mPhysicalDeviceProperties);
@@ -943,6 +968,7 @@ void VulkanPlatform::queryAndSetDeviceFeatures(Platform::DriverConfig const& dri
setContains(deviceExts, VK_EXT_PIPELINE_CREATION_FEEDBACK_EXTENSION_NAME);
context.mVertexInputDynamicStateSupported =
setContains(deviceExts, VK_EXT_VERTEX_INPUT_DYNAMIC_STATE_EXTENSION_NAME);
context.mGlobalPrioritySupported = globalPriorityFeatures.globalPriorityQuery == VK_TRUE;
} else {
VulkanSharedContext const* scontext = (VulkanSharedContext const*) sharedContext;
context.mDebugUtilsSupported = scontext->debugUtilsSupported;
@@ -1015,9 +1041,18 @@ void VulkanPlatform::createLogicalDeviceAndQueues(const ExtensionSet& deviceExte
for (auto const& ext: deviceExtensions) {
requestExtensions.push_back(ext.data());
}
bool const requiresGpuPriority =
requestedFeatures.gpuContextPriority != Platform::GpuContextPriority::DEFAULT;
VkDeviceQueueGlobalPriorityCreateInfoKHR queuePriorityCreateInfo = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_GLOBAL_PRIORITY_CREATE_INFO_KHR,
.globalPriority = getVkQueueGlobalPriority(requestedFeatures.gpuContextPriority),
};
VkDeviceQueueCreateInfo deviceQueueCreateInfo[2] = {};
deviceQueueCreateInfo[0] = {
.sType = VK_STRUCTURE_TYPE_DEVICE_QUEUE_CREATE_INFO,
.pNext = requiresGpuPriority ? &queuePriorityCreateInfo : nullptr,
.queueFamilyIndex = mImpl->mGraphicsQueueFamilyIndex,
.queueCount = 1,
.pQueuePriorities = &queuePriority[0],
@@ -1095,6 +1130,14 @@ void VulkanPlatform::createLogicalDeviceAndQueues(const ExtensionSet& deviceExte
chainStruct(&deviceCreateInfo, &protectedMemory);
}
VkPhysicalDeviceGlobalPriorityQueryFeaturesKHR globalPriority = {
.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_GLOBAL_PRIORITY_QUERY_FEATURES_KHR,
.globalPriorityQuery = VK_TRUE,
};
if (requiresGpuPriority) {
chainStruct(&deviceCreateInfo, &globalPriority);
}
mImpl->mDevice = createVkDevice(deviceCreateInfo);
}

View File

@@ -1,12 +1,12 @@
Pod::Spec.new do |spec|
spec.name = "Filament"
spec.version = "1.68.4"
spec.version = "1.68.5"
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.68.4/filament-v1.68.4-ios.tgz" }
spec.source = { :http => "https://github.com/google/filament/releases/download/v1.68.5/filament-v1.68.5-ios.tgz" }
spec.libraries = 'c++'

View File

@@ -1,6 +1,6 @@
{
"name": "filament",
"version": "1.68.4",
"version": "1.68.5",
"description": "Real-time physically based rendering engine",
"main": "filament.js",
"module": "filament.js",