Skip to content

Commit

Permalink
Add DXGI Adapter Removal Support Test (#481)
Browse files Browse the repository at this point in the history
* Add DXGIAdapterRemovalSupportTest which is referenced by the xGPU sample.

* Move Tools dir to the root
  • Loading branch information
sebmerry authored Oct 9, 2018
1 parent 96fcc20 commit 848fb48
Show file tree
Hide file tree
Showing 10 changed files with 1,586 additions and 0 deletions.
22 changes: 22 additions & 0 deletions Tools/DXGIAdapterRemovalSupportTest/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# DXGI AdapterRemovalSupport test sample

This sample test simulates D3D device removed events by disabling and enabling the hardware graphics/display adapters on the system. This helps determine if an application is able to support and survive adapter removals.

If the result of test is that the application seems to support adapter removal properly, then the application should declare it via DXGIDeclareAdapterRemovalSupport API. This allows Windows to identify such applications and act accordingly, for example, to allow safe detachment of the xGPU even when this application is rendering on it.

An example of an application that supports adapter removal behavior is the [D3D12xGPU sample application](../../Samples/Desktop/D3D12xGPU/readme.md).

### Command parameters usage
* -? (shows this help screen)
* -appPath \{proc.exe} [-launch] (to launch the application)
* -appPID \{#} (process id of currently running app)
* [-wait \{#}] (waits # seconds before simulating device removal)

### Example commands
* DXGIAdapterRemovalSupportTest.exe -appPath notepad.exe -launch
* DXGIAdapterRemovalSupportTest.exe -appPath gameApp.exe
* DXGIAdapterRemovalSupportTest.exe -appPID 12345

## Requirements
* Windows 10 16299 or higher
* [Visual Studio 2017](https://www.visualstudio.com/) with the Windows 10 16299 SDK
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@

Microsoft Visual Studio Solution File, Format Version 12.00
# Visual Studio 15
VisualStudioVersion = 15.0.27309.0
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DXGIAdapterRemovalSupportTest", "DXGIAdapterRemovalSupportTest.vcxproj", "{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|x64 = Debug|x64
Debug|x86 = Debug|x86
Release|x64 = Release|x64
Release|x86 = Release|x86
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Debug|x64.ActiveCfg = Debug|x64
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Debug|x64.Build.0 = Debug|x64
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Debug|x86.ActiveCfg = Debug|Win32
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Debug|x86.Build.0 = Debug|Win32
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Release|x64.ActiveCfg = Release|x64
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Release|x64.Build.0 = Release|x64
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Release|x86.ActiveCfg = Release|Win32
{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}.Release|x86.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {9F829D6D-4D95-43DC-9475-D93862A480AB}
EndGlobalSection
EndGlobal
Original file line number Diff line number Diff line change
@@ -0,0 +1,174 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>15.0</VCProjectVersion>
<ProjectGuid>{A7E7C729-937E-4E30-A9C0-F56E9B6F5E07}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>DXGIAdapterRemovalSupportTest</RootNamespace>
<WindowsTargetPlatformVersion>10.0.16299.0</WindowsTargetPlatformVersion>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v141</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile />
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dxgi.lib;OneCoreUAP.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>Disabled</Optimization>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_DEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile />
<RuntimeLibrary>MultiThreadedDebug</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dxgi.lib;OneCoreUAP.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile />
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dxgi.lib;OneCoreUAP.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<PrecompiledHeader>NotUsing</PrecompiledHeader>
<WarningLevel>Level3</WarningLevel>
<Optimization>MaxSpeed</Optimization>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<PrecompiledHeaderFile />
<RuntimeLibrary>MultiThreaded</RuntimeLibrary>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>dxgi.lib;OneCoreUAP.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="pch.h" />
<ClInclude Include="PnpListener.h" />
<ClInclude Include="TraceSession.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp" />
<ClCompile Include="PnpListener.cpp" />
<ClCompile Include="TraceSession.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="PnpListener.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="TraceSession.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="pch.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="PnpListener.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="TraceSession.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>
124 changes: 124 additions & 0 deletions Tools/DXGIAdapterRemovalSupportTest/src/PnpListener.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
//*********************************************************
//
// Copyright (c) Microsoft. All rights reserved.
// This code is licensed under the MIT License (MIT).
// THIS CODE IS PROVIDED *AS IS* WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING ANY
// IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR
// PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
//
//*********************************************************

#include "pch.h"

PnpListener::PnpListener(std::wstring DeviceInstanceId) : m_DeviceInstanceId(DeviceInstanceId)
{
// Create the manual reset events
m_PnpStartEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
m_PnpStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (!m_PnpStartEvent || !m_PnpStopEvent)
{
ScopedOutputColor outClr(ScopedOutputColor::COLOR_RED);
std::cout << "Error: Failed to create manual reset events" << std::endl;
m_CmNotification = nullptr;
return;
}

// Register the listener
CONFIGRET cr;
CM_NOTIFY_FILTER Filter = {};
Filter.cbSize = sizeof(Filter);

Filter.FilterType = CM_NOTIFY_FILTER_TYPE_DEVICEINTERFACE;
Filter.u.DeviceInterface.ClassGuid = GUID_DISPLAY_DEVICE_ARRIVAL;

cr = CM_Register_Notification(&Filter, this, PnPStartListener, &m_CmNotification);
if (cr != CR_SUCCESS)
{
ScopedOutputColor outClr(ScopedOutputColor::COLOR_RED);
std::cout << "Error: CM_Register_Notification failed, error code " << cr << std::endl;
m_CmNotification = nullptr;
}
}

PnpListener::~PnpListener()
{
// Un-register the notification
if (m_CmNotification)
{
CM_Unregister_Notification(m_CmNotification);
m_CmNotification = nullptr;
}

if (m_PnpStartEvent)
{
CloseHandle(m_PnpStartEvent);
m_PnpStartEvent = nullptr;
}

if (m_PnpStopEvent)
{
CloseHandle(m_PnpStopEvent);
m_PnpStopEvent = nullptr;
}
}

DWORD WINAPI PnpListener::PnPStartListener(
_In_ HCMNOTIFICATION hNotify,
_In_opt_ PVOID pContext,
_In_ CM_NOTIFY_ACTION Action,
_In_reads_bytes_(EventDataSize) PCM_NOTIFY_EVENT_DATA EventData,
_In_ DWORD EventDataSize
)
{
PnpListener* pThis = (PnpListener*)pContext;

UNREFERENCED_PARAMETER(hNotify);
UNREFERENCED_PARAMETER(EventDataSize);

ULONG BufferSize = MAX_DEVICE_ID_LEN * sizeof(WCHAR);
DEVPROPTYPE PropType;
WCHAR DeviceInstanceId[MAX_DEVICE_ID_LEN] = {};
if ((CR_SUCCESS != CM_Get_Device_Interface_Property(EventData->u.DeviceInterface.SymbolicLink,
&DEVPKEY_Device_InstanceId,
&PropType,
(PBYTE)DeviceInstanceId,
&BufferSize,
0)) ||
(PropType != DEVPROP_TYPE_STRING))
{
DeviceInstanceId[0] = L'\0';
}

if (!_wcsnicmp(pThis->m_DeviceInstanceId.c_str(), DeviceInstanceId, ARRAYSIZE(DeviceInstanceId)))
{
if (Action == CM_NOTIFY_ACTION_DEVICEINTERFACEARRIVAL)
{
SetEvent(pThis->m_PnpStartEvent);
}
else if ((Action == CM_NOTIFY_ACTION_DEVICEINTERFACEREMOVAL) ||
(Action == CM_NOTIFY_ACTION_DEVICEREMOVECOMPLETE))
{
SetEvent(pThis->m_PnpStopEvent);
}
}

return ERROR_SUCCESS;
}

bool PnpListener::WaitForPnpStart()
{
DWORD Ret = WaitForSingleObject(m_PnpStartEvent, PnpListener::WaitTimeout);
return Ret == WAIT_OBJECT_0;
}

bool PnpListener::WaitForPnpStop()
{
DWORD Ret = WaitForSingleObject(m_PnpStopEvent, PnpListener::WaitTimeout);
return Ret == WAIT_OBJECT_0;
}

bool PnpListener::HasError()
{
return m_CmNotification == nullptr;
}
Loading

0 comments on commit 848fb48

Please sign in to comment.