aboutsummaryrefslogtreecommitdiffstats
path: root/support/hololens/ServoApp/Common/DeviceResources.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'support/hololens/ServoApp/Common/DeviceResources.cpp')
-rw-r--r--support/hololens/ServoApp/Common/DeviceResources.cpp280
1 files changed, 280 insertions, 0 deletions
diff --git a/support/hololens/ServoApp/Common/DeviceResources.cpp b/support/hololens/ServoApp/Common/DeviceResources.cpp
new file mode 100644
index 00000000000..f5ffbec0d89
--- /dev/null
+++ b/support/hololens/ServoApp/Common/DeviceResources.cpp
@@ -0,0 +1,280 @@
+
+#include "pch.h"
+#include "DeviceResources.h"
+#include "DirectXHelper.h"
+
+using namespace D2D1;
+using namespace Microsoft::WRL;
+using namespace winrt::Windows::Graphics::DirectX::Direct3D11;
+using namespace winrt::Windows::Graphics::Display;
+using namespace winrt::Windows::Graphics::Holographic;
+
+// Constructor for DeviceResources.
+DX::DeviceResources::DeviceResources() { CreateDeviceIndependentResources(); }
+
+// Configures resources that don't depend on the Direct3D device.
+void DX::DeviceResources::CreateDeviceIndependentResources() {
+ // Initialize Direct2D resources.
+ D2D1_FACTORY_OPTIONS options{};
+
+#if defined(_DEBUG)
+ // If the project is in a debug build, enable Direct2D debugging via SDK
+ // Layers.
+ options.debugLevel = D2D1_DEBUG_LEVEL_INFORMATION;
+#endif
+
+ // Initialize the Direct2D Factory.
+ winrt::check_hresult(D2D1CreateFactory(D2D1_FACTORY_TYPE_SINGLE_THREADED,
+ __uuidof(ID2D1Factory2), &options,
+ &m_d2dFactory));
+
+ // Initialize the DirectWrite Factory.
+ winrt::check_hresult(DWriteCreateFactory(
+ DWRITE_FACTORY_TYPE_SHARED, __uuidof(IDWriteFactory2), &m_dwriteFactory));
+
+ // Initialize the Windows Imaging Component (WIC) Factory.
+ winrt::check_hresult(CoCreateInstance(CLSID_WICImagingFactory2, nullptr,
+ CLSCTX_INPROC_SERVER,
+ IID_PPV_ARGS(&m_wicFactory)));
+}
+
+void DX::DeviceResources::SetHolographicSpace(
+ HolographicSpace holographicSpace) {
+ // Cache the holographic space. Used to re-initalize during device-lost
+ // scenarios.
+ m_holographicSpace = holographicSpace;
+
+ InitializeUsingHolographicSpace();
+}
+
+void DX::DeviceResources::InitializeUsingHolographicSpace() {
+ // The holographic space might need to determine which adapter supports
+ // holograms, in which case it will specify a non-zero PrimaryAdapterId.
+ LUID id = {m_holographicSpace.PrimaryAdapterId().LowPart,
+ m_holographicSpace.PrimaryAdapterId().HighPart};
+
+ // When a primary adapter ID is given to the app, the app should find
+ // the corresponding DXGI adapter and use it to create Direct3D devices
+ // and device contexts. Otherwise, there is no restriction on the DXGI
+ // adapter the app can use.
+ if ((id.HighPart != 0) || (id.LowPart != 0)) {
+ UINT createFlags = 0;
+#ifdef DEBUG
+ if (DX::SdkLayersAvailable()) {
+ createFlags |= DXGI_CREATE_FACTORY_DEBUG;
+ }
+#endif
+ // Create the DXGI factory.
+ ComPtr<IDXGIFactory1> dxgiFactory;
+ winrt::check_hresult(
+ CreateDXGIFactory2(createFlags, IID_PPV_ARGS(&dxgiFactory)));
+ ComPtr<IDXGIFactory4> dxgiFactory4;
+ winrt::check_hresult(dxgiFactory.As(&dxgiFactory4));
+
+ // Retrieve the adapter specified by the holographic space.
+ winrt::check_hresult(
+ dxgiFactory4->EnumAdapterByLuid(id, IID_PPV_ARGS(&m_dxgiAdapter)));
+ } else {
+ m_dxgiAdapter.Reset();
+ }
+
+ CreateDeviceResources();
+
+ m_holographicSpace.SetDirect3D11Device(m_d3dInteropDevice);
+}
+
+// Configures the Direct3D device, and stores handles to it and the device
+// context.
+void DX::DeviceResources::CreateDeviceResources() {
+ // This flag adds support for surfaces with a different color channel ordering
+ // than the API default. It is required for compatibility with Direct2D.
+ UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
+
+#if defined(_DEBUG)
+ if (DX::SdkLayersAvailable()) {
+ // If the project is in a debug build, enable debugging via SDK Layers with
+ // this flag.
+ creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
+ }
+#endif
+
+ // This array defines the set of DirectX hardware feature levels this app will
+ // support. Note the ordering should be preserved. Note that HoloLens supports
+ // feature level 11.1. The HoloLens emulator is also capable of running on
+ // graphics cards starting with feature level 10.0.
+ D3D_FEATURE_LEVEL featureLevels[] = {
+ D3D_FEATURE_LEVEL_12_1, D3D_FEATURE_LEVEL_12_0, D3D_FEATURE_LEVEL_11_1,
+ D3D_FEATURE_LEVEL_11_0, D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_10_0};
+
+ // Create the Direct3D 11 API device object and a corresponding context.
+ ComPtr<ID3D11Device> device;
+ ComPtr<ID3D11DeviceContext> context;
+
+ const D3D_DRIVER_TYPE driverType = m_dxgiAdapter == nullptr
+ ? D3D_DRIVER_TYPE_HARDWARE
+ : D3D_DRIVER_TYPE_UNKNOWN;
+ const HRESULT hr = D3D11CreateDevice(
+ m_dxgiAdapter.Get(), // Either nullptr, or the primary adapter determined
+ // by Windows Holographic.
+ driverType, // Create a device using the hardware graphics driver.
+ 0, // Should be 0 unless the driver is D3D_DRIVER_TYPE_SOFTWARE.
+ creationFlags, // Set debug and Direct2D compatibility flags.
+ featureLevels, // List of feature levels this app can support.
+ ARRAYSIZE(featureLevels), // Size of the list above.
+ D3D11_SDK_VERSION, // Always set this to D3D11_SDK_VERSION for Windows
+ // Runtime apps.
+ &device, // Returns the Direct3D device created.
+ &m_d3dFeatureLevel, // Returns feature level of device created.
+ &context // Returns the device immediate context.
+ );
+
+ if (FAILED(hr)) {
+ // If the initialization fails, fall back to the WARP device.
+ // For more information on WARP, see:
+ // http://go.microsoft.com/fwlink/?LinkId=286690
+ winrt::check_hresult(D3D11CreateDevice(
+ nullptr, // Use the default DXGI adapter for WARP.
+ D3D_DRIVER_TYPE_WARP, // Create a WARP device instead of a hardware
+ // device.
+ 0, creationFlags, featureLevels, ARRAYSIZE(featureLevels),
+ D3D11_SDK_VERSION, &device, &m_d3dFeatureLevel, &context));
+ }
+
+ // Store pointers to the Direct3D device and immediate context.
+ winrt::check_hresult(device.As(&m_d3dDevice));
+ winrt::check_hresult(context.As(&m_d3dContext));
+
+ // Acquire the DXGI interface for the Direct3D device.
+ ComPtr<IDXGIDevice3> dxgiDevice;
+ winrt::check_hresult(m_d3dDevice.As(&dxgiDevice));
+
+ // Wrap the native device using a WinRT interop object.
+ winrt::com_ptr<::IInspectable> object;
+ winrt::check_hresult(CreateDirect3D11DeviceFromDXGIDevice(
+ dxgiDevice.Get(),
+ reinterpret_cast<IInspectable **>(winrt::put_abi(object))));
+ m_d3dInteropDevice = object.as<IDirect3DDevice>();
+
+ // Cache the DXGI adapter.
+ // This is for the case of no preferred DXGI adapter, or fallback to WARP.
+ ComPtr<IDXGIAdapter> dxgiAdapter;
+ winrt::check_hresult(dxgiDevice->GetAdapter(&dxgiAdapter));
+ winrt::check_hresult(dxgiAdapter.As(&m_dxgiAdapter));
+
+ // Check for device support for the optional feature that allows setting the
+ // render target array index from the vertex shader stage.
+ D3D11_FEATURE_DATA_D3D11_OPTIONS3 options;
+ m_d3dDevice->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &options,
+ sizeof(options));
+ if (options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer) {
+ m_supportsVprt = true;
+ }
+}
+
+// Validates the back buffer for each HolographicCamera and recreates
+// resources for back buffers that have changed.
+// Locks the set of holographic camera resources until the function exits.
+void DX::DeviceResources::EnsureCameraResources(
+ HolographicFrame frame, HolographicFramePrediction prediction) {
+ UseHolographicCameraResources<void>(
+ [this, frame,
+ prediction](std::map<UINT32, std::unique_ptr<CameraResources>>
+ &cameraResourceMap) {
+ for (HolographicCameraPose const &cameraPose :
+ prediction.CameraPoses()) {
+ HolographicCameraRenderingParameters renderingParameters =
+ frame.GetRenderingParameters(cameraPose);
+ CameraResources *pCameraResources =
+ cameraResourceMap[cameraPose.HolographicCamera().Id()].get();
+
+ pCameraResources->CreateResourcesForBackBuffer(this,
+ renderingParameters);
+ }
+ });
+}
+
+// Prepares to allocate resources and adds resource views for a camera.
+// Locks the set of holographic camera resources until the function exits.
+void DX::DeviceResources::AddHolographicCamera(HolographicCamera camera) {
+ UseHolographicCameraResources<void>(
+ [this, camera](std::map<UINT32, std::unique_ptr<CameraResources>>
+ &cameraResourceMap) {
+ cameraResourceMap[camera.Id()] =
+ std::make_unique<CameraResources>(camera);
+ });
+}
+
+// Deallocates resources for a camera and removes the camera from the set.
+// Locks the set of holographic camera resources until the function exits.
+void DX::DeviceResources::RemoveHolographicCamera(HolographicCamera camera) {
+ UseHolographicCameraResources<void>(
+ [this, camera](std::map<UINT32, std::unique_ptr<CameraResources>>
+ &cameraResourceMap) {
+ CameraResources *pCameraResources =
+ cameraResourceMap[camera.Id()].get();
+
+ if (pCameraResources != nullptr) {
+ pCameraResources->ReleaseResourcesForBackBuffer(this);
+ cameraResourceMap.erase(camera.Id());
+ }
+ });
+}
+
+// Recreate all device resources and set them back to the current state.
+// Locks the set of holographic camera resources until the function exits.
+void DX::DeviceResources::HandleDeviceLost() {
+ if (m_deviceNotify != nullptr) {
+ m_deviceNotify->OnDeviceLost();
+ }
+
+ UseHolographicCameraResources<void>(
+ [this](std::map<UINT32, std::unique_ptr<CameraResources>>
+ &cameraResourceMap) {
+ for (auto &pair : cameraResourceMap) {
+ CameraResources *pCameraResources = pair.second.get();
+ pCameraResources->ReleaseResourcesForBackBuffer(this);
+ }
+ });
+
+ InitializeUsingHolographicSpace();
+
+ if (m_deviceNotify != nullptr) {
+ m_deviceNotify->OnDeviceRestored();
+ }
+}
+
+// Register our DeviceNotify to be informed on device lost and creation.
+void DX::DeviceResources::RegisterDeviceNotify(
+ DX::IDeviceNotify *deviceNotify) {
+ m_deviceNotify = deviceNotify;
+}
+
+// Call this method when the app suspends. It provides a hint to the driver that
+// the app is entering an idle state and that temporary buffers can be reclaimed
+// for use by other apps.
+void DX::DeviceResources::Trim() {
+ m_d3dContext->ClearState();
+
+ ComPtr<IDXGIDevice3> dxgiDevice;
+ winrt::check_hresult(m_d3dDevice.As(&dxgiDevice));
+ dxgiDevice->Trim();
+}
+
+// Present the contents of the swap chain to the screen.
+// Locks the set of holographic camera resources until the function exits.
+void DX::DeviceResources::Present(HolographicFrame frame) {
+ // By default, this API waits for the frame to finish before it returns.
+ // Holographic apps should wait for the previous frame to finish before
+ // starting work on a new frame. This allows for better results from
+ // holographic frame predictions.
+ HolographicFramePresentResult presentResult =
+ frame.PresentUsingCurrentPrediction();
+
+ // The PresentUsingCurrentPrediction API will detect when the graphics device
+ // changes or becomes invalid. When this happens, it is considered a Direct3D
+ // device lost scenario.
+ if (presentResult == HolographicFramePresentResult::DeviceRemoved) {
+ // The Direct3D device, context, and resources should be recreated.
+ HandleDeviceLost();
+ }
+}