diff --git a/.reuse/dep5 b/.reuse/dep5 index 3df6553a..cedb22dd 100644 --- a/.reuse/dep5 +++ b/.reuse/dep5 @@ -54,8 +54,8 @@ Comment: Unmodified, vendored copy of a subset of the tiny-gltf repo v2.8.9 Files: src/external/d3dx12/* Copyright: Copyright (c) Microsoft Corporation. License: MIT -Comment: Unmodified, vendored copy of DirectX-Headers commit da7aedb - of https://github.com/microsoft/DirectX-Headers filtered to just d3dx12 headers +Comment: Unmodified, vendored copy of d3dx12.h from directx-vs-templates commit 86b9c45 + This repo includes ifdefs to improve compatibility with older Windows SDK verions. Files: src/external/mikktspace/* Copyright: 2011 by Morten S. Mikkelsen diff --git a/CHANGELOG.CTS.md b/CHANGELOG.CTS.md index dd89ef9f..e09d4125 100644 --- a/CHANGELOG.CTS.md +++ b/CHANGELOG.CTS.md @@ -17,6 +17,110 @@ particular, since it is primarily software, pull requests may be integrated as they are accepted even between periodic updates. However, versions that are not signed tags on the `approved` branch are not valid for conformance submission. +## OpenXR CTS 1.0.29.0 (2023-09-07) + +- Conformance Tests + - Fix: Use actual acquired image index in swapchain rendering test. + ([internal MR 2746](https://gitlab.khronos.org/openxr/openxr/merge_requests/2746)) + - Fix: Do not use Catch2 assertion macros in graphics plugin methods that may be + called before the first test case execution begins. + ([internal MR 2756](https://gitlab.khronos.org/openxr/openxr/merge_requests/2756), + [internal issue 1387](https://gitlab.khronos.org/openxr/openxr/issues/1387)) + - Fix: spelling. + ([internal MR 2766](https://gitlab.khronos.org/openxr/openxr/merge_requests/2766)) + - Fix: Fix `` element contents in Android manifest. + ([internal MR 2840](https://gitlab.khronos.org/openxr/openxr/merge_requests/2840), + [internal issue 2053](https://gitlab.khronos.org/openxr/openxr/issues/2053)) + - Fix: Allow building CTS with mingw compiler. + ([internal MR 2850](https://gitlab.khronos.org/openxr/openxr/merge_requests/2850)) + - Fix: Do not create an `XrInstance` during XML writing process, to prevent + possible crash if one already exists. + ([internal MR 2927](https://gitlab.khronos.org/openxr/openxr/merge_requests/2927)) + - Improvement: Refactor utilities that do not depend on Catch2 into a separate + internal library. + ([internal MR 2669](https://gitlab.khronos.org/openxr/openxr/merge_requests/2669)) + - Improvement: Refactor and standardize creation of swapchain image format + tables, fixing some Vulkan invalid usage. + ([internal MR 2685](https://gitlab.khronos.org/openxr/openxr/merge_requests/2685), + [internal issue 1978](https://gitlab.khronos.org/openxr/openxr/issues/1978)) + - Improvement: Make composition test help/example world locked but based on + initial view, for more natural reading. + ([internal MR 2689](https://gitlab.khronos.org/openxr/openxr/merge_requests/2689)) + - Improvement: Cleanup and code quality work. + ([internal MR 2704](https://gitlab.khronos.org/openxr/openxr/merge_requests/2704), + [internal MR 2717](https://gitlab.khronos.org/openxr/openxr/merge_requests/2717), + [internal MR 2784](https://gitlab.khronos.org/openxr/openxr/merge_requests/2784), + [internal MR 2785](https://gitlab.khronos.org/openxr/openxr/merge_requests/2785), + [internal MR 2808](https://gitlab.khronos.org/openxr/openxr/merge_requests/2808), + [internal MR 2809](https://gitlab.khronos.org/openxr/openxr/merge_requests/2809)) + - Improvement: Add separate license file for gradlew and gradlew.bat + ([internal MR 2725](https://gitlab.khronos.org/openxr/openxr/merge_requests/2725)) + - Improvement: Optionally poll `xrGetSystem` before running test cases. + ([internal MR 2735](https://gitlab.khronos.org/openxr/openxr/merge_requests/2735), + [OpenXR-CTS issue 53](https://github.com/KhronosGroup/OpenXR-CTS/issues/53), + [internal issue 1947](https://gitlab.khronos.org/openxr/openxr/issues/1947)) + - Improvement: Select the first enumerated environment blend mode by default, + rather than always using "opaque" + ([internal MR 2736](https://gitlab.khronos.org/openxr/openxr/merge_requests/2736), + [internal issue 1950](https://gitlab.khronos.org/openxr/openxr/issues/1950)) + - Improvement: Migrate more tests to use the `SKIP` macro when appropriate. + ([internal MR 2737](https://gitlab.khronos.org/openxr/openxr/merge_requests/2737), + [internal issue 1932](https://gitlab.khronos.org/openxr/openxr/issues/1932)) + - Improvement: Change background color based on selected blend mode: black for + additive and transparent for alpha blend. + ([internal MR 2883](https://gitlab.khronos.org/openxr/openxr/merge_requests/2883), + [internal issue 1949](https://gitlab.khronos.org/openxr/openxr/issues/1949)) + - Improvement: Add extra information to errors in case of CTS timeouts. + ([internal MR 2889](https://gitlab.khronos.org/openxr/openxr/merge_requests/2889)) + - Improvement: Remove conditional `XR_KHR_headless` support as the extension is + not part of OpenXR 1.0. + ([internal MR 2901](https://gitlab.khronos.org/openxr/openxr/merge_requests/2901)) + - Improvement: Remove empty `XR_EXT_performance_settings` test that was never + implemented + ([internal MR 2902](https://gitlab.khronos.org/openxr/openxr/merge_requests/2902)) + - Improvement: Fix names of tests to not have spaces, and adjust tags so that the + instructions in the README will cause all tests to be executed. + ([internal MR 2924](https://gitlab.khronos.org/openxr/openxr/merge_requests/2924)) + - New test: Verify two-call idiom behavior of `XR_MSFT_controller_model` as well + as handling of invalid model keys. + ([internal MR 2387](https://gitlab.khronos.org/openxr/openxr/merge_requests/2387), + [internal MR 2858](https://gitlab.khronos.org/openxr/openxr/merge_requests/2858)) + - New test: Added `XR_EXT_plane_detection` extension. + ([internal MR 2510](https://gitlab.khronos.org/openxr/openxr/merge_requests/2510), + [internal MR 2751](https://gitlab.khronos.org/openxr/openxr/merge_requests/2751), + [internal MR 2676](https://gitlab.khronos.org/openxr/openxr/merge_requests/2676)) + - New test: Add non-interactive test for `XR_EXT_palm_pose` vendor extension. + ([internal MR 2672](https://gitlab.khronos.org/openxr/openxr/merge_requests/2672)) + - New test: Add joint query to non-interactive test for `XR_EXT_hand_tracking`. + ([internal MR 2729](https://gitlab.khronos.org/openxr/openxr/merge_requests/2729), + [internal MR 2795](https://gitlab.khronos.org/openxr/openxr/merge_requests/2795), + [internal MR 2858](https://gitlab.khronos.org/openxr/openxr/merge_requests/2858), + [internal MR 2916](https://gitlab.khronos.org/openxr/openxr/merge_requests/2916)) + - New test: Add test for calling `xrAcquireSwapchainImage` multiple times without + calling `xrEndFrame`. + ([internal MR 2730](https://gitlab.khronos.org/openxr/openxr/merge_requests/2730)) + - New test: Add additional tests for `XR_EXT_debug_utils` based on the test app + `loader_test`. + ([internal MR 2775](https://gitlab.khronos.org/openxr/openxr/merge_requests/2775)) + - New test: Add checks for palm position and palm and wrist orientation to + `XR_EXT_hand_tracking` interactive tests. + ([internal MR 2798](https://gitlab.khronos.org/openxr/openxr/merge_requests/2798)) + - New test: Add unbound action set to action sets test. + ([internal MR 2862](https://gitlab.khronos.org/openxr/openxr/merge_requests/2862), + [internal issue 2043](https://gitlab.khronos.org/openxr/openxr/issues/2043)) + - New test: Add conformance test for calling `xrDestroyInstance` from a different + thread to `xrCreateInstance`, and `xrDestroySession` on a different thread to + `xrCreateSession`. + ([internal MR 2863](https://gitlab.khronos.org/openxr/openxr/merge_requests/2863)) + - New test: Add interactive conformance test for infrequently updated swapchains. + ([internal MR 2873](https://gitlab.khronos.org/openxr/openxr/merge_requests/2873)) + - New test: Add conformance tests for `xrCreateSession` failing, then passing + ([internal MR 2884](https://gitlab.khronos.org/openxr/openxr/merge_requests/2884)) + - New test: Test `xrSyncActions` with no active action sets. + ([internal MR 2903](https://gitlab.khronos.org/openxr/openxr/merge_requests/2903)) + - New test: Test calling `xrLocateSpace` with timestamps up to 1s old. + ([internal MR 2904](https://gitlab.khronos.org/openxr/openxr/merge_requests/2904)) + ## OpenXR CTS 1.0.27.0 (2023-05-10) This release contains a large number of new or improved tests. It is expected diff --git a/changes/conformance/mr.2387.gl.md b/changes/conformance/mr.2387.gl.md deleted file mode 100644 index 988c6921..00000000 --- a/changes/conformance/mr.2387.gl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -- mr.2858.gl ---- -New test: Verify two-call idiom behavior of `XR_MSFT_controller_model` as well as handling of invalid model keys. diff --git a/changes/conformance/mr.2510.gl.md b/changes/conformance/mr.2510.gl.md deleted file mode 100644 index bd57edb1..00000000 --- a/changes/conformance/mr.2510.gl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -- mr.2751.gl -- mr.2676.gl ---- -New test: Added `XR_EXT_plane_detection` extension. diff --git a/changes/conformance/mr.2669.gl.md b/changes/conformance/mr.2669.gl.md deleted file mode 100644 index abcfc994..00000000 --- a/changes/conformance/mr.2669.gl.md +++ /dev/null @@ -1 +0,0 @@ -Improvement: Refactor utilities that do not depend on Catch2 into a separate internal library. diff --git a/changes/conformance/mr.2672.gl.md b/changes/conformance/mr.2672.gl.md deleted file mode 100644 index a703b406..00000000 --- a/changes/conformance/mr.2672.gl.md +++ /dev/null @@ -1 +0,0 @@ -Improvement: Add non-interactive test for XR_EXT_palm_pose vendor extension. diff --git a/changes/conformance/mr.2685.gl.md b/changes/conformance/mr.2685.gl.md deleted file mode 100644 index c77f7c89..00000000 --- a/changes/conformance/mr.2685.gl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -- issue.1978.gl ---- -Improvement: Refactor and standardize creation of swapchain image format tables, fixing some Vulkan invalid usage. diff --git a/changes/conformance/mr.2689.gl.md b/changes/conformance/mr.2689.gl.md deleted file mode 100644 index 07b3e8bd..00000000 --- a/changes/conformance/mr.2689.gl.md +++ /dev/null @@ -1 +0,0 @@ -Improvement: Make composition test help/example world locked but based on initial view, for more natural reading. diff --git a/changes/conformance/mr.2704.gl.md b/changes/conformance/mr.2704.gl.md deleted file mode 100644 index a792439d..00000000 --- a/changes/conformance/mr.2704.gl.md +++ /dev/null @@ -1,7 +0,0 @@ ---- -- mr.2784.gl -- mr.2785.gl -- mr.2808.gl -- mr.2809.gl ---- -Improvement: Cleanup and code quality work. diff --git a/changes/conformance/mr.2717.gl.md b/changes/conformance/mr.2717.gl.md deleted file mode 100644 index cb4f77b3..00000000 --- a/changes/conformance/mr.2717.gl.md +++ /dev/null @@ -1 +0,0 @@ -Improvement: Fix clang warnings `-Wundef` and `-Wmissing-braces`. diff --git a/changes/conformance/mr.2725.gl.md b/changes/conformance/mr.2725.gl.md deleted file mode 100644 index e33f542f..00000000 --- a/changes/conformance/mr.2725.gl.md +++ /dev/null @@ -1 +0,0 @@ -gradle: Add license for gradlew and gradlew.bat diff --git a/changes/conformance/mr.2729.gl.md b/changes/conformance/mr.2729.gl.md deleted file mode 100644 index 7e44ad1a..00000000 --- a/changes/conformance/mr.2729.gl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -- mr.2795.gl -- mr.2858.gl ---- -Improvement: Add joint query to non-interactive test for `XR_EXT_hand_tracking`. diff --git a/changes/conformance/mr.2730.gl.md b/changes/conformance/mr.2730.gl.md deleted file mode 100644 index a7720525..00000000 --- a/changes/conformance/mr.2730.gl.md +++ /dev/null @@ -1 +0,0 @@ -Improvement: Add test for calling `xrAcquireSwapchainImage` multiple times without calling `xrEndFrame`. diff --git a/changes/conformance/mr.2735.gl.md b/changes/conformance/mr.2735.gl.md deleted file mode 100644 index d7f49116..00000000 --- a/changes/conformance/mr.2735.gl.md +++ /dev/null @@ -1,5 +0,0 @@ ---- -- issue.53.gh.OpenXR-CTS -- issue.1947.gl ---- -Improvement: Optionally poll `xrGetSystem` before running test cases. diff --git a/changes/conformance/mr.2736.gl.md b/changes/conformance/mr.2736.gl.md deleted file mode 100644 index 29a8c04a..00000000 --- a/changes/conformance/mr.2736.gl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -- issue.1950.gl ---- -Improvement: Select the first enumerated environment blend mode by default, rather than always using "opaque" diff --git a/changes/conformance/mr.2737.gl.md b/changes/conformance/mr.2737.gl.md deleted file mode 100644 index 1f289d4d..00000000 --- a/changes/conformance/mr.2737.gl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -- issue.1932.gl ---- -Improvement: Migrate more tests to use the `SKIP` macro when appropriate. diff --git a/changes/conformance/mr.2746.gl.md b/changes/conformance/mr.2746.gl.md deleted file mode 100644 index 34bc4818..00000000 --- a/changes/conformance/mr.2746.gl.md +++ /dev/null @@ -1 +0,0 @@ -Fix: Use actual acquired image index in swapchain rendering test. diff --git a/changes/conformance/mr.2756.gl.md b/changes/conformance/mr.2756.gl.md deleted file mode 100644 index ddfb77dc..00000000 --- a/changes/conformance/mr.2756.gl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -- issue.1387.gl ---- -Fix: Do not use Catch2 assertion macros in graphics plugin methods that may be called before the first test case execution begins. diff --git a/changes/conformance/mr.2766.gl.md b/changes/conformance/mr.2766.gl.md deleted file mode 100644 index 944b119d..00000000 --- a/changes/conformance/mr.2766.gl.md +++ /dev/null @@ -1 +0,0 @@ -Fix: spelling. diff --git a/changes/conformance/mr.2775.gl.md b/changes/conformance/mr.2775.gl.md deleted file mode 100644 index c2164b35..00000000 --- a/changes/conformance/mr.2775.gl.md +++ /dev/null @@ -1 +0,0 @@ -Improvement: Add additional tests for XR_EXT_debug_utils based on the test app loader_test. diff --git a/changes/conformance/mr.2840.gl.md b/changes/conformance/mr.2840.gl.md deleted file mode 100644 index 9860ffb9..00000000 --- a/changes/conformance/mr.2840.gl.md +++ /dev/null @@ -1,4 +0,0 @@ ---- -- issue.2053.gl ---- -- Fix: Fix `` element contents in Android manifest. diff --git a/changes/conformance/mr.2850.gl.md b/changes/conformance/mr.2850.gl.md deleted file mode 100644 index 85701ee8..00000000 --- a/changes/conformance/mr.2850.gl.md +++ /dev/null @@ -1 +0,0 @@ -Fix building CTS with mingw compiler. diff --git a/src/conformance/build.gradle b/src/conformance/build.gradle index 8276908d..4a4c7060 100644 --- a/src/conformance/build.gradle +++ b/src/conformance/build.gradle @@ -4,22 +4,11 @@ // Open this directory in Android Studio, or build with Gradle, // to build the conformance suite. -buildscript { - repositories { - google() - mavenCentral() - } - dependencies { - classpath 'com.android.tools.build:gradle:7.4.2' - } -} -repositories { - google() - mavenCentral() +plugins { + id 'com.android.application' version '7.4.2' } -apply plugin: 'com.android.application' // These next few lines are just to make the version match the OpenXR release. project.ext.repoRoot = file('../../') @@ -27,33 +16,30 @@ apply from: file('../version.gradle') def assetDest = layout.buildDir.dir('intermediates/assets') -task copyFont(type: Copy) { +task copyAssets(type: Copy) { + // fonts from('conformance_test') { include '*.otf' } - into assetDest -} -task copyAssets(type: Copy) { + // sample images from('conformance_test/composition_examples') { include '*.png' } - into assetDest - dependsOn copyFont -} -task copyLayerInfo(type: Copy) { + // layer manifests from('conformance_test/android_assets') { include '**/*.json' } + into assetDest - dependsOn copyFont } android { compileSdk 29 ndkVersion "21.4.7075529" buildToolsVersion = "30.0.3" + namespace 'org.khronos.openxr.cts' defaultConfig { applicationId "org.khronos.openxr.cts" @@ -65,8 +51,7 @@ android { externalNativeBuild { cmake { - arguments '-DANDROID_STL=c++_shared', - '-DBUILD_TESTS=OFF', + arguments '-DBUILD_TESTS=OFF', '-DBUILD_LOADER=ON', '-DBUILD_CONFORMANCE_TESTS=ON', '-DBUILD_ALL_EXTENSIONS=ON' @@ -74,7 +59,6 @@ android { } } preBuild.dependsOn(copyAssets) - preBuild.dependsOn(copyLayerInfo) } sourceSets { main { diff --git a/src/conformance/conformance_test/composition_examples/stale_swapchain.png b/src/conformance/conformance_test/composition_examples/stale_swapchain.png new file mode 100644 index 00000000..91afdfb8 Binary files /dev/null and b/src/conformance/conformance_test/composition_examples/stale_swapchain.png differ diff --git a/src/conformance/conformance_test/composition_examples/stale_swapchain.png.license b/src/conformance/conformance_test/composition_examples/stale_swapchain.png.license new file mode 100644 index 00000000..6d36aba0 --- /dev/null +++ b/src/conformance/conformance_test/composition_examples/stale_swapchain.png.license @@ -0,0 +1,3 @@ +SPDX-FileCopyrightText: 2020-2023, The Khronos Group Inc. + +SPDX-License-Identifier: Apache-2.0 diff --git a/src/conformance/conformance_test/test_FrameSubmission.cpp b/src/conformance/conformance_test/test_FrameSubmission.cpp index 1a343852..77662b8d 100644 --- a/src/conformance/conformance_test/test_FrameSubmission.cpp +++ b/src/conformance/conformance_test/test_FrameSubmission.cpp @@ -31,6 +31,7 @@ #define ENUM_LIST(name, val) name, constexpr XrEnvironmentBlendMode SupportedBlendModes[] = {XR_LIST_ENUM_XrEnvironmentBlendMode(ENUM_LIST)}; +#undef ENUM_LIST namespace Conformance { @@ -204,7 +205,8 @@ namespace Conformance CHECK(XR_SUCCESS == xrRequestExitSession(session)); - REQUIRE(FrameIterator::RunResult::Success == FrameIterator(&session).RunToSessionState(XR_SESSION_STATE_STOPPING, 5s)); + FrameIterator frameIterator(&session); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); CHECK(XR_SUCCESS == xrEndSession(session)); diff --git a/src/conformance/conformance_test/test_HapticInterrupt.cpp b/src/conformance/conformance_test/test_HapticInterrupt.cpp index 89422738..c5ad5d63 100644 --- a/src/conformance/conformance_test/test_HapticInterrupt.cpp +++ b/src/conformance/conformance_test/test_HapticInterrupt.cpp @@ -39,7 +39,7 @@ namespace Conformance { constexpr XrVector3f Up{0, 1, 0}; - TEST_CASE("Haptic Interrupt", "[scenario][interactive][no_auto]") + TEST_CASE("HapticInterrupt", "[scenario][interactive][no_auto]") { const char* instructions = "Press the select button on either hand to begin a 2 second haptic output. " diff --git a/src/conformance/conformance_test/test_InteractiveThrow.cpp b/src/conformance/conformance_test/test_InteractiveThrow.cpp index c3fdd4f8..b70c86b2 100644 --- a/src/conformance/conformance_test/test_InteractiveThrow.cpp +++ b/src/conformance/conformance_test/test_InteractiveThrow.cpp @@ -37,7 +37,7 @@ namespace Conformance // Purpose: Verify behavior of action timing and action space linear/angular velocity through throwing // 1. Use action state changed timestamp to query velocities // 2. Use action space velocities at various rigid offsets to verify "lever arm" effect is computed by runtime. - TEST_CASE("Interactive Throw", "[scenario][interactive][no_auto]") + TEST_CASE("InteractiveThrow", "[scenario][interactive][no_auto]") { const char* instructions = "Press and hold 'select' to spawn three rigidly-attached cubes to that controller. " diff --git a/src/conformance/conformance_test/test_LayerComposition.cpp b/src/conformance/conformance_test/test_LayerComposition.cpp index d3cf88c8..049d9340 100644 --- a/src/conformance/conformance_test/test_LayerComposition.cpp +++ b/src/conformance/conformance_test/test_LayerComposition.cpp @@ -653,4 +653,64 @@ namespace Conformance RenderLoop(compositionHelper.GetSession(), updateLayers).Loop(); } + + TEST_CASE("StaleSwapchain", "[composition][interactive][no_auto]") + { + CompositionHelper compositionHelper("Stale swapchain"); + InteractiveLayerManager interactiveLayerManager(compositionHelper, "stale_swapchain.png", + "Updates swapchain of each square at 1Hz. " + "Square on left should be constantly green, and square on right " + "should switch between green and blue every second. " + "If there is any flicker on the green square, " + "likely at the same time as the other square changes color, " + "that is a failure."); + compositionHelper.GetInteractionManager().AttachActionSets(); + compositionHelper.BeginSession(); + + const XrSpace viewSpace = compositionHelper.CreateReferenceSpace(XR_REFERENCE_SPACE_TYPE_VIEW, XrPosef{Quat::Identity, {0, 0, -1}}); + + constexpr int ImageSize = 1; + + // Create an array swapchain + auto swapchainCreateInfo = + compositionHelper.DefaultColorSwapchainCreateInfo(ImageSize, ImageSize, 0, GetGlobalData().graphicsPlugin->GetSRGBA8Format()); + swapchainCreateInfo.usageFlags |= XR_SWAPCHAIN_USAGE_TRANSFER_DST_BIT; + const XrSwapchain constantColorSwapchain = compositionHelper.CreateSwapchain(swapchainCreateInfo); + const XrSwapchain alternatingColorSwapchain = compositionHelper.CreateSwapchain(swapchainCreateInfo); + + RGBAImage images[2] = {RGBAImage(ImageSize, ImageSize), RGBAImage(ImageSize, ImageSize)}; + images[0].DrawRect(0, 0, ImageSize, ImageSize, Colors::Green); + images[1].DrawRect(0, 0, ImageSize, ImageSize, Colors::Blue); + images[0].ConvertToSRGB(); + images[1].ConvertToSRGB(); + + XrCompositionLayerQuad* const constantQuad = + compositionHelper.CreateQuadLayer(constantColorSwapchain, viewSpace, 0.02f, XrPosef{Quat::Identity, {-0.1f, 0, -1}}); + interactiveLayerManager.AddLayer(constantQuad); + + XrCompositionLayerQuad* const alternatingQuad = + compositionHelper.CreateQuadLayer(alternatingColorSwapchain, viewSpace, 0.02f, XrPosef{Quat::Identity, {0.1f, 0, -1}}); + interactiveLayerManager.AddLayer(alternatingQuad); + + XrTime lastUpdate = 0; + bool alternatingIndex = false; + RenderLoop(compositionHelper.GetSession(), [&](const XrFrameState& frameState) { + // Failing this test may create a flashing image. 1Hz is well outside the + // documented normal range for photosensitive epilepsy (rarely as low as 3Hz). + // Regardless, failures may e.g. create a black flash every second, so we use a + // small square to minimise any effects of the failure condition. + if (lastUpdate == 0 || (frameState.predictedDisplayTime - lastUpdate) >= 1_xrSeconds) { + lastUpdate = frameState.predictedDisplayTime; + compositionHelper.AcquireWaitReleaseImage(constantColorSwapchain, [&](const XrSwapchainImageBaseHeader* swapchainImage) { + GetGlobalData().graphicsPlugin->CopyRGBAImage(swapchainImage, 0, images[0]); + }); + compositionHelper.AcquireWaitReleaseImage(alternatingColorSwapchain, [&](const XrSwapchainImageBaseHeader* swapchainImage) { + GetGlobalData().graphicsPlugin->CopyRGBAImage(swapchainImage, 0, images[(uint32_t)alternatingIndex]); + alternatingIndex = !alternatingIndex; + }); + } + return interactiveLayerManager.EndFrame(frameState); + }).Loop(); + } + } // namespace Conformance diff --git a/src/conformance/conformance_test/test_Swapchains.cpp b/src/conformance/conformance_test/test_Swapchains.cpp index db0b5a93..42eddf4e 100644 --- a/src/conformance/conformance_test/test_Swapchains.cpp +++ b/src/conformance/conformance_test/test_Swapchains.cpp @@ -628,13 +628,8 @@ namespace Conformance auto graphicsPlugin = globalData.GetGraphicsPlugin(); - // how long the test should wait for the app to get focus: 10 seconds in release, infinite in debug builds. - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); XrSwapchain swapchain{XR_NULL_HANDLE}; XrExtent2Di widthHeight{0, 0}; // 0,0 means Use defaults. @@ -673,7 +668,7 @@ namespace Conformance } if ((j % 2) == 0) { - runResult = frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); } } diff --git a/src/conformance/conformance_test/test_XR_EXT_debug_utils.cpp b/src/conformance/conformance_test/test_XR_EXT_debug_utils.cpp index 2b6fda21..751defe6 100644 --- a/src/conformance/conformance_test/test_XR_EXT_debug_utils.cpp +++ b/src/conformance/conformance_test/test_XR_EXT_debug_utils.cpp @@ -796,9 +796,6 @@ namespace Conformance AutoBasicSession::createSession | AutoBasicSession::createSpaces | AutoBasicSession::createSwapchains, instance); FrameIterator frameIterator(&session); - auto timeout = (globalData.options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - // Create a label struct for initial testing XrDebugUtilsLabelEXT first_label = {XR_TYPE_DEBUG_UTILS_LABEL_EXT}; first_label.labelName = first_individual_label_name; @@ -862,8 +859,7 @@ namespace Conformance // Begin the session now. { - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_READY, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_READY); XrSessionBeginInfo session_begin_info = {XR_TYPE_SESSION_BEGIN_INFO}; session_begin_info.primaryViewConfigurationType = GetGlobalData().GetOptions().viewConfigurationValue; @@ -942,8 +938,7 @@ namespace Conformance { REQUIRE_RESULT(XR_SUCCESS, xrRequestExitSession(session)); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); REQUIRE_RESULT(XR_SUCCESS, xrEndSession(session)); } @@ -1062,11 +1057,8 @@ namespace Conformance AutoBasicInstance instance({XR_EXT_DEBUG_UTILS_EXTENSION_NAME}); AutoBasicSession session(AutoBasicSession::createSession, instance); - // Wait until the runtime is ready for us to begin a session - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_READY, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_READY); // Must call extension functions through a function pointer: diff --git a/src/conformance/conformance_test/test_XR_EXT_eye_gaze_interaction.cpp b/src/conformance/conformance_test/test_XR_EXT_eye_gaze_interaction.cpp index e62710a1..19b20bbf 100644 --- a/src/conformance/conformance_test/test_XR_EXT_eye_gaze_interaction.cpp +++ b/src/conformance/conformance_test/test_XR_EXT_eye_gaze_interaction.cpp @@ -43,7 +43,7 @@ namespace Conformance MakeSystemPropertiesBoolChecker(XrSystemEyeGazeInteractionPropertiesEXT{XR_TYPE_SYSTEM_EYE_GAZE_INTERACTION_PROPERTIES_EXT}, &XrSystemEyeGazeInteractionPropertiesEXT::supportsEyeGazeInteraction); - TEST_CASE("XR_EXT_eye_gaze_interaction", "[XR_EXT_eye_gaze_interaction][interactive][no_auto]") + TEST_CASE("XR_EXT_eye_gaze_interaction", "[scenario][interactive][no_auto][XR_EXT_eye_gaze_interaction]") { GlobalData& globalData = GetGlobalData(); if (!globalData.IsInstanceExtensionSupported(XR_EXT_EYE_GAZE_INTERACTION_EXTENSION_NAME)) { @@ -373,7 +373,7 @@ namespace Conformance } } - TEST_CASE("XR_EXT_eye_gaze_interaction-interactive_gaze_only", "[XR_EXT_eye_gaze_interaction][scenario][interactive][no_auto]") + TEST_CASE("XR_EXT_eye_gaze_interaction-interactive_gaze_only", "[scenario][interactive][no_auto][XR_EXT_eye_gaze_interaction]") { GlobalData& globalData = GetGlobalData(); diff --git a/src/conformance/conformance_test/test_XR_EXT_hand_tracking.cpp b/src/conformance/conformance_test/test_XR_EXT_hand_tracking.cpp index e37130fa..adea1a48 100644 --- a/src/conformance/conformance_test/test_XR_EXT_hand_tracking.cpp +++ b/src/conformance/conformance_test/test_XR_EXT_hand_tracking.cpp @@ -20,6 +20,7 @@ #include "utilities/system_properties_helper.h" #include "utilities/utils.h" #include +#include #include #include "common/xr_linear.h" @@ -137,10 +138,8 @@ namespace Conformance REQUIRE_RESULT(xrCreateReferenceSpace(session, &localSpaceCreateInfo, &localSpace), XR_SUCCESS); // Wait until the runtime is ready for us to begin a session - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_READY, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_READY); for (auto hand : {LEFT_HAND, RIGHT_HAND}) { std::array, HAND_COUNT> jointLocations; @@ -172,18 +171,12 @@ namespace Conformance // the returned radius must be a positive value. REQUIRE(jointLocations[hand][i].radius > 0); - // If an XrHandJointVelocitiesEXT structure is chained to XrHandJointLocationsEXT::next, - // the returned XrHandJointLocationsEXT::isActive is true, and the velocity is observed - // or can be calculated by the runtime, the runtime must fill in the linear velocity of - // each hand joint within the reference frame of baseSpace and set the - // XR_SPACE_VELOCITY_LINEAR_VALID_BIT. - // Similarly, if an XrHandJointVelocitiesEXT structure is chained to - // XrHandJointLocationsEXT::next, the returned XrHandJointLocationsEXT::isActive is true, - // and the angular velocity is observed or can be calculated by the runtime, the runtime - // must fill in the angular velocity of each joint within the reference frame of baseSpace - // and set the XR_SPACE_VELOCITY_ANGULAR_VALID_BIT. - REQUIRE((jointVelocities[hand][i].velocityFlags & XR_SPACE_VELOCITY_LINEAR_VALID_BIT) != 0); - REQUIRE((jointVelocities[hand][i].velocityFlags & XR_SPACE_VELOCITY_ANGULAR_VALID_BIT) != 0); + // From https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#_locate_hand_joints + // the velocity is observed or can be calculated by the runtime, the runtime must + // fill in the linear velocity of each hand joint within the reference frame of baseSpace + // and set the XR_SPACE_VELOCITY_LINEAR_VALID_BIT. + // So we cannot validate the jointVelocities flags XR_SPACE_VELOCITY_LINEAR_VALID_BIT + // or XR_SPACE_VELOCITY_ANGULAR_VALID_BIT. } else { // If the returned isActive is false, it indicates the hand tracker did not detect the hand @@ -207,10 +200,8 @@ namespace Conformance REQUIRE_RESULT(xrCreateReferenceSpace(session, &localSpaceCreateInfo, &localSpace), XR_SUCCESS); // Wait until the runtime is ready for us to begin a session - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_READY, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_READY); // The application must input jointCount as described by the XrHandJointSetEXT when creating the XrHandTrackerEXT. // Otherwise, the runtime must return XR_ERROR_VALIDATION_FAILURE. @@ -328,6 +319,74 @@ namespace Conformance locateInfo.baseSpace = localSpace; locateInfo.time = frameState.predictedDisplayTime; REQUIRE(XR_SUCCESS == xrLocateHandJointsEXT(handTracker[hand], &locateInfo, &locations)); + + if (locations.isActive) { + const auto& wrist = jointLocations[hand][XR_HAND_JOINT_WRIST_EXT]; + const auto& palm = jointLocations[hand][XR_HAND_JOINT_PALM_EXT]; + const auto& middleMetacarpal = jointLocations[hand][XR_HAND_JOINT_MIDDLE_METACARPAL_EXT]; + const auto& middleProximal = jointLocations[hand][XR_HAND_JOINT_MIDDLE_PROXIMAL_EXT]; + + // Check if the palm joint is located correctly for each hand. + if ((palm.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 && + (middleMetacarpal.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0 && + (middleProximal.locationFlags & XR_SPACE_LOCATION_POSITION_VALID_BIT) != 0) { + + // The palm joint is located at the center of the middle finger’s metacarpal bone. + XrPosef expectedPalmPose; + XrVector3f_Lerp(&expectedPalmPose.position, &middleMetacarpal.pose.position, &middleProximal.pose.position, 0.5f); + REQUIRE_THAT(palm.pose.position.x, Catch::Matchers::WithinRel(expectedPalmPose.position.x)); + REQUIRE_THAT(palm.pose.position.y, Catch::Matchers::WithinRel(expectedPalmPose.position.y)); + REQUIRE_THAT(palm.pose.position.z, Catch::Matchers::WithinRel(expectedPalmPose.position.z)); + } + + // Check the palm orientation for each hand if we have valid orientation. + if ((palm.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0 && + (middleMetacarpal.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0) { + + // The backward (+Z) direction is parallel to the middle finger’s metacarpal bone, and points away from the + // fingertips. + XrVector3f zAxis{0, 0, 1.0f}; + XrVector3f palmZAxis, middleMetacarpalZAxis; + XrQuaternionf_RotateVector3f(&palmZAxis, &palm.pose.orientation, &zAxis); + XrQuaternionf_RotateVector3f(&middleMetacarpalZAxis, &middleMetacarpal.pose.orientation, &zAxis); + REQUIRE_THAT(XrVector3f_Dot(&palmZAxis, &middleMetacarpalZAxis), Catch::Matchers::WithinRel(1.0f)); + + // The up (+Y) direction is perpendicular to palm surface and pointing towards the back of the hand. + // We can compare this to the +Y axis of the middle metacarpal bone to check gross direction. + XrVector3f yAxis{0, 1.0f, 0}; + XrVector3f palmYAxis, middleMetacarpalYAxis; + XrQuaternionf_RotateVector3f(&palmYAxis, &palm.pose.orientation, &yAxis); + XrQuaternionf_RotateVector3f(&middleMetacarpalYAxis, &middleMetacarpal.pose.orientation, &yAxis); + REQUIRE_THAT(XrVector3f_Dot(&palmYAxis, &middleMetacarpalYAxis), Catch::Matchers::WithinRel(1.0f, 0.1f)); + + // The X direction is perpendicular to the Y and Z directions and follows the right hand rule. + XrVector3f xAxis{0, 1.0f, 0}; + XrVector3f palmXAxis, middleMetacarpalXAxis; + XrQuaternionf_RotateVector3f(&palmXAxis, &palm.pose.orientation, &xAxis); + XrQuaternionf_RotateVector3f(&middleMetacarpalXAxis, &middleMetacarpal.pose.orientation, &xAxis); + REQUIRE_THAT(XrVector3f_Dot(&palmXAxis, &middleMetacarpalXAxis), Catch::Matchers::WithinRel(1.0f, 0.1f)); + } + + // Check the orientation of the wrist pose is correct for each hand, we can only reliably test the +Z direction + // programmatically. + if ((wrist.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0 && + (middleMetacarpal.locationFlags & XR_SPACE_LOCATION_ORIENTATION_VALID_BIT) != 0) { + + // The (wrist) backward (+Z) direction is parallel to the line from wrist joint to middle finger metacarpal joint, + // and points away from the fingertips. + XrVector3f zAxis{0, 0, 1.0f}; + XrVector3f wristZAxis, fromMiddleMetacarpalToWrist; + XrQuaternionf_RotateVector3f(&wristZAxis, &wrist.pose.orientation, &zAxis); + XrVector3f_Sub(&fromMiddleMetacarpalToWrist, &wrist.pose.position, &middleMetacarpal.pose.position); + XrVector3f_Normalize(&fromMiddleMetacarpalToWrist); + // 0.1 here represents 26 degrees variance between these orientations; which is more than can reasonable be + // explained by numerical inaccuracy... + REQUIRE_THAT(XrVector3f_Dot(&wristZAxis, &fromMiddleMetacarpalToWrist), Catch::Matchers::WithinRel(1.0f, 0.1f)); + if (XrVector3f_Dot(&wristZAxis, &fromMiddleMetacarpalToWrist) > 0.03) { + WARN("Variance between wrist z axis orientation and metacarpal greater than 14 degrees!"); + } + } + } } // Check if user has requested to complete the test. diff --git a/src/conformance/conformance_test/test_XR_EXT_local_floor.cpp b/src/conformance/conformance_test/test_XR_EXT_local_floor.cpp index 0207a3cb..3c80ca86 100644 --- a/src/conformance/conformance_test/test_XR_EXT_local_floor.cpp +++ b/src/conformance/conformance_test/test_XR_EXT_local_floor.cpp @@ -70,17 +70,12 @@ namespace Conformance AutoBasicSession::createSwapchains | AutoBasicSession::createSpaces, instance); - // how long the test should wait for the app to get focus: 10 seconds in release, infinite in debug builds. - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - // Get frames iterating to the point of app focused state. This will draw frames along the way. FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // Render one frame to get a predicted display time for the xrLocateSpace calls. - runResult = frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); // If stage space is defined, then LOCAL_FLOOR height off the floor must match STAGE diff --git a/src/conformance/conformance_test/test_XR_EXT_palm_pose.cpp b/src/conformance/conformance_test/test_XR_EXT_palm_pose.cpp index 3d2cb6c5..7955250a 100644 --- a/src/conformance/conformance_test/test_XR_EXT_palm_pose.cpp +++ b/src/conformance/conformance_test/test_XR_EXT_palm_pose.cpp @@ -472,14 +472,9 @@ namespace Conformance AutoBasicSession::createSwapchains, instance); - // how long the test should wait for the app to get focus: 10 seconds in release, infinite in debug builds. - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - // Get frames iterating to the point of app focused state. This will draw frames along the way. FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); XrSessionActionSetsAttachInfo attachInfo{XR_TYPE_SESSION_ACTION_SETS_ATTACH_INFO}; attachInfo.actionSets = &actionSet; diff --git a/src/conformance/conformance_test/test_XR_EXT_performance_settings.cpp b/src/conformance/conformance_test/test_XR_EXT_performance_settings.cpp deleted file mode 100644 index ee44c0dc..00000000 --- a/src/conformance/conformance_test/test_XR_EXT_performance_settings.cpp +++ /dev/null @@ -1,28 +0,0 @@ -// Copyright (c) 2019-2023, The Khronos Group Inc. -// -// SPDX-License-Identifier: Apache-2.0 -// -// 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. - -#include - -namespace Conformance -{ - - TEST_CASE("XR_EXT_performance_settings", "") - { - // XrResult xrPerfSettingsSetPerformanceLevelEXT(XrSession session, XrPerfSettingsDomainEXT domain, - // XrPerfSettingsLevelEXT level); - } - -} // namespace Conformance diff --git a/src/conformance/conformance_test/test_XR_KHR_D3D11_enable.cpp b/src/conformance/conformance_test/test_XR_KHR_D3D11_enable.cpp index bff5dd31..afe4f16e 100644 --- a/src/conformance/conformance_test/test_XR_KHR_D3D11_enable.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_D3D11_enable.cpp @@ -43,8 +43,10 @@ namespace Conformance SKIP(XR_KHR_D3D11_ENABLE_EXTENSION_NAME " not enabled"); } - AutoBasicInstance instance{AutoBasicInstance::createSystemId}; - XrSystemId systemId = instance.systemId; + AutoBasicInstance instance; + + XrSystemId systemId{XR_NULL_SYSTEM_ID}; + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); // Create the graphics plugin we'll need to exercise session create functionality below. std::shared_ptr graphicsPlugin; @@ -57,12 +59,15 @@ namespace Conformance // We'll use this XrSession and XrSessionCreateInfo for testing below. XrSession session = XR_NULL_HANDLE_CPP; - XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO, nullptr, 0, systemId}; + + XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO}; + sessionCreateInfo.systemId = systemId; + CleanupSessionOnScopeExit cleanup(session); SECTION("No graphics binding") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = nullptr; CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); cleanup.Destroy(); @@ -71,7 +76,7 @@ namespace Conformance SECTION("NULL D3D11 device") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingD3D11KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.device = nullptr; @@ -81,10 +86,39 @@ namespace Conformance graphicsPlugin->ShutdownDevice(); } + SECTION("Valid session after bad session") + { + // Pass invalid binding the first time + { + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingD3D11KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + graphicsBinding.device = nullptr; + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + + // Using the same instance pass valid binding the second time + { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingD3D11KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + } + SECTION("Singlethreaded D3D11 device") { // Verify that the runtime supports D3D11_CREATE_DEVICE_SINGLETHREADED. - graphicsPlugin->InitializeDevice(instance, systemId, true, D3D11_CREATE_DEVICE_SINGLETHREADED); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true, D3D11_CREATE_DEVICE_SINGLETHREADED)); XrGraphicsBindingD3D11KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); @@ -108,11 +142,28 @@ namespace Conformance } }; - graphicsPlugin->InitializeDevice(instance, systemId, true); + auto xrGetD3D11GraphicsRequirementsKHR = + GetInstanceExtensionFunction(instance, "xrGetD3D11GraphicsRequirementsKHR"); + + XrGraphicsRequirementsD3D11KHR referenceGraphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR}; + REQUIRE(xrGetD3D11GraphicsRequirementsKHR(instance, systemId, &referenceGraphicsRequirements) == XR_SUCCESS); + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingD3D11KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); for (int i = 0; i < 3; ++i) { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + XrGraphicsRequirementsD3D11KHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D11_KHR}; + REQUIRE(xrGetD3D11GraphicsRequirementsKHR(instance, systemId, &graphicsRequirements) == XR_SUCCESS); + + // We expect that the graphics requirements don't change... + REQUIRE(referenceGraphicsRequirements.adapterLuid.HighPart == graphicsRequirements.adapterLuid.HighPart); + REQUIRE(referenceGraphicsRequirements.adapterLuid.LowPart == graphicsRequirements.adapterLuid.LowPart); + REQUIRE(referenceGraphicsRequirements.minFeatureLevel == graphicsRequirements.minFeatureLevel); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); createSwapchains(graphicsPlugin, session); CHECK(xrDestroySession(session) == XR_SUCCESS); diff --git a/src/conformance/conformance_test/test_XR_KHR_D3D12_enable.cpp b/src/conformance/conformance_test/test_XR_KHR_D3D12_enable.cpp index 7bd3e69a..b815305c 100644 --- a/src/conformance/conformance_test/test_XR_KHR_D3D12_enable.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_D3D12_enable.cpp @@ -42,8 +42,10 @@ namespace Conformance SKIP(XR_KHR_D3D12_ENABLE_EXTENSION_NAME " not enabled"); } - AutoBasicInstance instance{AutoBasicInstance::createSystemId}; - XrSystemId systemId = instance.systemId; + AutoBasicInstance instance; + + XrSystemId systemId{XR_NULL_SYSTEM_ID}; + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); // Create the graphics plugin we'll need to exercise session create functionality below. std::shared_ptr graphicsPlugin; @@ -56,12 +58,15 @@ namespace Conformance // We'll use this XrSession and XrSessionCreateInfo for testing below. XrSession session = XR_NULL_HANDLE_CPP; - XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO, nullptr, 0, systemId}; + + XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO}; + sessionCreateInfo.systemId = systemId; + CleanupSessionOnScopeExit cleanup(session); SECTION("No graphics binding") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = nullptr; CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); cleanup.Destroy(); @@ -70,8 +75,9 @@ namespace Conformance SECTION("NULL D3D12 device") { - graphicsPlugin->InitializeDevice(instance, systemId, true); - XrGraphicsBindingD3D12KHR graphicsBinding = {XR_TYPE_GRAPHICS_BINDING_D3D12_KHR, nullptr}; + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingD3D12KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.device = nullptr; sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); @@ -81,6 +87,35 @@ namespace Conformance graphicsPlugin->ShutdownDevice(); } + SECTION("Valid session after bad session") + { + // Pass invalid binding the first time + { + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingD3D12KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + graphicsBinding.device = nullptr; + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + + // Using the same instance pass valid binding the second time + { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingD3D12KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + } + SECTION("Multiple session with same device") { auto createSwapchains = [](std::shared_ptr graphicsPlugin, XrSession session) { @@ -96,11 +131,28 @@ namespace Conformance } }; - graphicsPlugin->InitializeDevice(instance, systemId, true); + auto xrGetD3D12GraphicsRequirementsKHR = + GetInstanceExtensionFunction(instance, "xrGetD3D12GraphicsRequirementsKHR"); + + XrGraphicsRequirementsD3D12KHR referenceGraphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR}; + REQUIRE(xrGetD3D12GraphicsRequirementsKHR(instance, systemId, &referenceGraphicsRequirements) == XR_SUCCESS); + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingD3D12KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); for (int i = 0; i < 3; ++i) { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + XrGraphicsRequirementsD3D12KHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_D3D12_KHR}; + REQUIRE(xrGetD3D12GraphicsRequirementsKHR(instance, systemId, &graphicsRequirements) == XR_SUCCESS); + + // We expect that the graphics requirements don't change... + REQUIRE(referenceGraphicsRequirements.adapterLuid.HighPart == graphicsRequirements.adapterLuid.HighPart); + REQUIRE(referenceGraphicsRequirements.adapterLuid.LowPart == graphicsRequirements.adapterLuid.LowPart); + REQUIRE(referenceGraphicsRequirements.minFeatureLevel == graphicsRequirements.minFeatureLevel); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); createSwapchains(graphicsPlugin, session); CHECK(xrDestroySession(session) == XR_SUCCESS); diff --git a/src/conformance/conformance_test/test_XR_KHR_OpenGL_ES_enable.cpp b/src/conformance/conformance_test/test_XR_KHR_OpenGL_ES_enable.cpp index 429e460c..2d31abe0 100644 --- a/src/conformance/conformance_test/test_XR_KHR_OpenGL_ES_enable.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_OpenGL_ES_enable.cpp @@ -39,8 +39,10 @@ namespace Conformance SKIP(XR_KHR_OPENGL_ES_ENABLE_EXTENSION_NAME " not enabled"); } - AutoBasicInstance instance{AutoBasicInstance::createSystemId}; - XrSystemId systemId = instance.systemId; + AutoBasicInstance instance; + + XrSystemId systemId{XR_NULL_SYSTEM_ID}; + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); // Create the graphics plugin we'll need to exercise session create functionality below. std::shared_ptr graphicsPlugin; @@ -53,12 +55,15 @@ namespace Conformance // We'll use this XrSession and XrSessionCreateInfo for testing below. XrSession session = XR_NULL_HANDLE_CPP; - XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO, nullptr, 0, systemId}; + + XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO}; + sessionCreateInfo.systemId = systemId; + CleanupSessionOnScopeExit cleanup(session); SECTION("No graphics binding") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = nullptr; CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); cleanup.Destroy(); @@ -69,7 +74,7 @@ namespace Conformance // tests related to the graphics binding are OS specific SECTION("NULL context: context is NULL") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.context = EGL_NO_CONTEXT; @@ -78,6 +83,35 @@ namespace Conformance cleanup.Destroy(); graphicsPlugin->ShutdownDevice(); } + + SECTION("Valid session after bad session") + { + // Pass invalid binding the first time + { + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + graphicsBinding.context = EGL_NO_CONTEXT; + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + + // Using the same instance pass valid binding the second time + { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); + cleanup.Destroy(); + } + } + SECTION("Multiple session with same device") { auto createSwapchains = [](std::shared_ptr graphicsPlugin, XrSession session) { @@ -93,11 +127,27 @@ namespace Conformance } }; - graphicsPlugin->InitializeDevice(instance, systemId, true); + auto xrGetOpenGLESGraphicsRequirementsKHR = + GetInstanceExtensionFunction(instance, "xrGetOpenGLESGraphicsRequirementsKHR"); + + XrGraphicsRequirementsOpenGLESKHR referenceGraphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR}; + REQUIRE(xrGetOpenGLESGraphicsRequirementsKHR(instance, systemId, &referenceGraphicsRequirements) == XR_SUCCESS); + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingOpenGLESAndroidKHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); for (int i = 0; i < 3; ++i) { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + XrGraphicsRequirementsOpenGLESKHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_ES_KHR}; + REQUIRE(xrGetOpenGLESGraphicsRequirementsKHR(instance, systemId, &graphicsRequirements) == XR_SUCCESS); + + // We expect that the graphics requirements don't change... + REQUIRE(referenceGraphicsRequirements.maxApiVersionSupported == graphicsRequirements.maxApiVersionSupported); + REQUIRE(referenceGraphicsRequirements.minApiVersionSupported == graphicsRequirements.minApiVersionSupported); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); createSwapchains(graphicsPlugin, session); CHECK(xrDestroySession(session) == XR_SUCCESS); diff --git a/src/conformance/conformance_test/test_XR_KHR_OpenGL_enable.cpp b/src/conformance/conformance_test/test_XR_KHR_OpenGL_enable.cpp index 490500d6..bad989d0 100644 --- a/src/conformance/conformance_test/test_XR_KHR_OpenGL_enable.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_OpenGL_enable.cpp @@ -40,8 +40,10 @@ namespace Conformance SKIP(XR_KHR_OPENGL_ENABLE_EXTENSION_NAME " not enabled"); } - AutoBasicInstance instance{AutoBasicInstance::createSystemId}; - XrSystemId systemId = instance.systemId; + AutoBasicInstance instance; + + XrSystemId systemId{XR_NULL_SYSTEM_ID}; + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); // Create the graphics plugin we'll need to exercise session create functionality below. std::shared_ptr graphicsPlugin; @@ -54,12 +56,15 @@ namespace Conformance // We'll use this XrSession and XrSessionCreateInfo for testing below. XrSession session = XR_NULL_HANDLE_CPP; - XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO, nullptr, 0, systemId}; + + XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO}; + sessionCreateInfo.systemId = systemId; + CleanupSessionOnScopeExit cleanup(session); SECTION("No graphics binding") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = nullptr; CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); cleanup.Destroy(); @@ -70,7 +75,7 @@ namespace Conformance // tests related to the graphics binding are OS specific SECTION("NULL context: both are NULL") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingOpenGLWin32KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.hDC = nullptr; @@ -80,9 +85,10 @@ namespace Conformance cleanup.Destroy(); graphicsPlugin->ShutdownDevice(); } + SECTION("NULL context: DC is NULL") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingOpenGLWin32KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.hDC = nullptr; @@ -91,9 +97,10 @@ namespace Conformance cleanup.Destroy(); graphicsPlugin->ShutdownDevice(); } + SECTION("NULL context: GLRC is NULL") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingOpenGLWin32KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.hGLRC = nullptr; @@ -102,11 +109,41 @@ namespace Conformance cleanup.Destroy(); graphicsPlugin->ShutdownDevice(); } + + SECTION("Valid session after bad session") + { + // Pass invalid binding the first time + { + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingOpenGLWin32KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + graphicsBinding.hDC = nullptr; + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + + // Using the same instance pass valid binding the second time + { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingOpenGLWin32KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + } + // This test dies in the tear-down wglMakeCurrent in ksGpuContext_Destroy, turn it off for now. #if 0 SECTION("Context for runtime is not current") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = graphicsPlugin->GetGraphicsBinding(); // Exercise presence of unrecognized extensions, which the runtime should ignore. @@ -151,11 +188,27 @@ namespace Conformance } }; - graphicsPlugin->InitializeDevice(instance, systemId, true); + auto xrGetOpenGLGraphicsRequirementsKHR = + GetInstanceExtensionFunction(instance, "xrGetOpenGLGraphicsRequirementsKHR"); + + XrGraphicsRequirementsOpenGLKHR referenceGraphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR}; + REQUIRE(xrGetOpenGLGraphicsRequirementsKHR(instance, systemId, &referenceGraphicsRequirements) == XR_SUCCESS); + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingOpenGLWin32KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); for (int i = 0; i < 3; ++i) { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + XrGraphicsRequirementsOpenGLKHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_OPENGL_KHR}; + REQUIRE(xrGetOpenGLGraphicsRequirementsKHR(instance, systemId, &graphicsRequirements) == XR_SUCCESS); + + // We expect that the graphics requirements don't change... + REQUIRE(referenceGraphicsRequirements.maxApiVersionSupported == graphicsRequirements.maxApiVersionSupported); + REQUIRE(referenceGraphicsRequirements.minApiVersionSupported == graphicsRequirements.minApiVersionSupported); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); createSwapchains(graphicsPlugin, session); CHECK(xrDestroySession(session) == XR_SUCCESS); diff --git a/src/conformance/conformance_test/test_XR_KHR_composition_layer_cube.cpp b/src/conformance/conformance_test/test_XR_KHR_composition_layer_cube.cpp index a9ba932f..5cf450ae 100644 --- a/src/conformance/conformance_test/test_XR_KHR_composition_layer_cube.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_composition_layer_cube.cpp @@ -46,8 +46,6 @@ namespace Conformance } auto graphicsPlugin = globalData.GetGraphicsPlugin(); - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); AutoBasicInstance instance({XR_KHR_COMPOSITION_LAYER_CUBE_EXTENSION_NAME}); AutoBasicSession session(AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | @@ -55,8 +53,7 @@ namespace Conformance instance); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // At this point we have a session ready for us to generate custom frames for. // The current XrSessionState is XR_SESSION_STATE_FOCUSED. @@ -104,7 +101,7 @@ namespace Conformance // } XrCompositionLayerCubeKHR; for (const XrQuaternionf& orientation : orientationTestArray) { - runResult = frameIterator.PrepareSubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.PrepareSubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); // Set up our cubemap layer. We always make two, and some of the time we @@ -150,7 +147,6 @@ namespace Conformance result = xrRequestExitSession(session.GetSession()); CHECK(result == XR_SUCCESS); - runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - CHECK(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); } } // namespace Conformance diff --git a/src/conformance/conformance_test/test_XR_KHR_composition_layer_cylinder.cpp b/src/conformance/conformance_test/test_XR_KHR_composition_layer_cylinder.cpp index 624d320c..4013bde9 100644 --- a/src/conformance/conformance_test/test_XR_KHR_composition_layer_cylinder.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_composition_layer_cylinder.cpp @@ -43,17 +43,13 @@ namespace Conformance SKIP("Test run not using graphics plugin"); } - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - AutoBasicInstance instance({XR_KHR_COMPOSITION_LAYER_CYLINDER_EXTENSION_NAME}); AutoBasicSession session(AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | AutoBasicSession::createSpaces, instance); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // At this point we have a session ready for us to generate custom frames for. // The current XrSessionState is XR_SESSION_STATE_FOCUSED. @@ -71,7 +67,7 @@ namespace Conformance std::array radiusTestArray{0, 1.f, INFINITY}; // Spec explicitly supports radius 0 and +infinity for (float radius : radiusTestArray) { - runResult = frameIterator.PrepareSubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.PrepareSubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); // Set up our cylinder layer. We always make two, and some of the time we @@ -119,7 +115,6 @@ namespace Conformance result = xrRequestExitSession(session.GetSession()); CHECK(result == XR_SUCCESS); - runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - CHECK(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); } } // namespace Conformance diff --git a/src/conformance/conformance_test/test_XR_KHR_composition_layer_depth.cpp b/src/conformance/conformance_test/test_XR_KHR_composition_layer_depth.cpp index 0b1d18ed..445f70b6 100644 --- a/src/conformance/conformance_test/test_XR_KHR_composition_layer_depth.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_composition_layer_depth.cpp @@ -42,8 +42,6 @@ namespace Conformance auto graphicsPlugin = globalData.GetGraphicsPlugin(); - auto timeout = (globalData.options.debugMode ? 3600s : 10s); - CAPTURE(timeout); AutoBasicInstance instance({XR_KHR_COMPOSITION_LAYER_DEPTH_EXTENSION_NAME}); AutoBasicSession session(AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | AutoBasicSession::createSpaces, @@ -51,8 +49,7 @@ namespace Conformance REQUIRE(session.IsValidHandle()); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // At this point we have a session ready for us to generate custom frames for. // The current XrSessionState is XR_SESSION_STATE_FOCUSED. @@ -98,7 +95,7 @@ namespace Conformance DepthVaryingInfo{0.0f, 1.0f, std::numeric_limits::max(), minimum_useful_z}}; for (const DepthVaryingInfo& varyingInfo : varyingInfoTestArray) { - runResult = frameIterator.PrepareSubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.PrepareSubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); { @@ -148,8 +145,7 @@ namespace Conformance CHECK(result == XR_SUCCESS); } - runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - CHECK(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); for (const XrSwapchain& swapchain : depthSwapchains) { XrResult result = xrDestroySwapchain(swapchain); diff --git a/src/conformance/conformance_test/test_XR_KHR_composition_layer_equirect.cpp b/src/conformance/conformance_test/test_XR_KHR_composition_layer_equirect.cpp index 64deccc5..3c30ee33 100644 --- a/src/conformance/conformance_test/test_XR_KHR_composition_layer_equirect.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_composition_layer_equirect.cpp @@ -46,8 +46,6 @@ namespace Conformance } auto graphicsPlugin = globalData.GetGraphicsPlugin(); - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); AutoBasicInstance instance({XR_KHR_COMPOSITION_LAYER_EQUIRECT_EXTENSION_NAME}); AutoBasicSession session(AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | @@ -55,8 +53,7 @@ namespace Conformance instance); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // At this point we have a session ready for us to generate custom frames for. // The current XrSessionState is XR_SESSION_STATE_FOCUSED. @@ -109,7 +106,7 @@ namespace Conformance }; for (const XrQuaternionf& orientation : orientationTestArray) { - runResult = frameIterator.PrepareSubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.PrepareSubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); // Set up our equirect layer. We always make two, and some of the time we @@ -173,7 +170,6 @@ namespace Conformance result = xrRequestExitSession(session.GetSession()); CHECK(result == XR_SUCCESS); - runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - CHECK(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); } } // namespace Conformance diff --git a/src/conformance/conformance_test/test_XR_KHR_convert_timespec_time.cpp b/src/conformance/conformance_test/test_XR_KHR_convert_timespec_time.cpp index fa8718c9..b7a2d4de 100644 --- a/src/conformance/conformance_test/test_XR_KHR_convert_timespec_time.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_convert_timespec_time.cpp @@ -134,13 +134,12 @@ namespace Conformance CAPTURE(timespecBefore); // Wait until the runtime is ready for us to begin a session - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // Submit a frame and query the time for the next frame - frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); + REQUIRE(runResult == FrameIterator::RunResult::Success); XrTime nextFrameTime = frameIterator.frameState.predictedDisplayTime; // predicted display time is required to be a time in the future so it is fair to assume it is after now. diff --git a/src/conformance/conformance_test/test_XR_KHR_headless.cpp b/src/conformance/conformance_test/test_XR_KHR_headless.cpp deleted file mode 100644 index 2c266c43..00000000 --- a/src/conformance/conformance_test/test_XR_KHR_headless.cpp +++ /dev/null @@ -1,72 +0,0 @@ -// Copyright (c) 2019-2023, The Khronos Group Inc. -// -// SPDX-License-Identifier: Apache-2.0 -// -// 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. - -#include "utilities/utils.h" -#include "conformance_utils.h" -#include "conformance_framework.h" -#include -#include -#include -#include -#include -#include -#include - -namespace Conformance -{ - TEST_CASE("XR_KHR_headless", "") - { -#ifdef XR_KHR_headless - GlobalData& globalData = GetGlobalData(); - - // When this extension is enabled, the behavior of existing functions that interact with the - // graphics subsystem is altered. When calling the function xrCreateSession with no graphics - // binding structure, the session will be created as headless. - // - // When operating with a headless session, the function xrEnumerateSwapchainFormats must return - // an empty list of formats. Calls to functions xrCreateSwapchain, xrDestroySwapchain, - // xrAcquireSwapchainImage, xrWaitFrame are invalid. All other functions, including those - // related to tracking, input and haptics, are unaffected. - if (!globalData.IsInstanceExtensionEnabled("XR_KHR_headless")) { - return; - } - - AutoBasicSession session(AutoBasicSession::createSession | AutoBasicSession::skipGraphics); - - SECTION("xrEnumerateSwapchainFormats should return XR_SUCCESS but zero formats.") - { - uint32_t countOutput = UINT32_MAX; - REQUIRE(xrEnumerateSwapchainFormats(session, 0, &countOutput, nullptr) == XR_SUCCESS); - REQUIRE(countOutput == 0); - - int64_t formats[100]; - countOutput = UINT32_MAX; - REQUIRE(xrEnumerateSwapchainFormats(session, sizeof(formats) / sizeof(formats[0]), &countOutput, formats) == XR_SUCCESS); - REQUIRE(countOutput == 0); - } - - // Calls to functions xrCreateSwapchain, xrDestroySwapchain, xrAcquireSwapchainImage, - // xrWaitFrame are invalid, but there isn't a specification for what happens when called. - - // We begin a session and call valid session functions. - XrSessionBeginInfo sessionBeginInfo{XR_TYPE_SESSION_BEGIN_INFO, nullptr, globalData.options.viewConfigurationValue}; - REQUIRE_RESULT_UNQUALIFIED_SUCCESS(xrBeginSession(session, &sessionBeginInfo)); - - // To do: call input and tracking functions here. - REQUIRE_RESULT_UNQUALIFIED_SUCCESS(xrEndSession(session)); -#endif // XR_KHR_headless - } -} // namespace Conformance diff --git a/src/conformance/conformance_test/test_XR_KHR_visibility_mask.cpp b/src/conformance/conformance_test/test_XR_KHR_visibility_mask.cpp index 5a2fe5d5..2fd3a31e 100644 --- a/src/conformance/conformance_test/test_XR_KHR_visibility_mask.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_visibility_mask.cpp @@ -278,8 +278,11 @@ namespace Conformance { MeshHandle mesh; bool meshCoversHiddenArea = maskType == XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR; - XrColor4f color = meshCoversHiddenArea ? BrightRed : DarkSlateGrey; - XrColor4f bgColor = meshCoversHiddenArea ? DarkSlateGrey : BrightRed; + + XrColor4f normalBgColor = GetGlobalData().GetClearColorForBackground(); + + XrColor4f color = meshCoversHiddenArea ? BrightRed : normalBgColor; + XrColor4f bgColor = meshCoversHiddenArea ? normalBgColor : BrightRed; XrVisibilityMaskKHR visibilityMask{XR_TYPE_VISIBILITY_MASK_KHR}; @@ -327,7 +330,7 @@ namespace Conformance return {mesh, bgColor}; } - TEST_CASE("XR_KHR_visibility_mask-interactive", "[XR_KHR_visibility_mask][interactive][no_auto]") + TEST_CASE("XR_KHR_visibility_mask-interactive", "[scenario][interactive][no_auto][XR_KHR_visibility_mask]") { // successcodes="XR_SUCCESS,XR_SESSION_LOSS_PENDING" // errorcodes="XR_ERROR_HANDLE_INVALID,XR_ERROR_INSTANCE_LOST,XR_ERROR_RUNTIME_FAILURE,XR_ERROR_VALIDATION_FAILURE, @@ -379,7 +382,7 @@ namespace Conformance SKIP("No vertices returned, so no visibility mask available in this system."); } - std::vector bgColors{meshProjectionLayerHelper.GetViewCount(), DarkSlateGrey}; + std::vector bgColors{meshProjectionLayerHelper.GetViewCount(), Colors::Green}; // should be overwritten before render // const auto maskTypes = {XR_VISIBILITY_MASK_TYPE_HIDDEN_TRIANGLE_MESH_KHR, XR_VISIBILITY_MASK_TYPE_VISIBLE_TRIANGLE_MESH_KHR, // XR_VISIBILITY_MASK_TYPE_LINE_LOOP_KHR}; diff --git a/src/conformance/conformance_test/test_XR_KHR_vulkan_enable.cpp b/src/conformance/conformance_test/test_XR_KHR_vulkan_enable.cpp index fb12e8cc..3a6cc0f8 100644 --- a/src/conformance/conformance_test/test_XR_KHR_vulkan_enable.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_vulkan_enable.cpp @@ -40,8 +40,10 @@ namespace Conformance SKIP(XR_KHR_VULKAN_ENABLE_EXTENSION_NAME " not enabled"); } - AutoBasicInstance instance{AutoBasicInstance::createSystemId}; - XrSystemId systemId = instance.systemId; + AutoBasicInstance instance; + + XrSystemId systemId{XR_NULL_SYSTEM_ID}; + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); // Create the graphics plugin we'll need to exercise session create functionality below. std::shared_ptr graphicsPlugin; @@ -54,12 +56,15 @@ namespace Conformance // We'll use this XrSession and XrSessionCreateInfo for testing below. XrSession session = XR_NULL_HANDLE_CPP; - XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO, nullptr, 0, systemId}; + + XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO}; + sessionCreateInfo.systemId = systemId; + CleanupSessionOnScopeExit cleanup(session); SECTION("No graphics binding") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = nullptr; CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); cleanup.Destroy(); @@ -68,7 +73,7 @@ namespace Conformance SECTION("Valid vulkan device") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingVulkanKHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); @@ -79,7 +84,7 @@ namespace Conformance SECTION("NULL vulkan device") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingVulkanKHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.device = VK_NULL_HANDLE; @@ -89,6 +94,35 @@ namespace Conformance graphicsPlugin->ShutdownDevice(); } + SECTION("Valid session after bad session") + { + // Pass invalid binding the first time + { + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingVulkanKHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + graphicsBinding.device = VK_NULL_HANDLE; + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + + // Using the same instance pass valid binding the second time + { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingVulkanKHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + } + SECTION("Multiple session with same device") { auto createSwapchains = [](std::shared_ptr graphicsPlugin, XrSession session) { @@ -104,11 +138,27 @@ namespace Conformance } }; - graphicsPlugin->InitializeDevice(instance, systemId, true); + auto xrGetVulkanGraphicsRequirementsKHR = + GetInstanceExtensionFunction(instance, "xrGetVulkanGraphicsRequirementsKHR"); + + XrGraphicsRequirementsVulkanKHR referenceGraphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR}; + REQUIRE(xrGetVulkanGraphicsRequirementsKHR(instance, systemId, &referenceGraphicsRequirements) == XR_SUCCESS); + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingVulkanKHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); for (int i = 0; i < 3; ++i) { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + XrGraphicsRequirementsVulkanKHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN_KHR}; + REQUIRE(xrGetVulkanGraphicsRequirementsKHR(instance, systemId, &graphicsRequirements) == XR_SUCCESS); + + // We expect that the graphics requirements don't change... + REQUIRE(referenceGraphicsRequirements.maxApiVersionSupported == graphicsRequirements.maxApiVersionSupported); + REQUIRE(referenceGraphicsRequirements.minApiVersionSupported == graphicsRequirements.minApiVersionSupported); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); createSwapchains(graphicsPlugin, session); CHECK(xrDestroySession(session) == XR_SUCCESS); diff --git a/src/conformance/conformance_test/test_XR_KHR_vulkan_enable2.cpp b/src/conformance/conformance_test/test_XR_KHR_vulkan_enable2.cpp index 7c458dd4..6f2b1f62 100644 --- a/src/conformance/conformance_test/test_XR_KHR_vulkan_enable2.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_vulkan_enable2.cpp @@ -40,8 +40,10 @@ namespace Conformance SKIP(XR_KHR_VULKAN_ENABLE2_EXTENSION_NAME " not enabled"); } - AutoBasicInstance instance{AutoBasicInstance::createSystemId}; - XrSystemId systemId = instance.systemId; + AutoBasicInstance instance; + + XrSystemId systemId{XR_NULL_SYSTEM_ID}; + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); // Create the graphics plugin we'll need to exercise session create functionality below. std::shared_ptr graphicsPlugin; @@ -54,12 +56,15 @@ namespace Conformance // We'll use this XrSession and XrSessionCreateInfo for testing below. XrSession session = XR_NULL_HANDLE_CPP; - XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO, nullptr, 0, systemId}; + + XrSessionCreateInfo sessionCreateInfo{XR_TYPE_SESSION_CREATE_INFO}; + sessionCreateInfo.systemId = systemId; + CleanupSessionOnScopeExit cleanup(session); SECTION("No graphics binding") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); sessionCreateInfo.next = nullptr; CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); cleanup.Destroy(); @@ -68,7 +73,7 @@ namespace Conformance SECTION("Valid vulkan device") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingVulkan2KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); @@ -79,7 +84,7 @@ namespace Conformance SECTION("NULL vulkan device") { - graphicsPlugin->InitializeDevice(instance, systemId, true); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingVulkan2KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); graphicsBinding.device = nullptr; @@ -89,6 +94,35 @@ namespace Conformance graphicsPlugin->ShutdownDevice(); } + SECTION("Valid session after bad session") + { + // Pass invalid binding the first time + { + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingVulkan2KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + graphicsBinding.device = nullptr; + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_ERROR_GRAPHICS_DEVICE_INVALID); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + + // Using the same instance pass valid binding the second time + { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); + XrGraphicsBindingVulkan2KHR graphicsBinding = + *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); + sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); + cleanup.Destroy(); + graphicsPlugin->ShutdownDevice(); + } + } + SECTION("Multiple session with same device") { auto createSwapchains = [](std::shared_ptr graphicsPlugin, XrSession session) { @@ -104,11 +138,27 @@ namespace Conformance } }; - graphicsPlugin->InitializeDevice(instance, systemId, true); + auto xrGetVulkanGraphicsRequirements2KHR = + GetInstanceExtensionFunction(instance, "xrGetVulkanGraphicsRequirements2KHR"); + + XrGraphicsRequirementsVulkan2KHR referenceGraphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR}; + REQUIRE(xrGetVulkanGraphicsRequirements2KHR(instance, systemId, &referenceGraphicsRequirements) == XR_SUCCESS); + + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, true)); XrGraphicsBindingVulkan2KHR graphicsBinding = *reinterpret_cast(graphicsPlugin->GetGraphicsBinding()); sessionCreateInfo.next = reinterpret_cast(&graphicsBinding); for (int i = 0; i < 3; ++i) { + REQUIRE(XR_SUCCESS == FindBasicSystem(instance.GetInstance(), &systemId)); + sessionCreateInfo.systemId = systemId; + + XrGraphicsRequirementsVulkan2KHR graphicsRequirements{XR_TYPE_GRAPHICS_REQUIREMENTS_VULKAN2_KHR}; + REQUIRE(xrGetVulkanGraphicsRequirements2KHR(instance, systemId, &graphicsRequirements) == XR_SUCCESS); + + // We expect that the graphics requirements don't change... + REQUIRE(referenceGraphicsRequirements.maxApiVersionSupported == graphicsRequirements.maxApiVersionSupported); + REQUIRE(referenceGraphicsRequirements.minApiVersionSupported == graphicsRequirements.minApiVersionSupported); + CHECK(xrCreateSession(instance, &sessionCreateInfo, &session) == XR_SUCCESS); createSwapchains(graphicsPlugin, session); CHECK(xrDestroySession(session) == XR_SUCCESS); diff --git a/src/conformance/conformance_test/test_XR_KHR_win32_convert_performance_counter_time.cpp b/src/conformance/conformance_test/test_XR_KHR_win32_convert_performance_counter_time.cpp index 78edae70..fb43b0a2 100644 --- a/src/conformance/conformance_test/test_XR_KHR_win32_convert_performance_counter_time.cpp +++ b/src/conformance/conformance_test/test_XR_KHR_win32_convert_performance_counter_time.cpp @@ -121,13 +121,12 @@ namespace Conformance CAPTURE(qpcBefore); // Wait until the runtime is ready for us to begin a session - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // Submit a frame and query the time for the next frame - frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); + REQUIRE(runResult == FrameIterator::RunResult::Success); XrTime nextFrameTime = frameIterator.frameState.predictedDisplayTime; // predicted display time is required to be a time in the future so it is fair to assume it is after now. diff --git a/src/conformance/conformance_test/test_XR_META_performance_metrics.cpp b/src/conformance/conformance_test/test_XR_META_performance_metrics.cpp index 25b63a78..585b95ff 100644 --- a/src/conformance/conformance_test/test_XR_META_performance_metrics.cpp +++ b/src/conformance/conformance_test/test_XR_META_performance_metrics.cpp @@ -85,10 +85,6 @@ namespace Conformance SECTION("Query metrics after xrEndFrame") { - // how long the test should wait for the app to get focus: 10 seconds in release, 1hr in debug builds. - auto timeout = (globalData.options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - // Get a session started. AutoBasicSession session(AutoBasicSession::createInstance | AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | AutoBasicSession::createSpaces, @@ -101,11 +97,10 @@ namespace Conformance // Get frames iterating to the point of app focused state. This will draw frames along the way. FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // Render one frame to some frame stats. - runResult = frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); for (const XrPath& path : paths) { diff --git a/src/conformance/conformance_test/test_actions.cpp b/src/conformance/conformance_test/test_actions.cpp index ce37068f..fdb1132b 100644 --- a/src/conformance/conformance_test/test_actions.cpp +++ b/src/conformance/conformance_test/test_actions.cpp @@ -478,10 +478,7 @@ namespace Conformance CAPTURE(bindingPath); const XrActionType& actionType = inputSourcePathData.Type; -#define ENUM_NAME(e, val) {(XrActionType)val, #e}, - std::map actionTypeToString = {XR_LIST_ENUM_XrActionType(ENUM_NAME)}; -#undef ENUM_NAME - std::string actionTypeStr = actionTypeToString.at(actionType); + std::string actionTypeStr = enum_to_string(actionType); CAPTURE(actionTypeStr); XrAction* actionRef; @@ -1181,18 +1178,41 @@ namespace Conformance compositionHelper.BeginSession(); SECTION("No Focus") { - compositionHelper.GetInteractionManager().AddActionSet(actionSet); - compositionHelper.GetInteractionManager().AttachActionSets(); + SECTION("No active action sets") + { + XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO}; + syncInfo.activeActionSets = nullptr; + syncInfo.countActiveActionSets = 0; - XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO}; - XrActiveActionSet activeActionSet{actionSet}; - syncInfo.activeActionSets = &activeActionSet; - syncInfo.countActiveActionSets = 1; + { + INFO("No action sets attached"); + + REQUIRE_RESULT_SUCCEEDED(xrSyncActions(compositionHelper.GetSession(), &syncInfo)); + } + { + INFO("With action sets attached"); + + compositionHelper.GetInteractionManager().AddActionSet(actionSet); + compositionHelper.GetInteractionManager().AttachActionSets(); + + REQUIRE_RESULT_SUCCEEDED(xrSyncActions(compositionHelper.GetSession(), &syncInfo)); + } + } + SECTION("Active action sets") + { + compositionHelper.GetInteractionManager().AddActionSet(actionSet); + compositionHelper.GetInteractionManager().AttachActionSets(); - REQUIRE_RESULT(xrSyncActions(compositionHelper.GetSession(), &syncInfo), XR_SESSION_NOT_FOCUSED); + XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO}; + XrActiveActionSet activeActionSet{actionSet}; + syncInfo.activeActionSets = &activeActionSet; + syncInfo.countActiveActionSets = 1; - REQUIRE_RESULT(xrGetActionStateBoolean(compositionHelper.GetSession(), &getInfo, &actionStateBoolean), XR_SUCCESS); - REQUIRE_FALSE(actionStateBoolean.isActive); + REQUIRE_RESULT(xrSyncActions(compositionHelper.GetSession(), &syncInfo), XR_SESSION_NOT_FOCUSED); + + REQUIRE_RESULT(xrGetActionStateBoolean(compositionHelper.GetSession(), &getInfo, &actionStateBoolean), XR_SUCCESS); + REQUIRE_FALSE(actionStateBoolean.isActive); + } } SECTION("Focus") { @@ -1631,6 +1651,12 @@ namespace Conformance REQUIRE_RESULT(xrCreateActionSet(compositionHelper.GetInstance(), &actionSetCreateInfo, &subactionPathFreeActionSet), XR_SUCCESS); + XrActionSet unboundActionActionSet{XR_NULL_HANDLE}; + strcpy(actionSetCreateInfo.localizedActionSetName, "test action set localized name 5"); + strcpy(actionSetCreateInfo.actionSetName, "test_action_set_name_5"); + REQUIRE_RESULT(xrCreateActionSet(compositionHelper.GetInstance(), &actionSetCreateInfo, &unboundActionActionSet), + XR_SUCCESS); + XrAction leftHandAction{XR_NULL_HANDLE}; actionCreateInfo.actionType = XR_ACTION_TYPE_BOOLEAN_INPUT; strcpy(actionCreateInfo.localizedActionName, "test select action"); @@ -1645,12 +1671,19 @@ namespace Conformance actionCreateInfo.subactionPaths = &rightHandPath; REQUIRE_RESULT(xrCreateAction(actionSet, &actionCreateInfo, &rightHandAction), XR_SUCCESS); + XrAction unboundAction{XR_NULL_HANDLE}; + strcpy(actionCreateInfo.localizedActionName, "test select action 4"); + strcpy(actionCreateInfo.actionName, "test_select_action_4"); + actionCreateInfo.subactionPaths = &defaultDevicePath; + REQUIRE_RESULT(xrCreateAction(unboundActionActionSet, &actionCreateInfo, &unboundAction), XR_SUCCESS); + compositionHelper.GetInteractionManager().AddActionBindings( simpleControllerInteractionProfile, {{leftHandAction, StringToPath(compositionHelper.GetInstance(), "/user/hand/left/input/select/click")}, {rightHandAction, StringToPath(compositionHelper.GetInstance(), "/user/hand/right/input/select/click")}}); compositionHelper.GetInteractionManager().AddActionSet(actionSet); compositionHelper.GetInteractionManager().AddActionSet(subactionPathFreeActionSet); + compositionHelper.GetInteractionManager().AddActionSet(unboundActionActionSet); compositionHelper.GetInteractionManager().AttachActionSets(); if (globalData.leftHandUnderTest) { @@ -1663,6 +1696,7 @@ namespace Conformance XrActionsSyncInfo syncInfo{XR_TYPE_ACTIONS_SYNC_INFO}; XrActiveActionSet activeActionSet{actionSet}; XrActiveActionSet subactionPathFreeActiveActionSet{subactionPathFreeActionSet}; + XrActiveActionSet unboundActionActiveActionSet{unboundActionActionSet}; syncInfo.activeActionSets = &activeActionSet; syncInfo.countActiveActionSets = 1; @@ -1754,6 +1788,11 @@ namespace Conformance REQUIRE_RESULT(xrCreateActionSet(compositionHelper.GetInstance(), &actionSetCreateInfo, &unattachedActionSet), XR_SUCCESS); + INFO("Unbound action"); + syncInfo.activeActionSets = &unboundActionActiveActionSet; + unboundActionActiveActionSet.subactionPath = defaultDevicePath; + actionLayerManager.SyncActionsUntilFocusWithMessage(syncInfo); + INFO("unattached action set"); XrActiveActionSet activeActionSet2 = {unattachedActionSet}; syncInfo.countActiveActionSets = 1; diff --git a/src/conformance/conformance_test/test_multithreading.cpp b/src/conformance/conformance_test/test_multithreading.cpp index 75559484..77632e72 100644 --- a/src/conformance/conformance_test/test_multithreading.cpp +++ b/src/conformance/conformance_test/test_multithreading.cpp @@ -328,10 +328,6 @@ namespace Conformance // Exercise session multithreading. { - // how long the test should wait for the app to get focus: 10 seconds in release, infinite in debug builds. - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - ThreadTestEnvironment env(invocationCount); env.GetAutoBasicSession().Init(AutoBasicSession::beginSession | AutoBasicSession::createActions | AutoBasicSession::createSpaces | AutoBasicSession::createSwapchains); @@ -386,8 +382,7 @@ namespace Conformance // Get frames iterating to the point of app focused state. This will draw frames along the way. FrameIterator frameIterator(&env.GetAutoBasicSession()); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); env.lastFrameTime = frameIterator.frameState.predictedDisplayTime; diff --git a/src/conformance/conformance_test/test_xrCreateInstance.cpp b/src/conformance/conformance_test/test_xrCreateInstance.cpp index e7ab8232..6af99a31 100644 --- a/src/conformance/conformance_test/test_xrCreateInstance.cpp +++ b/src/conformance/conformance_test/test_xrCreateInstance.cpp @@ -24,6 +24,7 @@ #include #include +#include namespace Conformance { @@ -254,6 +255,7 @@ namespace Conformance // To do: Enable any layers and extensions available. } } + TEST_CASE("xrDestroyInstance", "") { SECTION("null handle") @@ -263,6 +265,18 @@ namespace Conformance CHECK(xrDestroyInstance(XR_NULL_HANDLE_CPP) == XR_ERROR_HANDLE_INVALID); } + SECTION("destroy on a different thread to create") + { + for (int i = 0; i < 2; ++i) { + CAPTURE(i); + AutoBasicInstance instance; + XrResult destroyResult = XR_ERROR_RUNTIME_FAILURE; + std::thread t([&destroyResult, &instance] { destroyResult = xrDestroyInstance(instance); }); + t.join(); + REQUIRE(destroyResult == XR_SUCCESS); + } + } + OPTIONAL_INVALID_HANDLE_VALIDATION_SECTION { GlobalData& globalData = GetGlobalData(); diff --git a/src/conformance/conformance_test/test_xrCreateSession.cpp b/src/conformance/conformance_test/test_xrCreateSession.cpp index a29d4612..cb6f1314 100644 --- a/src/conformance/conformance_test/test_xrCreateSession.cpp +++ b/src/conformance/conformance_test/test_xrCreateSession.cpp @@ -27,6 +27,7 @@ #include #include #include +#include namespace Conformance { @@ -81,7 +82,7 @@ namespace Conformance // Happens if the application tries to create the session but hasn't queried the graphics requirements (e.g. // xrGetD3D12GraphicsRequirementsKHR). This spec states that applications must call this, but // how we enforce it in conformance testing is problematic because a specific return code isn't specified. - graphicsPlugin->InitializeDevice(instance, systemId, false /* checkGraphicsRequirements */); + REQUIRE(graphicsPlugin->InitializeDevice(instance, systemId, false /* checkGraphicsRequirements */)); sessionCreateInfo.next = graphicsPlugin->GetGraphicsBinding(); XrResult sessionResult = xrCreateSession(instance, &sessionCreateInfo, &session); CHECK_THAT(sessionResult, In({XR_ERROR_VALIDATION_FAILURE, XR_ERROR_GRAPHICS_REQUIREMENTS_CALL_MISSING})); @@ -127,4 +128,31 @@ namespace Conformance } } } + + TEST_CASE("xrDestroySession", "") + { + SECTION("null handle") + { + CHECK(xrDestroySession(XR_NULL_HANDLE_CPP) == XR_ERROR_HANDLE_INVALID); + } + + SECTION("destroy on a different thread to create") + { + for (int i = 0; i < 2; ++i) { + CAPTURE(i); + + AutoBasicInstance instance; + AutoBasicSession session(AutoBasicSession::createSession, instance); + XrResult destroySessionResult = XR_ERROR_RUNTIME_FAILURE; + XrResult destroyInstanceResult = XR_ERROR_RUNTIME_FAILURE; + std::thread t([&destroySessionResult, &destroyInstanceResult, &session, &instance] { + destroySessionResult = xrDestroySession(session); + destroyInstanceResult = xrDestroyInstance(instance); + }); + t.join(); + REQUIRE(destroySessionResult == XR_SUCCESS); + REQUIRE(destroyInstanceResult == XR_SUCCESS); + } + } + } } // namespace Conformance diff --git a/src/conformance/conformance_test/test_xrLocateSpace.cpp b/src/conformance/conformance_test/test_xrLocateSpace.cpp index 99c2c6bc..96b54ffa 100644 --- a/src/conformance/conformance_test/test_xrLocateSpace.cpp +++ b/src/conformance/conformance_test/test_xrLocateSpace.cpp @@ -22,31 +22,28 @@ #include #include +#include #include #include #include #include +#include #include namespace Conformance { TEST_CASE("xrLocateSpace", "") { - // how long the test should wait for the app to get focus: 10 seconds in release, infinite in debug builds. - auto timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - // Get a session started. AutoBasicSession session(AutoBasicSession::createInstance | AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | AutoBasicSession::createSpaces); // Get frames iterating to the point of app focused state. This will draw frames along the way. FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // Render one frame to get a predicted display time for the xrLocateSpace calls. - runResult = frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); XrResult result; @@ -88,6 +85,31 @@ namespace Conformance XrTime time = frameIterator.frameState.predictedDisplayTime; CHECK(time != 0); + SECTION("valid inputs") + { + // two identical spaces: + result = xrCreateReferenceSpace(session, &spaceCreateInfo, &spaceA); + CHECK(result == XR_SUCCESS); + result = xrCreateReferenceSpace(session, &spaceCreateInfo, &spaceB); + CHECK(result == XR_SUCCESS); + + // Exercise the predicted display time + result = xrLocateSpace(spaceA, spaceB, time, &location); + CHECK(result == XR_SUCCESS); + + // Exercise 40ms ago (or the first valid time, whichever is later) + result = xrLocateSpace(spaceA, spaceB, std::max(time - 40_xrMilliseconds, (XrTime)1), &location); + CHECK(result == XR_SUCCESS); + + // Exercise 1s ago (or the first valid time, whichever is later) + result = xrLocateSpace(spaceA, spaceB, std::max(time - 1_xrSeconds, (XrTime)1), &location); + CHECK(result == XR_SUCCESS); + + // cleanup + CHECK(XR_SUCCESS == xrDestroySpace(spaceA)); + CHECK(XR_SUCCESS == xrDestroySpace(spaceB)); + } + SECTION("wrong inputs") { // two identical spaces: @@ -233,7 +255,6 @@ namespace Conformance result = xrRequestExitSession(session); CHECK(result == XR_SUCCESS); - runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - CHECK(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); } } // namespace Conformance diff --git a/src/conformance/conformance_test/test_xrLocateViews.cpp b/src/conformance/conformance_test/test_xrLocateViews.cpp index f1917d62..583dc66e 100644 --- a/src/conformance/conformance_test/test_xrLocateViews.cpp +++ b/src/conformance/conformance_test/test_xrLocateViews.cpp @@ -30,21 +30,16 @@ namespace Conformance { GlobalData& globalData = GetGlobalData(); - // how long the test should wait for the app to get focus: 10 seconds in release, 1hr in debug builds. - auto timeout = (globalData.options.debugMode ? 3600s : 10s); - CAPTURE(timeout); - // Get a session started. AutoBasicSession session(AutoBasicSession::createInstance | AutoBasicSession::createSession | AutoBasicSession::beginSession | AutoBasicSession::createSwapchains | AutoBasicSession::createSpaces); // Get frames iterating to the point of app focused state. This will draw frames along the way. FrameIterator frameIterator(&session); - FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeout); - REQUIRE(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); // Render one frame to get a predicted display time for the xrLocateViews calls. - runResult = frameIterator.SubmitFrame(); + FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); REQUIRE(runResult == FrameIterator::RunResult::Success); XrResult result; @@ -170,7 +165,6 @@ namespace Conformance result = xrRequestExitSession(session); CHECK(result == XR_SUCCESS); - runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING, timeout); - CHECK(runResult == FrameIterator::RunResult::Success); + frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING); } } // namespace Conformance diff --git a/src/conformance/framework/composition_utils.h b/src/conformance/framework/composition_utils.h index f20cdff5..21f835de 100644 --- a/src/conformance/framework/composition_utils.h +++ b/src/conformance/framework/composition_utils.h @@ -348,7 +348,9 @@ namespace Conformance constexpr XrColor4f Blue = {0, 0, 1, 1}; constexpr XrColor4f Yellow = {1, 1, 0, 1}; constexpr XrColor4f Orange = {1, 0.65f, 0, 1}; + constexpr XrColor4f Magenta = {1, 0, 1, 1}; constexpr XrColor4f Transparent = {0, 0, 0, 0}; + constexpr XrColor4f Black = {0, 0, 0, 1}; /// A list of unique colors, not including red which is a "failure color". constexpr std::array UniqueColors{Green, Blue, Yellow, Orange}; diff --git a/src/conformance/framework/conformance_framework.cpp b/src/conformance/framework/conformance_framework.cpp index a4dcb037..9a2fa3c7 100644 --- a/src/conformance/framework/conformance_framework.cpp +++ b/src/conformance/framework/conformance_framework.cpp @@ -16,6 +16,7 @@ #include "conformance_framework.h" +#include "composition_utils.h" // for Colors #include "graphics_plugin.h" #include "platform_plugin.h" #include "report.h" @@ -479,11 +480,6 @@ namespace Conformance if (IsInstanceExtensionEnabled(XR_MND_HEADLESS_EXTENSION_NAME)) { return false; } -#ifdef XR_KHR_headless - if (IsInstanceExtensionEnabled(XR_KHR_HEADLESS_EXTENSION_NAME)) { - return false; - } -#endif return true; } @@ -497,4 +493,18 @@ namespace Conformance std::unique_lock lock(dataMutex); conformanceReport.swapchainFormats.emplace_back(format, name); } + + XrColor4f GlobalData::GetClearColorForBackground() const + { + switch (options.environmentBlendModeValue) { + case XR_ENVIRONMENT_BLEND_MODE_OPAQUE: + return DarkSlateGrey; + case XR_ENVIRONMENT_BLEND_MODE_ADDITIVE: + return Colors::Black; + case XR_ENVIRONMENT_BLEND_MODE_ALPHA_BLEND: + return Colors::Transparent; + default: + XRC_THROW("Encountered unrecognized environment blend mode value while determining background color."); + } + } } // namespace Conformance diff --git a/src/conformance/framework/conformance_framework.h b/src/conformance/framework/conformance_framework.h index 20bc7f7e..7cb29a8b 100644 --- a/src/conformance/framework/conformance_framework.h +++ b/src/conformance/framework/conformance_framework.h @@ -355,7 +355,7 @@ namespace Conformance std::shared_ptr GetGraphicsPlugin(); /// Returns true if under the current test environment we require a graphics plugin. This may - /// be false, for example, if the XR_KHR_headless is enabled. + /// be false, for example, if the XR_MND_headless extension is enabled. bool IsGraphicsPluginRequired() const; /// Returns true if a graphics plugin was supplied, or if IsGraphicsPluginRequired() is true. @@ -364,6 +364,9 @@ namespace Conformance /// Record a swapchain format as being supported and tested. void PushSwapchainFormat(int64_t format, const std::string& name); + /// Calculate the clear color to use for the background based on the XrEnvironmentBlendMode in use. + XrColor4f GetClearColorForBackground() const; + public: /// Guards all member data. mutable std::recursive_mutex dataMutex; @@ -605,6 +608,7 @@ MAKE_ENUM_TO_STRING_FUNC(XrViewConfigurationType); MAKE_ENUM_TO_STRING_FUNC(XrVisibilityMaskTypeKHR); MAKE_ENUM_TO_STRING_FUNC(XrFormFactor); MAKE_ENUM_TO_STRING_FUNC(XrEnvironmentBlendMode); +MAKE_ENUM_TO_STRING_FUNC(XrActionType); namespace Catch { diff --git a/src/conformance/framework/conformance_utils.cpp b/src/conformance/framework/conformance_utils.cpp index 3a90faff..d796083b 100644 --- a/src/conformance/framework/conformance_utils.cpp +++ b/src/conformance/framework/conformance_utils.cpp @@ -392,7 +392,7 @@ namespace Conformance // Normally the testing requires a graphics plugin. However, there's currently one case in // which that's not true: when a headless extension is enabled. In that case the - // runtime supports creating a session without a graphics system. See XR_MND_headless and/or XR_KHR_headless doc. + // runtime supports creating a session without a graphics system. See XR_MND_headless doc. if (graphicsPlugin && enableGraphicsSystem) { // If the following fails then this app has a bug, not the runtime. assert(graphicsPlugin->IsInitialized()); @@ -481,8 +481,8 @@ namespace Conformance // that the session is ready. // timeout in case the runtime will never transition to READY: 10s in release, no practical limit in debug - std::chrono::nanoseconds timeout = (GetGlobalData().options.debugMode ? 3600s : 10s); - CountdownTimer countdownTimer(timeout); + auto timeoutToTransitionToSessionState = (GetGlobalData().options.debugMode ? 3600s : 10s); + CountdownTimer countdownTimer(timeoutToTransitionToSessionState); while ((sessionState != XR_SESSION_STATE_READY) && (!countdownTimer.IsTimeUp())) { XrEventDataBuffer eventData{XR_TYPE_EVENT_DATA_BUFFER}; @@ -503,7 +503,24 @@ namespace Conformance } if (sessionState != XR_SESSION_STATE_READY) { - XRC_THROW("Time out waiting for XR_SESSION_STATE_READY session state change"); + // We have failed this check with the timeout. This is a pretty common place to fail + // so we will offer helpful hints for the most common errors - as well as a generic + // message. + + // https://registry.khronos.org/OpenXR/specs/1.0/html/xrspec.html#sessionstatechanged-description + // If the system supports a user engagement sensor and runtime is in XR_SESSION_STATE_IDLE state, + // the runtime should not transition to the XR_SESSION_STATE_READY state until the user starts + // engaging with the device. + + std::string extraInfo; + if (sessionState == XR_SESSION_STATE_IDLE) { + extraInfo = + " If this system supports a user engagement sensor, the runtime may not transition to XR_SESSION_STATE_READY state until the user starts engaging with the device."; + } + + CAPTURE(timeoutToTransitionToSessionState); + CAPTURE(sessionState); + FAIL("Time out waiting for XR_SESSION_STATE_READY session state change after creating a new session." << extraInfo); } XrSessionBeginInfo sessionBeginInfo{XR_TYPE_SESSION_BEGIN_INFO, @@ -627,17 +644,13 @@ namespace Conformance //////////////////////////////////////////////////////////////////////////////////////////////// FrameIterator::FrameIterator(AutoBasicSession* autoBasicSession_) - : autoBasicSession(autoBasicSession_) - , sessionState(autoBasicSession->GetSessionState()) - , countdownTimer() - , frameState() - , viewVector() - { - } - - void FrameIterator::SetAutoBasicSession(AutoBasicSession* autoBasicSession_) + : autoBasicSession(autoBasicSession_), sessionState(autoBasicSession->GetSessionState()), frameState(), viewVector() { - autoBasicSession = autoBasicSession_; + XRC_CHECK_THROW(autoBasicSession); + XRC_CHECK_THROW(autoBasicSession->instance); + XRC_CHECK_THROW(autoBasicSession->session); + XRC_CHECK_THROW(!autoBasicSession->viewConfigurationTypeVector.empty()); + XRC_CHECK_THROW(!autoBasicSession->environmentBlendModeVector.empty()); } XrSessionState FrameIterator::GetCurrentSessionState() const @@ -647,12 +660,6 @@ namespace Conformance FrameIterator::TickResult FrameIterator::PollEvent() { - // App must have called SetAutoBasicSession and set flags enabling these. - if (!autoBasicSession) - return TickResult::Error; - if (!autoBasicSession->instance) - return TickResult::Error; - XrEventDataBuffer eventData{XR_TYPE_EVENT_DATA_BUFFER}; XrResult result = xrPollEvent(autoBasicSession->instance, &eventData); @@ -693,11 +700,10 @@ namespace Conformance if (!GetGlobalData().IsUsingGraphicsPlugin()) return RunResult::Success; - // App must have called SetAutoBasicSession and set flags enabling these. - if (!autoBasicSession) - return RunResult::Error; - if (autoBasicSession->swapchainVector.empty()) + if (autoBasicSession->swapchainVector.empty()) { + // AutoBasicSession must be created with flags including AutoBasicSession::createSwapchains return RunResult::Error; + } // Call the helper function for this. const XrDuration twoSeconds = 2_xrSeconds; @@ -715,15 +721,10 @@ namespace Conformance FrameIterator::RunResult FrameIterator::WaitAndBeginFrame() { - // App must have called SetAutoBasicSession and set flags enabling these. - if (!autoBasicSession) - return RunResult::Error; - if (!autoBasicSession->session) - return RunResult::Error; - if (autoBasicSession->spaceVector.empty()) - return RunResult::Error; - if (autoBasicSession->viewConfigurationTypeVector.empty()) + if (autoBasicSession->spaceVector.empty()) { + // AutoBasicSession must be created with flags including AutoBasicSession::createSpaces return RunResult::Error; + } XrResult result; @@ -756,13 +757,10 @@ namespace Conformance FrameIterator::RunResult FrameIterator::PrepareFrameEndInfo() { - // App must have called SetAutoBasicSession and set flags enabling these. - if (!autoBasicSession) - return RunResult::Error; - if (autoBasicSession->spaceVector.empty()) - return RunResult::Error; - if (autoBasicSession->environmentBlendModeVector.empty()) + if (autoBasicSession->spaceVector.empty()) { + // AutoBasicSession must be created with flags including AutoBasicSession::createSpaces return RunResult::Error; + } if (GetGlobalData().IsUsingGraphicsPlugin() && autoBasicSession->swapchainVector.empty()) return RunResult::Error; @@ -839,27 +837,28 @@ namespace Conformance // Runs until the given XrSessionState is achieved or timesout before so. // targetSessionState may be any XrSessionState, but some session states may require // special handling in order to get to, such as XR_SESSION_STATE_LOSS_PENDING. - FrameIterator::RunResult FrameIterator::RunToSessionState(XrSessionState targetSessionState, std::chrono::nanoseconds timeout) + void FrameIterator::RunToSessionState(XrSessionState targetSessionState) { - if (!autoBasicSession) // App must have called SetAutoBasicSession. - return RunResult::Error; + auto initialSessionState = sessionState; - countdownTimer.Restart(timeout); + auto timeoutToTransitionToSessionState = (GetGlobalData().options.debugMode ? 3600s : 10s); + CAPTURE(timeoutToTransitionToSessionState); + CountdownTimer countdownTimer(timeoutToTransitionToSessionState); while (!countdownTimer.IsTimeUp()) { TickResult tickResult = PollEvent(); + REQUIRE(tickResult != TickResult::Error); - if (tickResult == TickResult::Error) - return RunResult::Error; - - if (sessionState == targetSessionState) - return RunResult::Success; - - if ((sessionState == XR_SESSION_STATE_LOSS_PENDING) || (sessionState == XR_SESSION_STATE_EXITING) || - (sessionState == XR_SESSION_STATE_STOPPING)) { - return RunResult::Timeout; + if (sessionState == targetSessionState) { + // calling SUCCEED here to flush the CAPTURE / INFO messages from this function + SUCCEED(); + return; } + REQUIRE(sessionState != XR_SESSION_STATE_LOSS_PENDING); + REQUIRE(sessionState != XR_SESSION_STATE_EXITING); + REQUIRE(sessionState != XR_SESSION_STATE_STOPPING); + // At this point sessionState is one of XR_SESSION_STATE_UNKNOWN, // XR_SESSION_STATE_IDLE, XR_SESSION_STATE_READY, XR_SESSION_STATE_SYNCHRONIZED, // XR_SESSION_STATE_VISIBLE, XR_SESSION_STATE_FOCUSED. We proceed based on the @@ -882,9 +881,7 @@ namespace Conformance XrSessionBeginInfo sessionBeginInfo{ XR_TYPE_SESSION_BEGIN_INFO, globalData.GetPlatformPlugin()->PopulateNextFieldForStruct(XR_TYPE_SESSION_BEGIN_INFO), globalData.options.viewConfigurationValue}; - XrResult result = xrBeginSession(autoBasicSession->session, &sessionBeginInfo); - if (XR_FAILED(result)) - return RunResult::Error; + REQUIRE(xrBeginSession(autoBasicSession->session, &sessionBeginInfo) == XR_SUCCESS); } // Fall-through because frames must be submitted to get promoted from READY to SYNCHRONIZED. @@ -894,10 +891,8 @@ namespace Conformance case XR_SESSION_STATE_FOCUSED: { // In these states we need to submit frames. Otherwise the runtime won't // necessarily move us from synchronized to visible or focused. - RunResult runResult = SubmitFrame(); + REQUIRE(SubmitFrame() == RunResult::Success); - if (runResult == RunResult::Error) - return RunResult::Error; // Just keep going. We haven't reached the target state yet. break; } @@ -910,7 +905,17 @@ namespace Conformance } } - return RunResult::Timeout; + // We have failed this check with the timeout. This is a pretty common place to fail + // so we will offer helpful hints for the most common errors - as well as a generic + // message. + + std::string extraInfo; + if (targetSessionState == XR_SESSION_STATE_FOCUSED && initialSessionState == XR_SESSION_STATE_READY && + sessionState == XR_SESSION_STATE_VISIBLE) { + extraInfo = " This might indicate that some other (maybe system) application still has focus for the user."; + } + FAIL("Timeout while waiting for session state transition to: " << enum_to_string(targetSessionState) << " from initial state: " + << enum_to_string(initialSessionState) << "." << extraInfo); } bool WaitUntilPredicateWithTimeout(const std::function& predicate, const std::chrono::nanoseconds timeout, diff --git a/src/conformance/framework/conformance_utils.h b/src/conformance/framework/conformance_utils.h index d770f113..bcb1386a 100644 --- a/src/conformance/framework/conformance_utils.h +++ b/src/conformance/framework/conformance_utils.h @@ -398,11 +398,7 @@ namespace Conformance class CountdownTimer { public: - CountdownTimer() : stopwatch(), timeoutDuration() - { - } - - CountdownTimer(std::chrono::nanoseconds timeout) : stopwatch(), timeoutDuration(timeout) + explicit CountdownTimer(std::chrono::nanoseconds timeout) : stopwatch(), timeoutDuration(timeout) { stopwatch.Restart(); } @@ -717,11 +713,10 @@ namespace Conformance /// /// // Get frames iterating to the point of app focused state. This will draw frames along the way. /// FrameIterator frameIterator(&session); - /// FrameIterator::RunResult runResult = frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED, timeoutMicroseconds); - /// REQUIRE(runResult == FrameIterator::RunResult::Success); + /// frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED); /// /// // Let's have the FrameIterator draw one more frame itself. - /// runResult = frameIterator.SubmitFrame(); + /// FrameIterator::RunResult runResult = frameIterator.SubmitFrame(); /// REQUIRE(runResult == FrameIterator::RunResult::Success); /// /// // Now let's draw a frame ourselves. @@ -739,12 +734,9 @@ namespace Conformance class FrameIterator { public: - FrameIterator(AutoBasicSession* autoBasicSession_ = nullptr); + explicit FrameIterator(AutoBasicSession* autoBasicSession_ = nullptr); ~FrameIterator() = default; - /// Must not be called after calling any other member function. - void SetAutoBasicSession(AutoBasicSession* autoBasicSession_); - XrSessionState GetCurrentSessionState() const; enum class TickResult @@ -797,16 +789,16 @@ namespace Conformance /// an example of this. RunResult SubmitFrame(); - /// Runs until the given XrSessionState is achieved or timesout before so. + /// Runs until the given XrSessionState is achieved or times out before so. /// targetSessionState may be any XrSessionState, but some session states may require /// special handling in order to get to, such as XR_SESSION_STATE_LOSS_PENDING. /// Will repeatedly call SubmitFrame if necessary to get to the desired state. - RunResult RunToSessionState(XrSessionState targetSessionState, std::chrono::nanoseconds timeout); + /// Will fail test if targetSessionState is not reached. + void RunToSessionState(XrSessionState targetSessionState); protected: - AutoBasicSession* autoBasicSession; + AutoBasicSession* const autoBasicSession; XrSessionState sessionState; - CountdownTimer countdownTimer; public: XrFrameState frameState; //< xrWaitFrame from WaitAndBeginFrame fills this in. diff --git a/src/conformance/framework/graphics_plugin.h b/src/conformance/framework/graphics_plugin.h index a26b00f4..baf6e864 100644 --- a/src/conformance/framework/graphics_plugin.h +++ b/src/conformance/framework/graphics_plugin.h @@ -18,6 +18,7 @@ #include "platform_plugin.h" #include "conformance_utils.h" +#include "conformance_framework.h" #include "utilities/Geometry.h" #include "RGBAImage.h" @@ -307,8 +308,15 @@ namespace Conformance AllocateSwapchainImageDataWithDepthSwapchain(size_t size, const XrSwapchainCreateInfo& colorSwapchainCreateInfo, XrSwapchain depthSwapchain, const XrSwapchainCreateInfo& depthSwapchainCreateInfo) = 0; - virtual void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex = 0, - XrColor4f bgColor = DarkSlateGrey) = 0; + /// Clears a slice to an arbitrary color + virtual void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, XrColor4f color) = 0; + + /// Clears to the background color which varies depending on the environment blend mode that is active. + void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex = 0) + { + GlobalData& globalData = GetGlobalData(); + ClearImageSlice(colorSwapchainImage, imageArrayIndex, globalData.GetClearColorForBackground()); + } /// Create internal data for a mesh, returning a handle to refer to it. /// This handle expires when the internal data is cleared in Shutdown() and ShutdownDevice(). diff --git a/src/conformance/framework/graphics_plugin_d3d11.cpp b/src/conformance/framework/graphics_plugin_d3d11.cpp index a2dee28e..b5c9b551 100644 --- a/src/conformance/framework/graphics_plugin_d3d11.cpp +++ b/src/conformance/framework/graphics_plugin_d3d11.cpp @@ -200,8 +200,7 @@ namespace Conformance XrSwapchain depthSwapchain, const XrSwapchainCreateInfo& depthSwapchainCreateInfo) override; - void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor = DarkSlateGrey) override; + void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, XrColor4f color) override; MeshHandle MakeSimpleMesh(span idx, span vtx) override; @@ -643,7 +642,7 @@ namespace Conformance } void D3D11GraphicsPlugin::ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor) + XrColor4f color) { D3D11SwapchainImageData* swapchainData; @@ -655,7 +654,7 @@ namespace Conformance // Create RenderTargetView with original swapchain format (swapchain is typeless). ComPtr renderTargetView = CreateRenderTargetView(*swapchainData, imageIndex, imageArrayIndex); // TODO: Do not clear to a color when using a pass-through view configuration. - FLOAT bg[] = {bgColor.r, bgColor.g, bgColor.b, bgColor.a}; + FLOAT bg[] = {color.r, color.g, color.b, color.a}; d3d11DeviceContext->ClearRenderTargetView(renderTargetView.Get(), bg); // Clear depth buffer. diff --git a/src/conformance/framework/graphics_plugin_d3d12.cpp b/src/conformance/framework/graphics_plugin_d3d12.cpp index cd7b438d..0fd9e210 100644 --- a/src/conformance/framework/graphics_plugin_d3d12.cpp +++ b/src/conformance/framework/graphics_plugin_d3d12.cpp @@ -355,8 +355,7 @@ namespace Conformance XrSwapchain depthSwapchain, const XrSwapchainCreateInfo& depthSwapchainCreateInfo) override; - void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor = DarkSlateGrey) override; + void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, XrColor4f color) override; MeshHandle MakeSimpleMesh(span idx, span vtx) override; @@ -937,7 +936,7 @@ namespace Conformance } void D3D12GraphicsPlugin::ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor) + XrColor4f color) { D3D12SwapchainImageData* swapchainData; @@ -957,7 +956,7 @@ namespace Conformance D3D12_CPU_DESCRIPTOR_HANDLE renderTargetView = CreateRenderTargetView(colorTexture, imageArrayIndex, swapchainData->GetCreateInfo().format); // TODO: Do not clear to a color when using a pass-through view configuration. - FLOAT bg[] = {bgColor.r, bgColor.g, bgColor.b, bgColor.a}; + FLOAT bg[] = {color.r, color.g, color.b, color.a}; cmdList->ClearRenderTargetView(renderTargetView, bg, 0, nullptr); // Clear depth buffer. diff --git a/src/conformance/framework/graphics_plugin_opengl.cpp b/src/conformance/framework/graphics_plugin_opengl.cpp index 3ce587ab..b2d06d96 100644 --- a/src/conformance/framework/graphics_plugin_opengl.cpp +++ b/src/conformance/framework/graphics_plugin_opengl.cpp @@ -443,8 +443,7 @@ namespace Conformance XrSwapchain depthSwapchain, const XrSwapchainCreateInfo& depthSwapchainCreateInfo) override; - void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor = DarkSlateGrey) override; + void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, XrColor4f color) override; MeshHandle MakeSimpleMesh(span idx, span vtx) override; @@ -1024,7 +1023,7 @@ namespace Conformance } void OpenGLGraphicsPlugin::ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor) + XrColor4f color) { OpenGLSwapchainImageData* swapchainData; uint32_t imageIndex; @@ -1058,7 +1057,7 @@ namespace Conformance XRC_CHECK_THROW_GLCMD(glEnable(GL_SCISSOR_TEST)); // Clear swapchain and depth buffer. - XRC_CHECK_THROW_GLCMD(glClearColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a)); + XRC_CHECK_THROW_GLCMD(glClearColor(color.r, color.g, color.b, color.a)); XRC_CHECK_THROW_GLCMD(glClearDepth(1.0f)); XRC_CHECK_THROW_GLCMD(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT)); diff --git a/src/conformance/framework/graphics_plugin_opengles.cpp b/src/conformance/framework/graphics_plugin_opengles.cpp index 5632dd29..6930513e 100644 --- a/src/conformance/framework/graphics_plugin_opengles.cpp +++ b/src/conformance/framework/graphics_plugin_opengles.cpp @@ -291,8 +291,7 @@ namespace Conformance XrSwapchain depthSwapchain, const XrSwapchainCreateInfo& depthSwapchainCreateInfo) override; - void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor = DarkSlateGrey) override; + void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, XrColor4f color) override; MeshHandle MakeSimpleMesh(span idx, span vtx) override; @@ -1088,7 +1087,7 @@ namespace Conformance } void OpenGLESGraphicsPlugin::ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor) + XrColor4f color) { OpenGLESSwapchainImageData* swapchainData; uint32_t imageIndex; @@ -1121,7 +1120,7 @@ namespace Conformance GL(glEnable(GL_SCISSOR_TEST)); // Clear swapchain and depth buffer. - GL(glClearColor(bgColor.r, bgColor.g, bgColor.b, bgColor.a)); + GL(glClearColor(color.r, color.g, color.b, color.a)); GL(glClearDepthf(1.0f)); GL(glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT)); diff --git a/src/conformance/framework/graphics_plugin_vulkan.cpp b/src/conformance/framework/graphics_plugin_vulkan.cpp index 4db260a5..e8f869ef 100644 --- a/src/conformance/framework/graphics_plugin_vulkan.cpp +++ b/src/conformance/framework/graphics_plugin_vulkan.cpp @@ -629,8 +629,7 @@ namespace Conformance void SetViewportAndScissor(const VkRect2D& rect); - void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor = DarkSlateGrey) override; + void ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, XrColor4f color) override; MeshHandle MakeSimpleMesh(span idx, span vtx) override; @@ -1847,7 +1846,7 @@ namespace Conformance } void VulkanGraphicsPlugin::ClearImageSlice(const XrSwapchainImageBaseHeader* colorSwapchainImage, uint32_t imageArrayIndex, - XrColor4f bgColor) + XrColor4f color) { VulkanSwapchainImageData* swapchainData; uint32_t imageIndex; @@ -1882,10 +1881,10 @@ namespace Conformance // Clear the buffers static std::array clearValues; - clearValues[0].color.float32[0] = bgColor.r; - clearValues[0].color.float32[1] = bgColor.g; - clearValues[0].color.float32[2] = bgColor.b; - clearValues[0].color.float32[3] = bgColor.a; + clearValues[0].color.float32[0] = color.r; + clearValues[0].color.float32[1] = color.g; + clearValues[0].color.float32[2] = color.b; + clearValues[0].color.float32[3] = color.a; clearValues[1].depthStencil.depth = 1.0f; clearValues[1].depthStencil.stencil = 0; std::array clearAttachments{{ diff --git a/src/conformance/framework/mesh_projection_layer.cpp b/src/conformance/framework/mesh_projection_layer.cpp index af3990f6..5d572723 100644 --- a/src/conformance/framework/mesh_projection_layer.cpp +++ b/src/conformance/framework/mesh_projection_layer.cpp @@ -65,7 +65,7 @@ namespace Conformance MeshProjectionLayerHelper::MeshProjectionLayerHelper(CompositionHelper& compositionHelper) : m_baseHelper(compositionHelper, XR_REFERENCE_SPACE_TYPE_LOCAL) { - m_bgColors.resize(GetViewCount(), DarkSlateGrey); + m_bgColors.resize(GetViewCount(), Colors::Magenta); // should be overwritten before render } void MeshProjectionLayerHelper::SetMeshes(std::vector&& meshes) diff --git a/src/conformance/framework/xml_test_environment.cpp b/src/conformance/framework/xml_test_environment.cpp index 165f09a8..d7064d98 100644 --- a/src/conformance/framework/xml_test_environment.cpp +++ b/src/conformance/framework/xml_test_environment.cpp @@ -182,7 +182,6 @@ namespace Conformance WriteAvailableInstanceExtensions(xml, globalData.availableInstanceExtensions); if (globalData.IsGraphicsPluginRequired()) { - AutoBasicInstance instance(AutoBasicInstance::createSystemId); auto graphicsPlugin = globalData.GetGraphicsPlugin(); if (graphicsPlugin) { // DescribeGraphics may report only minimal info (name) due to not having a running instance, but this is OK for now. diff --git a/src/conformance/gradle.properties b/src/conformance/gradle.properties new file mode 100644 index 00000000..f4e35f07 --- /dev/null +++ b/src/conformance/gradle.properties @@ -0,0 +1,10 @@ +# Copyright (c) 2020-2023 The Khronos Group Inc. +# +# SPDX-License-Identifier: Apache-2.0 + +org.gradle.jvmargs=-Xmx2048m +android.useAndroidX=true +android.enableJetifier=false +android.defaults.buildfeatures.buildconfig=false +android.nonFinalResIds=true +android.nonTransitiveRClass=true diff --git a/src/conformance/gradle/wrapper/gradle-wrapper.jar b/src/conformance/gradle/wrapper/gradle-wrapper.jar index 249e5832..ccebba77 100644 Binary files a/src/conformance/gradle/wrapper/gradle-wrapper.jar and b/src/conformance/gradle/wrapper/gradle-wrapper.jar differ diff --git a/src/conformance/gradle/wrapper/gradle-wrapper.properties b/src/conformance/gradle/wrapper/gradle-wrapper.properties index 8049c684..91dc3417 100644 --- a/src/conformance/gradle/wrapper/gradle-wrapper.properties +++ b/src/conformance/gradle/wrapper/gradle-wrapper.properties @@ -1,5 +1,6 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists distributionUrl=https\://services.gradle.org/distributions/gradle-7.5-bin.zip +networkTimeout=10000 zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists diff --git a/src/conformance/gradlew b/src/conformance/gradlew index a69d9cb6..79a61d42 100755 --- a/src/conformance/gradlew +++ b/src/conformance/gradlew @@ -55,7 +55,7 @@ # Darwin, MinGW, and NonStop. # # (3) This script is generated from the Groovy template -# https://github.com/gradle/gradle/blob/master/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt +# https://github.com/gradle/gradle/blob/HEAD/subprojects/plugins/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt # within the Gradle project. # # You can find Gradle at https://github.com/gradle/gradle/. @@ -80,10 +80,10 @@ do esac done -APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit - -APP_NAME="Gradle" +# This is normally unused +# shellcheck disable=SC2034 APP_BASE_NAME=${0##*/} +APP_HOME=$( cd "${APP_HOME:-./}" && pwd -P ) || exit # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' @@ -143,12 +143,16 @@ fi if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then case $MAX_FD in #( max*) + # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 MAX_FD=$( ulimit -H -n ) || warn "Could not query maximum file descriptor limit" esac case $MAX_FD in #( '' | soft) :;; #( *) + # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked. + # shellcheck disable=SC3045 ulimit -n "$MAX_FD" || warn "Could not set maximum file descriptor limit to $MAX_FD" esac diff --git a/src/conformance/gradlew.bat b/src/conformance/gradlew.bat index f127cfd4..93e3f59f 100644 --- a/src/conformance/gradlew.bat +++ b/src/conformance/gradlew.bat @@ -26,6 +26,7 @@ if "%OS%"=="Windows_NT" setlocal set DIRNAME=%~dp0 if "%DIRNAME%"=="" set DIRNAME=. +@rem This is normally unused set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% diff --git a/src/conformance/platform_specific/AndroidManifest.xml b/src/conformance/platform_specific/AndroidManifest.xml index 66737109..94cb24b1 100644 --- a/src/conformance/platform_specific/AndroidManifest.xml +++ b/src/conformance/platform_specific/AndroidManifest.xml @@ -1,6 +1,6 @@ @@ -56,11 +56,14 @@ + android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen" + tools:ignore="NonResizeableActivity"> ()` consistently between Windows and WSL, instead of `__uuidof()`. -* `/src/dxguids.cpp`: This cpp file can be used as a replacement for linking against `dxguid.lib` on Windows, and as a convenient translation unit to define GUIDs without multiple definitions for WSL. -* `/test`: Simple CMake/Meson projects for validating the headers can be included in a given environment - -## Use on Windows - -Note that these headers may conflict with the headers from the Windows SDK, depending on include ordering. These headers should be added to the include directory list before the SDK, and should be included before other graphics headers (e.g. `d3d11.h`) from the Windows SDK. Otherwise, the corresponding header from the Windows SDK may be included first, and will define the include guards which prevents these headers from being used. - -## Use on WSL - -Note: WSL support is not intended for general purpose application development. At this time, the only recommended usage is for frameworks wishing to provide hardware acceleration for a Linux graphics/compute API in a WSL2 virtualization environment. - -Note: WSL support is only available for 64-bit binaries. - -The headers in the `/include/wsl` directory provide alternative definitions to macros and typedefs normally found in the Windows SDK. For the most part, they should be straightforward, but there are a couple to call attention to: - -|Type|Reason| -|---|---| -|`LONG`/`ULONG`|On 64-bit Windows, a `long` is 4 bytes, but on Linux it is typically 8 bytes. The D3D12 ABI for WSL uses `long` and therefore these should be 8 bytes.| -|`WCHAR`/`WCSTR`|On Windows, a `wchar_t` is 2 bytes, but on Linux it is typically 4 bytes. The D3D12 ABI for WSL uses the native 4-byte `wchar_t`, to enable applications and the runtime to use the system C library to perform string manipulation.| - -Additionally, APIs taking `HANDLE` (`void*`) for Win32 types should instead use `reinterpret_cast(fd)` for an appropriate type of file descriptor. For `ID3D12Fence::SetEventOnCompletion` this should be an `eventfd`, and for shared resources will be an opaque fd. - -## Ways to consume - -There are various ways to consume the headers in this project: - -* Manually: Just copy the headers somewhere and point your project at them. -* CMake subproject: Add this entire project as a subdirectory of your larger project, e.g. as a git submodule, and `add_subdirectory` into it. Use the resulting `DirectX-Headers` and/or `DirectX-Guids` targets as a link dependency -* Installed CMake: After building/installing this project, it can be found through CMake's `find_package` functionality and will expose the same `DirectX-Headers` and `DirectX-Guids` targets. -* FetchContent CMake (3.11+): Fetch this library using Git and easily add it to your project. -* Meson subproject/wrap: Add this entire project as a subproject of your larger project, and use `subproject` or `dependency` to consume it. -* Pkg-config: Use Meson to build this project, and the resulting installed package can be found via pkg-config. -* vcpkg: A vcpkg port has [been added](https://github.com/microsoft/vcpkg/pull/15222). - -Contributions for new mechanisms are welcome. - -## Contributing - -This project welcomes contributions and suggestions. Most contributions require you to agree to a Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com. - -When you submit a pull request, a CLA bot will automatically determine whether you need to provide a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions provided by the bot. You will only need to do this once across all repos using our CLA. - -This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/). For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments. - -## Trademarks - -This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft trademarks or logos is subject to and must follow [Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general). Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship. Any use of third-party trademarks or logos are subject to those third-party's policies. \ No newline at end of file diff --git a/src/external/d3dx12/d3dx12.h b/src/external/d3dx12/d3dx12.h index b1355989..562fb53a 100644 --- a/src/external/d3dx12/d3dx12.h +++ b/src/external/d3dx12/d3dx12.h @@ -217,6 +217,8 @@ struct CD3DX12_DEPTH_STENCIL_DESC : public D3D12_DEPTH_STENCIL_DESC }; //------------------------------------------------------------------------------------------------ +// Requires the Windows 10 Creators Update SDK (15063) +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) struct CD3DX12_DEPTH_STENCIL_DESC1 : public D3D12_DEPTH_STENCIL_DESC1 { CD3DX12_DEPTH_STENCIL_DESC1() = default; @@ -308,6 +310,7 @@ struct CD3DX12_DEPTH_STENCIL_DESC1 : public D3D12_DEPTH_STENCIL_DESC1 return D; } }; +#endif // NTDDI_WIN10_RS2 //------------------------------------------------------------------------------------------------ struct CD3DX12_BLEND_DESC : public D3D12_BLEND_DESC @@ -572,6 +575,7 @@ struct CD3DX12_RANGE : public D3D12_RANGE }; //------------------------------------------------------------------------------------------------ +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) struct CD3DX12_RANGE_UINT64 : public D3D12_RANGE_UINT64 { CD3DX12_RANGE_UINT64() = default; @@ -611,6 +615,7 @@ struct CD3DX12_SUBRESOURCE_RANGE_UINT64 : public D3D12_SUBRESOURCE_RANGE_UINT64 Range.End = end; } }; +#endif // NTDDI_WIN10_RS2 //------------------------------------------------------------------------------------------------ struct CD3DX12_SHADER_BYTECODE : public D3D12_SHADER_BYTECODE @@ -1823,6 +1828,8 @@ inline bool operator!=( const D3D12_RESOURCE_DESC& l, const D3D12_RESOURCE_DESC& { return !( l == r ); } //------------------------------------------------------------------------------------------------ +// Requires the Windows 10 SDK (19041) +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) struct CD3DX12_RESOURCE_DESC1 : public D3D12_RESOURCE_DESC1 { CD3DX12_RESOURCE_DESC1() = default; @@ -1949,8 +1956,11 @@ inline bool operator==( const D3D12_RESOURCE_DESC1& l, const D3D12_RESOURCE_DESC } inline bool operator!=( const D3D12_RESOURCE_DESC1& l, const D3D12_RESOURCE_DESC1& r ) noexcept { return !( l == r ); } +#endif // NTDDI_WIN10_VB //------------------------------------------------------------------------------------------------ +// Requires the Windows 10 Fall Creators Update SDK (16299) +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) struct CD3DX12_VIEW_INSTANCING_DESC : public D3D12_VIEW_INSTANCING_DESC { CD3DX12_VIEW_INSTANCING_DESC() = default; @@ -1973,6 +1983,7 @@ struct CD3DX12_VIEW_INSTANCING_DESC : public D3D12_VIEW_INSTANCING_DESC Flags = InFlags; } }; +#endif // NTDDI_WIN10_RS3 //------------------------------------------------------------------------------------------------ // Row-by-row memcpy @@ -2419,6 +2430,7 @@ inline HRESULT D3DX12SerializeVersionedRootSignature( } //------------------------------------------------------------------------------------------------ +#if defined(NTDDI_WIN10_RS2) && (NTDDI_VERSION >= NTDDI_WIN10_RS2) struct CD3DX12_RT_FORMAT_ARRAY : public D3D12_RT_FORMAT_ARRAY { CD3DX12_RT_FORMAT_ARRAY() = default; @@ -2473,8 +2485,10 @@ typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_STREAM_OUTPUT_DESC, typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_HS> CD3DX12_PIPELINE_STATE_STREAM_HS; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DS> CD3DX12_PIPELINE_STATE_STREAM_DS; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_PS> CD3DX12_PIPELINE_STATE_STREAM_PS; +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS> CD3DX12_PIPELINE_STATE_STREAM_AS; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_MS> CD3DX12_PIPELINE_STATE_STREAM_MS; +#endif typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_SHADER_BYTECODE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CS> CD3DX12_PIPELINE_STATE_STREAM_CS; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_BLEND_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_BLEND, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_BLEND_DESC; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_DEPTH_STENCIL_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_DEPTH_STENCIL, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_DEPTH_STENCIL; @@ -2485,7 +2499,9 @@ typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_RT_FORMAT_ARRAY, typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< DXGI_SAMPLE_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_DESC, DefaultSampleDesc> CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_DESC; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< UINT, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_SAMPLE_MASK, DefaultSampleMask> CD3DX12_PIPELINE_STATE_STREAM_SAMPLE_MASK; typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< D3D12_CACHED_PIPELINE_STATE, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_CACHED_PSO> CD3DX12_PIPELINE_STATE_STREAM_CACHED_PSO; +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) typedef CD3DX12_PIPELINE_STATE_STREAM_SUBOBJECT< CD3DX12_VIEW_INSTANCING_DESC, D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING, CD3DX12_DEFAULT> CD3DX12_PIPELINE_STATE_STREAM_VIEW_INSTANCING; +#endif //------------------------------------------------------------------------------------------------ // Stream Parser Helpers @@ -2506,8 +2522,10 @@ struct ID3DX12PipelineParserCallbacks virtual void DSCb(const D3D12_SHADER_BYTECODE&) {} virtual void PSCb(const D3D12_SHADER_BYTECODE&) {} virtual void CSCb(const D3D12_SHADER_BYTECODE&) {} +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) virtual void ASCb(const D3D12_SHADER_BYTECODE&) {} virtual void MSCb(const D3D12_SHADER_BYTECODE&) {} +#endif virtual void BlendStateCb(const D3D12_BLEND_DESC&) {} virtual void DepthStencilStateCb(const D3D12_DEPTH_STENCIL_DESC&) {} virtual void DepthStencilState1Cb(const D3D12_DEPTH_STENCIL_DESC1&) {} @@ -2516,7 +2534,9 @@ struct ID3DX12PipelineParserCallbacks virtual void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY&) {} virtual void SampleDescCb(const DXGI_SAMPLE_DESC&) {} virtual void SampleMaskCb(UINT) {} +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) virtual void ViewInstancingCb(const D3D12_VIEW_INSTANCING_DESC&) {} +#endif virtual void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE&) {} // Error Callbacks @@ -2527,6 +2547,7 @@ struct ID3DX12PipelineParserCallbacks virtual ~ID3DX12PipelineParserCallbacks() = default; }; +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) struct D3DX12_MESH_SHADER_PIPELINE_STATE_DESC { ID3D12RootSignature* pRootSignature; @@ -2665,7 +2686,9 @@ struct CD3DX12_PIPELINE_STATE_STREAM2 return D; } }; +#endif // NTDDI_WIN10_VB +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) // CD3DX12_PIPELINE_STATE_STREAM1 Works on OS Build 16299+ (where there is a new view instancing subobject). // Use CD3DX12_PIPELINE_STATE_STREAM for OS Build 15063+ support. struct CD3DX12_PIPELINE_STATE_STREAM1 @@ -2695,6 +2718,7 @@ struct CD3DX12_PIPELINE_STATE_STREAM1 , CachedPSO(Desc.CachedPSO) , ViewInstancingDesc(CD3DX12_VIEW_INSTANCING_DESC(CD3DX12_DEFAULT())) {} +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) CD3DX12_PIPELINE_STATE_STREAM1(const D3DX12_MESH_SHADER_PIPELINE_STATE_DESC& Desc) noexcept : Flags(Desc.Flags) , NodeMask(Desc.NodeMask) @@ -2711,6 +2735,7 @@ struct CD3DX12_PIPELINE_STATE_STREAM1 , CachedPSO(Desc.CachedPSO) , ViewInstancingDesc(CD3DX12_VIEW_INSTANCING_DESC(CD3DX12_DEFAULT())) {} +#endif CD3DX12_PIPELINE_STATE_STREAM1(const D3D12_COMPUTE_PIPELINE_STATE_DESC& Desc) noexcept : Flags(Desc.Flags) , NodeMask(Desc.NodeMask) @@ -2779,8 +2804,9 @@ struct CD3DX12_PIPELINE_STATE_STREAM1 return D; } }; +#endif // NTDDI_WIN10_RS3 - +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) struct CD3DX12_PIPELINE_MESH_STATE_STREAM { CD3DX12_PIPELINE_MESH_STATE_STREAM() = default; @@ -2837,6 +2863,7 @@ struct CD3DX12_PIPELINE_MESH_STATE_STREAM return D; } }; +#endif // NTDDI_WIN10_VB // CD3DX12_PIPELINE_STATE_STREAM works on OS Build 15063+ but does not support new subobject(s) added in OS Build 16299+. // See CD3DX12_PIPELINE_STATE_STREAM1 for instance. @@ -2931,6 +2958,7 @@ struct CD3DX12_PIPELINE_STATE_STREAM } }; +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) struct CD3DX12_PIPELINE_STATE_STREAM2_PARSE_HELPER : public ID3DX12PipelineParserCallbacks { CD3DX12_PIPELINE_STATE_STREAM2 PipelineStream; @@ -2990,11 +3018,15 @@ struct CD3DX12_PIPELINE_STATE_STREAM2_PARSE_HELPER : public ID3DX12PipelineParse private: bool SeenDSS; }; - +#endif // NTDDI_WIN10_VB struct CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER : public ID3DX12PipelineParserCallbacks { +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) CD3DX12_PIPELINE_STATE_STREAM1 PipelineStream; +#else + CD3DX12_PIPELINE_STATE_STREAM PipelineStream; +#endif CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER() noexcept : SeenDSS(false) { @@ -3043,7 +3075,9 @@ struct CD3DX12_PIPELINE_STATE_STREAM_PARSE_HELPER : public ID3DX12PipelineParser void RTVFormatsCb(const D3D12_RT_FORMAT_ARRAY& RTVFormats) override {PipelineStream.RTVFormats = RTVFormats;} void SampleDescCb(const DXGI_SAMPLE_DESC& SampleDesc) override {PipelineStream.SampleDesc = SampleDesc;} void SampleMaskCb(UINT SampleMask) override {PipelineStream.SampleMask = SampleMask;} +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) void ViewInstancingCb(const D3D12_VIEW_INSTANCING_DESC& ViewInstancingDesc) override {PipelineStream.ViewInstancingDesc = CD3DX12_VIEW_INSTANCING_DESC(ViewInstancingDesc);} +#endif void CachedPSOCb(const D3D12_CACHED_PIPELINE_STATE& CachedPSO) override {PipelineStream.CachedPSO = CachedPSO;} private: @@ -3120,6 +3154,7 @@ inline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& pCallbacks->CSCb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::CS); break; +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_AS: pCallbacks->ASCb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM2::AS); @@ -3128,6 +3163,7 @@ inline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& pCallbacks->MSCb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM2::MS); break; +#endif case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_STREAM_OUTPUT: pCallbacks->StreamOutputCb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::StreamOutput); @@ -3188,10 +3224,12 @@ inline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& pCallbacks->FlagsCb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM::Flags); break; +#if defined(NTDDI_WIN10_RS3) && (NTDDI_VERSION >= NTDDI_WIN10_RS3) case D3D12_PIPELINE_STATE_SUBOBJECT_TYPE_VIEW_INSTANCING: pCallbacks->ViewInstancingCb(*reinterpret_cast(pStream)); SizeOfSubobject = sizeof(CD3DX12_PIPELINE_STATE_STREAM1::ViewInstancingDesc); break; +#endif default: pCallbacks->ErrorUnknownSubobject(SubobjectType); return E_INVALIDARG; @@ -3200,7 +3238,10 @@ inline HRESULT D3DX12ParsePipelineStream(const D3D12_PIPELINE_STATE_STREAM_DESC& return S_OK; } +#endif // NTDDI_WIN10_RS2 +// Requires the Windows 10 October 2018 Update SDK (17763) +#if defined(NTDDI_WIN10_RS5) && (NTDDI_VERSION >= NTDDI_WIN10_RS5) //------------------------------------------------------------------------------------------------ inline bool operator==( const D3D12_CLEAR_VALUE &a, const D3D12_CLEAR_VALUE &b) noexcept { @@ -3282,17 +3323,7 @@ inline bool operator==( const D3D12_RENDER_PASS_DEPTH_STENCIL_DESC &a, const D3D #include #include #include -#ifndef D3DX12_USE_ATL #include -#define D3DX12_COM_PTR Microsoft::WRL::ComPtr -#define D3DX12_COM_PTR_GET(x) x.Get() -#define D3DX12_COM_PTR_ADDRESSOF(x) x.GetAddressOf() -#else -#include -#define D3DX12_COM_PTR ATL::CComPtr -#define D3DX12_COM_PTR_GET(x) x.p -#define D3DX12_COM_PTR_ADDRESSOF(x) &x.p -#endif //------------------------------------------------------------------------------------------------ class CD3DX12_STATE_OBJECT_DESC @@ -3480,7 +3511,9 @@ class CD3DX12_STATE_OBJECT_DESC friend class CD3DX12_HIT_GROUP_SUBOBJECT; friend class CD3DX12_RAYTRACING_SHADER_CONFIG_SUBOBJECT; friend class CD3DX12_RAYTRACING_PIPELINE_CONFIG_SUBOBJECT; +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) friend class CD3DX12_RAYTRACING_PIPELINE_CONFIG1_SUBOBJECT; +#endif friend class CD3DX12_GLOBAL_ROOT_SIGNATURE_SUBOBJECT; friend class CD3DX12_LOCAL_ROOT_SIGNATURE_SUBOBJECT; friend class CD3DX12_STATE_OBJECT_CONFIG_SUBOBJECT; @@ -3618,7 +3651,7 @@ class CD3DX12_EXISTING_COLLECTION_SUBOBJECT } void* Data() noexcept override { return &m_Desc; } D3D12_EXISTING_COLLECTION_DESC m_Desc; - D3DX12_COM_PTR m_CollectionRef; + Microsoft::WRL::ComPtr m_CollectionRef; CD3DX12_STATE_OBJECT_DESC::StringContainer m_Strings; std::vector m_Exports; }; @@ -3867,6 +3900,7 @@ class CD3DX12_RAYTRACING_PIPELINE_CONFIG_SUBOBJECT }; //------------------------------------------------------------------------------------------------ +#if defined(NTDDI_WIN10_VB) && (NTDDI_VERSION >= NTDDI_WIN10_VB) class CD3DX12_RAYTRACING_PIPELINE_CONFIG1_SUBOBJECT : public CD3DX12_STATE_OBJECT_DESC::SUBOBJECT_HELPER_BASE { @@ -3900,6 +3934,7 @@ class CD3DX12_RAYTRACING_PIPELINE_CONFIG1_SUBOBJECT void* Data() noexcept override { return &m_Desc; } D3D12_RAYTRACING_PIPELINE_CONFIG1 m_Desc; }; +#endif // NTDDI_WIN10_VB //------------------------------------------------------------------------------------------------ class CD3DX12_GLOBAL_ROOT_SIGNATURE_SUBOBJECT @@ -3924,15 +3959,15 @@ class CD3DX12_GLOBAL_ROOT_SIGNATURE_SUBOBJECT return D3D12_STATE_SUBOBJECT_TYPE_GLOBAL_ROOT_SIGNATURE; } operator const D3D12_STATE_SUBOBJECT&() const noexcept { return *m_pSubobject; } - operator ID3D12RootSignature*() const noexcept { return D3DX12_COM_PTR_GET(m_pRootSig); } + operator ID3D12RootSignature*() const noexcept { return m_pRootSig.Get(); } private: void Init() noexcept { SUBOBJECT_HELPER_BASE::Init(); m_pRootSig = nullptr; } - void* Data() noexcept override { return D3DX12_COM_PTR_ADDRESSOF(m_pRootSig); } - D3DX12_COM_PTR m_pRootSig; + void* Data() noexcept override { return m_pRootSig.GetAddressOf(); } + Microsoft::WRL::ComPtr m_pRootSig; }; //------------------------------------------------------------------------------------------------ @@ -3958,15 +3993,15 @@ class CD3DX12_LOCAL_ROOT_SIGNATURE_SUBOBJECT return D3D12_STATE_SUBOBJECT_TYPE_LOCAL_ROOT_SIGNATURE; } operator const D3D12_STATE_SUBOBJECT&() const noexcept { return *m_pSubobject; } - operator ID3D12RootSignature*() const noexcept { return D3DX12_COM_PTR_GET(m_pRootSig); } + operator ID3D12RootSignature*() const noexcept { return m_pRootSig.Get(); } private: void Init() noexcept { SUBOBJECT_HELPER_BASE::Init(); m_pRootSig = nullptr; } - void* Data() noexcept override { return D3DX12_COM_PTR_ADDRESSOF(m_pRootSig); } - D3DX12_COM_PTR m_pRootSig; + void* Data() noexcept override { return m_pRootSig.GetAddressOf(); } + Microsoft::WRL::ComPtr m_pRootSig; }; //------------------------------------------------------------------------------------------------ @@ -4037,13 +4072,9 @@ class CD3DX12_NODE_MASK_SUBOBJECT D3D12_NODE_MASK m_Desc; }; -#undef D3DX12_COM_PTR -#undef D3DX12_COM_PTR_GET -#undef D3DX12_COM_PTR_ADDRESSOF #endif // #ifndef D3DX12_NO_STATE_OBJECT_HELPERS +#endif // NTDDI_WIN10_RS5 #endif // defined( __cplusplus ) #endif //__D3DX12_H__ - -