Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Conversation

@jonahwilliams
Copy link
Contributor

@jonahwilliams jonahwilliams commented Sep 29, 2023

Fixes flutter/flutter#133101

Adds an API for reading the base mip level in whatever format a texture happens to be in.

@jonahwilliams jonahwilliams changed the title [Impeller] add Texture::GetContents for readback. [Impeller] add Context::GetTextureContents for readback. Sep 29, 2023
jonahwilliams added 2 commits September 28, 2023 20:27
return false;
}

void Context::GetTextureContents(const std::shared_ptr<Texture>& texture,
Copy link
Contributor Author

Choose a reason for hiding this comment

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

We have something similar implemented in image_decode_impeller.cc, eventually we need to get rid of that and replace with our own logic to convert pixel formats. I'm not sure if the Skia implementation is unintentionally pulling in the software renderer.

@jonahwilliams jonahwilliams marked this pull request as ready for review September 29, 2023 17:12
@jonahwilliams
Copy link
Contributor Author

Maybe we can do something like an MPSImageConversion on iOS, but probably want to avoid really slow pixel conversions.

@jonahwilliams
Copy link
Contributor Author

Actually we can just do the conversion in the blit pass.

@jonahwilliams
Copy link
Contributor Author

Looks like Metal blit passes wont do format conversions so I'd need to do a render pass. Maybe a separate helper to convert texture format a to format b, then we can have platform specific implementations.

@jonahwilliams
Copy link
Contributor Author

Filled flutter/flutter#135764

return;
}

if (!blit_pass->AddCopy(texture, device_buffer)) {
Copy link
Member

Choose a reason for hiding this comment

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

Does a texture->device buffer blit actually force a transfer from the device to the host? If it does, I really think that behavior should be decoupled (not now, but later). But if it doesn't force a host transfer, I don't think this patch will work?

Copy link
Member

Choose a reason for hiding this comment

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

Also, no cap check needed here (like SupportsBufferToTextureBlits)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

No, this is supported on all backends from my inspection. If it didn't work, then the test would be failing, no?

Copy link
Member

@bdero bdero Sep 29, 2023

Choose a reason for hiding this comment

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

For fixing up the blits (later), I think a good solution would be to have two different AddCopy overloads: One that only copies to the host, and another that only copies to a new device allocation. Copying to both should never be necessary.

  bool AddCopy(std::shared_ptr<Texture> source,
               std::vector<uint8_t>& destination,
               std::optional<IRect> source_region = std::nullopt,
               IPoint destination_origin = {},
               std::string label = "");

Copy link
Member

Choose a reason for hiding this comment

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

Made a follow-up issue about this here: flutter/flutter#135783

return false;
}

void Context::GetTextureContents(const std::shared_ptr<Texture>& texture,
Copy link
Member

Choose a reason for hiding this comment

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

As implemented, a more appropriate name would be CopyToDeviceBuffer.

virtual std::shared_ptr<CommandBuffer> CreateCommandBuffer() const = 0;

using ReadbackCallback =
std::function<void(std::shared_ptr<const DeviceBuffer> buffer)>;
Copy link
Member

Choose a reason for hiding this comment

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

Should this API emit a constant copy of the host byte data rather than a DeviceBuffer? I believe later we we can remove the unnecessary blit on all of the backends and even support onscreen textures on GLES.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I believe later we we can remove the unnecessary blit on all of the backends and even support onscreen textures on GLES.

What?

Copy link
Member

@bdero bdero Sep 29, 2023

Choose a reason for hiding this comment

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

Sorry, I meant we can get rid of the device->device copy, as blitting to a DeviceBuffer implies.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Ahh yeah makes sense. I went back and forth a few times on what the API should be. This actually needs to end up as. a unique_ptr of something, so that I can use the Dart typed data APIs for readback (eventually). So If I change this to be something like std::unique_ptr<const uint8_t[]> or whatever, I don't know C++ , that should all work nicely right?

Copy link
Member

Choose a reason for hiding this comment

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

Yeah, we could also just return an std::vector<uint8_t> and just use move semantics to avoid copies when it makes sense, especially since we're getting pretty good help from clang tidy in that department at this point.

Copy link
Member

Choose a reason for hiding this comment

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

This kind of thing would jive well with a non-DeviceBuffer variant of AddCopy I mentioned above. Might as well eat an extra copy on the host for now and fix both the copies later. :)

@chinmaygarde chinmaygarde changed the title [Impeller] add Context::GetTextureContents for readback. [Impeller] Add Context::GetTextureContents for readback. Sep 29, 2023
@jonahwilliams jonahwilliams added the Work in progress (WIP) Not ready (yet) for review! label Sep 29, 2023
@jonahwilliams
Copy link
Contributor Author

Moving to WIP while I iterate on some stuff

auto size = GetDeviceBufferDescriptor().size;
auto raw_data = static_cast<uint8_t*>(malloc(size));
memcpy(raw_data, OnGetContents(), size);
return std::unique_ptr<const uint8_t[]>(raw_data);
Copy link
Contributor Author

Choose a reason for hiding this comment

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

This is leaking right now because I need to give it a release proc

Copy link
Member

@bdero bdero Sep 30, 2023

Choose a reason for hiding this comment

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

Rather than lugging around a device allocation ref, you could just eat an extra host copy now and we can repair this later when we fix up the blits.

@jonahwilliams
Copy link
Contributor Author

I think I might find a way to move this to texture.h too.

@jonahwilliams
Copy link
Contributor Author

actually it looks like only vulkan textures have a weak ptr to their context, gles and mtl textures do not. I could add more weak ptrs, but it would really only be in service of making the API slightly more ergonomic.

jonahwilliams added 2 commits September 29, 2023 17:59
@jonahwilliams
Copy link
Contributor Author

The failing tests are entirely mock based. We should migrate them to dart:ui tests once flutter_tester supports impeller, but until then I'll leave the old readback approach.

@zanderso
Copy link
Member

zanderso commented Nov 2, 2023

@jonahwilliams What's the status of this PR?

@jonahwilliams
Copy link
Contributor Author

This is still a WIP

@jonahwilliams jonahwilliams marked this pull request as draft November 3, 2023 02:10
@jonahwilliams
Copy link
Contributor Author

Closing as I don't have time to work on this right now

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

e: impeller Work in progress (WIP) Not ready (yet) for review!

Projects

No open projects
Archived in project

Development

Successfully merging this pull request may close these issues.

[Impeller] Add Texture::GetContents for host-readable textures.

3 participants