Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Add copy buttons to all
 blocks
(function() {
function addCopyButtons() {
document.querySelectorAll('pre code').forEach(function(codeBlock) {
if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;
codeBlock.parentElement.setAttribute('data-copy-added', 'true');
var btn = document.createElement('button');
btn.textContent = 'Copy';
btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';
btn.onmouseover = function() { this.style.opacity = '1'; };
btn.onmouseout = function() { this.style.opacity = '0.7'; };
btn.onclick = function() {
navigator.clipboard.writeText(codeBlock.textContent).then(function() {
btn.textContent = 'Copied!';
setTimeout(function() { btn.textContent = 'Copy'; }, 1500);
});
};
codeBlock.parentElement.style.position = 'relative';
codeBlock.parentElement.appendChild(btn);
});
}
addCopyButtons();
// Re-run on dynamic content
var observer = new MutationObserver(addCopyButtons);
observer.observe(document.body, { childList: true, subtree: true });
})();
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Force GitHub README to respect dark mode (function() { var style = document.createElement('style'); style.textContent = ' .markdown-body { color-scheme: dark light; } .markdown-body pre { background: #161b22 !important; } .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; } .markdown-body table th, .markdown-body table td { border-color: #30363d !important; } .markdown-body img { background: #0d1117; } .markdown-body blockquote { border-left-color: #8b949e; } .markdown-body hr { border-color: #30363d; } '; document.head.appendChild(style); })(); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Highlight search terms from Google/DuckDuckGo/Bing referrer (function() { var ref = document.referrer; var terms = []; if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) { var url = new URL(ref); var q = url.searchParams.get('q') || url.searchParams.get('p'); if (q) { terms = q.split(/\s+/).filter(function(t) { return t.length > 2; }); } } if (terms.length === 0) return; var style = document.createElement('style'); style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }'; document.head.appendChild(style); function highlight(node) { if (node.nodeType === 3) { // text node var text = node.textContent; var found = false; terms.forEach(function(term) { var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\]\\]/g, '\\') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ' Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ' Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser
, 'i'); if (__m === '*' || __re.test(location.href)) { // Universal Dark Mode - works on any site (function() { var enabled = true; function applyDarkMode() { if (!enabled) return; // Create style element if it doesn't exist var style = document.getElementById('universal-dark-mode-style'); if (!style) { style = document.createElement('style'); style.id = 'universal-dark-mode-style'; document.head.appendChild(style); } // Dark mode CSS - inverts colors but preserves images/video style.textContent = ' /* Invert everything except media */ html { filter: invert(1) hue-rotate(180deg) !important; background: #1a1a2e !important; } /* Restore images, videos, iframes, canvas */ img, video, iframe, canvas, svg, picture, [style*="background-image"] { filter: invert(1) hue-rotate(180deg) !important; } /* Preserve specific elements that should not be inverted */ .no-dark-mode, .no-dark-mode *, [data-theme="light"], [data-theme="light"], .ace_editor, .ace_editor *, .CodeMirror, .CodeMirror *, .monaco-editor, .monaco-editor *, .markdown-body pre, .markdown-body pre *, .highlight, .highlight *, pre code, pre code * { filter: none !important; } /* Fix common UI elements */ .modal, .popup, .dropdown-menu, .tooltip, .popover { filter: invert(1) hue-rotate(180deg) !important; background: #2d2d44 !important; border-color: #444 !important; } /* Scrollbars */ ::-webkit-scrollbar { background: #1a1a2e !important; } ::-webkit-scrollbar-thumb { background: #444 !important; } ::-webkit-scrollbar-thumb:hover { background: #555 !important; } /* Selection */ ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; } ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; } '; } function removeDarkMode() { var style = document.getElementById('universal-dark-mode-style'); if (style) style.remove(); } // Toggle with Alt+Shift+D document.addEventListener('keydown', function(e) { if (e.altKey && e.shiftKey && e.key === 'D') { e.preventDefault(); enabled = !enabled; if (enabled) { applyDarkMode(); console.log('[Universal Dark Mode] Enabled'); } else { removeDarkMode(); console.log('[Universal Dark Mode] Disabled'); } } }); // Apply on load applyDarkMode(); // Re-apply on dynamic content var observer = new MutationObserver(function(mutations) { if (enabled && !document.getElementById('universal-dark-mode-style')) { applyDarkMode(); } }); observer.observe(document.head, { childList: true }); console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle'); })(); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })(); Pin encode device to a DRM render node by plasticchris · Pull Request #23 · hgaiser/pixelforge · GitHub
Skip to content

Pin encode device to a DRM render node - #23

Open
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main
Open

Pin encode device to a DRM render node#23
plasticchris wants to merge 1 commit into
hgaiser:mainfrom
plasticchris:main

Conversation

@plasticchris

Copy link
Copy Markdown

Select the Vulkan device whose VK_EXT_physical_device_drm render major:minor matches a caller-supplied node, so the encoder shares the compositor physical GPU. vendor:device ids cannot disambiguate identical GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds VideoContextBuilder::drm_render_node and a verify_drm_pin example.

Tested on a multi-gpu amd machine.

Select the Vulkan device whose VK_EXT_physical_device_drm render
major:minor matches a caller-supplied node, so the encoder shares the
compositor physical GPU. vendor:device ids cannot disambiguate identical
GPUs, and importing a DMA-BUF across GPUs corrupts frames. Adds
VideoContextBuilder::drm_render_node and a verify_drm_pin example.

@hgaiserhgaiser left a comment

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I like the idea, but I have some thoughts on how to improve it further. Thanks for the input!

Comment threadsrc/vulkan.rs
Comment on lines +259 to +282
// Resolve the preferred DRM render node to (major, minor). Used to pin
// the encoder to the same physical GPU as the compositor, since importing
// a DMA-BUF allocated on one GPU into an encoder on another corrupts the
// image and vendor:device filtering can't disambiguate identical GPUs.
let preferred_drm = builder.preferred_drm_render_node.as_deref().and_then(|path| {
match drm_render_major_minor(path) {
Some(mm) => {
info!(
"Encoder will prefer the GPU backing {} (drm {}:{})",
path.display(),
mm.0,
mm.1
);
Some(mm)
},
None => {
warn!(
"Could not resolve DRM major/minor for {}; encoder will pick the first suitable GPU",
path.display()
);
None
},
}
});

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I would prefer to return an error when the requested render node could not be used. It seems counterintuitive to continue with only a warning logged. If the caller wanted to try again with "any" render node, it could just create a new builder without a given render node.

This would also mean dropping the preferred in the variable naming.

Small nitpick: you mention compositor a few times, but technically the source can be anything. A video player, a game, etc.

Comment threadsrc/vulkan.rs
drm_render: Option<(i64, i64)>,
}

let mut candidates: Vec<DeviceCandidate> = Vec::new();

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Given that the provided drm render node becomes a hard requirement, the rest of the file changes significantly because we don't need to collect all candidates.

Comment threadsrc/vulkan.rs
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
pub fn drm_render_node(mut self, node: Option<std::path::PathBuf>) -> Self {

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Why make it an Option ? The user can simply not call it when it's None, right?

use ash::vk::TaggedStructure;
use pixelforge::VideoContextBuilder;
use std::ffi::CStr;
use std::os::unix::fs::MetadataExt;

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

This won't compile on macos/windows.

Comment threadsrc/vulkan.rs
Comment on lines +907 to +910
#[cfg(not(target_os = "linux"))]
fn drm_render_major_minor(_path: &std::path::Path) -> Option<(i64, i64)> {
None
}

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I don't know if it makes sense to implement this function on non-linux systems. Might be better to just gate the drm_render_major_minor (as is already done) and its usage.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

I understand the need to test the new feature, but I don't think this example makes sense to keep in pixelforge.

Comment threadsrc/vulkan.rs
Comment on lines +62 to +71
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.

Copy link
Copy Markdown
Owner

Choose a reason for hiding this comment

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

Suggested change
/// Prefer the physical device backing the given DRM render node
/// (e.g. `/dev/dri/renderD128`).
///
/// Device selection picks the encode-capable Vulkan device whose DRM
/// render major/minor (via `VK_EXT_physical_device_drm`) matches this node,
/// so the encoder runs on the same physical GPU as the compositor that
/// produced the DMA-BUFs. Without this, importing a buffer allocated on one
/// GPU into an encoder on another corrupts the image, and identical GPUs
/// can't be disambiguated by vendor:device id. Falls back to the first
/// suitable device when unset or unmatched. No-op on non-Linux.
/// Pin the encoder to the GPU identified by a DRM render node (e.g. `/dev/dri/renderD128`).
///
/// Only available on Linux.

Sign up for freeto join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants

@plasticchris@hgaiser