feat(encode): Vulkan Video B1 — RGB-direct encode source via VCN EFC (PUNKTFUNK_VULKAN_RGB_DIRECT=1)
apple / swift (push) Successful in 1m25s
windows-host / package (push) Successful in 11m6s
apple / screenshots (push) Successful in 6m55s
ci / web (push) Successful in 1m8s
ci / docs-site (push) Successful in 1m4s
decky / build-publish (push) Successful in 20s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 15s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
ci / rust (push) Failing after 10m50s
arch / build-publish (push) Successful in 14m36s
ci / bench (push) Successful in 6m3s
android / android (push) Successful in 15m19s
deb / build-publish-host (push) Successful in 9m39s
deb / build-publish (push) Successful in 10m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m53s
docker / deploy-docs (push) Successful in 18s
apple / swift (push) Successful in 1m25s
windows-host / package (push) Successful in 11m6s
apple / screenshots (push) Successful in 6m55s
ci / web (push) Successful in 1m8s
ci / docs-site (push) Successful in 1m4s
decky / build-publish (push) Successful in 20s
docker / build-push (--build-arg FEDORA_VERSION=44, ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora44-rpm) (push) Successful in 10s
docker / build-push (., web/Dockerfile, punktfunk-web) (push) Successful in 10s
docker / build-push (ci, ci/fedora-rpm.Dockerfile, punktfunk-fedora-rpm) (push) Successful in 11s
docker / build-push (ci, ci/rust-ci-noble.Dockerfile, punktfunk-rust-ci-noble) (push) Successful in 10s
docker / build-push (ci, ci/rust-ci.Dockerfile, punktfunk-rust-ci) (push) Successful in 15s
docker / build-push (docs-site, docs-site/Dockerfile, punktfunk-docs) (push) Successful in 10s
ci / rust (push) Failing after 10m50s
arch / build-publish (push) Successful in 14m36s
ci / bench (push) Successful in 6m3s
android / android (push) Successful in 15m19s
deb / build-publish-host (push) Successful in 9m39s
deb / build-publish (push) Successful in 10m24s
rpm / build-publish (43, bazzite, punktfunk-fedora-rpm) (push) Successful in 16m6s
rpm / build-publish (44, fedora-44, punktfunk-fedora44-rpm) (push) Successful in 15m53s
docker / deploy-docs (push) Successful in 18s
design/vulkan-rgb-direct-encode.md B1: when the probe passes AND
PUNKTFUNK_VULKAN_RGB_DIRECT=1 (default OFF until the B2 on-glass A/B),
the session opens with pictureFormat=B8G8R8A8 and the captured RGB frame
becomes the encode source — the VCN EFC front-end does the 709-narrow CSC
inline during encode. Deleted from the per-frame path: the compute CSC
dispatch, both NV12 plane copies, the semaphore hop and one queue submit
(dmabuf frames are ONE encode-queue submit; ~17 MB/frame of GPU traffic
gone). The DPB stays NV12; RFI/RC/quality-level machinery is untouched.
Shape:
- probe_rgb_direct now returns the chroma-siting bits to create the
session with (midpoint preferred, else cosited-even per axis); the open
verdict line gains "active" / "available(off; ...)" states.
- RgbProfileStack: the rgb-chained video profile rebuilt on the stack per
profiled-image creation after open (profile identity is by value) —
dmabuf imports become profiled VIDEO_ENCODE_SRC images (import cache
unchanged), the CPU staging image likewise (concurrent encode+compute).
- record_submit_rgb: steps 2–4 twin (dmabuf: single submit; CPU: staging
copy on the compute queue, semaphore-ordered); shared step-1/bookkeeping.
- begin_encode_cmd takes a SrcAcquire (CSC general / fresh-import FOREIGN
QFOT / cached visibility-only / staging TRANSFER_DST) so both paths
share the encode recording.
- RGB-direct frames skip the CSC per-slot resources entirely (make_frame
split into csc/common halves); cursor bitmaps warn once (EFC cannot
composite; gamescope — the flagship — embeds the cursor itself).
On-glass (780M RADV PHOENIX, host Mesa 26.0.4): all four smokes pass
(vulkan_smoke{,_av1,_rgb,_rgb_av1}); the EFC-encoded H265 stream decodes
clean and matches the CSC-encoded stream at 49.9 dB average PSNR (min
48.9) — within the design's ±1-code-value tolerance. (Raw-OBU ffmpeg
probing of the tiny AV1 dumps fails identically for BOTH paths —
pre-existing dump quirk, not a stream defect.) check+clippy+full unit
suite green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -77,6 +77,32 @@ pub(crate) unsafe fn import_rgb_dmabuf(
|
|||||||
d: &pf_frame::DmabufFrame,
|
d: &pf_frame::DmabufFrame,
|
||||||
cw: u32,
|
cw: u32,
|
||||||
ch: u32,
|
ch: u32,
|
||||||
|
) -> Result<(vk::Image, vk::DeviceMemory, vk::ImageView)> {
|
||||||
|
import_rgb_dmabuf_as(
|
||||||
|
device,
|
||||||
|
ext_fd,
|
||||||
|
mem_props,
|
||||||
|
d,
|
||||||
|
cw,
|
||||||
|
ch,
|
||||||
|
vk::ImageUsageFlags::SAMPLED,
|
||||||
|
None,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// [`import_rgb_dmabuf`] with the image usage explicit and an optional video-profile list
|
||||||
|
/// (chained into the image create) — the RGB-direct encode path imports the captured buffer
|
||||||
|
/// as a profiled `VIDEO_ENCODE_SRC` image instead of a sampled one.
|
||||||
|
#[allow(clippy::too_many_arguments)]
|
||||||
|
pub(crate) unsafe fn import_rgb_dmabuf_as(
|
||||||
|
device: &ash::Device,
|
||||||
|
ext_fd: &ash::khr::external_memory_fd::Device,
|
||||||
|
mem_props: &vk::PhysicalDeviceMemoryProperties,
|
||||||
|
d: &pf_frame::DmabufFrame,
|
||||||
|
cw: u32,
|
||||||
|
ch: u32,
|
||||||
|
usage: vk::ImageUsageFlags,
|
||||||
|
profile_list: Option<&mut vk::VideoProfileListInfoKHR>,
|
||||||
) -> Result<(vk::Image, vk::DeviceMemory, vk::ImageView)> {
|
) -> Result<(vk::Image, vk::DeviceMemory, vk::ImageView)> {
|
||||||
use anyhow::Context;
|
use anyhow::Context;
|
||||||
use std::os::fd::IntoRawFd;
|
use std::os::fd::IntoRawFd;
|
||||||
@@ -90,26 +116,27 @@ pub(crate) unsafe fn import_rgb_dmabuf(
|
|||||||
.plane_layouts(&plane);
|
.plane_layouts(&plane);
|
||||||
let mut ext = vk::ExternalMemoryImageCreateInfo::default()
|
let mut ext = vk::ExternalMemoryImageCreateInfo::default()
|
||||||
.handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
.handle_types(vk::ExternalMemoryHandleTypeFlags::DMA_BUF_EXT);
|
||||||
let img = device.create_image(
|
let mut ci = vk::ImageCreateInfo::default()
|
||||||
&vk::ImageCreateInfo::default()
|
.image_type(vk::ImageType::TYPE_2D)
|
||||||
.image_type(vk::ImageType::TYPE_2D)
|
.format(fmt)
|
||||||
.format(fmt)
|
.extent(vk::Extent3D {
|
||||||
.extent(vk::Extent3D {
|
width: cw,
|
||||||
width: cw,
|
height: ch,
|
||||||
height: ch,
|
depth: 1,
|
||||||
depth: 1,
|
})
|
||||||
})
|
.mip_levels(1)
|
||||||
.mip_levels(1)
|
.array_layers(1)
|
||||||
.array_layers(1)
|
.samples(vk::SampleCountFlags::TYPE_1)
|
||||||
.samples(vk::SampleCountFlags::TYPE_1)
|
.tiling(vk::ImageTiling::DRM_FORMAT_MODIFIER_EXT)
|
||||||
.tiling(vk::ImageTiling::DRM_FORMAT_MODIFIER_EXT)
|
.usage(usage)
|
||||||
.usage(vk::ImageUsageFlags::SAMPLED)
|
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
||||||
.sharing_mode(vk::SharingMode::EXCLUSIVE)
|
.initial_layout(vk::ImageLayout::UNDEFINED)
|
||||||
.initial_layout(vk::ImageLayout::UNDEFINED)
|
.push_next(&mut ext)
|
||||||
.push_next(&mut ext)
|
.push_next(&mut drm);
|
||||||
.push_next(&mut drm),
|
if let Some(pl) = profile_list {
|
||||||
None,
|
ci = ci.push_next(pl);
|
||||||
)?;
|
}
|
||||||
|
let img = device.create_image(&ci, None)?;
|
||||||
// dup the fd; Vulkan takes ownership of the dup on a successful import.
|
// dup the fd; Vulkan takes ownership of the dup on a successful import.
|
||||||
let dup = d.fd.try_clone().context("dup dmabuf fd")?.into_raw_fd();
|
let dup = d.fd.try_clone().context("dup dmabuf fd")?.into_raw_fd();
|
||||||
let fd_props = {
|
let fd_props = {
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user