Skip to content
Open
Show file tree
Hide file tree
Changes from 88 commits
Commits
Show all changes
89 commits
Select commit Hold shift + click to select a range
6218164
Adding the begin frame message for later xtrace post processing.
phoenixxxx Jun 4, 2024
e265850
Merge branch 'main' into main
phoenixxxx Jun 4, 2024
8671617
Merge branch 'main' into main
poweifeng Jun 5, 2024
d49554d
Merge branch 'main' into main
poweifeng Jun 5, 2024
4fccd95
Merge branch 'google:main' into main
phoenixxxx Jun 11, 2024
96cba96
Merge branch 'google:main' into main
phoenixxxx Jun 18, 2024
abe8a49
Merge branch 'google:main' into main
phoenixxxx Jun 27, 2024
c81cedd
Merge branch 'google:main' into main
phoenixxxx Sep 4, 2024
387942c
Merge branch 'google:main' into main
phoenixxxx Sep 21, 2024
0fdf1ca
Merge branch 'google:main' into main
phoenixxxx Oct 3, 2024
8bc4d3a
Merge branch 'google:main' into main
phoenixxxx Oct 9, 2024
9e92193
Merge branch 'google:main' into main
phoenixxxx Oct 18, 2024
01a2480
Merge branch 'google:main' into main
phoenixxxx Oct 26, 2024
48bb10a
Merge branch 'google:main' into main
phoenixxxx Oct 30, 2024
ff145f6
Merge branch 'google:main' into main
phoenixxxx Oct 31, 2024
c5c2d42
Merge branch 'google:main' into main
phoenixxxx Nov 5, 2024
3b0e44c
Merge branch 'google:main' into main
phoenixxxx Nov 5, 2024
80803f9
Merge branch 'google:main' into main
phoenixxxx Nov 6, 2024
ad3a5b7
Merge branch 'google:main' into main
phoenixxxx Dec 3, 2024
be6b6ae
Merge branch 'google:main' into main
phoenixxxx Dec 19, 2024
021c4f6
Merge branch 'google:main' into main
phoenixxxx Jan 13, 2025
0a661c1
Merge branch 'google:main' into main
phoenixxxx Jan 27, 2025
ea4c20e
Merge branch 'google:main' into main
phoenixxxx Jan 30, 2025
ba99844
Merge branch 'google:main' into main
phoenixxxx Mar 6, 2025
cfe6a42
Merge branch 'google:main' into main
phoenixxxx Mar 6, 2025
7f7dadd
Merge branch 'google:main' into main
phoenixxxx Mar 14, 2025
b570d48
Merge branch 'google:main' into main
phoenixxxx Mar 17, 2025
b09cbaf
Merge branch 'google:main' into main
phoenixxxx Mar 18, 2025
13e1d2a
Merge branch 'google:main' into main
phoenixxxx Mar 21, 2025
ff2827b
Merge branch 'google:main' into main
phoenixxxx Mar 28, 2025
55fc91b
Merge branch 'google:main' into main
phoenixxxx May 8, 2025
bcae04c
Merge branch 'google:main' into main
phoenixxxx May 12, 2025
2fac13e
Merge branch 'google:main' into main
phoenixxxx Aug 1, 2025
d45a265
First commit
phoenixxxx Aug 5, 2025
c00afac
This is not needed
phoenixxxx Aug 6, 2025
84fc69e
Bypass the AHB* issue.
phoenixxxx Aug 6, 2025
1b4f88b
Typo: Forgot to remove the function.
phoenixxxx Aug 6, 2025
839867e
Typo: No const specifier.
phoenixxxx Aug 6, 2025
397282a
Removing the const.
phoenixxxx Aug 6, 2025
75fdacb
no exception
phoenixxxx Aug 6, 2025
111ac62
Merge branch 'google:main' into main
phoenixxxx Aug 7, 2025
19cbb94
Merge branch 'main' into streamed_texture
phoenixxxx Aug 7, 2025
c612bfd
Feedback from discussions with Powei.
phoenixxxx Aug 11, 2025
3c93f00
Making the changes discussed with the team.
phoenixxxx Aug 12, 2025
487fb27
Merge branch 'google:main' into main
phoenixxxx Aug 12, 2025
fbf2f0d
Merge branch 'main' into streamed_texture
phoenixxxx Aug 12, 2025
8b6fa40
Removing useless comments.
phoenixxxx Aug 12, 2025
f548c58
Merge branch 'google:main' into main
phoenixxxx Aug 13, 2025
bee08b4
Merge branch 'main' into streamed_texture
phoenixxxx Aug 13, 2025
76fc21a
Adding the required methods for allocation.
phoenixxxx Aug 14, 2025
5858acf
Forgot one more switch case.
phoenixxxx Aug 14, 2025
e441cbb
Moving the resource to –fvkmemory::Resource type.
phoenixxxx Aug 15, 2025
5a0f78d
Merge branch 'google:main' into main
phoenixxxx Aug 18, 2025
865cb0a
Adding streamed set.
phoenixxxx Aug 18, 2025
a220f70
Merge branch 'main' into streamed_texture
phoenixxxx Aug 18, 2025
c6d0127
Allocating every frame for streamed textures.
phoenixxxx Aug 19, 2025
8017d5e
Changing the binding logic.
phoenixxxx Aug 20, 2025
ad57838
Proper checks for the streamed texture.
phoenixxxx Aug 25, 2025
0210611
Merge branch 'google:main' into main
phoenixxxx Aug 25, 2025
1e5d37a
Merge branch 'main' into streamed_texture
phoenixxxx Aug 25, 2025
29e3f07
Cleanup.
phoenixxxx Aug 25, 2025
406a348
Chaning the logic of the state tracking for streamed textures.
phoenixxxx Aug 28, 2025
3a1aebe
Fixed full screen bug.
phoenixxxx Aug 28, 2025
0c07c3f
Refactoring of the code.
phoenixxxx Aug 29, 2025
f503205
Merge branch 'google:main' into main
phoenixxxx Aug 29, 2025
6e8959e
Merge branch 'main' into streamed_texture
phoenixxxx Aug 29, 2025
39be20b
Typo.
phoenixxxx Aug 29, 2025
db83dc0
GitHub feedback.
phoenixxxx Sep 4, 2025
54c636d
Merge branch 'google:main' into main
phoenixxxx Sep 4, 2025
562eeed
Merge branch 'main' into streamed_texture
phoenixxxx Sep 4, 2025
74ffe4e
Github feedback
phoenixxxx Sep 5, 2025
32ca1d3
feedback.
phoenixxxx Sep 5, 2025
3457700
Typo
phoenixxxx Sep 5, 2025
85c899a
Feedback.
phoenixxxx Sep 9, 2025
0ba9c2a
Feedback.
phoenixxxx Sep 9, 2025
78d5e34
Feedback
phoenixxxx Sep 11, 2025
1216024
Feedback
phoenixxxx Sep 12, 2025
e022396
Feedback
phoenixxxx Sep 15, 2025
48cd99a
Fixing the Android path.
phoenixxxx Sep 18, 2025
83a89b5
Fixing the Android path.
phoenixxxx Sep 18, 2025
1a390f4
Feedback.
phoenixxxx Sep 19, 2025
c9b3104
Merge branch 'google:main' into main
phoenixxxx Sep 19, 2025
0a11d0c
Merge branch 'main' into streamed_texture
phoenixxxx Sep 19, 2025
86f0afe
feedback
phoenixxxx Sep 19, 2025
44b506b
Feedback.
phoenixxxx Sep 22, 2025
df284fe
Nit
phoenixxxx Sep 22, 2025
f96afef
Feedback
phoenixxxx Sep 23, 2025
e4f29b0
Feedback
phoenixxxx Sep 24, 2025
56831e2
Feedback
phoenixxxx Sep 25, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions filament/backend/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -199,6 +199,8 @@ if (FILAMENT_SUPPORTS_VULKAN)
src/vulkan/VulkanDriverFactory.h
src/vulkan/VulkanExternalImageManager.cpp
src/vulkan/VulkanExternalImageManager.h
src/vulkan/VulkanStreamedImageManager.cpp
src/vulkan/VulkanStreamedImageManager.h
src/vulkan/VulkanFboCache.cpp
src/vulkan/VulkanFboCache.h
src/vulkan/VulkanHandles.cpp
Expand Down
3 changes: 3 additions & 0 deletions filament/backend/include/backend/Platform.h
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,9 @@ class UTILS_PUBLIC Platform {
ExternalImageHandle& operator=(ExternalImageHandle const& rhs) noexcept;
ExternalImageHandle& operator=(ExternalImageHandle&& rhs) noexcept;

bool operator==(const ExternalImageHandle& rhs) const noexcept {
return mTarget == rhs.mTarget;
}
explicit operator bool() const noexcept { return mTarget != nullptr; }

ExternalImage* UTILS_NULLABLE get() noexcept { return mTarget; }
Expand Down
163 changes: 161 additions & 2 deletions filament/backend/src/vulkan/VulkanDriver.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@
#include "vulkan/memory/ResourcePointer.h"
#include "vulkan/utils/Conversion.h"
#include "vulkan/utils/Definitions.h"
#include "vulkan/utils/Image.h"

#include <backend/DriverEnums.h>
#include <backend/platforms/VulkanPlatform.h>
Expand Down Expand Up @@ -145,6 +146,31 @@ static CallbackHandler::Callback syncCallbackWrapper = [](void* userData) {
cbData->cb(cbData->sync, cbData->userData);
};

// This needs to be discussed because Vulkan has different default Matrix formats
// right now this is following GL.
static void copyMat3f(void* addr, size_t const offset, const math::mat3f& v) noexcept {
struct mat43 {
float v[3][4];
};

addr = static_cast<char*>(addr) + offset;
mat43& temp = *static_cast<mat43*>(addr);

temp.v[0][0] = v[0][0];
temp.v[0][1] = v[0][1];
temp.v[0][2] = v[0][2];

temp.v[1][0] = v[1][0];
temp.v[1][1] = v[1][1];
temp.v[1][2] = v[1][2];

temp.v[2][0] = v[2][0];
temp.v[2][1] = v[2][1];
temp.v[2][2] = v[2][2];

// don't store anything in temp.v[][3] because there could be uniforms packed there
}

}// anonymous namespace

#if FVK_ENABLED(FVK_DEBUG_DEBUG_UTILS)
Expand Down Expand Up @@ -239,6 +265,7 @@ VulkanDriver::VulkanDriver(VulkanPlatform* platform, VulkanContext& context,
mQueryManager(mPlatform->getDevice()),
mExternalImageManager(platform, &mSamplerCache, &mYcbcrConversionCache, &mDescriptorSetCache,
&mDescriptorSetLayoutCache),
mStreamedImageManager(&mExternalImageManager, &mDescriptorSetCache, &mSamplerCache),
mIsSRGBSwapChainSupported(mPlatform->getCustomization().isSRGBSwapChainSupported),
mIsMSAASwapChainSupported(false), // TODO: support MSAA swapchain
mStereoscopicType(driverConfig.stereoscopicType) {
Expand Down Expand Up @@ -466,13 +493,17 @@ void VulkanDriver::updateDescriptorSetTexture(
if (UTILS_UNLIKELY(mExternalImageManager.isExternallySampledTexture(texture))) {
mExternalImageManager.bindExternallySampledTexture(set, binding, texture, params);
mAppState.hasBoundExternalImages = true;
} else if (bool(texture->getStream())) {
Copy link
Contributor

Choose a reason for hiding this comment

The 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?

Copy link
Contributor Author

Choose a reason for hiding this comment

The 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:

    1. From a format
    1. From an external image
    1. By setting a stream
      Although you could logically do 2) and then set a stream via 3, I question the meaning of that.

mStreamedImageManager.bindStreamedTexture(set, binding, texture, params);
mAppState.hasBoundExternalImages = true;
} else {
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);
}
}

Expand Down Expand Up @@ -1050,6 +1081,12 @@ void VulkanDriver::destroySwapChain(Handle<HwSwapChain> sch) {
}

void VulkanDriver::destroyStream(Handle<HwStream> sh) {
FVK_SYSTRACE_SCOPE();
if (!sh) {
return;
}
auto stream = resource_ptr<VulkanStream>::cast(&mResourceManager, sh);
stream.dec();
}

void VulkanDriver::destroySync(Handle<HwSync> sh) {
Expand Down Expand Up @@ -1087,25 +1124,112 @@ void VulkanDriver::destroyDescriptorSet(Handle<HwDescriptorSet> dsh) {
}

Handle<HwStream> VulkanDriver::createStreamNative(void* nativeStream, utils::CString tag) {
FILAMENT_CHECK_PRECONDITION(false) << "createStreamNative not supported in Vulkan.";
return {};
}

Handle<HwStream> VulkanDriver::createStreamAcquired(utils::CString tag) {
return {};
// @TODO This is still not thread-safe. We might have to revisit this question.
FVK_SYSTRACE_SCOPE();
auto handle = mResourceManager.allocHandle<VulkanStream>();
auto stream = resource_ptr<VulkanStream>::make(&mResourceManager, handle);
stream.inc();
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);
assert_invariant(stream->streamType == StreamType::ACQUIRED);
assert_invariant(image != nullptr);
// This covers the case where setAcquiredImage is called back to back (no updateStreams in between)
if (stream->previousNeedsRelease()) {
scheduleRelease(stream->takePrevious());
}
stream->acquire({ image, cb, userData, handler});
stream->setFrontEndTransform(transform);
mStreamsWithPendingAcquiredImage.push_back(stream);
}

void VulkanDriver::setStreamDimensions(Handle<HwStream> sh, uint32_t width, uint32_t height) {
FVK_SYSTRACE_SCOPE();
auto stream = resource_ptr<VulkanStream>::cast(&mResourceManager, sh);
stream->width = width;
stream->height = height;
}

int64_t VulkanDriver::getStreamTimestamp(Handle<HwStream> sh) {
return 0;
}

void VulkanDriver::updateStreams(CommandStream* driver) {
FVK_SYSTRACE_SCOPE();
if (UTILS_UNLIKELY(!mStreamsWithPendingAcquiredImage.empty())) {
for (auto& stream: mStreamsWithPendingAcquiredImage) {
if (stream->previousNeedsRelease()) {
scheduleRelease(stream->takePrevious());
}

// This executes on the backend thread (updateStreams is synchonous which means it
// executes on the user thread) Note: stream is captured by copy which is fine, this is
// a copy of a resource_ptr<VulkanStream>. We only need it find the associated stream
// inside the mStreamedImageManager texture bindings
driver->queueCommand([this, stream, s = stream.get(),
image = stream->getAcquired().image,
transform = stream->getFrontEndTransform()]() {
auto texture = s->getTexture(image);
s->setBackendTransform(transform);
if (!texture) {
auto externalImage = fvkutils::createExternalImageFromRaw(mPlatform, 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);

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);

if (imgData.external.valid()) {
mExternalImageManager.addExternallySampledTexture(newTexture,
externalImage);
// Cache the AHB backed image. Acquires the image here.
s->pushImage(image, newTexture);
}

texture = newTexture;
}

mStreamedImageManager.onStreamAcquireImage(texture, stream);
});
}
mStreamsWithPendingAcquiredImage.clear();
}
}

void VulkanDriver::destroyFence(Handle<HwFence> fh) {
Expand Down Expand Up @@ -1378,7 +1502,9 @@ void VulkanDriver::updateIndexBuffer(Handle<HwIndexBuffer> ibh, BufferDescriptor

void VulkanDriver::registerBufferObjectStreams(Handle<HwBufferObject> boh,
BufferObjectStreamDescriptor&& streams) {
// Noop

auto bo = resource_ptr<VulkanBufferObject>::cast(&mResourceManager, boh);
mStreamUniformDescriptors[bo.get()] = std::move(streams);
}

void VulkanDriver::updateBufferObject(Handle<HwBufferObject> boh, BufferDescriptor&& bd,
Expand All @@ -1389,6 +1515,33 @@ void VulkanDriver::updateBufferObject(Handle<HwBufferObject> boh, BufferDescript
commands.acquire(bo);
bo->loadFromCpu(commands, bd.buffer, byteOffset, bd.size);

if (UTILS_UNLIKELY(!mStreamUniformDescriptors.empty())) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

shouldnt the copyMat3f happen before bo->loadFromCpu?
right now its copying the current bd.buffer to the gpu memory and then its updating the transform

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes that's right, good catch.

auto streamDescriptors = mStreamUniformDescriptors.find(bo.get());
if (streamDescriptors != mStreamUniformDescriptors.end()) {
for (auto const& [offset, streamHandle, associationType]:
streamDescriptors->second.mStreams) {
if (associationType == BufferObjectStreamAssociationType::TRANSFORM_MATRIX) {
math::mat3f transform;
if (streamHandle) {
auto stream =
resource_ptr<VulkanStream>::cast(&mResourceManager, streamHandle);
if (stream->streamType == StreamType::NATIVE) {
FILAMENT_CHECK_PRECONDITION(false)
<< "Native Stream not supported in Vulkan.";
} else {
// Backend call since getStreamTransformMatrix is called from async
// updateBufferObject.
transform = stream->getBackEndTransform();
}
}

copyMat3f(bd.buffer, offset, transform);
}
}
mStreamUniformDescriptors.erase(streamDescriptors);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

why do we have to erase this?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So the logic is that the user has to submit an update to the stream descriptor every time the xform changes. Once we process it, we can remove it from the list.

}
}

scheduleDestroy(std::move(bd));
}

Expand Down Expand Up @@ -1454,6 +1607,12 @@ TimerQueryResult VulkanDriver::getTimerQueryValue(Handle<HwTimerQuery> tqh, uint
}

void VulkanDriver::setExternalStream(Handle<HwTexture> th, Handle<HwStream> sh) {
FVK_SYSTRACE_SCOPE();
auto t = resource_ptr<VulkanTexture>::cast(&mResourceManager, th);
assert_invariant(t);
auto s = resource_ptr<VulkanStream>::cast(&mResourceManager, sh);
assert_invariant(s);
t->setStream(s);
}

void VulkanDriver::generateMipmaps(Handle<HwTexture> th) {
Expand Down
11 changes: 11 additions & 0 deletions filament/backend/src/vulkan/VulkanDriver.h
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@
#include "vulkan/VulkanDescriptorSetCache.h"
#include "vulkan/VulkanDescriptorSetLayoutCache.h"
#include "vulkan/VulkanExternalImageManager.h"
#include "vulkan/VulkanStreamedImageManager.h"
#include "vulkan/VulkanPipelineLayoutCache.h"
#include "vulkan/memory/ResourceManager.h"
#include "vulkan/memory/ResourcePointer.h"
Expand Down Expand Up @@ -153,6 +154,12 @@ class VulkanDriver final : public DriverBase {
VulkanDescriptorSetCache mDescriptorSetCache;
VulkanQueryManager mQueryManager;
VulkanExternalImageManager mExternalImageManager;
VulkanStreamedImageManager mStreamedImageManager;

// Stream transforms
std::unordered_map<VulkanBufferObject*, BufferObjectStreamDescriptor> mStreamUniformDescriptors;
math::mat3f getStreamTransformMatrix(Handle<HwStream> sh);


// This is necessary for us to write to push constants after binding a pipeline.
using DescriptorSetLayoutHandleList = std::array<resource_ptr<VulkanDescriptorSetLayout>,
Expand Down Expand Up @@ -189,6 +196,10 @@ class VulkanDriver final : public DriverBase {
bool const mIsSRGBSwapChainSupported;
bool const mIsMSAASwapChainSupported;
backend::StereoscopicType const mStereoscopicType;

// setAcquiredImage is a DECL_DRIVER_API_SYNCHRONOUS_N which means we don't necessarily have the
// data to process it at call time. So we store it and process it during updateStreams.
std::vector<resource_ptr<VulkanStream>> mStreamsWithPendingAcquiredImage;
};

} // namespace filament::backend
Expand Down
12 changes: 11 additions & 1 deletion filament/backend/src/vulkan/VulkanExternalImageManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,7 +261,17 @@ void VulkanExternalImageManager::bindExternallySampledTexture(
fvkmemory::resource_ptr<VulkanTexture> image, SamplerParams samplerParams) {
// Should we do duplicate validation here?
auto& imageData = findImage(mImages, image);
mSetBindings.push_back({ bindingPoint, imageData.image, set, samplerParams });
auto itr = std::find_if(mSetBindings.begin(), mSetBindings.end(),
[&](SetBindingInfo const& binding) {
return (binding.set == set && binding.binding == bindingPoint);
});
if (itr == mSetBindings.end()) {
mSetBindings.push_back({ bindingPoint, imageData.image, set, samplerParams });
} else {
// override the image data in the binding point
itr->image = image;
itr->samplerParams = samplerParams;
}
}

void VulkanExternalImageManager::addExternallySampledTexture(
Expand Down
2 changes: 1 addition & 1 deletion filament/backend/src/vulkan/VulkanExternalImageManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ class VulkanSamplerCache;
class VulkanDescriptorSetLayoutCache;
class VulkanDescriptorSetCache;

// Manages the logic of external images and their quirks wrt Vulikan.
// Manages the logic of external images and their quirks wrt Vulkan.
class VulkanExternalImageManager {
public:

Expand Down
Loading