Fix Android Vulkan blit synchronization and pipeline blits - #186
Draft
ruccho wants to merge 3 commits into
Draft
Conversation
…und trip On Android the blit path awaited the whole round trip inside `push`: the graphics event is drained once per frame on the C# side, the render thread executes it later, and the fence signals only after the GPU has also finished the work Unity submitted before it. Pushes are serialized by the encoder input lock, so the recording frame rate was capped at one frame per round trip (several frames), while the readback path overlaps its requests and was not affected. `push` now returns as soon as the event is issued. A completion task awaits the outstanding blits in issue order and queues each frame to MediaCodec, so successive frames overlap on the GPU. In-flight frames are bounded by a semaphore below the ImageWriter's max images so that `dequeueInputImage` never has to wait, and the dequeue itself runs on the blocking pool instead of an executor worker. End of stream is signalled by the completion task once the pending frames have been queued, since `Drop` cannot wait for them. Errors from the completion task are surfaced by the next `push`. Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
ruccho
force-pushed
the
feature/android-vulkan-blit-fixes
branch
from
September 11, 2026 09:47
96d6f39 to
bb8bbc8
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Stacked on #174 (
feature/native-logging);bb8bbc8switches the new code fromprintln!to thelogcrate introduced there.Fixes two problems in the Android Vulkan blit path (
unienc_android_mc), the readback-free path that renders the source texture into aHardwareBufferhanded to MediaCodec:pushawaited the whole GPU round trip and pushes are serialized, so the encoder could only accept one frame per round trip (several frames of latency).Synchronization with Unity and spec fixes (
47e7994)GraphicsQueueAccess::Allowandflags = ModifiesCommandBuffersStateonly, dropping the defaultEnsurePreviousFrameSubmission.vkQueueSubmitfrom the render thread could therefore race Unity's submission thread. The event now usesDontCarewith the default flags, and the submission goes throughIUnityGraphicsVulkan::AccessQueue(flush = true), which Unity invokes where queue access is guaranteed and after its own pending command buffers are submitted.VkImagewas read from the rawGetNativeTexturePtr()pointer with no layout transition or barrier while the descriptor declaredSHADER_READ_ONLY_OPTIMAL. It is now acquired throughAccessTexture(..., PipelineBarrier), so Unity records the transition and keeps tracking the layout. TheVkFormatreported by Unity replaces theGraphicsFormatmapping table.vkFreeCommandBuffersran on a blocking-pool thread while the render thread allocated from the sameVkCommandPool(externally synchronized object). Command buffers are now taken from a mutex-guarded pool and recycled after the fence signals instead of being freed.final_layoutwasPRESENT_SRC_KHRwhile the following release barrier declaredold_layout = COLOR_ATTACHMENT_OPTIMAL; both are nowCOLOR_ATTACHMENT_OPTIMAL.VK_QUEUE_FAMILY_EXTERNALusedVK_QUEUE_FAMILY_IGNOREDas the source; it now uses Unity's graphics queue family.Pipelined blits (
6bb84fe)pushreturns as soon as the graphics event is issued. A single completion task awaits the outstanding blits in issue order and queues each frame to MediaCodec, so successive frames overlap on the GPU and the recording frame rate follows the frame provider instead of the round-trip latency.MAX_BLITS_IN_FLIGHT = 2, below the ImageWriter'smax_images = 3) sodequeueInputImagenever has to wait; the dequeue itself runs on the blocking pool.Drop). Errors from the completion task are surfaced by the nextpush.Testing
cargo ndk -t aarch64-linux-android --platform 26 build/clippyforunienc_android_mcpass with no new warnings; hostcargo check -p unienc_cpasses.🤖 Generated with Claude Code