HolographicRemoting version 2.4.0 (#19)
Co-authored-by: Florian Bagar <flbagar@microsoft.com>
54
LICENSE
|
@ -1,21 +1,41 @@
|
|||
MIT License
|
||||
Mixed Reality Samples
|
||||
|
||||
Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
MIT License
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
Copyright (c) 2012-2020 Microsoft Corp
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
OpenXR Samples
|
||||
|
||||
Copyright (c) 2020 Microsoft Corp
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
|
|
19
README.md
|
@ -1,9 +1,10 @@
|
|||
|
||||
# Holographic Remoting Samples
|
||||
|
||||
This repository hosts the two sample applications for Holographic Remoting. (https://docs.microsoft.com/en-us/windows/mixed-reality/holographic-remoting-player)
|
||||
* The remote sample shows how to write an application streaming content to a Microsoft HoloLens 2 or a PC running Windows Mixed Reality.
|
||||
* The player sample shows how to write an application running on your Microsoft HoloLens 2 or a Windows Mixed Reality PC and recieving streamed content. The player sample is very similar to the Holographic Remoting Player available in the store.
|
||||
The [Holographic Remoting Samples
|
||||
](https://github.com/microsoft/MixedReality-HolographicRemoting-Samples) repository hosts sample applications for [Holographic Remoting](https://docs.microsoft.com/en-us/windows/mixed-reality/holographic-remoting-player).
|
||||
* The two remote samples show how to write an application for streaming content to a Microsoft HoloLens 2 or a PC running Windows Mixed Reality, using either the Mixed Reality or OpenXR runtime.
|
||||
* The player sample shows how to write an application running on your Microsoft HoloLens 2 or a Windows Mixed Reality PC and receive streamed content, using the Mixed Reality runtime. The player sample is very similar to the Holographic Remoting Player available in the store.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
|
@ -16,11 +17,23 @@ This repository hosts the two sample applications for Holographic Remoting. (htt
|
|||
|
||||
## Getting Started
|
||||
|
||||
### Mixed Reality
|
||||
|
||||
1. Open one of the ```.sln``` files either under ```player/``` or ```remote/```.
|
||||
2. On first use ensure to restore any missing nuget packages.
|
||||
3. Then build and run.
|
||||
* When running the remote app, pass the ip address of your HoloLens device as first argument to the application.
|
||||
|
||||
For more information, please refer to the official [Mixed Reality documentation](https://docs.microsoft.com/en-us/windows/mixed-reality/).
|
||||
|
||||
### OpenXR
|
||||
1. Open the ```.sln``` file under ```remote_openxr```.
|
||||
2. On first use ensure to restore any missing nuget packages.
|
||||
3. Then build and run.
|
||||
* When running the remote app, pass the ip address of your HoloLens device as first argument to the application.
|
||||
|
||||
For more information, please refer to the official [OpenXR reference](https://www.khronos.org/openxr/).
|
||||
|
||||
## Contributing
|
||||
|
||||
This project welcomes contributions and suggestions. Most contributions require you to agree to a
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" xmlns:uap2="http://schemas.microsoft.com/appx/manifest/uap/windows10/2" xmlns:uap5="http://schemas.microsoft.com/appx/manifest/uap/windows10/5" IgnorableNamespaces="uap mp uap2 uap5">
|
||||
<Identity Name="SampleHolographicRemotingPlayer" Publisher="CN=SampleHolographicRemotingPlayer" Version="2.3.0.0" />
|
||||
<Identity Name="SampleHolographicRemotingPlayer" Publisher="CN=SampleHolographicRemotingPlayer" Version="2.4.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="b65c9a46-d0b3-4954-829a-6a60bed54d0a" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>Sample Holographic AppRemoting Player</DisplayName>
|
||||
|
|
|
@ -361,6 +361,6 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.2.3.0\build\native\Microsoft.Holographic.Remoting.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.2.3.0\build\native\Microsoft.Holographic.Remoting.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.2.4.0\build\native\Microsoft.Holographic.Remoting.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.2.4.0\build\native\Microsoft.Holographic.Remoting.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting" version="2.3.0" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting" version="2.4.0" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
||||
<Identity Name="b0cf2e39-8f6e-4238-b33a-868c9b1122ce" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="2.3.0.0" />
|
||||
<Identity Name="b0cf2e39-8f6e-4238-b33a-868c9b1122ce" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="2.4.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="b0cf2e39-8f6e-4238-b33a-868c9b1122ce" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>SampleRemote</DisplayName>
|
||||
|
|
|
@ -309,6 +309,6 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.2.3.0\build\native\Microsoft.Holographic.Remoting.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.2.3.0\build\native\Microsoft.Holographic.Remoting.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.2.4.0\build\native\Microsoft.Holographic.Remoting.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.2.4.0\build\native\Microsoft.Holographic.Remoting.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting" version="2.3.0" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting" version="2.4.0" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -65,7 +65,7 @@ void PerceptionDeviceHandler::Start()
|
|||
|
||||
m_rootObjectChangeHandler = winrt::make_self<RootObjectChangeHandler>(*this);
|
||||
|
||||
std::array<const GUID, 2> rootObjectIds{QRCodeTracker::GetStaticPropertyId()};
|
||||
std::array<const GUID, 1> rootObjectIds{QRCodeTracker::GetStaticPropertyId()};
|
||||
for (size_t i = 0; i < rootObjectIds.size(); ++i)
|
||||
{
|
||||
winrt::com_ptr<IPerceptionDeviceRootObjectWatcher> watcher;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Package xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10" xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest" xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10" IgnorableNamespaces="uap mp">
|
||||
<Identity Name="b0cf2e39-8f6e-4238-b33a-868c9b1122ce" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="2.3.0.0" />
|
||||
<Identity Name="b0cf2e39-8f6e-4238-b33a-868c9b1122ce" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" Version="2.4.0.0" />
|
||||
<mp:PhoneIdentity PhoneProductId="b0cf2e39-8f6e-4238-b33a-868c9b1122ce" PhonePublisherId="00000000-0000-0000-0000-000000000000" />
|
||||
<Properties>
|
||||
<DisplayName>SampleRemote</DisplayName>
|
||||
|
|
|
@ -367,6 +367,6 @@
|
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.2.3.0\build\native\Microsoft.Holographic.Remoting.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.2.3.0\build\native\Microsoft.Holographic.Remoting.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.2.4.0\build\native\Microsoft.Holographic.Remoting.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.2.4.0\build\native\Microsoft.Holographic.Remoting.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting" version="2.3.0" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting" version="2.4.0" targetFramework="native" />
|
||||
</packages>
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
---
|
||||
# Created at https://zed0.co.uk/clang-format-configurator/
|
||||
AllowShortBlocksOnASingleLine: 'false'
|
||||
AllowShortFunctionsOnASingleLine: 'false'
|
||||
AccessModifierOffset: '-4'
|
||||
AlignEscapedNewlines: 'Left'
|
||||
AlwaysBreakTemplateDeclarations: 'true'
|
||||
BinPackParameters: false
|
||||
BinPackArguments: false
|
||||
BreakBeforeBraces: Custom
|
||||
BreakConstructorInitializers: 'BeforeComma'
|
||||
ColumnLimit: '140'
|
||||
ConstructorInitializerAllOnOneLineOrOnePerLine: 'false'
|
||||
IndentCaseLabels: 'false'
|
||||
IndentWidth: '4'
|
||||
IndentWrappedFunctionNames: 'false'
|
||||
ForEachMacros: ['TEST_CLASS']
|
||||
KeepEmptyLinesAtTheStartOfBlocks: 'false'
|
||||
MaxEmptyLinesToKeep: '1'
|
||||
NamespaceIndentation: All
|
||||
PenaltyReturnTypeOnItsOwnLine: 100
|
||||
PointerAlignment: Left
|
||||
SortIncludes: 'false'
|
||||
SpaceAfterCStyleCast: 'false'
|
||||
SpaceBeforeAssignmentOperators: 'true'
|
||||
SpaceBeforeParens: ControlStatements
|
||||
SpaceInEmptyParentheses: 'false'
|
||||
SpacesInAngles: 'false'
|
||||
SpacesInCStyleCastParentheses: 'false'
|
||||
SpacesInContainerLiterals: 'false'
|
||||
SpacesInParentheses: 'false'
|
||||
SpacesInSquareBrackets: 'false'
|
||||
Standard: Cpp11
|
||||
UseTab: Never
|
||||
|
||||
...
|
|
@ -0,0 +1,44 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#include "pch.h"
|
||||
#include "OpenXrProgram.h"
|
||||
|
||||
#include <SampleShared/CommandLineUtility.h>
|
||||
|
||||
#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_DESKTOP)
|
||||
constexpr const char* ProgramName = "SampleRemoteOpenXr_win32";
|
||||
#else
|
||||
constexpr const char* ProgramName = "SampleRemoteOpenXr_uwp";
|
||||
#endif
|
||||
|
||||
int __stdcall WinMain(_In_ HINSTANCE, _In_opt_ HINSTANCE, _In_ LPSTR, _In_ int) {
|
||||
try {
|
||||
sample::AppOptions options;
|
||||
sample::ParseCommandLine(options);
|
||||
|
||||
auto graphics = sample::CreateCubeGraphics();
|
||||
auto program = sample::CreateOpenXrProgram(ProgramName, std::move(graphics), options);
|
||||
program->Run();
|
||||
} catch (const std::exception& ex) {
|
||||
DEBUG_PRINT("Unhandled Exception: %s\n", ex.what());
|
||||
return 1;
|
||||
} catch (...) {
|
||||
DEBUG_PRINT("Unhandled Exception\n");
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
После Ширина: | Высота: | Размер: 1.9 KiB |
После Ширина: | Высота: | Размер: 46 KiB |
После Ширина: | Высота: | Размер: 12 KiB |
После Ширина: | Высота: | Размер: 3.1 KiB |
Двоичные данные
remote_openxr/desktop/Assets/Square44x44Logo.targetsize-24_altform-unplated.png
Normal file
После Ширина: | Высота: | Размер: 1.3 KiB |
После Ширина: | Высота: | Размер: 1.9 KiB |
После Ширина: | Высота: | Размер: 12 KiB |
|
@ -0,0 +1,289 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#include "pch.h"
|
||||
#include "OpenXrProgram.h"
|
||||
#include "DxUtility.h"
|
||||
|
||||
namespace {
|
||||
namespace CubeShader {
|
||||
struct Vertex {
|
||||
XrVector3f Position;
|
||||
XrVector3f Color;
|
||||
};
|
||||
|
||||
constexpr XrVector3f Red{1, 0, 0};
|
||||
constexpr XrVector3f DarkRed{0.25f, 0, 0};
|
||||
constexpr XrVector3f Green{0, 1, 0};
|
||||
constexpr XrVector3f DarkGreen{0, 0.25f, 0};
|
||||
constexpr XrVector3f Blue{0, 0, 1};
|
||||
constexpr XrVector3f DarkBlue{0, 0, 0.25f};
|
||||
|
||||
// Vertices for a 1x1x1 meter cube. (Left/Right, Top/Bottom, Front/Back)
|
||||
constexpr XrVector3f LBB{-0.5f, -0.5f, -0.5f};
|
||||
constexpr XrVector3f LBF{-0.5f, -0.5f, 0.5f};
|
||||
constexpr XrVector3f LTB{-0.5f, 0.5f, -0.5f};
|
||||
constexpr XrVector3f LTF{-0.5f, 0.5f, 0.5f};
|
||||
constexpr XrVector3f RBB{0.5f, -0.5f, -0.5f};
|
||||
constexpr XrVector3f RBF{0.5f, -0.5f, 0.5f};
|
||||
constexpr XrVector3f RTB{0.5f, 0.5f, -0.5f};
|
||||
constexpr XrVector3f RTF{0.5f, 0.5f, 0.5f};
|
||||
|
||||
#define CUBE_SIDE(V1, V2, V3, V4, V5, V6, COLOR) {V1, COLOR}, {V2, COLOR}, {V3, COLOR}, {V4, COLOR}, {V5, COLOR}, {V6, COLOR},
|
||||
|
||||
constexpr Vertex c_cubeVertices[] = {
|
||||
CUBE_SIDE(LTB, LBF, LBB, LTB, LTF, LBF, DarkRed) // -X
|
||||
CUBE_SIDE(RTB, RBB, RBF, RTB, RBF, RTF, Red) // +X
|
||||
CUBE_SIDE(LBB, LBF, RBF, LBB, RBF, RBB, DarkGreen) // -Y
|
||||
CUBE_SIDE(LTB, RTB, RTF, LTB, RTF, LTF, Green) // +Y
|
||||
CUBE_SIDE(LBB, RBB, RTB, LBB, RTB, LTB, DarkBlue) // -Z
|
||||
CUBE_SIDE(LBF, LTF, RTF, LBF, RTF, RBF, Blue) // +Z
|
||||
};
|
||||
|
||||
// Winding order is clockwise. Each side uses a different color.
|
||||
constexpr unsigned short c_cubeIndices[] = {
|
||||
0, 1, 2, 3, 4, 5, // -X
|
||||
6, 7, 8, 9, 10, 11, // +X
|
||||
12, 13, 14, 15, 16, 17, // -Y
|
||||
18, 19, 20, 21, 22, 23, // +Y
|
||||
24, 25, 26, 27, 28, 29, // -Z
|
||||
30, 31, 32, 33, 34, 35, // +Z
|
||||
};
|
||||
|
||||
struct ModelConstantBuffer {
|
||||
DirectX::XMFLOAT4X4 Model;
|
||||
};
|
||||
|
||||
struct ViewProjectionConstantBuffer {
|
||||
DirectX::XMFLOAT4X4 ViewProjection[2];
|
||||
};
|
||||
|
||||
constexpr uint32_t MaxViewInstance = 2;
|
||||
|
||||
// Separate entrypoints for the vertex and pixel shader functions.
|
||||
constexpr char ShaderHlsl[] = R"_(
|
||||
struct VSOutput {
|
||||
float4 Pos : SV_POSITION;
|
||||
float3 Color : COLOR0;
|
||||
uint viewId : SV_RenderTargetArrayIndex;
|
||||
};
|
||||
struct VSInput {
|
||||
float3 Pos : POSITION;
|
||||
float3 Color : COLOR0;
|
||||
uint instId : SV_InstanceID;
|
||||
};
|
||||
cbuffer ModelConstantBuffer : register(b0) {
|
||||
float4x4 Model;
|
||||
};
|
||||
cbuffer ViewProjectionConstantBuffer : register(b1) {
|
||||
float4x4 ViewProjection[2];
|
||||
};
|
||||
|
||||
VSOutput MainVS(VSInput input) {
|
||||
VSOutput output;
|
||||
output.Pos = mul(mul(float4(input.Pos, 1), Model), ViewProjection[input.instId]);
|
||||
output.Color = input.Color;
|
||||
output.viewId = input.instId;
|
||||
return output;
|
||||
}
|
||||
|
||||
float4 MainPS(VSOutput input) : SV_TARGET {
|
||||
return float4(input.Color, 1);
|
||||
}
|
||||
)_";
|
||||
|
||||
} // namespace CubeShader
|
||||
|
||||
struct CubeGraphics : sample::IGraphicsPluginD3D11 {
|
||||
ID3D11Device* InitializeDevice(LUID adapterLuid, const std::vector<D3D_FEATURE_LEVEL>& featureLevels) override {
|
||||
const winrt::com_ptr<IDXGIAdapter1> adapter = sample::dx::GetAdapter(adapterLuid);
|
||||
|
||||
sample::dx::CreateD3D11DeviceAndContext(adapter.get(), featureLevels, m_device.put(), m_deviceContext.put());
|
||||
|
||||
InitializeD3DResources();
|
||||
|
||||
return m_device.get();
|
||||
}
|
||||
|
||||
void InitializeD3DResources() {
|
||||
const winrt::com_ptr<ID3DBlob> vertexShaderBytes = sample::dx::CompileShader(CubeShader::ShaderHlsl, "MainVS", "vs_5_0");
|
||||
CHECK_HRCMD(m_device->CreateVertexShader(
|
||||
vertexShaderBytes->GetBufferPointer(), vertexShaderBytes->GetBufferSize(), nullptr, m_vertexShader.put()));
|
||||
|
||||
const winrt::com_ptr<ID3DBlob> pixelShaderBytes = sample::dx::CompileShader(CubeShader::ShaderHlsl, "MainPS", "ps_5_0");
|
||||
CHECK_HRCMD(m_device->CreatePixelShader(
|
||||
pixelShaderBytes->GetBufferPointer(), pixelShaderBytes->GetBufferSize(), nullptr, m_pixelShader.put()));
|
||||
|
||||
const D3D11_INPUT_ELEMENT_DESC vertexDesc[] = {
|
||||
{"POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
{"COLOR", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, D3D11_APPEND_ALIGNED_ELEMENT, D3D11_INPUT_PER_VERTEX_DATA, 0},
|
||||
};
|
||||
|
||||
CHECK_HRCMD(m_device->CreateInputLayout(vertexDesc,
|
||||
(UINT)std::size(vertexDesc),
|
||||
vertexShaderBytes->GetBufferPointer(),
|
||||
vertexShaderBytes->GetBufferSize(),
|
||||
m_inputLayout.put()));
|
||||
|
||||
const CD3D11_BUFFER_DESC modelConstantBufferDesc(sizeof(CubeShader::ModelConstantBuffer), D3D11_BIND_CONSTANT_BUFFER);
|
||||
CHECK_HRCMD(m_device->CreateBuffer(&modelConstantBufferDesc, nullptr, m_modelCBuffer.put()));
|
||||
|
||||
const CD3D11_BUFFER_DESC viewProjectionConstantBufferDesc(sizeof(CubeShader::ViewProjectionConstantBuffer),
|
||||
D3D11_BIND_CONSTANT_BUFFER);
|
||||
CHECK_HRCMD(m_device->CreateBuffer(&viewProjectionConstantBufferDesc, nullptr, m_viewProjectionCBuffer.put()));
|
||||
|
||||
const D3D11_SUBRESOURCE_DATA vertexBufferData{CubeShader::c_cubeVertices};
|
||||
const CD3D11_BUFFER_DESC vertexBufferDesc(sizeof(CubeShader::c_cubeVertices), D3D11_BIND_VERTEX_BUFFER);
|
||||
CHECK_HRCMD(m_device->CreateBuffer(&vertexBufferDesc, &vertexBufferData, m_cubeVertexBuffer.put()));
|
||||
|
||||
const D3D11_SUBRESOURCE_DATA indexBufferData{CubeShader::c_cubeIndices};
|
||||
const CD3D11_BUFFER_DESC indexBufferDesc(sizeof(CubeShader::c_cubeIndices), D3D11_BIND_INDEX_BUFFER);
|
||||
CHECK_HRCMD(m_device->CreateBuffer(&indexBufferDesc, &indexBufferData, m_cubeIndexBuffer.put()));
|
||||
|
||||
D3D11_FEATURE_DATA_D3D11_OPTIONS3 options;
|
||||
m_device->CheckFeatureSupport(D3D11_FEATURE_D3D11_OPTIONS3, &options, sizeof(options));
|
||||
CHECK_MSG(options.VPAndRTArrayIndexFromAnyShaderFeedingRasterizer,
|
||||
"This sample requires VPRT support. Adjust sample shaders on GPU without VRPT.");
|
||||
|
||||
CD3D11_DEPTH_STENCIL_DESC depthStencilDesc(CD3D11_DEFAULT{});
|
||||
depthStencilDesc.DepthEnable = true;
|
||||
depthStencilDesc.DepthWriteMask = D3D11_DEPTH_WRITE_MASK_ALL;
|
||||
depthStencilDesc.DepthFunc = D3D11_COMPARISON_GREATER;
|
||||
CHECK_HRCMD(m_device->CreateDepthStencilState(&depthStencilDesc, m_reversedZDepthNoStencilTest.put()));
|
||||
}
|
||||
|
||||
const std::vector<DXGI_FORMAT>& SupportedColorFormats() const override {
|
||||
const static std::vector<DXGI_FORMAT> SupportedColorFormats = {
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM,
|
||||
DXGI_FORMAT_R8G8B8A8_UNORM_SRGB,
|
||||
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB,
|
||||
};
|
||||
return SupportedColorFormats;
|
||||
}
|
||||
|
||||
const std::vector<DXGI_FORMAT>& SupportedDepthFormats() const override {
|
||||
const static std::vector<DXGI_FORMAT> SupportedDepthFormats = {
|
||||
DXGI_FORMAT_D32_FLOAT,
|
||||
DXGI_FORMAT_D16_UNORM,
|
||||
DXGI_FORMAT_D24_UNORM_S8_UINT,
|
||||
DXGI_FORMAT_D32_FLOAT_S8X24_UINT,
|
||||
};
|
||||
return SupportedDepthFormats;
|
||||
}
|
||||
|
||||
void RenderView(const XrRect2Di& imageRect,
|
||||
const float renderTargetClearColor[4],
|
||||
const std::vector<xr::math::ViewProjection>& viewProjections,
|
||||
DXGI_FORMAT colorSwapchainFormat,
|
||||
ID3D11Texture2D* colorTexture,
|
||||
DXGI_FORMAT depthSwapchainFormat,
|
||||
ID3D11Texture2D* depthTexture,
|
||||
const std::vector<const sample::Cube*>& cubes) override {
|
||||
const uint32_t viewInstanceCount = (uint32_t)viewProjections.size();
|
||||
CHECK_MSG(viewInstanceCount <= CubeShader::MaxViewInstance,
|
||||
"Sample shader supports 2 or fewer view instances. Adjust shader to accommodate more.")
|
||||
|
||||
CD3D11_VIEWPORT viewport(
|
||||
(float)imageRect.offset.x, (float)imageRect.offset.y, (float)imageRect.extent.width, (float)imageRect.extent.height);
|
||||
m_deviceContext->RSSetViewports(1, &viewport);
|
||||
|
||||
// Create RenderTargetView with the original swapchain format (swapchain image is typeless).
|
||||
winrt::com_ptr<ID3D11RenderTargetView> renderTargetView;
|
||||
const CD3D11_RENDER_TARGET_VIEW_DESC renderTargetViewDesc(D3D11_RTV_DIMENSION_TEXTURE2DARRAY, colorSwapchainFormat);
|
||||
CHECK_HRCMD(m_device->CreateRenderTargetView(colorTexture, &renderTargetViewDesc, renderTargetView.put()));
|
||||
|
||||
// Create a DepthStencilView with the original swapchain format (swapchain image is typeless)
|
||||
winrt::com_ptr<ID3D11DepthStencilView> depthStencilView;
|
||||
CD3D11_DEPTH_STENCIL_VIEW_DESC depthStencilViewDesc(D3D11_DSV_DIMENSION_TEXTURE2DARRAY, depthSwapchainFormat);
|
||||
CHECK_HRCMD(m_device->CreateDepthStencilView(depthTexture, &depthStencilViewDesc, depthStencilView.put()));
|
||||
|
||||
const bool reversedZ = viewProjections[0].NearFar.Near > viewProjections[0].NearFar.Far;
|
||||
const float depthClearValue = reversedZ ? 0.f : 1.f;
|
||||
|
||||
// Clear swapchain and depth buffer. NOTE: This will clear the entire render target view, not just the specified view.
|
||||
m_deviceContext->ClearRenderTargetView(renderTargetView.get(), renderTargetClearColor);
|
||||
m_deviceContext->ClearDepthStencilView(depthStencilView.get(), D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, depthClearValue, 0);
|
||||
m_deviceContext->OMSetDepthStencilState(reversedZ ? m_reversedZDepthNoStencilTest.get() : nullptr, 0);
|
||||
|
||||
ID3D11RenderTargetView* renderTargets[] = {renderTargetView.get()};
|
||||
m_deviceContext->OMSetRenderTargets((UINT)std::size(renderTargets), renderTargets, depthStencilView.get());
|
||||
|
||||
ID3D11Buffer* const constantBuffers[] = {m_modelCBuffer.get(), m_viewProjectionCBuffer.get()};
|
||||
m_deviceContext->VSSetConstantBuffers(0, (UINT)std::size(constantBuffers), constantBuffers);
|
||||
m_deviceContext->VSSetShader(m_vertexShader.get(), nullptr, 0);
|
||||
m_deviceContext->PSSetShader(m_pixelShader.get(), nullptr, 0);
|
||||
|
||||
CubeShader::ViewProjectionConstantBuffer viewProjectionCBufferData{};
|
||||
|
||||
for (uint32_t k = 0; k < viewInstanceCount; k++) {
|
||||
const DirectX::XMMATRIX spaceToView = xr::math::LoadInvertedXrPose(viewProjections[k].Pose);
|
||||
const DirectX::XMMATRIX projectionMatrix = ComposeProjectionMatrix(viewProjections[k].Fov, viewProjections[k].NearFar);
|
||||
|
||||
// Set view projection matrix for each view, transpose for shader usage.
|
||||
DirectX::XMStoreFloat4x4(&viewProjectionCBufferData.ViewProjection[k],
|
||||
DirectX::XMMatrixTranspose(spaceToView * projectionMatrix));
|
||||
}
|
||||
m_deviceContext->UpdateSubresource(m_viewProjectionCBuffer.get(), 0, nullptr, &viewProjectionCBufferData, 0, 0);
|
||||
|
||||
// Set cube primitive data.
|
||||
const UINT strides[] = {sizeof(CubeShader::Vertex)};
|
||||
const UINT offsets[] = {0};
|
||||
ID3D11Buffer* vertexBuffers[] = {m_cubeVertexBuffer.get()};
|
||||
m_deviceContext->IASetVertexBuffers(0, (UINT)std::size(vertexBuffers), vertexBuffers, strides, offsets);
|
||||
m_deviceContext->IASetIndexBuffer(m_cubeIndexBuffer.get(), DXGI_FORMAT_R16_UINT, 0);
|
||||
m_deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
|
||||
m_deviceContext->IASetInputLayout(m_inputLayout.get());
|
||||
|
||||
// Render each cube
|
||||
for (const sample::Cube* cube : cubes) {
|
||||
// Compute and update the model transform for each cube, transpose for shader usage.
|
||||
CubeShader::ModelConstantBuffer model;
|
||||
const DirectX::XMMATRIX scaleMatrix = DirectX::XMMatrixScaling(cube->Scale.x, cube->Scale.y, cube->Scale.z);
|
||||
DirectX::XMStoreFloat4x4(&model.Model,
|
||||
DirectX::XMMatrixTranspose(scaleMatrix * xr::math::LoadXrPose(cube->PoseInAppSpace)));
|
||||
m_deviceContext->UpdateSubresource(m_modelCBuffer.get(), 0, nullptr, &model, 0, 0);
|
||||
|
||||
// Draw the cube.
|
||||
m_deviceContext->DrawIndexedInstanced((UINT)std::size(CubeShader::c_cubeIndices), viewInstanceCount, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
void ClearView(ID3D11Texture2D* colorTexture, const float renderTargetClearColor[4]) override {
|
||||
winrt::com_ptr<ID3D11RenderTargetView> renderTargetView;
|
||||
CHECK_HRCMD(m_device->CreateRenderTargetView(colorTexture, nullptr, renderTargetView.put()));
|
||||
m_deviceContext->ClearRenderTargetView(renderTargetView.get(), renderTargetClearColor);
|
||||
}
|
||||
|
||||
private:
|
||||
winrt::com_ptr<ID3D11Device> m_device;
|
||||
winrt::com_ptr<ID3D11DeviceContext> m_deviceContext;
|
||||
winrt::com_ptr<ID3D11VertexShader> m_vertexShader;
|
||||
winrt::com_ptr<ID3D11PixelShader> m_pixelShader;
|
||||
winrt::com_ptr<ID3D11InputLayout> m_inputLayout;
|
||||
winrt::com_ptr<ID3D11Buffer> m_modelCBuffer;
|
||||
winrt::com_ptr<ID3D11Buffer> m_viewProjectionCBuffer;
|
||||
winrt::com_ptr<ID3D11Buffer> m_cubeVertexBuffer;
|
||||
winrt::com_ptr<ID3D11Buffer> m_cubeIndexBuffer;
|
||||
winrt::com_ptr<ID3D11DepthStencilState> m_reversedZDepthNoStencilTest;
|
||||
};
|
||||
} // namespace
|
||||
|
||||
namespace sample {
|
||||
std::unique_ptr<sample::IGraphicsPluginD3D11> CreateCubeGraphics() {
|
||||
return std::make_unique<CubeGraphics>();
|
||||
}
|
||||
} // namespace sample
|
|
@ -0,0 +1,103 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#include "pch.h"
|
||||
#include "DxUtility.h"
|
||||
#include <D3Dcompiler.h>
|
||||
#pragma comment(lib, "D3DCompiler.lib")
|
||||
|
||||
namespace sample::dx {
|
||||
winrt::com_ptr<IDXGIAdapter1> GetAdapter(LUID adapterId) {
|
||||
// Create the DXGI factory.
|
||||
winrt::com_ptr<IDXGIFactory1> dxgiFactory;
|
||||
CHECK_HRCMD(CreateDXGIFactory1(winrt::guid_of<IDXGIFactory1>(), dxgiFactory.put_void()));
|
||||
|
||||
for (UINT adapterIndex = 0;; adapterIndex++) {
|
||||
// EnumAdapters1 will fail with DXGI_ERROR_NOT_FOUND when there are no more adapters to enumerate.
|
||||
winrt::com_ptr<IDXGIAdapter1> dxgiAdapter;
|
||||
CHECK_HRCMD(dxgiFactory->EnumAdapters1(adapterIndex, dxgiAdapter.put()));
|
||||
|
||||
DXGI_ADAPTER_DESC1 adapterDesc;
|
||||
CHECK_HRCMD(dxgiAdapter->GetDesc1(&adapterDesc));
|
||||
if (memcmp(&adapterDesc.AdapterLuid, &adapterId, sizeof(adapterId)) == 0) {
|
||||
DEBUG_PRINT("Using graphics adapter %ws", adapterDesc.Description);
|
||||
return dxgiAdapter;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CreateD3D11DeviceAndContext(IDXGIAdapter1* adapter,
|
||||
const std::vector<D3D_FEATURE_LEVEL>& featureLevels,
|
||||
ID3D11Device** device,
|
||||
ID3D11DeviceContext** deviceContext) {
|
||||
UINT creationFlags = D3D11_CREATE_DEVICE_BGRA_SUPPORT;
|
||||
|
||||
#ifdef _DEBUG
|
||||
creationFlags |= D3D11_CREATE_DEVICE_DEBUG;
|
||||
#endif
|
||||
|
||||
// Create the Direct3D 11 API device object and a corresponding context.
|
||||
D3D_DRIVER_TYPE driverType = adapter == nullptr ? D3D_DRIVER_TYPE_HARDWARE : D3D_DRIVER_TYPE_UNKNOWN;
|
||||
|
||||
TryAgain:
|
||||
const HRESULT hr = D3D11CreateDevice(adapter,
|
||||
driverType,
|
||||
0,
|
||||
creationFlags,
|
||||
featureLevels.data(),
|
||||
(UINT)featureLevels.size(),
|
||||
D3D11_SDK_VERSION,
|
||||
device,
|
||||
nullptr,
|
||||
deviceContext);
|
||||
|
||||
if (FAILED(hr)) {
|
||||
// If initialization failed, it may be because device debugging isn't supprted, so retry without that.
|
||||
if ((creationFlags & D3D11_CREATE_DEVICE_DEBUG) && (hr == DXGI_ERROR_SDK_COMPONENT_MISSING)) {
|
||||
creationFlags &= ~D3D11_CREATE_DEVICE_DEBUG;
|
||||
goto TryAgain;
|
||||
}
|
||||
|
||||
// If the initialization still fails, fall back to the WARP device.
|
||||
// For more information on WARP, see: http://go.microsoft.com/fwlink/?LinkId=286690
|
||||
if (driverType != D3D_DRIVER_TYPE_WARP) {
|
||||
driverType = D3D_DRIVER_TYPE_WARP;
|
||||
goto TryAgain;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
winrt::com_ptr<ID3DBlob> CompileShader(const char* hlsl, const char* entrypoint, const char* shaderTarget) {
|
||||
winrt::com_ptr<ID3DBlob> compiled;
|
||||
winrt::com_ptr<ID3DBlob> errMsgs;
|
||||
DWORD flags = D3DCOMPILE_PACK_MATRIX_COLUMN_MAJOR | D3DCOMPILE_ENABLE_STRICTNESS | D3DCOMPILE_WARNINGS_ARE_ERRORS;
|
||||
|
||||
#ifdef _DEBUG
|
||||
flags |= D3DCOMPILE_SKIP_OPTIMIZATION | D3DCOMPILE_DEBUG;
|
||||
#else
|
||||
flags |= D3DCOMPILE_OPTIMIZATION_LEVEL3;
|
||||
#endif
|
||||
|
||||
HRESULT hr =
|
||||
D3DCompile(hlsl, strlen(hlsl), nullptr, nullptr, nullptr, entrypoint, shaderTarget, flags, 0, compiled.put(), errMsgs.put());
|
||||
if (FAILED(hr)) {
|
||||
std::string errMsg((const char*)errMsgs->GetBufferPointer(), errMsgs->GetBufferSize());
|
||||
DEBUG_PRINT("D3DCompile failed %X: %s", hr, errMsg.c_str());
|
||||
CHECK_HRESULT(hr, "D3DCompile failed");
|
||||
}
|
||||
|
||||
return compiled;
|
||||
}
|
||||
} // namespace sample::dx
|
|
@ -0,0 +1,30 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#include <d3dcommon.h> //ID3DBlob
|
||||
|
||||
namespace sample::dx {
|
||||
|
||||
winrt::com_ptr<IDXGIAdapter1> GetAdapter(LUID adapterId);
|
||||
|
||||
void CreateD3D11DeviceAndContext(IDXGIAdapter1* adapter,
|
||||
const std::vector<D3D_FEATURE_LEVEL>& featureLevels,
|
||||
ID3D11Device** device,
|
||||
ID3D11DeviceContext** deviceContext);
|
||||
|
||||
winrt::com_ptr<ID3DBlob> CompileShader(const char* hlsl, const char* entrypoint, const char* shaderTarget);
|
||||
} // namespace sample::dx
|
|
@ -0,0 +1,63 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <SampleShared/CommandLineUtility.h>
|
||||
|
||||
namespace sample {
|
||||
struct Cube {
|
||||
xr::SpaceHandle Space{};
|
||||
std::optional<XrPosef> PoseInSpace{}; // Relative pose in cube Space. Default to identity.
|
||||
XrVector3f Scale{0.1f, 0.1f, 0.1f};
|
||||
|
||||
XrPosef PoseInAppSpace = xr::math::Pose::Identity(); // Cube pose in app space that gets updated every frame
|
||||
};
|
||||
|
||||
struct IOpenXrProgram {
|
||||
virtual ~IOpenXrProgram() = default;
|
||||
virtual void Run() = 0;
|
||||
};
|
||||
|
||||
struct IGraphicsPluginD3D11 {
|
||||
virtual ~IGraphicsPluginD3D11() = default;
|
||||
|
||||
// Create an instance of this graphics api for the provided instance and systemId.
|
||||
virtual ID3D11Device* InitializeDevice(LUID adapterLuid, const std::vector<D3D_FEATURE_LEVEL>& featureLevels) = 0;
|
||||
|
||||
// List of color pixel formats supported by this app.
|
||||
virtual const std::vector<DXGI_FORMAT>& SupportedColorFormats() const = 0;
|
||||
virtual const std::vector<DXGI_FORMAT>& SupportedDepthFormats() const = 0;
|
||||
|
||||
// Render to swapchain images using stereo image array
|
||||
virtual void RenderView(const XrRect2Di& imageRect,
|
||||
const float renderTargetClearColor[4],
|
||||
const std::vector<xr::math::ViewProjection>& viewProjections,
|
||||
DXGI_FORMAT colorSwapchainFormat,
|
||||
ID3D11Texture2D* colorTexture,
|
||||
DXGI_FORMAT depthSwapchainFormat,
|
||||
ID3D11Texture2D* depthTexture,
|
||||
const std::vector<const sample::Cube*>& cubes) = 0;
|
||||
|
||||
virtual void ClearView(ID3D11Texture2D* colorTexture, const float renderTargetClearColor[4]) = 0;
|
||||
};
|
||||
|
||||
std::unique_ptr<IGraphicsPluginD3D11> CreateCubeGraphics();
|
||||
std::unique_ptr<IOpenXrProgram> CreateOpenXrProgram(std::string applicationName,
|
||||
std::unique_ptr<IGraphicsPluginD3D11> graphicsPlugin,
|
||||
const sample::AppOptions& options);
|
||||
|
||||
} // namespace sample
|
|
@ -0,0 +1,51 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
|
||||
<Package
|
||||
xmlns="http://schemas.microsoft.com/appx/manifest/foundation/windows10"
|
||||
xmlns:mp="http://schemas.microsoft.com/appx/2014/phone/manifest"
|
||||
xmlns:uap="http://schemas.microsoft.com/appx/manifest/uap/windows10"
|
||||
IgnorableNamespaces="uap mp">
|
||||
|
||||
<Identity
|
||||
Name="364f83f4-6e13-42e4-8253-71dd3040951c"
|
||||
Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US"
|
||||
Version="1.0.0.0" />
|
||||
|
||||
<mp:PhoneIdentity PhoneProductId="364f83f4-6e13-42e4-8253-71dd3040951c" PhonePublisherId="00000000-0000-0000-0000-000000000000"/>
|
||||
|
||||
<Properties>
|
||||
<DisplayName>SampleRemoteOpenXr</DisplayName>
|
||||
<PublisherDisplayName>Microsoft Corporation</PublisherDisplayName>
|
||||
<Logo>Assets\StoreLogo.png</Logo>
|
||||
</Properties>
|
||||
|
||||
<Dependencies>
|
||||
<TargetDeviceFamily Name="Windows.Universal" MinVersion="10.0.17134.0" MaxVersionTested="10.0.18295.0" />
|
||||
</Dependencies>
|
||||
|
||||
<Resources>
|
||||
<Resource Language="x-generate"/>
|
||||
</Resources>
|
||||
|
||||
<Applications>
|
||||
<Application Id="App"
|
||||
Executable="$targetnametoken$.exe"
|
||||
EntryPoint="SampleRemoteOpenXr.App">
|
||||
<uap:VisualElements
|
||||
DisplayName="SampleRemoteOpenXr"
|
||||
Square150x150Logo="Assets\Square150x150Logo.png"
|
||||
Square44x44Logo="Assets\Square44x44Logo.png"
|
||||
Description="SampleRemoteOpenXr"
|
||||
BackgroundColor="transparent">
|
||||
<uap:DefaultTile Wide310x150Logo="Assets\Wide310x150Logo.png"/>
|
||||
<uap:SplashScreen Image="Assets\SplashScreen.png" />
|
||||
</uap:VisualElements>
|
||||
</Application>
|
||||
</Applications>
|
||||
|
||||
<Capabilities>
|
||||
<Capability Name="internetClient" />
|
||||
<Capability Name="internetClientServer" />
|
||||
<Capability Name="privateNetworkClientServer" />
|
||||
</Capabilities>
|
||||
</Package>
|
|
@ -0,0 +1,32 @@
|
|||
|
||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||
# Visual Studio Version 16
|
||||
VisualStudioVersion = 16.0.29806.167
|
||||
MinimumVisualStudioVersion = 10.0.40219.1
|
||||
Project("{106A4908-2E14-3378-9618-10668523A8A8}") = "SampleRemoteOpenXR", "SampleRemoteOpenXR.vcxproj", "{BDD6541B-7845-3E17-B3C6-6011A4343E9E}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|x64 = Debug|x64
|
||||
Release|x64 = Release|x64
|
||||
RelWithDebInfo|x64 = RelWithDebInfo|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.Debug|x64.Build.0 = Debug|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.Debug|x64.Deploy.0 = Debug|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.Release|x64.ActiveCfg = Release|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.Release|x64.Build.0 = Release|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.Release|x64.Deploy.0 = Release|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
|
||||
{BDD6541B-7845-3E17-B3C6-6011A4343E9E}.RelWithDebInfo|x64.Deploy.0 = RelWithDebInfo|x64
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {76313AE8-8A6B-4837-8649-81C867BF70B2}
|
||||
EndGlobalSection
|
||||
EndGlobal
|
||||
|
|
@ -0,0 +1,258 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="16.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.props')" />
|
||||
<Import Project="packages\OpenXR.Headers.1.0.10.2\build\native\OpenXR.Headers.props" Condition="Exists('packages\OpenXR.Headers.1.0.10.2\build\native\OpenXR.Headers.props')" />
|
||||
<Import Project="packages\OpenXR.Loader.1.0.10.2\build\native\OpenXR.Loader.props" Condition="Exists('packages\OpenXR.Loader.1.0.10.2\build\native\OpenXR.Loader.props')" />
|
||||
<PropertyGroup>
|
||||
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
|
||||
</PropertyGroup>
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="RelWithDebInfo|x64">
|
||||
<Configuration>RelWithDebInfo</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{BDD6541B-7845-3E17-B3C6-6011A4343E9E}</ProjectGuid>
|
||||
<WindowsTargetPlatformVersion>10.0.19041.0</WindowsTargetPlatformVersion>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<Platform>x64</Platform>
|
||||
<ProjectName>SampleRemoteOpenXR</ProjectName>
|
||||
<VCProjectUpgraderObjectName>NoUpgrade</VCProjectUpgraderObjectName>
|
||||
</PropertyGroup>
|
||||
<Import Project="C:/Program Files (x86)/Microsoft Visual Studio/2019/Enterprise/VC/Auxiliary/Build/14.26/Microsoft.VCToolsVersion.14.26.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
<SpectreMitigation>Spectre</SpectreMitigation>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="Configuration">
|
||||
<ConfigurationType>Application</ConfigurationType>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup>
|
||||
<_ProjectFileVersion>10.0.20506.1</_ProjectFileVersion>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">bin\Debug\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">SampleRemoteOpenXR.dir\Debug\</IntDir>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">SampleRemoteOpenXR</TargetName>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">.exe</TargetExt>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</LinkIncremental>
|
||||
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">true</GenerateManifest>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">bin\Release\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='Release|x64'">SampleRemoteOpenXR.dir\Release\</IntDir>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='Release|x64'">SampleRemoteOpenXR</TargetName>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='Release|x64'">.exe</TargetExt>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='Release|x64'">false</LinkIncremental>
|
||||
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='Release|x64'">true</GenerateManifest>
|
||||
<OutDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">bin\RelWithDebInfo\</OutDir>
|
||||
<IntDir Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">SampleRemoteOpenXR.dir\RelWithDebInfo\</IntDir>
|
||||
<TargetName Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">SampleRemoteOpenXR</TargetName>
|
||||
<TargetExt Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">.exe</TargetExt>
|
||||
<LinkIncremental Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">true</LinkIncremental>
|
||||
<GenerateManifest Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">true</GenerateManifest>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /await</AdditionalOptions>
|
||||
<AdditionalUsingDirectories>$(VCIDEInstallDir)vcpackages;$(WindowsSDK_UnionMetadataPath)</AdditionalUsingDirectories>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<InlineFunctionExpansion>Disabled</InlineFunctionExpansion>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<Optimization>Disabled</Optimization>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<UseFullPaths>false</UseFullPaths>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;ALLOW_INSECURE_RANDOM_DEVICE=1;HAR_ENABLE_OPENXR;HAR_DEVELOPMENT;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;UNICODE;CMAKE_INTDIR="Debug";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>WIN32;_DEBUG;_WINDOWS;ALLOW_INSECURE_RANDOM_DEVICE=1;HAR_ENABLE_OPENXR;HAR_DEVELOPMENT;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;UNICODE;CMAKE_INTDIR=\"Debug\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
|
||||
<HeaderFileName>%(Filename).h</HeaderFileName>
|
||||
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
|
||||
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
|
||||
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
|
||||
</Midl>
|
||||
<Link>
|
||||
<AdditionalDependencies>d2d1.lib;d3d11.lib;dxgi.lib;dwrite.lib;windowscodecs.lib;pathcch.lib;Mswsock.lib;mfreadwrite.lib;Mfplat.lib;mfuuid.lib;ntdll.lib;Secur32.lib;crypt32.lib;secur32.lib;avrt.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /machine:x64 /PDBALTPATH:$(TargetName).pdb</AdditionalOptions>
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<ImportLibrary>lib/Debug/SampleRemoteOpenXR.lib</ImportLibrary>
|
||||
<OptimizeReferences>false</OptimizeReferences>
|
||||
<ProgramDataBaseFile>bin/Debug/SampleRemoteOpenXR.pdb</ProgramDataBaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<LinkLibraryDependencies>false</LinkLibraryDependencies>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /await</AdditionalOptions>
|
||||
<AdditionalUsingDirectories>$(VCIDEInstallDir)vcpackages;$(WindowsSDK_UnionMetadataPath)</AdditionalUsingDirectories>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<ControlFlowGuard>Guard</ControlFlowGuard>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<UseFullPaths>false</UseFullPaths>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;ALLOW_INSECURE_RANDOM_DEVICE=1;HAR_ENABLE_OPENXR;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;UNICODE;CMAKE_INTDIR="Release";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;ALLOW_INSECURE_RANDOM_DEVICE=1;HAR_ENABLE_OPENXR;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;UNICODE;CMAKE_INTDIR=\"Release\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
|
||||
<HeaderFileName>%(Filename).h</HeaderFileName>
|
||||
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
|
||||
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
|
||||
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
|
||||
</Midl>
|
||||
<Link>
|
||||
<AdditionalDependencies>d2d1.lib;d3d11.lib;dxgi.lib;dwrite.lib;windowscodecs.lib;pathcch.lib;Mswsock.lib;mfreadwrite.lib;Mfplat.lib;mfuuid.lib;ntdll.lib;Secur32.lib;crypt32.lib;secur32.lib;avrt.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /machine:x64 /PDBALTPATH:$(TargetName).pdb</AdditionalOptions>
|
||||
<GenerateDebugInformation>DebugFull</GenerateDebugInformation>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<ImportLibrary>lib/Release/SampleRemoteOpenXR.lib</ImportLibrary>
|
||||
<ProgramDataBaseFile>bin/Release/SampleRemoteOpenXR.pdb</ProgramDataBaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<LinkLibraryDependencies>false</LinkLibraryDependencies>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
|
||||
<ClCompile>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /await</AdditionalOptions>
|
||||
<AdditionalUsingDirectories>$(VCIDEInstallDir)vcpackages;$(WindowsSDK_UnionMetadataPath)</AdditionalUsingDirectories>
|
||||
<AssemblerListingLocation>$(IntDir)</AssemblerListingLocation>
|
||||
<CompileAs>CompileAsCpp</CompileAs>
|
||||
<ConformanceMode>true</ConformanceMode>
|
||||
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
|
||||
<ExceptionHandling>Sync</ExceptionHandling>
|
||||
<InlineFunctionExpansion>OnlyExplicitInline</InlineFunctionExpansion>
|
||||
<LanguageStandard>stdcpp17</LanguageStandard>
|
||||
<MultiProcessorCompilation>true</MultiProcessorCompilation>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
|
||||
<RuntimeTypeInfo>true</RuntimeTypeInfo>
|
||||
<SDLCheck>true</SDLCheck>
|
||||
<UseFullPaths>false</UseFullPaths>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;ALLOW_INSECURE_RANDOM_DEVICE=1;HAR_ENABLE_OPENXR;HAR_DEVELOPMENT;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;UNICODE;CMAKE_INTDIR="RelWithDebInfo";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<ObjectFileName>$(IntDir)</ObjectFileName>
|
||||
</ClCompile>
|
||||
<ResourceCompile>
|
||||
<PreprocessorDefinitions>WIN32;_WINDOWS;NDEBUG;ALLOW_INSECURE_RANDOM_DEVICE=1;HAR_ENABLE_OPENXR;HAR_DEVELOPMENT;_SILENCE_CXX17_ITERATOR_BASE_CLASS_DEPRECATION_WARNING;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING;UNICODE;CMAKE_INTDIR=\"RelWithDebInfo\";%(PreprocessorDefinitions)</PreprocessorDefinitions>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
</ResourceCompile>
|
||||
<Midl>
|
||||
<AdditionalIncludeDirectories>.;.\SampleShared;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
|
||||
<OutputDirectory>$(ProjectDir)/$(IntDir)</OutputDirectory>
|
||||
<HeaderFileName>%(Filename).h</HeaderFileName>
|
||||
<TypeLibraryName>%(Filename).tlb</TypeLibraryName>
|
||||
<InterfaceIdentifierFileName>%(Filename)_i.c</InterfaceIdentifierFileName>
|
||||
<ProxyFileName>%(Filename)_p.c</ProxyFileName>
|
||||
</Midl>
|
||||
<Link>
|
||||
<AdditionalDependencies>d2d1.lib;d3d11.lib;dxgi.lib;dwrite.lib;windowscodecs.lib;pathcch.lib;Mswsock.lib;mfreadwrite.lib;Mfplat.lib;mfuuid.lib;ntdll.lib;Secur32.lib;crypt32.lib;secur32.lib;avrt.lib;WindowsApp.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories>%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<AdditionalOptions>%(AdditionalOptions) /machine:x64 /PDBALTPATH:$(TargetName).pdb</AdditionalOptions>
|
||||
<EnableCOMDATFolding>false</EnableCOMDATFolding>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<IgnoreSpecificDefaultLibraries>%(IgnoreSpecificDefaultLibraries)</IgnoreSpecificDefaultLibraries>
|
||||
<ImportLibrary>lib/RelWithDebInfo/SampleRemoteOpenXR.lib</ImportLibrary>
|
||||
<OptimizeReferences>false</OptimizeReferences>
|
||||
<ProgramDataBaseFile>bin/RelWithDebInfo/SampleRemoteOpenXR.pdb</ProgramDataBaseFile>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
</Link>
|
||||
<ProjectReference>
|
||||
<LinkLibraryDependencies>false</LinkLibraryDependencies>
|
||||
</ProjectReference>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include=".\OpenXrProgram.cpp" />
|
||||
<ClInclude Include=".\OpenXrProgram.h" />
|
||||
<ClInclude Include=".\pch.h" />
|
||||
<ClCompile Include=".\pch.cpp" />
|
||||
<ClCompile Include=".\App.cpp" />
|
||||
<ClCompile Include=".\CubeGraphics.cpp" />
|
||||
<ClCompile Include=".\DxUtility.cpp" />
|
||||
<ClInclude Include=".\DxUtility.h" />
|
||||
<ClCompile Include=".\SampleShared\CommandLineUtility.cpp" />
|
||||
<ClCompile Include=".\SampleShared\SampleWindowWin32.cpp" />
|
||||
<Image Include=".\Assets\LockScreenLogo.scale-200.png" />
|
||||
<Image Include=".\Assets\SplashScreen.scale-200.png" />
|
||||
<Image Include=".\Assets\Square150x150Logo.scale-200.png" />
|
||||
<Image Include=".\Assets\Square44x44Logo.scale-200.png" />
|
||||
<Image Include=".\Assets\Square44x44Logo.targetsize-24_altform-unplated.png" />
|
||||
<Image Include=".\Assets\StoreLogo.png" />
|
||||
<Image Include=".\Assets\Wide310x150Logo.scale-200.png" />
|
||||
<AppxManifest Include=".\Package.appxmanifest" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
<Import Project="packages\OpenXR.Headers.1.0.10.2\build\native\OpenXR.Headers.targets" Condition="Exists('packages\OpenXR.Headers.1.0.10.2\build\native\OpenXR.Headers.targets')" />
|
||||
<Import Project="packages\OpenXR.Loader.1.0.10.2\build\native\OpenXR.Loader.targets" Condition="Exists('packages\OpenXR.Loader.1.0.10.2\build\native\OpenXR.Loader.targets')" />
|
||||
<Import Project="packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets" Condition="Exists('packages\Microsoft.Windows.CppWinRT.2.0.200729.8\build\native\Microsoft.Windows.CppWinRT.targets')" />
|
||||
<Import Project="packages\Microsoft.Holographic.Remoting.OpenXr.2.4.0\build\native\Microsoft.Holographic.Remoting.OpenXr.targets" Condition="Exists('packages\Microsoft.Holographic.Remoting.OpenXr.2.4.0\build\native\Microsoft.Holographic.Remoting.OpenXr.targets')" />
|
||||
</ImportGroup>
|
||||
</Project>
|
|
@ -0,0 +1,145 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// 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>
|
||||
|
||||
#include <CommandLineUtility.h>
|
||||
|
||||
#include <regex>
|
||||
#include <shellapi.h>
|
||||
|
||||
namespace {
|
||||
std::string SplitHostnameAndPortString(const std::string& address, uint16_t& port) {
|
||||
static std::basic_regex<char> addressMatcher("(?:(\\[.*\\])|([^:]*))(?:[:](\\d+))?");
|
||||
std::match_results<typename std::string::const_iterator> results;
|
||||
if (std::regex_match(address, results, addressMatcher)) {
|
||||
if (results[3].matched) {
|
||||
std::string portStr = results[3].str();
|
||||
port = static_cast<uint16_t>(std::strtol(portStr.c_str(), nullptr, 10));
|
||||
}
|
||||
|
||||
return (results[1].matched) ? results[1].str() : results[2].str();
|
||||
} else {
|
||||
return address;
|
||||
}
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace sample {
|
||||
|
||||
void ParseCommandLine(sample::AppOptions& options) {
|
||||
int numArgs = __argc;
|
||||
char** argList = __argv;
|
||||
|
||||
for (int i = 1; i < numArgs; ++i) {
|
||||
if (strlen(argList[i]) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string arg = argList[i];
|
||||
if (arg[0] == '-') {
|
||||
std::string param = arg.substr(1);
|
||||
std::transform(param.begin(), param.end(), param.begin(), ::tolower);
|
||||
|
||||
if (param == "listen") {
|
||||
options.listen = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "standalone") {
|
||||
options.isStandalone = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "nouserwait") {
|
||||
options.noUserWait = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "ephemeralport") {
|
||||
options.useEphemeralPort = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "transportport") {
|
||||
if (numArgs > i + 1) {
|
||||
std::string transportPortStr = argList[i + 1];
|
||||
try {
|
||||
options.transportPort = std::stoi(transportPortStr);
|
||||
} catch (const std::invalid_argument&) {
|
||||
// Ignore invalid transport port strings.
|
||||
}
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "secureconnection") {
|
||||
options.secureConnection = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "authenticationtoken") {
|
||||
if (numArgs > i + 1) {
|
||||
options.authenticationToken = argList[i + 1];
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "allowcertificatenamemismatch") {
|
||||
options.allowCertificateNameMismatch = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "allowunverifiedcertificatechain") {
|
||||
options.allowUnverifiedCertificateChain = true;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "certificatestore") {
|
||||
if (numArgs > i + 1) {
|
||||
options.certificateStore = argList[i + 1];
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "keypassphrase") {
|
||||
if (numArgs > i + 1) {
|
||||
options.keyPassphrase = argList[i + 1];
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "subjectname") {
|
||||
if (numArgs > i + 1) {
|
||||
options.subjectName = argList[i + 1];
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
if (param == "authenticationrealm") {
|
||||
if (numArgs > i + 1) {
|
||||
options.authenticationRealm = argList[i + 1];
|
||||
i++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
options.host = SplitHostnameAndPortString(arg, options.port);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace sample
|
|
@ -0,0 +1,35 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
namespace sample {
|
||||
struct AppOptions {
|
||||
bool listen{false};
|
||||
std::string host;
|
||||
uint16_t port{0};
|
||||
uint16_t transportPort{0};
|
||||
bool isStandalone = false;
|
||||
bool noUserWait = false;
|
||||
bool useEphemeralPort = false;
|
||||
bool secureConnection{false};
|
||||
std::string authenticationToken;
|
||||
bool allowCertificateNameMismatch{false};
|
||||
bool allowUnverifiedCertificateChain{false};
|
||||
std::string certificateStore;
|
||||
std::string keyPassphrase;
|
||||
std::string subjectName;
|
||||
std::string authenticationRealm{"OpenXR Remoting"};
|
||||
};
|
||||
|
||||
void ParseCommandLine(sample::AppOptions& options);
|
||||
|
||||
} // namespace sample
|
|
@ -0,0 +1,191 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// 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>
|
||||
|
||||
#include <SampleWindowWin32.h>
|
||||
|
||||
#include <future>
|
||||
|
||||
#include <dxgi1_2.h>
|
||||
|
||||
namespace {
|
||||
std::once_flag g_createWindowClass;
|
||||
|
||||
LRESULT CALLBACK WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
|
||||
LRESULT result = 0;
|
||||
switch (msg) {
|
||||
case WM_CLOSE: {
|
||||
sample::SampleWindowWin32* window = reinterpret_cast<sample::SampleWindowWin32*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
window->OnClosed();
|
||||
|
||||
DestroyWindow(hWnd);
|
||||
result = 0;
|
||||
} break;
|
||||
|
||||
case WM_DESTROY: {
|
||||
PostQuitMessage(0);
|
||||
result = 0;
|
||||
} break;
|
||||
|
||||
case WM_CHAR: {
|
||||
sample::SampleWindowWin32* window = reinterpret_cast<sample::SampleWindowWin32*>(GetWindowLongPtr(hWnd, GWLP_USERDATA));
|
||||
window->OnKeyPress(static_cast<wchar_t>(wParam));
|
||||
}
|
||||
|
||||
default: {
|
||||
result = DefWindowProc(hWnd, msg, wParam, lParam);
|
||||
} break;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
HWND CreateWindowWin32(sample::SampleWindowWin32* window, std::wstring title, long width, long height) {
|
||||
const wchar_t* windowClassName = L"SampleWindowWin32Class";
|
||||
|
||||
std::call_once(g_createWindowClass, [&] {
|
||||
WNDCLASSEX wcex = {};
|
||||
wcex.cbSize = sizeof(wcex);
|
||||
wcex.style = CS_HREDRAW | CS_VREDRAW;
|
||||
wcex.lpfnWndProc = ::WndProc;
|
||||
wcex.hInstance = 0;
|
||||
wcex.hIcon = LoadIcon(0, IDI_APPLICATION);
|
||||
wcex.hCursor = LoadCursor(nullptr, IDC_ARROW);
|
||||
wcex.hbrBackground = static_cast<HBRUSH>(GetStockObject(NULL_BRUSH));
|
||||
wcex.lpszClassName = windowClassName;
|
||||
RegisterClassEx(&wcex);
|
||||
});
|
||||
|
||||
RECT rc = {0, 0, width, height};
|
||||
AdjustWindowRectEx(&rc, WS_OVERLAPPEDWINDOW, FALSE, 0);
|
||||
|
||||
HWND hWnd = CreateWindow(windowClassName,
|
||||
title.c_str(),
|
||||
WS_OVERLAPPEDWINDOW ^ WS_THICKFRAME,
|
||||
CW_USEDEFAULT,
|
||||
CW_USEDEFAULT,
|
||||
rc.right - rc.left,
|
||||
rc.bottom - rc.top,
|
||||
nullptr,
|
||||
nullptr,
|
||||
0,
|
||||
nullptr);
|
||||
|
||||
SetWindowLongPtr(hWnd, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(window));
|
||||
|
||||
return hWnd;
|
||||
}
|
||||
|
||||
winrt::com_ptr<IDXGISwapChain1> CreateSwapchain(HWND hWnd, ID3D11Device* device) {
|
||||
winrt::com_ptr<IDXGISwapChain1> swapchain;
|
||||
|
||||
DXGI_SWAP_CHAIN_DESC1 desc{};
|
||||
desc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
|
||||
desc.Stereo = false;
|
||||
desc.SampleDesc.Count = 1;
|
||||
desc.SampleDesc.Quality = 0;
|
||||
desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
||||
desc.BufferCount = 2;
|
||||
desc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_SEQUENTIAL;
|
||||
desc.Flags = 0;
|
||||
desc.AlphaMode = DXGI_ALPHA_MODE_IGNORE;
|
||||
desc.Scaling = DXGI_SCALING_STRETCH;
|
||||
|
||||
winrt::com_ptr<IDXGIDevice1> dxgiDevice;
|
||||
device->QueryInterface(dxgiDevice.put());
|
||||
|
||||
winrt::com_ptr<IDXGIAdapter> dxgiAdapter;
|
||||
winrt::check_hresult(dxgiDevice->GetAdapter(dxgiAdapter.put()));
|
||||
|
||||
winrt::com_ptr<IDXGIFactory2> dxgiFactory;
|
||||
winrt::check_hresult(dxgiAdapter->GetParent(IID_PPV_ARGS(dxgiFactory.put())));
|
||||
|
||||
winrt::check_hresult(dxgiFactory->MakeWindowAssociation(hWnd, DXGI_MWA_NO_ALT_ENTER));
|
||||
winrt::check_hresult(dxgiFactory->CreateSwapChainForHwnd(device, hWnd, &desc, nullptr, nullptr, swapchain.put()));
|
||||
|
||||
return swapchain;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
namespace sample {
|
||||
SampleWindowWin32::SampleWindowWin32(std::wstring title, ID3D11Device* device)
|
||||
: SampleWindowWin32(title, device, 512, 512) {
|
||||
}
|
||||
|
||||
SampleWindowWin32::SampleWindowWin32(std::wstring title, ID3D11Device* device, long width, long height) {
|
||||
std::promise<HWND> hWndPromise;
|
||||
std::future<HWND> hWndFuture = hWndPromise.get_future();
|
||||
|
||||
m_windowThread = std::thread([&]() mutable {
|
||||
HWND hWnd = nullptr;
|
||||
try {
|
||||
hWnd = CreateWindowWin32(this, title, width, height);
|
||||
hWndPromise.set_value(hWnd);
|
||||
} catch (...) {
|
||||
hWndPromise.set_exception(std::current_exception());
|
||||
return;
|
||||
}
|
||||
|
||||
MSG msg;
|
||||
while (GetMessage(&msg, nullptr, 0, 0) > 0) {
|
||||
TranslateMessage(&msg);
|
||||
DispatchMessage(&msg);
|
||||
}
|
||||
});
|
||||
|
||||
m_hWnd = hWndFuture.get();
|
||||
m_swapchain = CreateSwapchain(m_hWnd, device);
|
||||
|
||||
ShowWindow(m_hWnd, SW_SHOWNORMAL);
|
||||
}
|
||||
|
||||
SampleWindowWin32::~SampleWindowWin32() {
|
||||
SendMessage(m_hWnd, WM_CLOSE, 0, 0);
|
||||
m_windowThread.join();
|
||||
}
|
||||
|
||||
ID3D11Texture2D* SampleWindowWin32::GetNextSwapchainTexture() {
|
||||
ID3D11Texture2D* texture;
|
||||
m_swapchain->GetBuffer(0, IID_PPV_ARGS(&texture));
|
||||
|
||||
return texture;
|
||||
}
|
||||
|
||||
void SampleWindowWin32::PresentSwapchain() {
|
||||
m_swapchain->Present(0, 0);
|
||||
}
|
||||
|
||||
void SampleWindowWin32::OnClosed() {
|
||||
std::lock_guard lock(m_windowMutex);
|
||||
m_isClosed = true;
|
||||
}
|
||||
|
||||
bool SampleWindowWin32::IsClosed() const {
|
||||
std::lock_guard lock(m_windowMutex);
|
||||
return m_isClosed;
|
||||
}
|
||||
|
||||
void SampleWindowWin32::SetKeyPressedHandler(KeyPressHandler keyPressedHandler) {
|
||||
std::lock_guard lock(m_windowMutex);
|
||||
m_keyPressedHandler = keyPressedHandler;
|
||||
}
|
||||
|
||||
void SampleWindowWin32::OnKeyPress(wchar_t key) {
|
||||
std::lock_guard lock(m_windowMutex);
|
||||
if (m_keyPressedHandler) {
|
||||
m_keyPressedHandler(key);
|
||||
}
|
||||
}
|
||||
|
||||
void SampleWindowWin32::SetWindowTitle(std::wstring title) {
|
||||
SetWindowTextW(m_hWnd, title.c_str());
|
||||
}
|
||||
} // namespace sample
|
|
@ -0,0 +1,48 @@
|
|||
//*********************************************************
|
||||
//
|
||||
// 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.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#pragma once
|
||||
#include <functional>
|
||||
#include <mutex>
|
||||
|
||||
struct IDXGISwapChain1;
|
||||
|
||||
namespace sample {
|
||||
class SampleWindowWin32 {
|
||||
public:
|
||||
SampleWindowWin32(std::wstring title, ID3D11Device* device);
|
||||
SampleWindowWin32(std::wstring title, ID3D11Device* device, long width, long height);
|
||||
|
||||
~SampleWindowWin32();
|
||||
|
||||
using KeyPressHandler = std::function<void(wchar_t)>;
|
||||
void SetKeyPressedHandler(KeyPressHandler keyPressedHandler);
|
||||
void OnKeyPress(wchar_t key);
|
||||
|
||||
void SetWindowTitle(std::wstring title);
|
||||
|
||||
ID3D11Texture2D* GetNextSwapchainTexture();
|
||||
void PresentSwapchain();
|
||||
|
||||
void OnClosed();
|
||||
bool IsClosed() const;
|
||||
|
||||
private:
|
||||
std::thread m_windowThread;
|
||||
mutable std::mutex m_windowMutex;
|
||||
|
||||
HWND m_hWnd = nullptr;
|
||||
winrt::com_ptr<IDXGISwapChain1> m_swapchain;
|
||||
|
||||
KeyPressHandler m_keyPressedHandler;
|
||||
bool m_isClosed;
|
||||
};
|
||||
} // namespace sample
|
|
@ -0,0 +1,112 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <stdexcept>
|
||||
#include "XrToString.h"
|
||||
|
||||
#define CHECK_XRCMD(cmd) xr::detail::_CheckXrResult(cmd, #cmd, FILE_AND_LINE)
|
||||
#define CHECK_XRRESULT(res, cmdStr) xr::detail::_CheckXrResult(res, cmdStr, FILE_AND_LINE)
|
||||
|
||||
#define CHECK_HRCMD(cmd) xr::detail::_CheckHResult(cmd, #cmd, FILE_AND_LINE)
|
||||
#define CHECK_HRESULT(res, cmdStr) xr::detail::_CheckHResult(res, cmdStr, FILE_AND_LINE)
|
||||
|
||||
#define DEBUG_PRINT(...) ::OutputDebugStringA((xr::detail::_Fmt(__VA_ARGS__) + "\n").c_str())
|
||||
|
||||
namespace xr::detail {
|
||||
#define CHK_STRINGIFY(x) #x
|
||||
#define TOSTRING(x) CHK_STRINGIFY(x)
|
||||
#define FILE_AND_LINE __FILE__ ":" TOSTRING(__LINE__)
|
||||
|
||||
inline std::string _Fmt(const char* fmt, ...) {
|
||||
va_list vl;
|
||||
va_start(vl, fmt);
|
||||
int size = std::vsnprintf(nullptr, 0, fmt, vl);
|
||||
va_end(vl);
|
||||
|
||||
if (size != -1) {
|
||||
std::unique_ptr<char[]> buffer(new char[size + 1]);
|
||||
|
||||
va_start(vl, fmt);
|
||||
size = std::vsnprintf(buffer.get(), size + 1, fmt, vl);
|
||||
va_end(vl);
|
||||
if (size != -1) {
|
||||
return std::string(buffer.get(), size);
|
||||
}
|
||||
}
|
||||
|
||||
throw std::runtime_error("Unexpected vsnprintf failure");
|
||||
}
|
||||
|
||||
[[noreturn]] inline void _Throw(std::string failureMessage, const char* originator = nullptr, const char* sourceLocation = nullptr) {
|
||||
if (originator != nullptr) {
|
||||
failureMessage += _Fmt("\n Origin: %s", originator);
|
||||
}
|
||||
if (sourceLocation != nullptr) {
|
||||
failureMessage += _Fmt("\n Source: %s", sourceLocation);
|
||||
}
|
||||
|
||||
throw std::logic_error(failureMessage);
|
||||
}
|
||||
|
||||
#define THROW(msg) xr::detail::_Throw(msg, nullptr, FILE_AND_LINE)
|
||||
#define CHECK(exp) \
|
||||
{ \
|
||||
if (!(exp)) { \
|
||||
xr::detail::_Throw("Check failed", #exp, FILE_AND_LINE); \
|
||||
} \
|
||||
}
|
||||
#define CHECK_MSG(exp, msg) \
|
||||
{ \
|
||||
if (!(exp)) { \
|
||||
xr::detail::_Throw(msg, #exp, FILE_AND_LINE); \
|
||||
} \
|
||||
}
|
||||
|
||||
[[noreturn]] inline void _ThrowXrResult(XrResult res, const char* originator = nullptr, const char* sourceLocation = nullptr) {
|
||||
std::string failure{xr::ToCString(res)};
|
||||
|
||||
if (failure == "Unknown XrResult") {
|
||||
std::string failureRemoting{xr::ToCString(static_cast<XrRemotingResult>(res))};
|
||||
if (failureRemoting != "Unknown XrRemotingResult") {
|
||||
xr::detail::_Throw(_Fmt("XrRemotingResult failure [%s]", failureRemoting.c_str()), originator, sourceLocation);
|
||||
}
|
||||
}
|
||||
|
||||
xr::detail::_Throw(_Fmt("XrResult failure [%s]", failure.c_str()), originator, sourceLocation);
|
||||
}
|
||||
|
||||
inline XrResult _CheckXrResult(XrResult res, const char* originator = nullptr, const char* sourceLocation = nullptr) {
|
||||
if (XR_FAILED(res)) {
|
||||
xr::detail::_ThrowXrResult(res, originator, sourceLocation);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
[[noreturn]] inline void _ThrowHResult(HRESULT hr, const char* originator = nullptr, const char* sourceLocation = nullptr) {
|
||||
xr::detail::_Throw(xr::detail::_Fmt("HRESULT failure [%x]", hr), originator, sourceLocation);
|
||||
}
|
||||
|
||||
inline HRESULT _CheckHResult(HRESULT hr, const char* originator = nullptr, const char* sourceLocation = nullptr) {
|
||||
if (FAILED(hr)) {
|
||||
xr::detail::_ThrowHResult(hr, originator, sourceLocation);
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
} // namespace xr::detail
|
|
@ -0,0 +1,52 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#define FOR_EACH_SAMPLE_EXTENSION_FUNCTION(_) \
|
||||
_(xrCreateSpatialAnchorMSFT) \
|
||||
_(xrCreateSpatialAnchorSpaceMSFT) \
|
||||
_(xrDestroySpatialAnchorMSFT) \
|
||||
_(xrGetD3D11GraphicsRequirementsKHR)
|
||||
|
||||
#define FOR_EACH_HAR_EXPERIMENTAL_EXTENSION_FUNCTION(_) \
|
||||
_(xrRemotingSetContextPropertiesMSFT) \
|
||||
_(xrRemotingConnectMSFT) \
|
||||
_(xrRemotingListenMSFT) \
|
||||
_(xrRemotingDisconnectMSFT) \
|
||||
_(xrRemotingGetConnectionStateMSFT) \
|
||||
_(xrRemotingSetSecureConnectionClientCallbacksMSFT) \
|
||||
_(xrRemotingSetSecureConnectionServerCallbacksMSFT)
|
||||
|
||||
#define GET_INSTANCE_PROC_ADDRESS(name) \
|
||||
(void)xrGetInstanceProcAddr(instance, #name, reinterpret_cast<PFN_xrVoidFunction*>(const_cast<PFN_##name*>(&name)));
|
||||
#define DEFINE_PROC_MEMBER(name) const PFN_##name name{nullptr};
|
||||
|
||||
namespace xr {
|
||||
struct ExtensionDispatchTable {
|
||||
FOR_EACH_SAMPLE_EXTENSION_FUNCTION(DEFINE_PROC_MEMBER);
|
||||
FOR_EACH_HAR_EXPERIMENTAL_EXTENSION_FUNCTION(DEFINE_PROC_MEMBER);
|
||||
|
||||
ExtensionDispatchTable() = default;
|
||||
void PopulateDispatchTable(XrInstance instance) {
|
||||
FOR_EACH_SAMPLE_EXTENSION_FUNCTION(GET_INSTANCE_PROC_ADDRESS);
|
||||
FOR_EACH_HAR_EXPERIMENTAL_EXTENSION_FUNCTION(GET_INSTANCE_PROC_ADDRESS);
|
||||
}
|
||||
};
|
||||
} // namespace xr
|
||||
|
||||
#undef DEFINE_PROC_MEMBER
|
||||
#undef GET_INSTANCE_PROC_ADDRESS
|
||||
#undef FOR_EACH_EXTENSION_FUNCTION
|
|
@ -0,0 +1,96 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
namespace xr {
|
||||
|
||||
template <typename HandleType>
|
||||
class UniqueExtHandle {
|
||||
using PFN_DestroyFunction = XrResult(XRAPI_PTR*)(HandleType);
|
||||
|
||||
public:
|
||||
UniqueExtHandle() = default;
|
||||
UniqueExtHandle(const UniqueExtHandle&) = delete;
|
||||
UniqueExtHandle(UniqueExtHandle&& other) noexcept {
|
||||
*this = std::move(other);
|
||||
}
|
||||
|
||||
~UniqueExtHandle() noexcept {
|
||||
Reset();
|
||||
}
|
||||
|
||||
UniqueExtHandle& operator=(const UniqueExtHandle&) = delete;
|
||||
UniqueExtHandle& operator=(UniqueExtHandle&& other) noexcept {
|
||||
if (m_handle != other.m_handle || m_destroyer != other.m_destroyer) {
|
||||
Reset();
|
||||
|
||||
m_handle = other.m_handle;
|
||||
m_destroyer = other.m_destroyer;
|
||||
|
||||
other.m_handle = XR_NULL_HANDLE;
|
||||
other.m_destroyer = nullptr;
|
||||
}
|
||||
return *this;
|
||||
}
|
||||
|
||||
operator bool() const noexcept {
|
||||
return m_handle != XR_NULL_HANDLE;
|
||||
}
|
||||
|
||||
HandleType Get() const noexcept {
|
||||
return m_handle;
|
||||
}
|
||||
|
||||
// Extension functions cannot be statically linked, so the creator must pass in the destroy function.
|
||||
HandleType* Put(PFN_DestroyFunction destroyFunction) noexcept {
|
||||
assert(destroyFunction != nullptr);
|
||||
Reset();
|
||||
m_destroyer = destroyFunction;
|
||||
return &m_handle;
|
||||
}
|
||||
|
||||
void Reset() noexcept {
|
||||
if (m_handle != XR_NULL_HANDLE) {
|
||||
m_destroyer(m_handle);
|
||||
m_handle = XR_NULL_HANDLE;
|
||||
}
|
||||
|
||||
m_destroyer = nullptr;
|
||||
}
|
||||
|
||||
private:
|
||||
HandleType m_handle{XR_NULL_HANDLE};
|
||||
PFN_DestroyFunction m_destroyer{nullptr};
|
||||
};
|
||||
|
||||
template <typename HandleType, XrResult(XRAPI_PTR* DestroyFunction)(HandleType)>
|
||||
class UniqueHandle : public UniqueExtHandle<HandleType> {
|
||||
public:
|
||||
HandleType* Put() noexcept {
|
||||
return UniqueExtHandle<HandleType>::Put(DestroyFunction);
|
||||
}
|
||||
};
|
||||
|
||||
class ActionHandle : public UniqueHandle<XrAction, xrDestroyAction> {};
|
||||
class ActionSetHandle : public UniqueHandle<XrActionSet, xrDestroyActionSet> {};
|
||||
class InstanceHandle : public UniqueHandle<XrInstance, xrDestroyInstance> {};
|
||||
class SessionHandle : public UniqueHandle<XrSession, xrDestroySession> {};
|
||||
class SpaceHandle : public UniqueHandle<XrSpace, xrDestroySpace> {};
|
||||
class SwapchainHandle : public UniqueHandle<XrSwapchain, xrDestroySwapchain> {};
|
||||
class SpatialAnchorHandle : public UniqueExtHandle<XrSpatialAnchorMSFT> {};
|
||||
class HandTrackerHandle : public UniqueExtHandle<XrHandTrackerEXT> {};
|
||||
|
||||
} // namespace xr
|
|
@ -0,0 +1,594 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
#include <DirectXMath.h>
|
||||
#include <stdexcept>
|
||||
#include <cmath>
|
||||
|
||||
namespace xr::math {
|
||||
constexpr float QuaternionEpsilon = 0.01f;
|
||||
|
||||
// A large number that can be used as maximum finite depth value, beyond which a value can be treated as infinity
|
||||
constexpr float OneOverFloatEpsilon = 1.0f / std::numeric_limits<float>::epsilon();
|
||||
|
||||
namespace Pose {
|
||||
constexpr XrPosef Identity();
|
||||
constexpr XrPosef Translation(const XrVector3f& translation);
|
||||
|
||||
XrPosef LookAt(const XrVector3f& origin, const XrVector3f& forward, const XrVector3f& up);
|
||||
XrPosef Multiply(const XrPosef& a, const XrPosef& b);
|
||||
XrPosef Slerp(const XrPosef& a, const XrPosef& b, float alpha);
|
||||
XrPosef Invert(const XrPosef& pose);
|
||||
|
||||
constexpr bool IsPoseValid(const XrSpaceLocation& location);
|
||||
constexpr bool IsPoseTracked(const XrSpaceLocation& location);
|
||||
constexpr bool IsPoseValid(const XrHandJointLocationEXT& jointLocation);
|
||||
constexpr bool IsPoseTracked(const XrHandJointLocationEXT& jointLocation);
|
||||
constexpr bool IsPoseValid(const XrViewState& viewState);
|
||||
constexpr bool IsPoseTracked(const XrViewState& viewState);
|
||||
|
||||
template <typename Quaternion, typename Vector3>
|
||||
constexpr XrPosef MakePose(const Quaternion& orientation, const Vector3& position);
|
||||
} // namespace Pose
|
||||
|
||||
namespace Quaternion {
|
||||
constexpr XrQuaternionf Identity();
|
||||
bool IsNormalized(const XrQuaternionf& quaternion);
|
||||
XrQuaternionf RotationAxisAngle(const XrVector3f& axis, float angleInRadians);
|
||||
XrQuaternionf RotationRollPitchYaw(const XrVector3f& eulerAnglesInRadians);
|
||||
XrQuaternionf Slerp(const XrQuaternionf& a, const XrQuaternionf& b, float alpha);
|
||||
} // namespace Quaternion
|
||||
|
||||
struct NearFar {
|
||||
float Near;
|
||||
float Far;
|
||||
};
|
||||
|
||||
struct ViewProjection {
|
||||
XrPosef Pose;
|
||||
XrFovf Fov;
|
||||
NearFar NearFar;
|
||||
};
|
||||
|
||||
// Type conversion between math types
|
||||
template <typename X, typename Y>
|
||||
constexpr const X& cast(const Y& value);
|
||||
|
||||
// Convert XR types to DX
|
||||
DirectX::XMVECTOR XM_CALLCONV LoadXrVector2(const XrVector2f& vector);
|
||||
DirectX::XMVECTOR XM_CALLCONV LoadXrVector3(const XrVector3f& vector);
|
||||
DirectX::XMVECTOR XM_CALLCONV LoadXrVector4(const XrVector4f& vector);
|
||||
DirectX::XMVECTOR XM_CALLCONV LoadXrQuaternion(const XrQuaternionf& quaternion);
|
||||
DirectX::XMMATRIX XM_CALLCONV LoadXrPose(const XrPosef& rigidTransform);
|
||||
DirectX::XMMATRIX XM_CALLCONV LoadInvertedXrPose(const XrPosef& rigidTransform);
|
||||
DirectX::XMVECTOR XM_CALLCONV LoadXrExtent(const XrExtent2Df& extend);
|
||||
|
||||
// Convert DX types to XR
|
||||
void XM_CALLCONV StoreXrVector2(XrVector2f* outVec, DirectX::FXMVECTOR inVec);
|
||||
void XM_CALLCONV StoreXrVector3(XrVector3f* outVec, DirectX::FXMVECTOR inVec);
|
||||
void XM_CALLCONV StoreXrVector4(XrVector4f* outVec, DirectX::FXMVECTOR inVec);
|
||||
void XM_CALLCONV StoreXrQuaternion(XrQuaternionf* outQuat, DirectX::FXMVECTOR inQuat);
|
||||
bool XM_CALLCONV StoreXrPose(XrPosef* out, DirectX::FXMMATRIX matrix);
|
||||
void XM_CALLCONV StoreXrExtent(XrExtent2Df* extend, DirectX::FXMVECTOR inVec);
|
||||
|
||||
// Projection matrix math
|
||||
DirectX::XMMATRIX ComposeProjectionMatrix(const XrFovf& fov, const NearFar& nearFar);
|
||||
NearFar GetProjectionNearFar(const DirectX::XMFLOAT4X4& projectionMatrix);
|
||||
XrFovf DecomposeProjectionMatrix(const DirectX::XMFLOAT4X4& projectionMatrix);
|
||||
} // namespace xr::math
|
||||
|
||||
#pragma region Implementation
|
||||
|
||||
namespace xr::math {
|
||||
namespace detail {
|
||||
template <typename X, typename Y>
|
||||
constexpr const X& implement_math_cast(const Y& value) {
|
||||
static_assert(std::is_trivially_copyable<X>::value, "Unsafe to cast between non-POD types.");
|
||||
static_assert(std::is_trivially_copyable<Y>::value, "Unsafe to cast between non-POD types.");
|
||||
static_assert(!std::is_pointer<X>::value, "Incorrect cast between pointer types.");
|
||||
static_assert(!std::is_pointer<Y>::value, "Incorrect cast between pointer types.");
|
||||
static_assert(sizeof(X) == sizeof(Y), "Incorrect cast between types with different sizes.");
|
||||
return reinterpret_cast<const X&>(value);
|
||||
}
|
||||
|
||||
template <typename X, typename Y>
|
||||
constexpr X& implement_math_cast(Y& value) {
|
||||
static_assert(std::is_trivially_copyable<X>::value, "Unsafe to cast between non-POD types.");
|
||||
static_assert(std::is_trivially_copyable<Y>::value, "Unsafe to cast between non-POD types.");
|
||||
static_assert(!std::is_pointer<X>::value, "Incorrect cast between pointer types.");
|
||||
static_assert(!std::is_pointer<Y>::value, "Incorrect cast between pointer types.");
|
||||
static_assert(sizeof(X) == sizeof(Y), "Incorrect cast between types with different sizes.");
|
||||
return reinterpret_cast<X&>(value);
|
||||
}
|
||||
} // namespace detail
|
||||
|
||||
#ifdef _MSC_VER
|
||||
template <typename X, typename Y>
|
||||
constexpr const X& cast(const Y& value) {
|
||||
static_assert(false, "Undefined cast from Y to type X");
|
||||
}
|
||||
#endif
|
||||
|
||||
#define DEFINE_CAST(X, Y) \
|
||||
template <> \
|
||||
constexpr const X& cast<X, Y>(const Y& value) { \
|
||||
return detail::implement_math_cast<X>(value); \
|
||||
}
|
||||
|
||||
static_assert(offsetof(DirectX::XMFLOAT2, x) == offsetof(XrVector2f, x));
|
||||
static_assert(offsetof(DirectX::XMFLOAT2, y) == offsetof(XrVector2f, y));
|
||||
DEFINE_CAST(XrVector2f, DirectX::XMFLOAT2);
|
||||
DEFINE_CAST(DirectX::XMFLOAT2, XrVector2f);
|
||||
|
||||
static_assert(offsetof(DirectX::XMFLOAT3, x) == offsetof(XrVector3f, x));
|
||||
static_assert(offsetof(DirectX::XMFLOAT3, y) == offsetof(XrVector3f, y));
|
||||
static_assert(offsetof(DirectX::XMFLOAT3, z) == offsetof(XrVector3f, z));
|
||||
DEFINE_CAST(XrVector3f, DirectX::XMFLOAT3);
|
||||
DEFINE_CAST(DirectX::XMFLOAT3, XrVector3f);
|
||||
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, x) == offsetof(XrVector4f, x));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, y) == offsetof(XrVector4f, y));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, z) == offsetof(XrVector4f, z));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, w) == offsetof(XrVector4f, w));
|
||||
DEFINE_CAST(XrVector4f, DirectX::XMFLOAT4);
|
||||
DEFINE_CAST(DirectX::XMFLOAT4, XrVector4f);
|
||||
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, x) == offsetof(XrQuaternionf, x));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, y) == offsetof(XrQuaternionf, y));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, z) == offsetof(XrQuaternionf, z));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, w) == offsetof(XrQuaternionf, w));
|
||||
DEFINE_CAST(XrQuaternionf, DirectX::XMFLOAT4);
|
||||
DEFINE_CAST(DirectX::XMFLOAT4, XrQuaternionf);
|
||||
|
||||
static_assert(offsetof(DirectX::XMINT2, x) == offsetof(XrExtent2Di, width));
|
||||
static_assert(offsetof(DirectX::XMINT2, y) == offsetof(XrExtent2Di, height));
|
||||
DEFINE_CAST(XrExtent2Di, DirectX::XMINT2);
|
||||
DEFINE_CAST(DirectX::XMINT2, XrExtent2Di);
|
||||
|
||||
static_assert(offsetof(DirectX::XMFLOAT2, x) == offsetof(XrExtent2Df, width));
|
||||
static_assert(offsetof(DirectX::XMFLOAT2, y) == offsetof(XrExtent2Df, height));
|
||||
DEFINE_CAST(XrExtent2Df, DirectX::XMFLOAT2);
|
||||
DEFINE_CAST(DirectX::XMFLOAT2, XrExtent2Df);
|
||||
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, x) == offsetof(XrColor4f, r));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, y) == offsetof(XrColor4f, g));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, z) == offsetof(XrColor4f, b));
|
||||
static_assert(offsetof(DirectX::XMFLOAT4, w) == offsetof(XrColor4f, a));
|
||||
DEFINE_CAST(XrColor4f, DirectX::XMFLOAT4);
|
||||
DEFINE_CAST(DirectX::XMFLOAT4, XrColor4f);
|
||||
|
||||
#undef DEFINE_CAST
|
||||
|
||||
// Shortcut non-templated overload of cast() function
|
||||
#define DEFINE_CAST(X, Y) \
|
||||
constexpr const X& cast(const Y& value) { \
|
||||
return detail::implement_math_cast<X>(value); \
|
||||
} \
|
||||
constexpr X& cast(Y& value) { \
|
||||
return detail::implement_math_cast<X>(value); \
|
||||
}
|
||||
|
||||
DEFINE_CAST(DirectX::XMFLOAT2, XrVector2f);
|
||||
DEFINE_CAST(DirectX::XMFLOAT3, XrVector3f);
|
||||
DEFINE_CAST(DirectX::XMFLOAT4, XrVector4f);
|
||||
DEFINE_CAST(DirectX::XMFLOAT4, XrQuaternionf);
|
||||
DEFINE_CAST(DirectX::XMFLOAT2, XrExtent2Df);
|
||||
#undef DEFINE_CAST
|
||||
|
||||
#define VECTOR3F_OPERATOR(op) \
|
||||
constexpr XrVector3f operator op(const XrVector3f& a, const XrVector3f& b) { \
|
||||
return XrVector3f{a.x op b.x, a.y op b.y, a.z op b.z}; \
|
||||
}
|
||||
VECTOR3F_OPERATOR(+);
|
||||
VECTOR3F_OPERATOR(-);
|
||||
VECTOR3F_OPERATOR(*);
|
||||
VECTOR3F_OPERATOR(/);
|
||||
#undef VECTOR3F_OPERATOR
|
||||
|
||||
#define VECTOR3F_OPERATOR(op) \
|
||||
constexpr XrVector3f operator op(const XrVector3f& a, float s) { \
|
||||
return XrVector3f{a.x op s, a.y op s, a.z op s}; \
|
||||
}
|
||||
VECTOR3F_OPERATOR(+);
|
||||
VECTOR3F_OPERATOR(-);
|
||||
VECTOR3F_OPERATOR(*);
|
||||
VECTOR3F_OPERATOR(/);
|
||||
#undef VECTOR3F_OPERATOR
|
||||
|
||||
#define VECTOR3F_OPERATOR(op) \
|
||||
constexpr XrVector3f operator op(float s, const XrVector3f& a) { \
|
||||
return XrVector3f{s op a.x, s op a.y, s op a.z}; \
|
||||
}
|
||||
VECTOR3F_OPERATOR(+);
|
||||
VECTOR3F_OPERATOR(-);
|
||||
VECTOR3F_OPERATOR(*);
|
||||
VECTOR3F_OPERATOR(/);
|
||||
#undef VECTOR3F_OPERATOR
|
||||
|
||||
inline DirectX::XMVECTOR XM_CALLCONV LoadXrVector2(const XrVector2f& vector) {
|
||||
return DirectX::XMLoadFloat2(&xr::math::cast(vector));
|
||||
}
|
||||
|
||||
inline DirectX::XMVECTOR XM_CALLCONV LoadXrVector3(const XrVector3f& vector) {
|
||||
return DirectX::XMLoadFloat3(&xr::math::cast(vector));
|
||||
}
|
||||
|
||||
inline DirectX::XMVECTOR XM_CALLCONV LoadXrVector4(const XrVector4f& vector) {
|
||||
return DirectX::XMLoadFloat4(&xr::math::cast(vector));
|
||||
}
|
||||
|
||||
inline DirectX::XMVECTOR XM_CALLCONV LoadXrQuaternion(const XrQuaternionf& quaternion) {
|
||||
return DirectX::XMLoadFloat4(&xr::math::cast(quaternion));
|
||||
}
|
||||
|
||||
inline DirectX::XMVECTOR XM_CALLCONV LoadXrExtent(const XrExtent2Df& extend) {
|
||||
return DirectX::XMLoadFloat2(&xr::math::cast(extend));
|
||||
}
|
||||
|
||||
inline DirectX::XMMATRIX XM_CALLCONV LoadXrPose(const XrPosef& pose) {
|
||||
const DirectX::XMVECTOR orientation = LoadXrQuaternion(pose.orientation);
|
||||
const DirectX::XMVECTOR position = LoadXrVector3(pose.position);
|
||||
DirectX::XMMATRIX matrix = DirectX::XMMatrixRotationQuaternion(orientation);
|
||||
matrix.r[3] = DirectX::XMVectorAdd(matrix.r[3], position);
|
||||
return matrix;
|
||||
}
|
||||
|
||||
inline DirectX::XMMATRIX XM_CALLCONV LoadInvertedXrPose(const XrPosef& pose) {
|
||||
return LoadXrPose(Pose::Invert(pose));
|
||||
}
|
||||
|
||||
inline void XM_CALLCONV StoreXrVector2(XrVector2f* outVec, DirectX::FXMVECTOR inVec) {
|
||||
DirectX::XMStoreFloat2(&detail::implement_math_cast<DirectX::XMFLOAT2>(*outVec), inVec);
|
||||
}
|
||||
|
||||
inline void XM_CALLCONV StoreXrVector3(XrVector3f* outVec, DirectX::FXMVECTOR inVec) {
|
||||
DirectX::XMStoreFloat3(&detail::implement_math_cast<DirectX::XMFLOAT3>(*outVec), inVec);
|
||||
}
|
||||
|
||||
inline void XM_CALLCONV StoreXrVector4(XrVector4f* outVec, DirectX::FXMVECTOR inVec) {
|
||||
DirectX::XMStoreFloat4(&detail::implement_math_cast<DirectX::XMFLOAT4>(*outVec), inVec);
|
||||
}
|
||||
|
||||
inline void XM_CALLCONV StoreXrQuaternion(XrQuaternionf* outQuat, DirectX::FXMVECTOR inQuat) {
|
||||
DirectX::XMStoreFloat4(&detail::implement_math_cast<DirectX::XMFLOAT4>(*outQuat), inQuat);
|
||||
}
|
||||
|
||||
inline void XM_CALLCONV StoreXrExtent(XrExtent2Df* outVec, DirectX::FXMVECTOR inVec) {
|
||||
DirectX::XMStoreFloat2(&detail::implement_math_cast<DirectX::XMFLOAT2>(*outVec), inVec);
|
||||
}
|
||||
|
||||
inline bool XM_CALLCONV StoreXrPose(XrPosef* out, DirectX::FXMMATRIX matrix) {
|
||||
DirectX::XMVECTOR position;
|
||||
DirectX::XMVECTOR orientation;
|
||||
DirectX::XMVECTOR scale;
|
||||
|
||||
if (!DirectX::XMMatrixDecompose(&scale, &orientation, &position, matrix)) {
|
||||
return false; // Non-SRT matrix encountered
|
||||
}
|
||||
|
||||
StoreXrQuaternion(&out->orientation, orientation);
|
||||
StoreXrVector3(&out->position, position);
|
||||
return true;
|
||||
}
|
||||
|
||||
namespace Pose {
|
||||
constexpr XrPosef Identity() {
|
||||
return {{0, 0, 0, 1}, {0, 0, 0}};
|
||||
}
|
||||
|
||||
constexpr XrPosef Translation(const XrVector3f& translation) {
|
||||
XrPosef pose = Identity();
|
||||
pose.position = translation;
|
||||
return pose;
|
||||
}
|
||||
|
||||
inline XrPosef LookAt(const XrVector3f& origin, const XrVector3f& forward, const XrVector3f& up) {
|
||||
DirectX::XMMATRIX virtualToGazeOrientation =
|
||||
DirectX::XMMatrixLookToRH(xr::math::LoadXrVector3(origin), xr::math::LoadXrVector3(forward), xr::math::LoadXrVector3(up));
|
||||
XrPosef pose;
|
||||
xr::math::StoreXrPose(&pose, DirectX::XMMatrixInverse(nullptr, virtualToGazeOrientation));
|
||||
|
||||
return pose;
|
||||
}
|
||||
|
||||
inline XrPosef Slerp(const XrPosef& a, const XrPosef& b, float alpha) {
|
||||
return MakePose(Quaternion::Slerp(a.orientation, b.orientation, alpha), a.position + (b.position - a.position) * alpha);
|
||||
}
|
||||
|
||||
inline XrPosef Invert(const XrPosef& pose) {
|
||||
const DirectX::XMVECTOR orientation = LoadXrQuaternion(pose.orientation);
|
||||
const DirectX::XMVECTOR invertOrientation = DirectX::XMQuaternionConjugate(orientation);
|
||||
|
||||
const DirectX::XMVECTOR position = LoadXrVector3(pose.position);
|
||||
const DirectX::XMVECTOR invertPosition = DirectX::XMVector3Rotate(DirectX::XMVectorNegate(position), invertOrientation);
|
||||
|
||||
XrPosef result;
|
||||
StoreXrQuaternion(&result.orientation, invertOrientation);
|
||||
StoreXrVector3(&result.position, invertPosition);
|
||||
return result;
|
||||
}
|
||||
|
||||
inline XrPosef Multiply(const XrPosef& a, const XrPosef& b) {
|
||||
// Q: Quaternion, P: Position, R:Rotation, T:Translation
|
||||
// (Qa Pa) * (Qb Pb)
|
||||
// = Ra * Ta * Rb * Tb
|
||||
// = Ra * (Ta * Rb) * Tb
|
||||
// = Ra * RotationOf(Ta * Rb) * TranslationOf(Ta * Rb) * Tb
|
||||
// => Rc = Ra * RotationOf(Ta * Rb)
|
||||
// Qc = Qa * Qb;
|
||||
// => Tc = TranslationOf(Ta * Rb) * Tb
|
||||
// Pc = XMVector3Rotate(Pa, Qb) + Pb;
|
||||
|
||||
const DirectX::XMVECTOR pa = LoadXrVector3(a.position);
|
||||
const DirectX::XMVECTOR qa = LoadXrQuaternion(a.orientation);
|
||||
const DirectX::XMVECTOR pb = LoadXrVector3(b.position);
|
||||
const DirectX::XMVECTOR qb = LoadXrQuaternion(b.orientation);
|
||||
|
||||
XrPosef c;
|
||||
StoreXrQuaternion(&c.orientation, DirectX::XMQuaternionMultiply(qa, qb));
|
||||
StoreXrVector3(&c.position, DirectX::XMVectorAdd(DirectX::XMVector3Rotate(pa, qb), pb));
|
||||
return c;
|
||||
}
|
||||
|
||||
constexpr bool IsPoseValid(const XrSpaceLocation& spaceLocation) {
|
||||
constexpr XrSpaceLocationFlags PoseValidFlags = XR_SPACE_LOCATION_POSITION_VALID_BIT | XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
|
||||
return (spaceLocation.locationFlags & PoseValidFlags) == PoseValidFlags;
|
||||
}
|
||||
|
||||
constexpr bool IsPoseTracked(const XrSpaceLocation& spaceLocation) {
|
||||
constexpr XrSpaceLocationFlags PoseTrackedFlags =
|
||||
XR_SPACE_LOCATION_POSITION_TRACKED_BIT | XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT;
|
||||
return (spaceLocation.locationFlags & PoseTrackedFlags) == PoseTrackedFlags;
|
||||
}
|
||||
|
||||
constexpr bool IsPoseValid(const XrHandJointLocationEXT& jointLocation) {
|
||||
constexpr XrSpaceLocationFlags PoseValidFlags = XR_SPACE_LOCATION_POSITION_VALID_BIT | XR_SPACE_LOCATION_ORIENTATION_VALID_BIT;
|
||||
return (jointLocation.locationFlags & PoseValidFlags) == PoseValidFlags;
|
||||
}
|
||||
|
||||
constexpr bool IsPoseTracked(const XrHandJointLocationEXT& jointLocation) {
|
||||
constexpr XrSpaceLocationFlags PoseTrackedFlags =
|
||||
XR_SPACE_LOCATION_POSITION_TRACKED_BIT | XR_SPACE_LOCATION_ORIENTATION_TRACKED_BIT;
|
||||
return (jointLocation.locationFlags & PoseTrackedFlags) == PoseTrackedFlags;
|
||||
}
|
||||
|
||||
constexpr bool IsPoseValid(const XrViewState& viewState) {
|
||||
constexpr XrViewStateFlags PoseValidFlags = XR_VIEW_STATE_POSITION_VALID_BIT | XR_VIEW_STATE_ORIENTATION_VALID_BIT;
|
||||
return (viewState.viewStateFlags & PoseValidFlags) == PoseValidFlags;
|
||||
}
|
||||
|
||||
constexpr bool IsPoseTracked(const XrViewState& viewState) {
|
||||
constexpr XrViewStateFlags PoseTrackedFlags = XR_VIEW_STATE_POSITION_TRACKED_BIT | XR_VIEW_STATE_ORIENTATION_TRACKED_BIT;
|
||||
return (viewState.viewStateFlags & PoseTrackedFlags) == PoseTrackedFlags;
|
||||
}
|
||||
|
||||
template <typename Quaternion, typename Vector3>
|
||||
constexpr XrPosef MakePose(const Quaternion& orientation, const Vector3& position) {
|
||||
return XrPosef{orientation.x, orientation.y, orientation.z, orientation.w, position.x, position.y, position.z};
|
||||
}
|
||||
} // namespace Pose
|
||||
|
||||
namespace Quaternion {
|
||||
constexpr inline XrQuaternionf Identity() {
|
||||
return {0, 0, 0, 1};
|
||||
}
|
||||
|
||||
inline float Length(const XrQuaternionf& quaternion) {
|
||||
DirectX::XMVECTOR vector = LoadXrQuaternion(quaternion);
|
||||
return DirectX::XMVectorGetX(DirectX::XMVector4Length(vector));
|
||||
}
|
||||
|
||||
inline bool IsNormalized(const XrQuaternionf& quaternion) {
|
||||
return fabs(1 - Length(quaternion)) <= QuaternionEpsilon;
|
||||
}
|
||||
|
||||
inline XrQuaternionf RotationAxisAngle(const XrVector3f& axis, float angleInRadians) {
|
||||
XrQuaternionf q;
|
||||
StoreXrQuaternion(&q, DirectX::XMQuaternionRotationAxis(LoadXrVector3(axis), angleInRadians));
|
||||
return q;
|
||||
}
|
||||
|
||||
inline XrQuaternionf RotationRollPitchYaw(const XrVector3f& anglesInRadians) {
|
||||
XrQuaternionf q;
|
||||
StoreXrQuaternion(&q, DirectX::XMQuaternionRotationRollPitchYaw(anglesInRadians.x, anglesInRadians.y, anglesInRadians.z));
|
||||
return q;
|
||||
}
|
||||
|
||||
inline XrQuaternionf Slerp(const XrQuaternionf& a, const XrQuaternionf& b, float alpha) {
|
||||
DirectX::XMVECTOR qa = LoadXrQuaternion(a);
|
||||
DirectX::XMVECTOR qb = LoadXrQuaternion(b);
|
||||
DirectX::XMVECTOR qr = DirectX::XMQuaternionSlerp(qa, qb, alpha);
|
||||
XrQuaternionf result;
|
||||
StoreXrQuaternion(&result, qr);
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace Quaternion
|
||||
|
||||
inline XrPosef operator*(const XrPosef& a, const XrPosef& b) {
|
||||
return Pose::Multiply(a, b);
|
||||
}
|
||||
|
||||
inline float Dot(const XrVector3f& a, const XrVector3f& b) {
|
||||
return a.x * b.x + a.y * b.y + a.z * b.z;
|
||||
}
|
||||
|
||||
inline float Length(const XrVector3f& v) {
|
||||
return std::sqrt(Dot(v, v));
|
||||
}
|
||||
|
||||
inline XrVector3f Normalize(const XrVector3f& a) {
|
||||
return a / std::sqrt(Dot(a, a));
|
||||
}
|
||||
|
||||
inline bool IsValidFov(const XrFovf& fov) {
|
||||
if (fov.angleRight >= DirectX::XM_PIDIV2 || fov.angleLeft <= -DirectX::XM_PIDIV2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (fov.angleUp >= DirectX::XM_PIDIV2 || fov.angleDown <= -DirectX::XM_PIDIV2) {
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// 2 * n / (r - l) 0 0 0
|
||||
// 0 2 * n / (t - b) 0 0
|
||||
// (r + l) / (r - l) (t + b) / (t - b) f / (n - f) -1
|
||||
// 0 0 n*f / (n - f) 0
|
||||
inline DirectX::XMMATRIX ComposeProjectionMatrix(const XrFovf& fov, const NearFar& nearFar) {
|
||||
if (!IsValidFov(fov)) {
|
||||
throw std::runtime_error("Invalid projection specification");
|
||||
}
|
||||
|
||||
const float nearPlane = nearFar.Near;
|
||||
const float farPlane = nearFar.Far;
|
||||
const bool infNearPlane = isinf(nearPlane);
|
||||
const bool infFarPlane = isinf(farPlane);
|
||||
|
||||
float l = tan(fov.angleLeft);
|
||||
float r = tan(fov.angleRight);
|
||||
float b = tan(fov.angleDown);
|
||||
float t = tan(fov.angleUp);
|
||||
if (!infNearPlane) {
|
||||
l *= nearPlane;
|
||||
r *= nearPlane;
|
||||
b *= nearPlane;
|
||||
t *= nearPlane;
|
||||
}
|
||||
|
||||
if (nearPlane < 0.f || farPlane < 0.f) {
|
||||
throw std::runtime_error("Invalid projection specification");
|
||||
}
|
||||
|
||||
if (infNearPlane || infFarPlane) {
|
||||
if (infNearPlane && infFarPlane) {
|
||||
throw std::runtime_error("Invalid projection specification");
|
||||
}
|
||||
|
||||
const float reciprocalWidth = 1.0f / (r - l);
|
||||
const float reciprocalHeight = 1.0f / (t - b);
|
||||
|
||||
DirectX::XMFLOAT4X4 projectionMatrix;
|
||||
|
||||
float twoNearZ;
|
||||
if (infNearPlane) {
|
||||
twoNearZ = 2;
|
||||
|
||||
projectionMatrix._33 = 0.0f; // far / (near - far) = far / inf = 0
|
||||
projectionMatrix._43 = farPlane; // near * far / (near - far) = far * (near / (near - far)) = far * (inf / inf) = far
|
||||
} else {
|
||||
twoNearZ = nearPlane + nearPlane;
|
||||
|
||||
projectionMatrix._33 = -1.0f; // far / (near - far) = inf / -inf = -1
|
||||
projectionMatrix._43 = -nearPlane; // near * far / (near - far) = near * inf / -inf = -near
|
||||
}
|
||||
|
||||
projectionMatrix._11 = twoNearZ * reciprocalWidth;
|
||||
projectionMatrix._12 = 0.0f;
|
||||
projectionMatrix._13 = 0.0f;
|
||||
projectionMatrix._14 = 0.0f;
|
||||
|
||||
projectionMatrix._21 = 0.0f;
|
||||
projectionMatrix._22 = twoNearZ * reciprocalHeight;
|
||||
projectionMatrix._23 = 0.0f;
|
||||
projectionMatrix._24 = 0.0f;
|
||||
|
||||
projectionMatrix._31 = (l + r) * reciprocalWidth;
|
||||
projectionMatrix._32 = (t + b) * reciprocalHeight;
|
||||
projectionMatrix._34 = -1.0f;
|
||||
|
||||
projectionMatrix._41 = 0.0f;
|
||||
projectionMatrix._42 = 0.0f;
|
||||
projectionMatrix._44 = 0.0f;
|
||||
|
||||
return DirectX::XMLoadFloat4x4(&projectionMatrix);
|
||||
} else {
|
||||
return DirectX::XMMatrixPerspectiveOffCenterRH(l, r, b, t, nearPlane, farPlane);
|
||||
}
|
||||
}
|
||||
|
||||
inline bool IsInfiniteNearPlaneProjectionMatrix(const DirectX::XMFLOAT4X4& p) {
|
||||
return (p._33 == 0);
|
||||
}
|
||||
|
||||
inline bool IsInfiniteFarPlaneProjectionMatrix(const DirectX::XMFLOAT4X4& p) {
|
||||
return (p._33 == -1);
|
||||
}
|
||||
|
||||
inline void ValidateProjectionMatrix(const DirectX::XMFLOAT4X4& p) {
|
||||
// Reference equations on top of ComposeProjectionMatrix() above.
|
||||
if (p._12 != 0 || p._13 != 0 || p._14 != 0 ||
|
||||
// p._21 is not 0 on old MR devices, but small enough to be ignored. For future MR devices, it should be 0 (no shear)
|
||||
p._23 != 0 || p._24 != 0 ||
|
||||
// When near or far plane is infinite, p._33 is 0 or -1, respectively. They are valid cases.
|
||||
p._34 != -1 || p._41 != 0 || p._42 != 0 || p._44 != 0) {
|
||||
throw std::runtime_error("Invalid projection matrix");
|
||||
}
|
||||
}
|
||||
|
||||
inline NearFar GetProjectionNearFar(const DirectX::XMFLOAT4X4& p) {
|
||||
ValidateProjectionMatrix(p);
|
||||
|
||||
NearFar d;
|
||||
|
||||
if (IsInfiniteNearPlaneProjectionMatrix(p)) {
|
||||
d.Near = std::numeric_limits<float>::infinity();
|
||||
d.Far = p._43;
|
||||
} else if (IsInfiniteFarPlaneProjectionMatrix(p)) {
|
||||
d.Near = -p._43;
|
||||
d.Far = std::numeric_limits<float>::infinity();
|
||||
} else {
|
||||
// Reference equations on top of ComposeProjectionMatrix() above.
|
||||
d.Near = p._43 / p._33;
|
||||
d.Far = p._43 / (1 + p._33);
|
||||
}
|
||||
|
||||
return d;
|
||||
}
|
||||
|
||||
inline XrFovf DecomposeProjectionMatrix(const DirectX::XMFLOAT4X4& p) {
|
||||
ValidateProjectionMatrix(p);
|
||||
|
||||
// n = m43 / m33
|
||||
// f = m43 / (1 + m33)
|
||||
// l = n * (m31 - 1) / m11 => angle left = atan2(l, n) => atan2(m31 - 1, m11)
|
||||
// r = n * (m31 + 1) / m11 => so on
|
||||
// b = n * (m32 - 1) / m22 => and
|
||||
// t = n * (m32 + 1) / m22 => so forth
|
||||
XrFovf fov;
|
||||
fov.angleLeft = atan2(p._31 - 1, p._11);
|
||||
fov.angleRight = atan2(p._31 + 1, p._11);
|
||||
fov.angleDown = atan2(p._32 - 1, p._22);
|
||||
fov.angleUp = atan2(p._32 + 1, p._22);
|
||||
return fov;
|
||||
}
|
||||
|
||||
template <uint32_t alignment>
|
||||
inline constexpr uint32_t AlignTo(uint32_t n) {
|
||||
static_assert((alignment & (alignment - 1)) == 0); // must be power-of-two
|
||||
return (n + alignment - 1) & ~(alignment - 1);
|
||||
}
|
||||
|
||||
inline constexpr uint32_t DivideRoundingUp(uint32_t x, uint32_t y) {
|
||||
return (x + y - 1) / y;
|
||||
}
|
||||
} // namespace xr::math
|
||||
|
||||
#pragma endregion
|
|
@ -0,0 +1,94 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_reflection.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "XrToString.h"
|
||||
#include "XrError.h"
|
||||
|
||||
namespace xr {
|
||||
|
||||
inline XrPath StringToPath(XrInstance instance, const char* str) {
|
||||
XrPath path;
|
||||
CHECK_XRCMD(xrStringToPath(instance, str, &path));
|
||||
return path;
|
||||
}
|
||||
|
||||
inline std::vector<XrPath> StringsToPaths(XrInstance instance, const std::vector<std::string>& strings) {
|
||||
std::vector<XrPath> paths;
|
||||
|
||||
for (auto string : strings) {
|
||||
paths.push_back(StringToPath(instance, string.c_str()));
|
||||
}
|
||||
|
||||
return paths;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
inline std::wstring utf8_to_wide(std::string_view utf8Text) {
|
||||
if (utf8Text.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::wstring wideText;
|
||||
const int wideLength = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), nullptr, 0);
|
||||
if (wideLength == 0) {
|
||||
DEBUG_PRINT("utf8_to_wide get size error: {}", ::GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
// MultiByteToWideChar returns number of chars of the input buffer, regardless of null terminitor
|
||||
wideText.resize(wideLength, 0);
|
||||
const int length = ::MultiByteToWideChar(CP_UTF8, 0, utf8Text.data(), (int)utf8Text.size(), wideText.data(), wideLength);
|
||||
if (length != wideLength) {
|
||||
DEBUG_PRINT("utf8_to_wide convert string error: {}", ::GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
return wideText;
|
||||
}
|
||||
|
||||
inline std::string wide_to_utf8(std::wstring_view wideText) {
|
||||
if (wideText.empty()) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::string narrowText;
|
||||
int narrowLength = ::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), nullptr, 0, nullptr, nullptr);
|
||||
if (narrowLength == 0) {
|
||||
DEBUG_PRINT("wide_to_utf8 get size error: {}", ::GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
// WideCharToMultiByte returns number of chars of the input buffer, regardless of null terminitor
|
||||
narrowText.resize(narrowLength, 0);
|
||||
const int length =
|
||||
::WideCharToMultiByte(CP_UTF8, 0, wideText.data(), (int)wideText.size(), narrowText.data(), narrowLength, nullptr, nullptr);
|
||||
if (length != narrowLength) {
|
||||
DEBUG_PRINT("wide_to_utf8 convert string error: {}", ::GetLastError());
|
||||
return {};
|
||||
}
|
||||
|
||||
return narrowText;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace xr
|
|
@ -0,0 +1,73 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
#pragma once
|
||||
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_reflection.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#define XR_LIST_ENUM_XrRemotingResult(_) \
|
||||
_(XR_ERROR_REMOTING_NOT_DISCONNECTED_MSFT, -1000065000) \
|
||||
_(XR_ERROR_REMOTING_CODEC_NOT_FOUND_MSFT, -1000065001) \
|
||||
_(XR_ERROR_REMOTING_CALLBACK_ERROR_MSFT, -1000065002) \
|
||||
_(XR_ERROR_REMOTING_DEPTH_BUFFER_STREAM_DISABLED_MSFT, -1000065003) \
|
||||
_(XR_RESULT_MAX_ENUM, 0x7FFFFFFF)
|
||||
|
||||
// Macro to generate stringify functions for OpenXR enumerations based data provided in openxr_reflection.h
|
||||
// clang-format off
|
||||
#define ENUM_CASE_STR(name, val) case name: return #name;
|
||||
|
||||
// Returns C string pointing to a string literal. Unknown values are returned as 'Unknown <type>'.
|
||||
#define MAKE_TO_CSTRING_FUNC(enumType) \
|
||||
constexpr const char* ToCString(enumType e) noexcept { \
|
||||
switch (e) { \
|
||||
XR_LIST_ENUM_##enumType(ENUM_CASE_STR) \
|
||||
default: return "Unknown " #enumType; \
|
||||
} \
|
||||
}
|
||||
|
||||
// Returns a STL string. Unknown values are stringified as an integer.
|
||||
#define MAKE_TO_STRING_FUNC(enumType) \
|
||||
inline std::string ToString(enumType e) { \
|
||||
switch (e) { \
|
||||
XR_LIST_ENUM_##enumType(ENUM_CASE_STR) \
|
||||
default: return std::to_string(e); \
|
||||
} \
|
||||
}
|
||||
|
||||
#define MAKE_TO_STRING_FUNCS(enumType) \
|
||||
MAKE_TO_CSTRING_FUNC(enumType) \
|
||||
MAKE_TO_STRING_FUNC(enumType)
|
||||
// clang-format on
|
||||
|
||||
namespace xr {
|
||||
MAKE_TO_STRING_FUNCS(XrReferenceSpaceType);
|
||||
MAKE_TO_STRING_FUNCS(XrViewConfigurationType);
|
||||
MAKE_TO_STRING_FUNCS(XrEnvironmentBlendMode);
|
||||
MAKE_TO_STRING_FUNCS(XrSessionState);
|
||||
MAKE_TO_STRING_FUNCS(XrResult);
|
||||
MAKE_TO_STRING_FUNCS(XrRemotingResult);
|
||||
MAKE_TO_STRING_FUNCS(XrStructureType);
|
||||
MAKE_TO_STRING_FUNCS(XrFormFactor);
|
||||
MAKE_TO_STRING_FUNCS(XrEyeVisibility);
|
||||
MAKE_TO_STRING_FUNCS(XrObjectType);
|
||||
MAKE_TO_STRING_FUNCS(XrActionType);
|
||||
MAKE_TO_STRING_FUNCS(XrHandEXT);
|
||||
MAKE_TO_STRING_FUNCS(XrHandPoseTypeMSFT);
|
||||
MAKE_TO_CSTRING_FUNC(XrHandJointEXT);
|
||||
MAKE_TO_STRING_FUNCS(XrVisibilityMaskTypeKHR);
|
||||
} // namespace xr
|
|
@ -0,0 +1,7 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Microsoft.Windows.CppWinRT" version="2.0.200729.8" targetFramework="native" />
|
||||
<package id="OpenXR.Headers" version="1.0.10.2" targetFramework="native" />
|
||||
<package id="OpenXR.Loader" version="1.0.10.2" targetFramework="native" />
|
||||
<package id="Microsoft.Holographic.Remoting.OpenXr" version="2.4.0" targetFramework="native" />
|
||||
</packages>
|
|
@ -0,0 +1,17 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#include "pch.h"
|
|
@ -0,0 +1,52 @@
|
|||
//*********************************************************
|
||||
// Copyright (c) Microsoft. All rights reserved.
|
||||
//
|
||||
// Apache 2.0 License
|
||||
//
|
||||
// You may obtain a copy of the License at
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
// implied. See the License for the specific language governing
|
||||
// permissions and limitations under the License.
|
||||
//
|
||||
//*********************************************************
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <thread>
|
||||
#include <chrono>
|
||||
#include <atomic>
|
||||
#include <array>
|
||||
#include <map>
|
||||
#include <list>
|
||||
#include <unordered_map>
|
||||
#include <algorithm>
|
||||
#include <assert.h>
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#define NOMINMAX
|
||||
#include <windows.h>
|
||||
|
||||
#include <d3d11.h>
|
||||
|
||||
#define XR_USE_PLATFORM_WIN32
|
||||
#define XR_USE_GRAPHICS_API_D3D11
|
||||
#include <openxr/openxr.h>
|
||||
#include <openxr/openxr_platform.h>
|
||||
|
||||
#include <openxr/openxr_msft_holographic_remoting.h>
|
||||
#include <openxr/openxr_msft_remoting_frame_mirroring.h>
|
||||
|
||||
#include <XrUtility/XrError.h>
|
||||
#include <XrUtility/XrHandle.h>
|
||||
#include <XrUtility/XrMath.h>
|
||||
#include <XrUtility/XrString.h>
|
||||
#include <XrUtility/XrExtensions.h>
|
||||
|
||||
#include <winrt/base.h> // winrt::com_ptr
|