-
Notifications
You must be signed in to change notification settings - Fork 2k
Stream API Vulkan Backend #9164
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 67 commits
6218164
e265850
8671617
d49554d
4fccd95
96cba96
abe8a49
c81cedd
387942c
0fdf1ca
8bc4d3a
9e92193
01a2480
48bb10a
ff145f6
c5c2d42
3b0e44c
80803f9
ad3a5b7
be6b6ae
021c4f6
0a661c1
ea4c20e
ba99844
cfe6a42
7f7dadd
b570d48
b09cbaf
13e1d2a
ff2827b
55fc91b
bcae04c
2fac13e
d45a265
c00afac
84fc69e
1b4f88b
839867e
397282a
75fdacb
111ac62
19cbb94
c612bfd
3c93f00
487fb27
fbf2f0d
8b6fa40
f548c58
bee08b4
76fc21a
5858acf
e441cbb
5a0f78d
865cb0a
a220f70
c6d0127
8017d5e
ad57838
0210611
1e5d37a
29e3f07
406a348
3a1aebe
0c07c3f
f503205
6e8959e
39be20b
db83dc0
54c636d
562eeed
74ffe4e
32ca1d3
3457700
85c899a
0ba9c2a
78d5e34
1216024
e022396
48cd99a
83a89b5
1a390f4
c9b3104
0a11d0c
86f0afe
44b506b
df284fe
f96afef
e4f29b0
56831e2
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -28,6 +28,8 @@ class VulkanPlatformAndroid : public VulkanPlatform { | |
public: | ||
ExternalImageHandle UTILS_PUBLIC createExternalImage(AHardwareBuffer const* buffer, | ||
bool sRGB) noexcept; | ||
virtual ExternalImageHandle createExternalImageFromRaw(void* image, | ||
bool sRGB) noexcept override; | ||
|
||
|
||
struct UTILS_PUBLIC ExternalImageDescAndroid { | ||
uint32_t width; // Texture width | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -231,6 +231,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context, | |
mQueryManager(mPlatform->getDevice()), | ||
mExternalImageManager(platform, &mSamplerCache, &mYcbcrConversionCache, &mDescriptorSetCache, | ||
&mDescriptorSetLayoutCache), | ||
mStreamedImageManager(&mExternalImageManager, &mDescriptorSetCache, &mSamplerCache), | ||
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported), | ||
mStereoscopicType(driverConfig.stereoscopicType) { | ||
|
||
|
@@ -455,13 +456,18 @@ void VulkanDriver::updateDescriptorSetTexture( | |
if (UTILS_UNLIKELY(mExternalImageManager.isExternallySampledTexture(texture))) { | ||
mExternalImageManager.bindExternallySampledTexture(set, binding, texture, params); | ||
mAppState.hasBoundExternalImages = true; | ||
} else { | ||
} else if (bool(texture->getStream())) { | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. can a texture be external sampled and streamed at the same time? or are they mutually exclusive? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Logically yes. But that would mean that a texture that is external was attached to a stream. And that seems like something went wrong, because from the frontend's perspective you can create a texture one of 3 ways:
|
||
mStreamedImageManager.bindStreamedTexture(set, binding, texture, params); | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
mAppState.hasBoundExternalImages = true; | ||
} | ||
else { | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
VulkanSamplerCache::Params cacheParams = { | ||
.sampler = params, | ||
}; | ||
VkSampler const vksampler = mSamplerCache.getSampler(cacheParams); | ||
mDescriptorSetCache.updateSampler(set, binding, texture, vksampler); | ||
mExternalImageManager.clearTextureBinding(set, binding); | ||
mStreamedImageManager.unbindStreamedTexture(set, binding); | ||
} | ||
} | ||
|
||
|
@@ -965,6 +971,11 @@ void VulkanDriver::destroySwapChain(Handle<HwSwapChain> sch) { | |
} | ||
|
||
void VulkanDriver::destroyStream(Handle<HwStream> sh) { | ||
if (!sh) { | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return; | ||
} | ||
auto stream = resource_ptr<VulkanStream>::cast(&mResourceManager, sh); | ||
stream.dec(); | ||
} | ||
|
||
void VulkanDriver::destroyTimerQuery(Handle<HwTimerQuery> tqh) { | ||
|
@@ -991,25 +1002,99 @@ void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) { | |
} | ||
|
||
Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream) { | ||
return {}; | ||
auto handle = mResourceManager.allocHandle<VulkanStream>(); | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
auto stream = resource_ptr<VulkanStream>::make(&mResourceManager, handle); | ||
stream.inc(); | ||
return handle; | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
} | ||
|
||
Handle<HwStream> VulkanDriver::createStreamAcquired() { | ||
return {}; | ||
auto handle = mResourceManager.allocHandle<VulkanStream>(); | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
auto stream = resource_ptr<VulkanStream>::make(&mResourceManager, handle); | ||
stream.inc(); | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return handle; | ||
} | ||
|
||
void VulkanDriver::setAcquiredImage(Handle<HwStream> sh, void* image, const math::mat3f& transform, | ||
CallbackHandler* handler, StreamCallback cb, void* userData) { | ||
FVK_SYSTRACE_SCOPE(); | ||
auto stream = resource_ptr<VulkanStream>::cast(&mResourceManager, sh); | ||
stream->acquire({ image, cb, userData, handler }); | ||
mStreamsWithPendingAcquiredImage.push_back(stream); | ||
poweifeng marked this conversation as resolved.
Show resolved
Hide resolved
|
||
} | ||
|
||
void VulkanDriver::setStreamDimensions(Handle<HwStream> sh, uint32_t width, uint32_t height) { | ||
auto stream = resource_ptr<VulkanStream>::cast(&mResourceManager, sh); | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
stream->width = width; | ||
stream->height = height; | ||
} | ||
|
||
int64_t VulkanDriver::getStreamTimestamp(Handle<HwStream> sh) { | ||
return 0; | ||
} | ||
|
||
void VulkanDriver::updateStreams(CommandStream* driver) { | ||
if (UTILS_UNLIKELY(!mStreamsWithPendingAcquiredImage.empty())) { | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
for (auto& stream: mStreamsWithPendingAcquiredImage) { | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (stream->previousNeedsRelease()) { | ||
scheduleRelease(stream->takePrevious()); | ||
} | ||
|
||
auto texture = stream->getTexture(stream->getAcquired().image); | ||
bool newImage = false; | ||
if (!texture) { | ||
auto externalImage = | ||
mPlatform->createExternalImageFromRaw(stream->getAcquired().image, false); | ||
auto metadata = mPlatform->extractExternalImageMetadata(externalImage); | ||
auto imgData = mPlatform->createVkImageFromExternal(externalImage); | ||
|
||
assert_invariant(imgData.internal.valid() || imgData.external.valid()); | ||
|
||
VkFormat vkformat = metadata.format; | ||
VkImage vkimage = VK_NULL_HANDLE; | ||
VkDeviceMemory memory = VK_NULL_HANDLE; | ||
if (imgData.internal.valid()) { | ||
metadata.externalFormat = 0; | ||
vkimage = imgData.internal.image; | ||
memory = imgData.internal.memory; | ||
} else { | ||
vkformat = VK_FORMAT_UNDEFINED; | ||
vkimage = imgData.external.image; | ||
memory = imgData.external.memory; | ||
} | ||
|
||
VkSamplerYcbcrConversion const conversion = | ||
mExternalImageManager.getVkSamplerYcbcrConversion(metadata); | ||
|
||
auto newTexture = resource_ptr<VulkanTexture>::construct(&mResourceManager, mContext, | ||
mPlatform->getDevice(), mAllocator, &mResourceManager, &mCommands, vkimage, | ||
memory, vkformat, conversion, metadata.samples, metadata.width, | ||
metadata.height, metadata.layers, metadata.filamentUsage, mStagePool); | ||
|
||
// We shouldn't need to do this when we allocate the texture | ||
if (true) { | ||
auto& commands = mCommands.get(); | ||
// Unlike uploaded textures or swapchains, we need to explicit transition this | ||
// texture into the read layout. | ||
newTexture->transitionLayout(&commands, newTexture->getPrimaryViewRange(), | ||
VulkanLayout::FRAG_READ); | ||
} | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
if (imgData.external.valid()) { | ||
mExternalImageManager.addExternallySampledTexture(newTexture, externalImage); | ||
// Cache the AHB backed image. | ||
stream->pushImage(stream->getAcquired().image, newTexture); | ||
newImage = true; | ||
} | ||
|
||
newTexture.inc(); | ||
texture = newTexture; | ||
} | ||
|
||
mStreamedImageManager.onStreamAcquireImage(texture, stream, newImage); | ||
} | ||
mStreamsWithPendingAcquiredImage.clear(); | ||
} | ||
} | ||
|
||
void VulkanDriver::destroyFence(Handle<HwFence> fh) { | ||
|
@@ -1331,6 +1416,11 @@ TimerQueryResult VulkanDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint | |
} | ||
|
||
void VulkanDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) { | ||
auto t = resource_ptr<VulkanTexture>::cast(&mResourceManager, th); | ||
phoenixxxx marked this conversation as resolved.
Show resolved
Hide resolved
|
||
assert_invariant(t); | ||
auto s = resource_ptr<VulkanStream>::cast(&mResourceManager, sh); | ||
assert_invariant(s); | ||
t->setStream(s); | ||
} | ||
|
||
void VulkanDriver::generateMipmaps(Handle<HwTexture> th) { | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,83 @@ | ||
/* | ||
* Copyright (C) 2025 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#include "VulkanStreamedImageManager.h" | ||
|
||
#include "VulkanDescriptorSetCache.h" | ||
#include "VulkanExternalImageManager.h" | ||
#include "VulkanDescriptorSetLayoutCache.h" | ||
#include "VulkanSamplerCache.h" | ||
|
||
namespace filament::backend { | ||
VulkanStreamedImageManager::VulkanStreamedImageManager( | ||
VulkanExternalImageManager* manager, | ||
VulkanDescriptorSetCache* descriptorSet, | ||
VulkanSamplerCache* samplerCache) | ||
: mExternalImageManager(manager), | ||
mDescriptorSetCache(descriptorSet), | ||
mSamplerCache(samplerCache) { | ||
|
||
} | ||
|
||
VulkanStreamedImageManager::~VulkanStreamedImageManager() = default; | ||
|
||
void VulkanStreamedImageManager::terminate() {} | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
||
void VulkanStreamedImageManager::bindStreamedTexture( | ||
fvkmemory::resource_ptr<VulkanDescriptorSet> set, | ||
uint8_t bindingPoint, fvkmemory::resource_ptr<VulkanTexture> image, | ||
SamplerParams samplerParams) { | ||
mStreamedTexturesBindings.push_back({ bindingPoint, image, set, samplerParams }); | ||
} | ||
|
||
void VulkanStreamedImageManager::unbindStreamedTexture( | ||
fvkmemory::resource_ptr<VulkanDescriptorSet> set, | ||
uint8_t bindingPoint) { | ||
auto iter = std::remove_if(mStreamedTexturesBindings.begin(), mStreamedTexturesBindings.end(), | ||
[&](streamedTextureBinding& binding) { | ||
return ((binding.set == set) && (binding.binding == bindingPoint)); | ||
}); | ||
mStreamedTexturesBindings.erase(iter, mStreamedTexturesBindings.end()); | ||
} | ||
|
||
void VulkanStreamedImageManager::onStreamAcquireImage(fvkmemory::resource_ptr<VulkanTexture> image, | ||
fvkmemory::resource_ptr<VulkanStream> stream, bool newImage) { | ||
for (streamedTextureBinding const& data: mStreamedTexturesBindings) { | ||
if (data.image->getStream() == stream) { | ||
if (newImage) { | ||
mExternalImageManager->bindExternallySampledTexture(data.set, data.binding, image, | ||
data.samplerParams); | ||
} else { | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
// For some reason, some of the frames coming to us, are on streams where the | ||
// descriptor set isn't external... | ||
if (data.set->getExternalSamplerVkSet()) { | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
mDescriptorSetCache->updateSamplerForExternalSamplerSet(data.set, data.binding, | ||
image); | ||
} else { | ||
//... In this case we just default to using the normal path and update the | ||
//sampler. | ||
VulkanSamplerCache::Params cacheParams = { | ||
.sampler = data.samplerParams, | ||
}; | ||
VkSampler const vksampler = mSamplerCache->getSampler(cacheParams); | ||
mDescriptorSetCache->updateSampler(data.set, data.binding, image, vksampler); | ||
} | ||
} | ||
} | ||
} | ||
} | ||
|
||
} // namespace filament::backend |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,68 @@ | ||
/* | ||
* Copyright (C) 2025 The Android Open Source Project | ||
* | ||
* Licensed under the Apache License, Version 2.0 (the "License"); | ||
* you may not use this file except in compliance with the License. | ||
* You may obtain a copy of the License at | ||
* | ||
* http://www.apache.org/licenses/LICENSE-2.0 | ||
* | ||
* Unless required by applicable law or agreed to in writing, software | ||
* distributed under the License is distributed on an "AS IS" BASIS, | ||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||
* See the License for the specific language governing permissions and | ||
* limitations under the License. | ||
*/ | ||
|
||
#ifndef TNT_FILAMENT_BACKEND_CACHING_VULKANSTREAMEDIMAGEMANAGER_H | ||
#define TNT_FILAMENT_BACKEND_CACHING_VULKANSTREAMEDIMAGEMANAGER_H | ||
|
||
#include "VulkanHandles.h" | ||
|
||
#include <backend/DriverEnums.h> | ||
|
||
#include <array> | ||
#include <vector> | ||
|
||
namespace filament::backend { | ||
|
||
class VulkanExternalImageManager; | ||
class VulkanDescriptorSetCache; | ||
class VulkanSamplerCache; | ||
|
||
// Manages the logic of streamed and streamed images. | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
class VulkanStreamedImageManager { | ||
public: | ||
VulkanStreamedImageManager( | ||
VulkanExternalImageManager* manager, | ||
VulkanDescriptorSetCache* descriptorSet, | ||
VulkanSamplerCache* samplerCache); | ||
~VulkanStreamedImageManager(); | ||
void terminate(); | ||
|
||
public: | ||
void bindStreamedTexture(fvkmemory::resource_ptr<VulkanDescriptorSet> set, uint8_t bindingPoint, | ||
fvkmemory::resource_ptr<VulkanTexture> image, SamplerParams samplerParams); | ||
void unbindStreamedTexture(fvkmemory::resource_ptr<VulkanDescriptorSet> set, | ||
uint8_t bindingPoint); | ||
void onStreamAcquireImage(fvkmemory::resource_ptr<VulkanTexture> image, | ||
fvkmemory::resource_ptr<VulkanStream> stream, bool newImage); | ||
|
||
private: | ||
struct streamedTextureBinding { | ||
phoenixxxx marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
uint8_t binding = 0; | ||
fvkmemory::resource_ptr<VulkanTexture> image; | ||
fvkmemory::resource_ptr<VulkanDescriptorSet> set; | ||
SamplerParams samplerParams; | ||
}; | ||
// keep track of all the stream bindings | ||
std::vector<streamedTextureBinding> mStreamedTexturesBindings; | ||
|
||
VulkanExternalImageManager* mExternalImageManager; | ||
VulkanDescriptorSetCache* mDescriptorSetCache; | ||
VulkanSamplerCache* mSamplerCache; | ||
}; | ||
|
||
} // namespace filament::backend | ||
|
||
#endif // TNT_FILAMENT_BACKEND_CACHING_VULKANSTREAMEDIMAGEMANAGER_H |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.