mirror of
https://github.com/rustdesk/rustdesk.git
synced 2026-09-05 04:57:03 +00:00
fix: reuse the dxgi staging texture instead of one per frame
ohgodwhat() created a full screen D3D11_USAGE_STAGING texture for every captured frame and pinned each one with SetEvictionPriority(MAXIMUM). Because D3D11 resource destruction may be deferred, that per-frame churn can accumulate a large amount of graphics kernel paged pool on affected drivers. Keep a single staging texture and rebuild it only when the desktop image changes shape. Also check the IDXGISurface QueryInterface result, so a failure can no longer leave surface null while readable holds a valid texture. Reported in #15945. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_011sw75MSAz7PTqrSALdStXe
This commit is contained in:
co-authored by
Claude Opus 5
parent
1fe451c2e8
commit
7c830e76c6
+32
-17
@@ -48,6 +48,7 @@ pub struct Capturer {
|
||||
duplication: ComPtr<IDXGIOutputDuplication>,
|
||||
fastlane: bool,
|
||||
surface: ComPtr<IDXGISurface>,
|
||||
readable: ComPtr<ID3D11Texture2D>,
|
||||
texture: ComPtr<ID3D11Texture2D>,
|
||||
width: usize,
|
||||
height: usize,
|
||||
@@ -163,6 +164,7 @@ impl Capturer {
|
||||
duplication: ComPtr(duplication),
|
||||
fastlane: desc.DesktopImageInSystemMemory == TRUE,
|
||||
surface: ComPtr(ptr::null_mut()),
|
||||
readable: ComPtr(ptr::null_mut()),
|
||||
texture: ComPtr(ptr::null_mut()),
|
||||
width: display.width() as usize,
|
||||
height: display.height() as usize,
|
||||
@@ -346,14 +348,14 @@ impl Capturer {
|
||||
if self.fastlane {
|
||||
wrap_hresult((*self.duplication.0).MapDesktopSurface(&mut rect))?;
|
||||
} else {
|
||||
self.surface = ComPtr(self.ohgodwhat(frame.0)?);
|
||||
self.ohgodwhat(frame.0)?;
|
||||
wrap_hresult((*self.surface.0).Map(&mut rect, DXGI_MAP_READ))?;
|
||||
}
|
||||
Ok((rect.pBits, rect.Pitch))
|
||||
}
|
||||
|
||||
// copy from GPU memory to system memory
|
||||
unsafe fn ohgodwhat(&mut self, frame: *mut IDXGIResource) -> io::Result<*mut IDXGISurface> {
|
||||
unsafe fn ohgodwhat(&mut self, frame: *mut IDXGIResource) -> io::Result<()> {
|
||||
let mut texture: *mut ID3D11Texture2D = ptr::null_mut();
|
||||
(*frame).QueryInterface(
|
||||
&IID_ID3D11Texture2D,
|
||||
@@ -370,24 +372,37 @@ impl Capturer {
|
||||
texture_desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
|
||||
texture_desc.MiscFlags = 0;
|
||||
|
||||
let mut readable = ptr::null_mut();
|
||||
wrap_hresult((*self.device.0).CreateTexture2D(
|
||||
&mut texture_desc,
|
||||
ptr::null(),
|
||||
&mut readable,
|
||||
))?;
|
||||
(*readable).SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
|
||||
let readable = ComPtr(readable);
|
||||
// Avoid per-frame staging texture allocation and the kernel allocation churn it causes.
|
||||
let mut current: D3D11_TEXTURE2D_DESC = mem::zeroed();
|
||||
if !self.surface.is_null() {
|
||||
(*self.readable.0).GetDesc(&mut current);
|
||||
}
|
||||
if current.Width != texture_desc.Width
|
||||
|| current.Height != texture_desc.Height
|
||||
|| current.Format != texture_desc.Format
|
||||
{
|
||||
let mut readable = ptr::null_mut();
|
||||
wrap_hresult((*self.device.0).CreateTexture2D(
|
||||
&mut texture_desc,
|
||||
ptr::null(),
|
||||
&mut readable,
|
||||
))?;
|
||||
(*readable).SetEvictionPriority(DXGI_RESOURCE_PRIORITY_MAXIMUM);
|
||||
let readable = ComPtr(readable);
|
||||
|
||||
let mut surface = ptr::null_mut();
|
||||
(*readable.0).QueryInterface(
|
||||
&IID_IDXGISurface,
|
||||
&mut surface as *mut *mut _ as *mut *mut _,
|
||||
);
|
||||
let mut surface = ptr::null_mut();
|
||||
wrap_hresult((*readable.0).QueryInterface(
|
||||
&IID_IDXGISurface,
|
||||
&mut surface as *mut *mut _ as *mut *mut _,
|
||||
))?;
|
||||
|
||||
(*self.context.0).CopyResource(readable.0 as *mut _, texture.0 as *mut _);
|
||||
self.readable = readable;
|
||||
self.surface = ComPtr(surface);
|
||||
}
|
||||
|
||||
Ok(surface)
|
||||
(*self.context.0).CopyResource(self.readable.0 as *mut _, texture.0 as *mut _);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn frame<'a>(&'a mut self, timeout: UINT) -> io::Result<Frame<'a>> {
|
||||
|
||||
Reference in New Issue
Block a user