Skip to content

Commit d665b5c

Browse files
committed
Fix D3DDD issue on hybrid gpu laptops
1. Some Desktop Duplication setup was done in advance, even if that method won't be used 2. Hybrid GPU laptops can have issues with D3D Desktop Duplication. The issue and a workaround is now documented
1 parent 5e31a82 commit d665b5c

File tree

4 files changed

+77
-19
lines changed

4 files changed

+77
-19
lines changed

D3DDD-Note-Laptops.md

Lines changed: 47 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,47 @@
1+
# Installation Note: D3D Desktop Duplication on Laptops
2+
3+
Windows has a little quirk when running Desktop Duplication on laptops with hybrid GPU systems (integrated + dedicated). You will need to perform an additional tweak to get _D3D Desktop Duplication_ to work correctly on your system.
4+
5+
## Problem
6+
7+
The problem is fully documented in [this article](https://support.microsoft.com/en-us/help/3019314/error-generated-when-desktop-duplication-api-capable-application-is-ru)
8+
9+
## Solution
10+
11+
The solution is presented as such:
12+
13+
> Run the application on the integrated GPU instead of on the discrete GPU
14+
15+
Therefore, to be able to use _D3D Desktop Duplication_ on hybrid GPU laptops, we need to force Python to run on the integrated GPU.
16+
17+
## Approach 1: Windows 10 Settings
18+
19+
_You must be running Windows 10 1809 or later for this to work._
20+
21+
1. Press the Windows Key, type `Graphics settings` and press enter
22+
2. You should see the following window:
23+
![image](https://user-images.githubusercontent.com/35039/84433008-a3b65d00-abfb-11ea-8343-81b8f265afc4.png)
24+
3. Make sure the dropdown is set to `Desktop App` and click `Browse`
25+
4. Find the `python.exe` used by your _D3D Desktop Duplication_ project. Example:
26+
![image](https://user-images.githubusercontent.com/35039/84433419-3d7e0a00-abfc-11ea-99a4-b5176535b0e5.png)
27+
5. Click on `Options`
28+
6. Select `Power saving` and click `Save`
29+
![image](https://user-images.githubusercontent.com/35039/84433562-7918d400-abfc-11ea-807a-e3c0b15d9fb2.png)
30+
7. If you did everything right it should look like this:
31+
![image](https://user-images.githubusercontent.com/35039/84433706-bda46f80-abfc-11ea-9c64-a702b96095b8.png)
32+
8. Repeat the process for other potentially relevant executables for your project: `ipython.exe`, `jupyter-kernel.exe` etc.
33+
34+
## Approach 2: Nvidia Control Panel
35+
36+
Need help to fill in this section. See issue [SerpentAI/D3DShot#27](https://github.com/SerpentAI/D3DShot/issues/27)
37+
38+
## Approach 3: AMD Catalyst Control Center
39+
40+
Need help to fill in this section. See issue [SerpentAI/D3DShot#28](https://github.com/SerpentAI/D3DShot/issues/28)
41+
42+
## Question: Won't this impede on my ability to use CUDA, OpenCL etc?
43+
44+
Preliminary answer: No. This is telling Windows how to _render_ Python processes with the Desktop Window Manager. Most Python applications are console applications that don't have a window. Even if you have a GUI application with one or more windows, this should only affect the rendering aspect (i.e. your windows won't be rendered through the dedicated GPU) and shouldn't limit hardware access in any way.
45+
46+
---
47+
(copied and adapted from <https://github.com/SerpentAI/D3DShot/wiki/Installation-Note:-Laptops>)

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,7 @@ Refer to the [build instructions](build%20instructions.md) if you'd like to buil
8282
It can record OpenGL and Hardware Accelerated windows.
8383
About 10-15x slower than BitBlt. Not affected by window size.
8484
overlapping windows will show up and can't record across displays.
85+
This option may not be available for hybrid GPU laptops, see [D3DDD-Note-Laptops.md](/D3DDD-Note-Laptops.md) for a solution.
8586
- **Force Full Content Rendering** (very slow, can affect rendering pipeline)
8687
Uses BitBlt behind the scene, but passes a special flag to PrintWindow to force rendering the entire desktop.
8788
About 10-15x slower than BitBlt based on original window size and can mess up some applications' rendering pipelines.

src/capture_method/DesktopDuplicationCaptureMethod.py

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -14,10 +14,10 @@
1414
if TYPE_CHECKING:
1515
from AutoSplit import AutoSplit
1616

17-
desktop_duplication = d3dshot.create(capture_output="numpy")
18-
1917

2018
class DesktopDuplicationCaptureMethod(BitBltCaptureMethod): # pylint: disable=too-few-public-methods
19+
desktop_duplication = d3dshot.create(capture_output="numpy")
20+
2121
def get_frame(self, autosplit: AutoSplit):
2222
selection = autosplit.settings_dict["capture_region"]
2323
hwnd = autosplit.hwnd
@@ -26,19 +26,19 @@ def get_frame(self, autosplit: AutoSplit):
2626
return None, False
2727

2828
left_bounds, top_bounds, *_ = get_window_bounds(hwnd)
29-
desktop_duplication.display = [
29+
self.desktop_duplication.display = [
3030
display for display
31-
in desktop_duplication.displays
31+
in self.desktop_duplication.displays
3232
if display.hmonitor == hmonitor
3333
][0]
3434
offset_x, offset_y, *_ = win32gui.GetWindowRect(hwnd)
35-
offset_x -= desktop_duplication.display.position["left"]
36-
offset_y -= desktop_duplication.display.position["top"]
35+
offset_x -= self.desktop_duplication.display.position["left"]
36+
offset_y -= self.desktop_duplication.display.position["top"]
3737
left = selection["x"] + offset_x + left_bounds
3838
top = selection["y"] + offset_y + top_bounds
3939
right = selection["width"] + left
4040
bottom = selection["height"] + top
41-
screenshot = desktop_duplication.screenshot((left, top, right, bottom))
41+
screenshot = self.desktop_duplication.screenshot((left, top, right, bottom))
4242
if screenshot is None:
4343
return None, False
4444
return cv2.cvtColor(cast(cv2.Mat, screenshot), cv2.COLOR_RGBA2BGRA), False

src/capture_method/__init__.py

Lines changed: 22 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
from enum import Enum, EnumMeta, unique
77
from typing import TYPE_CHECKING, TypedDict, cast
88

9+
from _ctypes import COMError # pylint: disable=C2701
910
from pygrabber.dshow_graph import FilterGraph
1011

1112
from capture_method.BitBltCaptureMethod import BitBltCaptureMethod
@@ -14,7 +15,7 @@
1415
from capture_method.ForceFullContentRenderingCaptureMethod import ForceFullContentRenderingCaptureMethod
1516
from capture_method.VideoCaptureDeviceCaptureMethod import VideoCaptureDeviceCaptureMethod
1617
from capture_method.WindowsGraphicsCaptureMethod import WindowsGraphicsCaptureMethod
17-
from utils import WINDOWS_BUILD_NUMBER, first, try_get_direct3d_device
18+
from utils import GITHUB_REPOSITORY, WINDOWS_BUILD_NUMBER, first, try_get_direct3d_device
1819

1920
if TYPE_CHECKING:
2021
from AutoSplit import AutoSplit
@@ -147,17 +148,26 @@ def get(self, __key: CaptureMethodEnum):
147148

148149
implementation=BitBltCaptureMethod,
149150
)
150-
CAPTURE_METHODS[CaptureMethodEnum.DESKTOP_DUPLICATION] = CaptureMethodInfo(
151-
name="Direct3D Desktop Duplication",
152-
short_description="slower, bound to display",
153-
description=(
154-
"\nDuplicates the desktop using Direct3D. "
155-
"\nIt can record OpenGL and Hardware Accelerated windows. "
156-
"\nAbout 10-15x slower than BitBlt. Not affected by window size. "
157-
"\nOverlapping windows will show up and can't record across displays. "
158-
),
159-
implementation=DesktopDuplicationCaptureMethod,
160-
)
151+
try:
152+
import d3dshot
153+
d3dshot.create(capture_output="numpy")
154+
except (ModuleNotFoundError, COMError):
155+
pass
156+
else:
157+
CAPTURE_METHODS[CaptureMethodEnum.DESKTOP_DUPLICATION] = CaptureMethodInfo(
158+
name="Direct3D Desktop Duplication",
159+
short_description="slower, bound to display",
160+
description=(
161+
"\nDuplicates the desktop using Direct3D. "
162+
"\nIt can record OpenGL and Hardware Accelerated windows. "
163+
"\nAbout 10-15x slower than BitBlt. Not affected by window size. "
164+
"\nOverlapping windows will show up and can't record across displays. "
165+
"\nThis option may not be available for hybrid GPU laptops, "
166+
"\nsee D3DDD-Note-Laptops.md for a solution. "
167+
f"\nhttps://www.github.com/{GITHUB_REPOSITORY}#capture-method "
168+
),
169+
implementation=DesktopDuplicationCaptureMethod,
170+
)
161171
CAPTURE_METHODS[CaptureMethodEnum.PRINTWINDOW_RENDERFULLCONTENT] = CaptureMethodInfo(
162172
name="Force Full Content Rendering",
163173
short_description="very slow, can affect rendering pipeline",

0 commit comments

Comments
 (0)