feat: depth-2 encoder pipelining#12
Conversation
|
hi i've noticed issues when using this PR in my moonshine build and was able to resolve it with porkloin#1 . I haven't benchmarked it yet but it takes away the issue I had with the stream freezing after a while. i would be happy to benchmark and refine the implementaiton with your help (or you could do it if you like) once your new benchmarker for the moonshine refactor is ready. |
|
I'd like to see this PR move forward personally as well, atleast before I start making bigger overarching improvements to the project code so there's less conflicts (i.e. 2024 edition update, ash crate update..). If you're busy with life @porkloin - maybe @urwrstkn8mare can have the go-ahead to bring the improvements in, alternatively if you're both busy I can make new PR bringing in porkloin#1 and this PR combined into single one. |
|
yeah i was actually working on a PR that was essentially a complete reimplementation updated for pixelforge v0.6.0. This was because I couldn't really keep my branch up to date without bringing in upstream changes to my PR against porkloin's PR - which means I couldn't really use it on my moonshine dev branch which I use as a daily :(. i'll try getting it done EOD |
|
I can only superficially review this PR, which has been blocking me from actually merging it. I like the concept, even though I think there is likely a different underlying issue for the latency in moonshine that is not solved by this. @DatCaptainHorse (and maybe @urwrstkn8mare ?), would you mind reviewing this PR? It would be good to have an extra set of eyes on it. This is besides the work to bring it up-to-date on v0.6.0. |
|
I'm working on a complete reimplementation that should consolidate a bunch of logic and make it easier to review. 🙏 |
|
@hgaiser @DatCaptainHorse PR created 🎊 |
|
Closing in favor of #21 . Regardless, thanks! |
Smaller scope followup to #10 that only includes encoder pipelining at depth-2.
This allows the next frame to begin being processed by the encoder before the current frame is complete.
As with #10, this aims to address latency in situations where the GPU is saturated by rendering work, and especially in cases where the frame budget is tight (4k 175 fps, for example).
Each codec encoder (H.264, H.265, AV1) gets a pair of slots; each slot owns its own command buffer, query pool, fence, bitstream buffer, input image, and DPB output slot.
encode()becomes:Unlike #10, this is a non-breaking change for
Encoder::encode(), the single arg function signature remains the same. This also doesn't touch the converter process or do any parallel convert/encode.There is a real trade off with this approach: since frames are functionally arriving 1 frame late, end-to-end latency will rise by whatever the current host processing latency is. However, the increased throughput should make this a worthwhile tradeoff.
Benchmarking:
I've been benchmarking this with moonshine pull 77 which adds the ability to benchmark without a real moonlight client.
The important part about benchmarking this is to make sure you have a benchmark workload that completely saturates your GPU to the point that the real host encoder latency begins to exceed the frame budget for the requested framerate. For me on an AMD 9070XT, gravitybench at 4K HDR 175 with raytracing has worked well for getting those conditions with a bench-friendly executable.
Steps to benchmark:
pixelforge = { git = "https://github.com/porkloin/pixelforge", branch = "pipelining", features = ["dmabuf"] }cargo build --release --bin moonshine./target/release/moonshine /path/to/config.toml bench --duration 30 --warmup 5 --codec hevc --resolution 3840x2160 --fps 175 --hdr /path/to/gravitymark/run_fullscreen_vk_rt.sh -close 0My results:
With this PR:
Without this PR:
Consolidated Results:
With this PR:
Without this PR: