aboutsummaryrefslogtreecommitdiffstats
path: root/support/hololens/ServoApp/Common/CameraResources.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'support/hololens/ServoApp/Common/CameraResources.cpp')
-rw-r--r--support/hololens/ServoApp/Common/CameraResources.cpp234
1 files changed, 234 insertions, 0 deletions
diff --git a/support/hololens/ServoApp/Common/CameraResources.cpp b/support/hololens/ServoApp/Common/CameraResources.cpp
new file mode 100644
index 00000000000..4391a55c74e
--- /dev/null
+++ b/support/hololens/ServoApp/Common/CameraResources.cpp
@@ -0,0 +1,234 @@
+#include "pch.h"
+
+#include "CameraResources.h"
+#include "Common/DirectXHelper.h"
+#include "DeviceResources.h"
+
+using namespace DirectX;
+using namespace Microsoft::WRL;
+using namespace winrt::Windows::Foundation::Numerics;
+using namespace winrt::Windows::Graphics::DirectX::Direct3D11;
+using namespace winrt::Windows::Graphics::Holographic;
+using namespace winrt::Windows::Perception::Spatial;
+
+DX::CameraResources::CameraResources(HolographicCamera const &camera)
+ : m_holographicCamera(camera), m_isStereo(camera.IsStereo()),
+ m_d3dRenderTargetSize(camera.RenderTargetSize()) {
+ m_d3dViewport = CD3D11_VIEWPORT(0.f, 0.f, m_d3dRenderTargetSize.Width,
+ m_d3dRenderTargetSize.Height);
+};
+
+// Updates resources associated with a holographic camera's swap chain.
+// The app does not access the swap chain directly, but it does create
+// resource views for the back buffer.
+void DX::CameraResources::CreateResourcesForBackBuffer(
+ DX::DeviceResources *pDeviceResources,
+ HolographicCameraRenderingParameters const &cameraParameters) {
+ ID3D11Device *device = pDeviceResources->GetD3DDevice();
+
+ // Get the WinRT object representing the holographic camera's back buffer.
+ IDirect3DSurface surface = cameraParameters.Direct3D11BackBuffer();
+
+ // Get the holographic camera's back buffer.
+ // Holographic apps do not create a swap chain themselves; instead, buffers
+ // are owned by the system. The Direct3D back buffer resources are provided to
+ // the app using WinRT interop APIs.
+ ComPtr<ID3D11Texture2D> cameraBackBuffer;
+ winrt::check_hresult(surface
+ .as<::Windows::Graphics::DirectX::Direct3D11::
+ IDirect3DDxgiInterfaceAccess>()
+ ->GetInterface(IID_PPV_ARGS(&cameraBackBuffer)));
+
+ // Determine if the back buffer has changed. If so, ensure that the render
+ // target view is for the current back buffer.
+ if (m_d3dBackBuffer.Get() != cameraBackBuffer.Get()) {
+ // This can change every frame as the system moves to the next buffer in the
+ // swap chain. This mode of operation will occur when certain rendering
+ // modes are activated.
+ m_d3dBackBuffer = cameraBackBuffer;
+
+ // Create a render target view of the back buffer.
+ // Creating this resource is inexpensive, and is better than keeping track
+ // of the back buffers in order to pre-allocate render target views for each
+ // one.
+ winrt::check_hresult(device->CreateRenderTargetView(
+ m_d3dBackBuffer.Get(), nullptr, &m_d3dRenderTargetView));
+
+ // Get the DXGI format for the back buffer.
+ // This information can be accessed by the app using
+ // CameraResources::GetBackBufferDXGIFormat().
+ D3D11_TEXTURE2D_DESC backBufferDesc;
+ m_d3dBackBuffer->GetDesc(&backBufferDesc);
+ m_dxgiFormat = backBufferDesc.Format;
+
+ // Check for render target size changes.
+ winrt::Windows::Foundation::Size currentSize =
+ m_holographicCamera.RenderTargetSize();
+ if (m_d3dRenderTargetSize != currentSize) {
+ // Set render target size.
+ m_d3dRenderTargetSize = currentSize;
+
+ // A new depth stencil view is also needed.
+ m_d3dDepthStencilView.Reset();
+ }
+ }
+
+ // Refresh depth stencil resources, if needed.
+ if (m_d3dDepthStencilView == nullptr) {
+ // Create a depth stencil view for use with 3D rendering if needed.
+ CD3D11_TEXTURE2D_DESC depthStencilDesc(
+ DXGI_FORMAT_R16_TYPELESS,
+ static_cast<UINT>(m_d3dRenderTargetSize.Width),
+ static_cast<UINT>(m_d3dRenderTargetSize.Height),
+ m_isStereo ? 2 : 1, // Create two textures when rendering in stereo.
+ 1, // Use a single mipmap level.
+ D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE);
+
+ winrt::check_hresult(device->CreateTexture2D(&depthStencilDesc, nullptr,
+ &m_d3dDepthStencil));
+
+ CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(
+ m_isStereo ? D3D11_DSV_DIMENSION_TEXTURE2DARRAY
+ : D3D11_DSV_DIMENSION_TEXTURE2D,
+ DXGI_FORMAT_D16_UNORM);
+ winrt::check_hresult(device->CreateDepthStencilView(
+ m_d3dDepthStencil.Get(), &depthStencilViewDesc,
+ &m_d3dDepthStencilView));
+ }
+
+ // Create the constant buffer, if needed.
+ if (m_viewProjectionConstantBuffer == nullptr) {
+ // Create a constant buffer to store view and projection matrices for the
+ // camera.
+ CD3D11_BUFFER_DESC constantBufferDesc(sizeof(ViewProjectionConstantBuffer),
+ D3D11_BIND_CONSTANT_BUFFER);
+ winrt::check_hresult(device->CreateBuffer(&constantBufferDesc, nullptr,
+ &m_viewProjectionConstantBuffer));
+ }
+}
+
+// Releases resources associated with a back buffer.
+void DX::CameraResources::ReleaseResourcesForBackBuffer(
+ DX::DeviceResources *pDeviceResources) {
+ ID3D11DeviceContext *context = pDeviceResources->GetD3DDeviceContext();
+
+ // Release camera-specific resources.
+ m_d3dBackBuffer.Reset();
+ m_d3dDepthStencil.Reset();
+ m_d3dRenderTargetView.Reset();
+ m_d3dDepthStencilView.Reset();
+ m_viewProjectionConstantBuffer.Reset();
+
+ // Ensure system references to the back buffer are released by clearing the
+ // render target from the graphics pipeline state, and then flushing the
+ // Direct3D context.
+ ID3D11RenderTargetView *nullViews[D3D11_SIMULTANEOUS_RENDER_TARGET_COUNT] = {
+ nullptr};
+ context->OMSetRenderTargets(ARRAYSIZE(nullViews), nullViews, nullptr);
+ context->Flush();
+}
+
+// Updates the view/projection constant buffer for a holographic camera.
+void DX::CameraResources::UpdateViewProjectionBuffer(
+ std::shared_ptr<DX::DeviceResources> deviceResources,
+ HolographicCameraPose const &cameraPose,
+ SpatialCoordinateSystem const &coordinateSystem) {
+ // The system changes the viewport on a per-frame basis for system
+ // optimizations.
+ auto viewport = cameraPose.Viewport();
+ m_d3dViewport =
+ CD3D11_VIEWPORT(viewport.X, viewport.Y, viewport.Width, viewport.Height);
+
+ // The projection transform for each frame is provided by the
+ // HolographicCameraPose.
+ HolographicStereoTransform cameraProjectionTransform =
+ cameraPose.ProjectionTransform();
+
+ // Get a container object with the view and projection matrices for the given
+ // pose in the given coordinate system.
+ auto viewTransformContainer =
+ cameraPose.TryGetViewTransform(coordinateSystem);
+
+ // If TryGetViewTransform returns a null pointer, that means the pose and
+ // coordinate system cannot be understood relative to one another; content
+ // cannot be rendered in this coordinate system for the duration of the
+ // current frame. This usually means that positional tracking is not active
+ // for the current frame, in which case it is possible to use a
+ // SpatialLocatorAttachedFrameOfReference to render content that is not
+ // world-locked instead.
+ DX::ViewProjectionConstantBuffer viewProjectionConstantBufferData;
+ bool viewTransformAcquired = viewTransformContainer != nullptr;
+ if (viewTransformAcquired) {
+ // Otherwise, the set of view transforms can be retrieved.
+ HolographicStereoTransform viewCoordinateSystemTransform =
+ viewTransformContainer.Value();
+
+ // Update the view matrices. Holographic cameras (such as Microsoft
+ // HoloLens) are constantly moving relative to the world. The view matrices
+ // need to be updated every frame.
+ XMStoreFloat4x4(
+ &viewProjectionConstantBufferData.viewProjection[0],
+ XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Left) *
+ XMLoadFloat4x4(&cameraProjectionTransform.Left)));
+ XMStoreFloat4x4(
+ &viewProjectionConstantBufferData.viewProjection[1],
+ XMMatrixTranspose(XMLoadFloat4x4(&viewCoordinateSystemTransform.Right) *
+ XMLoadFloat4x4(&cameraProjectionTransform.Right)));
+ }
+
+ // Use the D3D device context to update Direct3D device-based resources.
+ ID3D11DeviceContext *context = deviceResources->GetD3DDeviceContext();
+
+ // Loading is asynchronous. Resources must be created before they can be
+ // updated.
+ if (context == nullptr || m_viewProjectionConstantBuffer == nullptr ||
+ !viewTransformAcquired) {
+ m_framePending = false;
+ } else {
+ // Update the view and projection matrices.
+ context->UpdateSubresource(m_viewProjectionConstantBuffer.Get(), 0, nullptr,
+ &viewProjectionConstantBufferData, 0, 0);
+
+ m_framePending = true;
+ }
+}
+
+// Gets the view-projection constant buffer for the HolographicCamera and
+// attaches it to the shader pipeline.
+bool DX::CameraResources::AttachViewProjectionBuffer(
+ std::shared_ptr<DX::DeviceResources> &deviceResources) {
+ // This method uses Direct3D device-based resources.
+ ID3D11DeviceContext *context = deviceResources->GetD3DDeviceContext();
+
+ // Loading is asynchronous. Resources must be created before they can be
+ // updated. Cameras can also be added asynchronously, in which case they must
+ // be initialized before they can be used.
+ if (context == nullptr || m_viewProjectionConstantBuffer == nullptr ||
+ m_framePending == false) {
+ return false;
+ }
+
+ // Set the viewport for this camera.
+ context->RSSetViewports(1, &m_d3dViewport);
+
+ // Send the constant buffer to the vertex shader.
+ context->VSSetConstantBuffers(1, 1,
+ m_viewProjectionConstantBuffer.GetAddressOf());
+
+ // The template includes a pass-through geometry shader that is used by
+ // default on systems that don't support the D3D11_FEATURE_D3D11_OPTIONS3::
+ // VPAndRTArrayIndexFromAnyShaderFeedingRasterizer extension. The shader
+ // will be enabled at run-time on systems that require it.
+ // If your app will also use the geometry shader for other tasks and those
+ // tasks require the view/projection matrix, uncomment the following line
+ // of code to send the constant buffer to the geometry shader as well.
+ /*context->GSSetConstantBuffers(
+ 1,
+ 1,
+ m_viewProjectionConstantBuffer.GetAddressOf()
+ );*/
+
+ m_framePending = false;
+
+ return true;
+}