diff --git a/.github/workflows/android-cts-build.yml b/.github/workflows/android-cts-build.yml
index 100154ea..43635ba7 100644
--- a/.github/workflows/android-cts-build.yml
+++ b/.github/workflows/android-cts-build.yml
@@ -26,7 +26,7 @@ jobs:
fetch-depth: "${{ github.event.release && '0' || '1'}}"
- name: Get modern CMake and Ninja
- uses: lukka/get-cmake@v3.30.3
+ uses: lukka/get-cmake@v3.30.5
- name: set up JDK 11
uses: actions/setup-java@v4
diff --git a/.github/workflows/android-cts-pr.yml b/.github/workflows/android-cts-pr.yml
index acae4f12..c9bc83c7 100644
--- a/.github/workflows/android-cts-pr.yml
+++ b/.github/workflows/android-cts-pr.yml
@@ -19,7 +19,7 @@ jobs:
lfs: true
- name: Get modern CMake and Ninja
- uses: lukka/get-cmake@v3.30.3
+ uses: lukka/get-cmake@v3.30.5
- name: set up JDK 11
uses: actions/setup-java@v4
diff --git a/.github/workflows/msvc-build-preset.yml b/.github/workflows/msvc-build-preset.yml
index 877b9cc5..5b94b950 100644
--- a/.github/workflows/msvc-build-preset.yml
+++ b/.github/workflows/msvc-build-preset.yml
@@ -36,7 +36,7 @@ jobs:
fetch-depth: "${{ github.event.release && '0' || '1'}}"
- name: Get modern CMake and Ninja
- uses: lukka/get-cmake@v3.30.3
+ uses: lukka/get-cmake@v3.30.5
- name: Add msbuild to PATH
uses: microsoft/setup-msbuild@v2
diff --git a/.reuse/dep5 b/.reuse/dep5
index ac74aa84..ac059d99 100644
--- a/.reuse/dep5
+++ b/.reuse/dep5
@@ -50,7 +50,7 @@ Files: src/external/tinygltf/README.md
src/external/tinygltf/tiny_gltf.h
Copyright: 2015-Present, Syoyo Fujita, Aurélien Chatelain and many contributors
License: MIT
-Comment: Unmodified, vendored copy of a subset of the tiny-gltf repo v2.8.9
+Comment: Unmodified, vendored copy of a subset of the tiny-gltf repo v2.9.3
Files: src/external/d3dx12/*
Copyright: Copyright (c) Microsoft Corporation.
diff --git a/changes/conformance/mr.2578.gl.md b/changes/conformance/mr.2578.gl.md
new file mode 100644
index 00000000..6b860722
--- /dev/null
+++ b/changes/conformance/mr.2578.gl.md
@@ -0,0 +1,2 @@
+- Improvement: Update `stb_image` from 2.27 to 2.30 (latest upstream) for fixes, security improvements, and optimizations.
+- Improvement: Update `stb_typetype` to latest upstream for float comparison fixes.
diff --git a/changes/conformance/mr.3017.gl.md b/changes/conformance/mr.3017.gl.md
new file mode 100644
index 00000000..aa564c9e
--- /dev/null
+++ b/changes/conformance/mr.3017.gl.md
@@ -0,0 +1 @@
+Improvement: Reorganize session state tests and use test sections, annotating assertions with spec links.
diff --git a/changes/conformance/mr.3351.gl.md b/changes/conformance/mr.3351.gl.md
new file mode 100644
index 00000000..fc9ec4a6
--- /dev/null
+++ b/changes/conformance/mr.3351.gl.md
@@ -0,0 +1,4 @@
+---
+- issue.2239.gl
+---
+- New test: Show a perceptively-smooth gradient in two swapchain formats or two layer types (projection vs quad), to do basic rendering verification. This primarily catches issues where non-linear textures are being interpreted as linear or vice-versa in a runtime's compositor.
diff --git a/changes/conformance/mr.3366.gl.md b/changes/conformance/mr.3366.gl.md
new file mode 100644
index 00000000..6d6c98b4
--- /dev/null
+++ b/changes/conformance/mr.3366.gl.md
@@ -0,0 +1 @@
+Improvement: Update tinygltf to version 2.9.3.
diff --git a/changes/conformance/mr.3489.gl.md b/changes/conformance/mr.3489.gl.md
new file mode 100644
index 00000000..b414ea44
--- /dev/null
+++ b/changes/conformance/mr.3489.gl.md
@@ -0,0 +1 @@
+Improvement: List failed test cases, and unmatched test specs, at end of CTS run.
diff --git a/changes/conformance/mr.3493.gl.md b/changes/conformance/mr.3493.gl.md
new file mode 100644
index 00000000..b6afca7f
--- /dev/null
+++ b/changes/conformance/mr.3493.gl.md
@@ -0,0 +1 @@
+- Fix: Update generated code to allow dash in interaction profile paths.
diff --git a/changes/conformance/mr.3499.gl.md b/changes/conformance/mr.3499.gl.md
new file mode 100644
index 00000000..af0bcd80
--- /dev/null
+++ b/changes/conformance/mr.3499.gl.md
@@ -0,0 +1,4 @@
+---
+- mr.3499.gl
+---
+Improvement: Add warnings if supporting OpenXR 1.1 but not supporting optional, but recommended, extensions providing compatibility for OpenXR 1.0 apps/engines.
diff --git a/changes/conformance/mr.3506.gl.md b/changes/conformance/mr.3506.gl.md
new file mode 100644
index 00000000..ed72abca
--- /dev/null
+++ b/changes/conformance/mr.3506.gl.md
@@ -0,0 +1 @@
+Fix: Allow interaction profiles which do not expose boolean paths to be tested.
diff --git a/changes/conformance/mr.3507.gl.1.md b/changes/conformance/mr.3507.gl.1.md
new file mode 100644
index 00000000..ad188b5d
--- /dev/null
+++ b/changes/conformance/mr.3507.gl.1.md
@@ -0,0 +1 @@
+- Improvement: Make generated interaction profile sources reproducible/deterministic.
diff --git a/changes/conformance/mr.3507.gl.2.md b/changes/conformance/mr.3507.gl.2.md
new file mode 100644
index 00000000..96dcd82e
--- /dev/null
+++ b/changes/conformance/mr.3507.gl.2.md
@@ -0,0 +1,5 @@
+---
+- mr.3507.gl.2
+- mr.3521.gl
+---
+- Fix: Correctly parse and process interaction profile path and binding path dependencies from XML, and clean up code in `interaction_profile_processor.py`.
diff --git a/changes/conformance/mr.3507.gl.md b/changes/conformance/mr.3507.gl.md
new file mode 100644
index 00000000..9369faca
--- /dev/null
+++ b/changes/conformance/mr.3507.gl.md
@@ -0,0 +1,4 @@
+---
+- issue.2350.gl
+---
+- Fix: Include interaction profile dependencies in generated binding path dependencies.
diff --git a/changes/conformance/mr.3517.gl.md b/changes/conformance/mr.3517.gl.md
new file mode 100644
index 00000000..618ebadd
--- /dev/null
+++ b/changes/conformance/mr.3517.gl.md
@@ -0,0 +1,6 @@
+---
+- mr.3517.gl
+- mr.3541.gl
+- mr.3544.gl
+---
+- Fix: Add missing XML description of `EXT_hand_interaction` additions to several interaction profiles, affecting generated interaction profile tests.
diff --git a/changes/conformance/mr.3521.gl.md b/changes/conformance/mr.3521.gl.md
new file mode 100644
index 00000000..f77c5879
--- /dev/null
+++ b/changes/conformance/mr.3521.gl.md
@@ -0,0 +1 @@
+- Improvement: Correct the build-time dependencies of the generated interaction profile data.
diff --git a/changes/conformance/mr.3523.gl.md b/changes/conformance/mr.3523.gl.md
new file mode 100644
index 00000000..372f9359
--- /dev/null
+++ b/changes/conformance/mr.3523.gl.md
@@ -0,0 +1 @@
+New test: When using `XR_FB_space_warp`, verify runtime returns `XR_ERROR_VALIDATION_FAILURE` if `nearZ` is equal to `farZ`
diff --git a/changes/conformance/mr.3524.gl.md b/changes/conformance/mr.3524.gl.md
new file mode 100644
index 00000000..dda7f881
--- /dev/null
+++ b/changes/conformance/mr.3524.gl.md
@@ -0,0 +1,4 @@
+---
+- mr.3506.gl
+---
+Improvement: Note in the Usage document that `/interaction_profiles/ext/hand_interaction_ext` and `/interaction_profiles/ext/eye_gaze_interaction` are generic interaction profiles that should be tested if supported.
diff --git a/changes/conformance/mr.3527.gl.md b/changes/conformance/mr.3527.gl.md
new file mode 100644
index 00000000..098d2da2
--- /dev/null
+++ b/changes/conformance/mr.3527.gl.md
@@ -0,0 +1 @@
+Improvement: added support for `PRIMARY_STEREO_WITH_FOVEATED_INSET` in `xrLocateViews` tests.
diff --git a/changes/conformance/mr.3534.gl.md b/changes/conformance/mr.3534.gl.md
new file mode 100644
index 00000000..b6484234
--- /dev/null
+++ b/changes/conformance/mr.3534.gl.md
@@ -0,0 +1,5 @@
+---
+- mr.3534.gl
+- mr.3559.gl
+---
+Improvement: Add additional tests for `xrGetInputSourceLocalizedName`
diff --git a/changes/conformance/mr.3547.gl.md b/changes/conformance/mr.3547.gl.md
new file mode 100644
index 00000000..940c0ca2
--- /dev/null
+++ b/changes/conformance/mr.3547.gl.md
@@ -0,0 +1 @@
+- Fix: remove unused `functionPtr` field in global `FunctionInfoMap` as it is invalid if called with a different instance
diff --git a/changes/conformance/mr.3553.gl.md b/changes/conformance/mr.3553.gl.md
new file mode 100644
index 00000000..c6c3c4fc
--- /dev/null
+++ b/changes/conformance/mr.3553.gl.md
@@ -0,0 +1,2 @@
+- Improvement: Add command lines for Android for the self tests in the Usage document.
+- Fix: Correct an outdated description of the self tests in the Usage document, glTF files now load asynchronously in those tests.
diff --git a/changes/conformance/mr.3562.gl.md b/changes/conformance/mr.3562.gl.md
new file mode 100644
index 00000000..73492d2b
--- /dev/null
+++ b/changes/conformance/mr.3562.gl.md
@@ -0,0 +1 @@
+- Fix: Internal cross-references in the "Submission Package" section of the Usage document.
diff --git a/changes/registry/mr.3513.gl.md b/changes/registry/mr.3513.gl.md
deleted file mode 100644
index dab7f51f..00000000
--- a/changes/registry/mr.3513.gl.md
+++ /dev/null
@@ -1,5 +0,0 @@
----
-- issue.2350.gl
-- issue.2375.gl
----
-Fix: Correct XML description of OpenXR 1.1 related additions to the promoted Meta Touch Plus, Touch Pro, and Touch (Rift CV1) controller interaction profiles.
diff --git a/specification/Makefile b/specification/Makefile
index f9e92a09..76ae74a7 100644
--- a/specification/Makefile
+++ b/specification/Makefile
@@ -39,7 +39,7 @@ endif
VERSIONS := XR_VERSION_1_0 XR_VERSION_1_1 XR_LOADER_VERSION_1_0
VERSIONOPTIONS := $(foreach version,$(VERSIONS),-feature $(version))
-SPECREVISION = 1.1.41
+SPECREVISION = 1.1.42
REVISION_COMPONENTS = $(subst ., ,$(SPECREVISION))
MAJORMINORVER = $(word 1,$(REVISION_COMPONENTS)).$(word 2,$(REVISION_COMPONENTS))
@@ -334,7 +334,8 @@ html: $(HTMLSPEC)
ASCIIDOCTOR_TARGETS += $(HTMLSPEC)
# Target-specific variables and deps customizing the AsciiDoctor rule
-$(HTMLSPEC): ATTRIBOPTS += -a sectanchors
+# EXTRAATRIBS is for build-time customization
+$(HTMLSPEC): ATTRIBOPTS += -a sectanchors $(EXTRAATTRIBS)
$(HTMLSPEC): ADOCOPTS += $(ADOCHTMLOPTS)
$(HTMLSPEC): $(COMMONDOCS)
@@ -349,7 +350,8 @@ pdfA4: $(PDFA4SPEC)
ASCIIDOCTOR_TARGETS += $(PDFSPEC) $(PDFA4SPEC)
# Target-specific variables and deps customizing the AsciiDoctor rule
-$(PDFSPEC) $(PDFA4SPEC): BACKEND_ARGS=--backend pdf --require asciidoctor-pdf -a compress --require ./scripts/pdf-index-customizer.rb
+# EXTRAATRIBS is for build-time customization
+$(PDFSPEC) $(PDFA4SPEC): BACKEND_ARGS=--backend pdf --require asciidoctor-pdf -a compress --require ./scripts/pdf-index-customizer.rb $(EXTRAATTRIBS)
$(PDFSPEC): PAGESIZE=LETTER
$(PDFA4SPEC): PAGESIZE=A4
$(PDFSPEC) $(PDFA4SPEC): $(COMMONDOCS)
diff --git a/specification/registry/xr.xml b/specification/registry/xr.xml
index d7a4b1c8..17ea6811 100644
--- a/specification/registry/xr.xml
+++ b/specification/registry/xr.xml
@@ -135,7 +135,7 @@ maintained in the default branch of the Khronos OpenXR GitHub project.
updates them automatically by processing a line at a time.
-->
// OpenXR current version number.
-#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 41)
+#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(1, 1, 42)
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
-
+
@@ -8474,8 +8499,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
-
@@ -8491,15 +8514,13 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
-
-
+
@@ -8588,14 +8609,19 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
+
+
+
+
+
+
-
+
@@ -8623,9 +8649,8 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
-
+
@@ -8689,7 +8714,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8718,7 +8742,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8747,9 +8770,8 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
-
+
@@ -8781,7 +8803,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8810,7 +8831,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8835,7 +8855,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8860,7 +8879,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8915,7 +8933,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -8924,7 +8941,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
@@ -9763,6 +9779,11 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
@@ -10208,7 +10229,7 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
+
@@ -10229,6 +10250,12 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
+
+
+
+
+
@@ -10659,8 +10686,20 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -11242,6 +11281,17 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
+
+
+
+
+
+
+
+
+
+
@@ -11349,6 +11399,11 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
@@ -11367,12 +11422,6 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
-
-
-
-
-
-
@@ -12367,6 +12416,17 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
+
+
+
+
+
+
+
+
+
+
@@ -12595,6 +12655,40 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
@@ -15873,6 +15967,11 @@ typedef XrResult (XRAPI_PTR *PFN_xrCreateApiLayerInstance)(
+
+
+
+
+
diff --git a/specification/scripts/docgenerator.py b/specification/scripts/docgenerator.py
index 72960e49..e31f5a6e 100644
--- a/specification/scripts/docgenerator.py
+++ b/specification/scripts/docgenerator.py
@@ -34,6 +34,7 @@ class _Enumerant:
comment: str
extname: Optional[str] = None
deprecated: Optional[str] = None
+ alias: Optional[str] = None
def orgLevelKey(name):
@@ -447,7 +448,6 @@ def genStruct(self, typeinfo, typeName, alias):
self.writeInclude('structs', typeName, body)
-
def _maybe_return_enumerant_object_for_table(
self, elems, elem, missing_comments: List[str]
) -> Optional[_Enumerant]:
@@ -466,15 +466,21 @@ def _maybe_return_enumerant_object_for_table(
return
comment = elem.get("comment")
+ alias = elem.get("alias")
if comment is None:
if name.endswith("_UNKNOWN") and num_val == 0:
# This is a placeholder for 0-initialization to be clearly invalid.
# Just skip this silently
return
- # Skip but record this in case it is an odd-one-out missing
- # a comment.
- missing_comments.append(name)
- return
+ if alias is not None:
+ # oh it's an alias. That's fine. We can generate a comment.
+ comment = f"Alias for ename:{alias}"
+
+ else:
+ # Skip but record this in case it is an odd-one-out missing
+ # a comment.
+ missing_comments.append(name)
+ return
assert num_val is not None
@@ -531,13 +537,18 @@ def genEnumTable(self, groupinfo, groupName):
if maybe_data:
values.append(maybe_data)
- if values:
- # If any had a comment, output it.
+ if values and any(v.alias is None for v in values):
+ # If any had a (non-alias) comment, output it.
if missing_comments:
- self.logMsg('warn', 'The following values for', groupName,
- 'were omitted from the table due to missing comment attributes:',
- ', '.join(missing_comments))
+ # Warn if it looks like we have comments, but some were missed.
+ if len(missing_comments) < len(values):
+ self.logMsg('warn', 'The following value(s) for', groupName,
+ 'were omitted from the table due to missing comment attributes:',
+ ', '.join(missing_comments))
+ else:
+ self.logMsg('warn', 'The enumeration ', groupName,
+ 'appears to be missing comments for most of its elements')
group_type = groupinfo.elem.get('type')
if groupName == self.result_type:
diff --git a/specification/scripts/update_version.py b/specification/scripts/update_version.py
index 1c4ba8c9..a6d4bbc9 100755
--- a/specification/scripts/update_version.py
+++ b/specification/scripts/update_version.py
@@ -17,12 +17,10 @@
def update_makefile(fn, spec_version):
for line in fileinput.input(fn, inplace=True):
- printed = False
if 'SPECREVISION = ' in line:
- printed = True
print('SPECREVISION = %s.%s.%s' % spec_version)
- if not printed:
- print(f"{line}", end='')
+ else:
+ print(line, end='')
if __name__ == "__main__":
@@ -32,8 +30,6 @@ def update_makefile(fn, spec_version):
config = configparser.ConfigParser()
config.read_file(fp)
versions = config['Version']
- major_version = versions['MAJOR']
- minor_version = versions['MINOR']
spec_version = (versions['MAJOR'], versions['MINOR'], versions['PATCH'])
# Now update the version in the appropriate places in the
@@ -41,13 +37,10 @@ def update_makefile(fn, spec_version):
#
print('Replacing version lines in the registry')
for line in fileinput.input('registry/xr.xml', inplace=True):
- printed = False
- if 'XR_CURRENT_API_VERSION' in line:
- if 'XR_MAKE_VERSION' in line:
- printed = True
- print('#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(%s, %s, %s)' % spec_version)
- if not printed:
- print(f"{line}", end='')
+ if 'XR_CURRENT_API_VERSION' in line and 'XR_MAKE_VERSION' in line:
+ print('#define XR_CURRENT_API_VERSION XR_MAKE_VERSION(%s, %s, %s)' % spec_version)
+ else:
+ print(line, end='')
# Now update the version in the appropriate places in the
# specification make file (Makefile).
diff --git a/src/common/platform_utils.hpp b/src/common/platform_utils.hpp
index 19cd41cb..59b5bf2f 100644
--- a/src/common/platform_utils.hpp
+++ b/src/common/platform_utils.hpp
@@ -71,6 +71,8 @@
#define XR_ARCH_ABI "riscv64"
#elif defined(__sparc__) && defined(__arch64__)
#define XR_ARCH_ABI "sparc64"
+#elif defined(__loongarch64)
+#define XR_ARCH_ABI "loong64"
#else
#error "No architecture string known!"
#endif
diff --git a/src/conformance/conformance_test/composition_examples/gradient_linearity.png b/src/conformance/conformance_test/composition_examples/gradient_linearity.png
new file mode 100644
index 00000000..32220f75
--- /dev/null
+++ b/src/conformance/conformance_test/composition_examples/gradient_linearity.png
@@ -0,0 +1,3 @@
+version https://git-lfs.github.com/spec/v1
+oid sha256:fda1ad7752044e8a8087f415c9cb6df65b7a5dbdd77db80b2e97736508151caa
+size 39900
diff --git a/src/conformance/conformance_test/composition_examples/gradient_linearity.png.license b/src/conformance/conformance_test/composition_examples/gradient_linearity.png.license
new file mode 100644
index 00000000..c94a118e
--- /dev/null
+++ b/src/conformance/conformance_test/composition_examples/gradient_linearity.png.license
@@ -0,0 +1,3 @@
+SPDX-FileCopyrightText: 2024, The Khronos Group Inc.
+
+SPDX-License-Identifier: Apache-2.0
diff --git a/src/conformance/conformance_test/conformance_test.cpp b/src/conformance/conformance_test/conformance_test.cpp
index efed4359..a3eec100 100644
--- a/src/conformance/conformance_test/conformance_test.cpp
+++ b/src/conformance/conformance_test/conformance_test.cpp
@@ -177,6 +177,65 @@ namespace
}
}
+ TEST_CASE("ValidateExpectedFeatures")
+ {
+ // Create and destroy an XrInstance with a particular apiVersion to validate that
+ // it is possible and supported.
+ auto validateOpenXRVersionSupported = [](XrVersion apiVersion) -> bool {
+ GlobalData& globalData = GetGlobalData();
+
+ XrInstanceCreateInfo createInfo{XR_TYPE_INSTANCE_CREATE_INFO};
+ createInfo.applicationInfo.applicationVersion = 1;
+ strcpy(createInfo.applicationInfo.applicationName, "conformance test");
+ createInfo.applicationInfo.apiVersion = apiVersion;
+ createInfo.enabledApiLayerCount = (uint32_t)globalData.enabledAPILayerNames.size();
+ createInfo.enabledApiLayerNames = globalData.enabledAPILayerNames.data();
+
+ StringVec extensions(globalData.enabledInstanceExtensionNames);
+ createInfo.enabledExtensionCount = (uint32_t)extensions.size();
+ createInfo.enabledExtensionNames = extensions.data();
+
+ if (globalData.requiredPlatformInstanceCreateStruct != nullptr) {
+ createInfo.next = globalData.requiredPlatformInstanceCreateStruct;
+ }
+
+ XrInstance instance{XR_NULL_HANDLE};
+ XrResult result = xrCreateInstance(&createInfo, &instance);
+ if (XR_FAILED(result)) {
+ return false;
+ }
+
+ xrDestroyInstance(instance);
+ return true;
+ };
+
+ SECTION("OpenXR 1.1")
+ {
+ GlobalData& globalData = GetGlobalData();
+
+ FeatureSet available;
+ globalData.PopulateVersionAndAvailableExtensions(available);
+
+ if (available.Get(FeatureBitIndex::BIT_XR_VERSION_1_1)) {
+ bool openxr1_1_supported = validateOpenXRVersionSupported(XR_API_VERSION_1_1);
+ bool openxr1_0_supported = validateOpenXRVersionSupported(XR_API_VERSION_1_0);
+ REQUIRE(openxr1_1_supported);
+
+ if (!available.Get(FeatureBitIndex::BIT_XR_KHR_locate_spaces)) {
+ WARN(
+ "Runtime supports OpenXR 1.1 but does not support XR_KHR_locate_spaces; this is not strictly required but is surprising.");
+ }
+ if (!available.Get(FeatureBitIndex::BIT_XR_KHR_maintenance1)) {
+ WARN(
+ "Runtime supports OpenXR 1.1 but does not support XR_KHR_maintenance1; this is not strictly required but is surprising.");
+ }
+ if (!openxr1_0_supported) {
+ WARN("Runtime supports OpenXR 1.1 but does not support OpenXR 1.0; this is not strictly required but is surprising.");
+ }
+ }
+ }
+ }
+
// Ensure conformance is configured correctly.
TEST_CASE("ValidateEnvironment")
{
@@ -339,6 +398,8 @@ namespace
globalData.options.viewConfiguration = arg;
if (striequal(globalData.options.viewConfiguration.c_str(), "stereo"))
globalData.options.viewConfigurationValue = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO;
+ else if (striequal(globalData.options.viewConfiguration.c_str(), "stereoFoveated"))
+ globalData.options.viewConfigurationValue = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO_WITH_FOVEATED_INSET;
else if (striequal(globalData.options.viewConfiguration.c_str(), "mono"))
globalData.options.viewConfigurationValue = XR_VIEW_CONFIGURATION_TYPE_PRIMARY_MONO;
else {
@@ -410,8 +471,8 @@ namespace
("Choose which hands to test: left, right, or both. Default is both.")
.optional()
- | Opt(parseViewConfig, "Stereo|Mono") // view configuration
- ["-V"]["--viewConfiguration"] //
+ | Opt(parseViewConfig, "Stereo|StereoFoveated|Mono") // view configuration
+ ["-V"]["--viewConfiguration"] //
("Specify view configuration. Default is Stereo.")
.optional()
@@ -519,8 +580,8 @@ namespace
Base::testCaseEnded(testCaseStats);
Conformance::GlobalData& globalData = Conformance::GetGlobalData();
- globalData.conformanceReport.testSuccessCount += testCaseStats.totals.testCases.passed;
- globalData.conformanceReport.testFailureCount += testCaseStats.totals.testCases.failed;
+ globalData.conformanceReport.results[testCaseStats.testInfo->name].testSuccessCount += testCaseStats.totals.testCases.passed;
+ globalData.conformanceReport.results[testCaseStats.testInfo->name].testFailureCount += testCaseStats.totals.testCases.failed;
}
void sectionStarting(Catch::SectionInfo const& sectionInfo) override
@@ -547,10 +608,10 @@ namespace
m_sectionIndent--;
}
- void noMatchingTestCases(Catch::StringRef /* unmatchedSpec */) override
+ void noMatchingTestCases(Catch::StringRef unmatchedSpec) override
{
Conformance::GlobalData& globalData = Conformance::GetGlobalData();
- globalData.conformanceReport.unmatchedTestSpecs = true;
+ globalData.conformanceReport.unmatchedTestSpecs.push_back(unmatchedSpec.data());
}
void testRunEnded(Catch::TestRunStats const& testRunStats) override
@@ -704,7 +765,7 @@ XrcResult XRAPI_CALL xrcRunConformanceTests(const ConformanceLaunchSettings* con
int exitCode = CreateOrGetCatchSession().run();
Conformance::GlobalData& globalData = Conformance::GetGlobalData();
- *failureCount = globalData.conformanceReport.testFailureCount;
+ *failureCount = globalData.conformanceReport.TestFailureCount();
const auto& totals = globalData.conformanceReport.totals;
conformanceTestsRun = true;
@@ -712,7 +773,7 @@ XrcResult XRAPI_CALL xrcRunConformanceTests(const ConformanceLaunchSettings* con
if (skipActuallyTesting) {
*testResult = XRC_TEST_RESULT_SUCCESS;
}
- else if (globalData.conformanceReport.unmatchedTestSpecs && catchConfig.warnAboutUnmatchedTestSpecs()) {
+ else if (!globalData.conformanceReport.unmatchedTestSpecs.empty() && catchConfig.warnAboutUnmatchedTestSpecs()) {
*testResult = XRC_TEST_RESULT_UNMATCHED_TEST_SPEC;
}
else if (totals.testCases.total() == 0 && !catchConfig.zeroTestsCountAsSuccess()) {
diff --git a/src/conformance/conformance_test/test_GradientFormatsLinearVsNonLinear.cpp b/src/conformance/conformance_test/test_GradientFormatsLinearVsNonLinear.cpp
new file mode 100644
index 00000000..b4dac66e
--- /dev/null
+++ b/src/conformance/conformance_test/test_GradientFormatsLinearVsNonLinear.cpp
@@ -0,0 +1,299 @@
+// Copyright (c) 2019-2024, 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 "composition_utils.h"
+#include "graphics_plugin.h"
+#include "utilities/array_size.h"
+#include "utilities/bitmask_to_string.h"
+#include "utilities/swapchain_parameters.h"
+#include "utilities/throw_helpers.h"
+#include "utilities/types_and_constants.h"
+#include "utilities/xr_math_operators.h"
+
+#include
+
+#include
+
+#include
+#include
+
+namespace Conformance
+{
+ using namespace openxr::math_operators;
+
+ static XrSwapchainCreateInfo MakeDefaultSwapchainCreateInfo(int64_t imageFormat, const SwapchainCreateTestParameters& tp)
+ {
+ XrSwapchainCreateInfo createInfo{XR_TYPE_SWAPCHAIN_CREATE_INFO};
+ createInfo.faceCount = 1;
+ createInfo.format = imageFormat;
+ XrSwapchainCreateFlagsRefCPP(createInfo.createFlags) = tp.createFlagsVector[0];
+ XrSwapchainUsageFlagsRefCPP(createInfo.usageFlags) = tp.usageFlagsVector[0];
+ createInfo.sampleCount = 1;
+ createInfo.width = 64;
+ createInfo.height = 64;
+ createInfo.arraySize = tp.arrayCountVector[0];
+ createInfo.mipCount = tp.mipCountVector[0];
+ return createInfo;
+ }
+
+ namespace
+ {
+
+ constexpr int32_t labelImageWidth = 512;
+ constexpr int32_t labelImageHeight = 32;
+ constexpr int32_t labelFontSize = 18; // some format names are long!
+ constexpr float labelWidth = 2.0f;
+ constexpr float labelHeight = labelWidth * labelImageHeight / labelImageWidth;
+ constexpr float labelMargin = 0.2f;
+ inline XrCompositionLayerQuad* MakeFormatLabel(CompositionHelper& compositionHelper, XrSpace viewSpace, const std::string& label,
+ const XrVector3f& position)
+ {
+
+ return compositionHelper.CreateQuadLayer(
+ compositionHelper.CreateStaticSwapchainImage(
+ CreateTextImage(labelImageWidth, labelImageHeight, label.c_str(), labelFontSize, WordWrap::Disabled)),
+ viewSpace, labelWidth, {Quat::Identity, position});
+ }
+
+ constexpr int32_t aspectRatio = 8;
+ constexpr int32_t gradientImageHeight = 32;
+ constexpr int32_t gradientImageWidth = gradientImageHeight * aspectRatio;
+ constexpr float gradientWidth = 1.0f;
+ constexpr float gradientHeight = gradientWidth / aspectRatio;
+ constexpr float quadZ = -3; // How far away quads are placed.
+ constexpr float margin = 0.02f; // the gap between quads
+ constexpr float yOffset = (gradientHeight + margin) / 2;
+
+ inline MeshHandle MakeGradientMesh(IGraphicsPlugin& graphicsPlugin, SwapchainFormat::RawColorComponents referenceComponents)
+ {
+ // 0-2
+ // |/|
+ // 1-3
+ std::vector vertices;
+ vertices.reserve(2 * gradientImageWidth);
+ for (int col = 0; col < gradientImageWidth; col++) {
+ float value = col / (float)gradientImageWidth;
+
+ // if any of the other format's color channels aren't present,
+ // they should be sampled as zero, so also zero them here to match
+ using Components = SwapchainFormat::RawColorComponents;
+ XrColor4f color{
+ referenceComponents & Components::r ? value : 0.0f,
+ referenceComponents & Components::g ? value : 0.0f,
+ referenceComponents & Components::b ? value : 0.0f,
+ 1.0,
+ };
+
+ color = ColorUtils::FromSRGB(color); // perceptual gradient instead of linear
+ float x = -(gradientWidth / 2) + gradientWidth * value;
+ vertices.push_back(Geometry::Vertex{{x, gradientHeight / 2, 0}, {color.r, color.g, color.b}});
+ vertices.push_back(Geometry::Vertex{{x, -gradientHeight / 2, 0}, {color.r, color.g, color.b}});
+ }
+ const uint16_t quadIndices[] = {1, 0, 2, 2, 3, 1};
+ std::vector indices;
+ indices.reserve((gradientImageWidth - 1) * ArraySize(quadIndices));
+ for (int col = 0; col < gradientImageWidth - 1; col++) {
+ for (const uint16_t index : quadIndices) {
+ indices.push_back((uint16_t)(col * 2 + index));
+ }
+ }
+
+ return graphicsPlugin.MakeSimpleMesh(indices, vertices);
+ }
+ } // namespace
+
+ TEST_CASE("GradientFormatsLinearVsNonLinear", "[composition][interactive]")
+ {
+ const GlobalData& globalData = GetGlobalData();
+ if (!globalData.IsUsingGraphicsPlugin()) {
+ // Nothing to check - no graphics plugin means no swapchain
+ SKIP("Cannot test swapchains without a graphics plugin");
+ }
+
+ CompositionHelper compositionHelper("Linear vs Non-Linear");
+ InteractiveLayerManager interactiveLayerManager(compositionHelper, "gradient_linearity.png",
+ "Both gradients should match both each other"
+ " and the example image, except for banding artifacts,"
+ " and should appear perceptually linear."
+ " Banding may introduce small color artifacts, but"
+ " the gradients should be broadly the same color.");
+
+ XrSession session = compositionHelper.GetSession();
+
+ const XrSpace viewSpace = compositionHelper.CreateReferenceSpace(XR_REFERENCE_SPACE_TYPE_VIEW, Pose::Identity);
+
+ // Enumerate formats
+ std::vector imageFormatArray;
+ {
+ uint32_t countOutput = 0;
+ XRC_CHECK_THROW_XRCMD_UNQUALIFIED_SUCCESS(xrEnumerateSwapchainFormats(session, 0, &countOutput, nullptr));
+ if (countOutput > 0) {
+ imageFormatArray.resize(countOutput, XRC_INVALID_IMAGE_FORMAT);
+ XRC_CHECK_THROW_XRCMD_UNQUALIFIED_SUCCESS(
+ xrEnumerateSwapchainFormats(session, countOutput, &countOutput, imageFormatArray.data()));
+ }
+ }
+
+ int64_t defaultFormat = globalData.graphicsPlugin->GetSRGBA8Format();
+ SwapchainCreateTestParameters defaultTestParameters;
+ REQUIRE(globalData.graphicsPlugin->GetSwapchainCreateTestParameters(defaultFormat, &defaultTestParameters));
+
+ compositionHelper.GetInteractionManager().AttachActionSets();
+ compositionHelper.BeginSession();
+
+ auto doInteractiveRenderTest = [&](int64_t projFormat, const SwapchainCreateTestParameters& projTestParameters, //
+ int64_t quadFormat, const SwapchainCreateTestParameters& quadTestParameters) {
+ // Set up composition projection layer and swapchains (one swapchain per view).
+ std::vector swapchains;
+ XrCompositionLayerProjection* const projLayer = compositionHelper.CreateProjectionLayer(viewSpace);
+ {
+ const std::vector viewProperties = compositionHelper.EnumerateConfigurationViews();
+ XrSwapchainCreateInfo createInfo = MakeDefaultSwapchainCreateInfo(projFormat, projTestParameters);
+ for (uint32_t j = 0; j < projLayer->viewCount; j++) {
+ // this may need to be rounded up for compressed formats (maybe compensated for with a subimage?)
+ createInfo.width = viewProperties[j].recommendedImageRectWidth;
+ createInfo.height = viewProperties[j].recommendedImageRectHeight;
+ const XrSwapchain swapchain = compositionHelper.CreateSwapchain(createInfo);
+ const_cast(projLayer->views[j].subImage) = compositionHelper.MakeDefaultSubImage(swapchain, 0);
+ swapchains.push_back(swapchain);
+ }
+ }
+
+ // Set up swapchain for composition quad layer
+ XrSwapchain gradientQuadSwapchain;
+ {
+ XrSwapchainCreateInfo createInfo = MakeDefaultSwapchainCreateInfo(quadFormat, quadTestParameters);
+ // this may need to be rounded up for compressed formats (maybe compensated for with a subimage?)
+ createInfo.width = gradientImageWidth;
+ createInfo.height = gradientImageHeight;
+ gradientQuadSwapchain = compositionHelper.CreateSwapchain(createInfo);
+ }
+
+ const float labelYOffset = gradientHeight + (labelHeight / 2) + labelMargin;
+
+ XrCompositionLayerQuad* const projFormatLabelQuad = MakeFormatLabel(
+ compositionHelper, viewSpace, "Projection: " + projTestParameters.imageFormatName, {0, labelYOffset, quadZ});
+ interactiveLayerManager.AddLayer(projFormatLabelQuad);
+
+ XrCompositionLayerQuad* const quadFormatLabelQuad =
+ MakeFormatLabel(compositionHelper, viewSpace, "Quad: " + quadTestParameters.imageFormatName, {0, -labelYOffset, quadZ});
+ interactiveLayerManager.AddLayer(quadFormatLabelQuad);
+
+ XrCompositionLayerQuad* gradientQuad = compositionHelper.CreateQuadLayer(gradientQuadSwapchain, viewSpace, gradientWidth,
+ XrPosef{Quat::Identity, {0, -yOffset, quadZ}});
+ interactiveLayerManager.AddLayer(gradientQuad);
+
+ // Each mesh should only write non-zero to the color components that the **other** format supports, which is why the below looks backwards.
+ // We could do an intersection of the two format components, but e.g. writing all white to a format with fewer channels
+ // may expose errors that writing something more limited would not.
+ MeshHandle quadMesh = MakeGradientMesh(*globalData.graphicsPlugin, projTestParameters.colorComponents);
+ MeshHandle projMesh = MakeGradientMesh(*globalData.graphicsPlugin, quadTestParameters.colorComponents);
+
+ auto updateLayers = [&](const XrFrameState& frameState) {
+ auto viewData = compositionHelper.LocateViews(viewSpace, frameState.predictedDisplayTime);
+ const auto& viewState = std::get(viewData);
+
+ std::vector layers;
+ if (viewState.viewStateFlags & XR_VIEW_STATE_POSITION_VALID_BIT &&
+ viewState.viewStateFlags & XR_VIEW_STATE_ORIENTATION_VALID_BIT) {
+ const auto& views = std::get>(viewData);
+
+ const uint32_t imageArrayIndex = 0;
+ // Render the gradient into the quad's swapchain
+ compositionHelper.AcquireWaitReleaseImage(gradientQuadSwapchain, [&](const XrSwapchainImageBaseHeader* swapchainImage) {
+ GetGlobalData().graphicsPlugin->ClearImageSlice(swapchainImage, imageArrayIndex, Colors::Black);
+
+ XrCompositionLayerProjectionView view = {XR_TYPE_COMPOSITION_LAYER_PROJECTION_VIEW};
+ const float quadRenderDistance = 1.0;
+ const float halfAngleX = std::atan2(gradientWidth / 2, quadRenderDistance);
+ const float halfAngleY = std::atan2(gradientHeight / 2, quadRenderDistance);
+ view.fov = {-halfAngleX, halfAngleX, halfAngleY, -halfAngleY};
+ view.pose = Pose::Identity;
+ view.subImage = compositionHelper.MakeDefaultSubImage(gradientQuadSwapchain, imageArrayIndex);
+
+ auto quadMeshList = {MeshDrawable{quadMesh, {Quat::Identity, {0, 0, -quadRenderDistance}}}};
+ GetGlobalData().graphicsPlugin->RenderView(view, swapchainImage, RenderParams().Draw(quadMeshList));
+ });
+
+ auto projMeshList = {MeshDrawable{projMesh, {Quat::Identity, {0, yOffset, quadZ}}}};
+ // Render into each of the separate swapchains using the projection layer view fov and pose.
+ for (size_t view = 0; view < views.size(); view++) {
+ compositionHelper.AcquireWaitReleaseImage(swapchains[view], [&](const XrSwapchainImageBaseHeader* swapchainImage) {
+ GetGlobalData().graphicsPlugin->ClearImageSlice(swapchainImage, imageArrayIndex, Colors::Black);
+ const_cast(projLayer->views[view].fov) = views[view].fov;
+ const_cast(projLayer->views[view].pose) = views[view].pose;
+ GetGlobalData().graphicsPlugin->RenderView(projLayer->views[view], swapchainImage,
+ RenderParams().Draw(projMeshList));
+ });
+ }
+
+ layers.push_back({reinterpret_cast(projLayer)});
+ }
+ return interactiveLayerManager.EndFrame(frameState, layers);
+ };
+
+ RenderLoop(session, updateLayers).Loop();
+ };
+
+ for (int64_t imageFormat : imageFormatArray) {
+
+ SwapchainCreateTestParameters tp;
+ REQUIRE(globalData.graphicsPlugin->GetSwapchainCreateTestParameters(imageFormat, &tp));
+
+ if (!tp.supportsRendering) {
+ // currently, we render to the format,
+ // but we could generate the image
+ // or render to another format and copy.
+ continue;
+ }
+ if (!tp.colorFormat) {
+ // we are testing by visual inspection
+ continue;
+ }
+ if (tp.colorIntegerRange != SwapchainFormat::ColorIntegerRange::NoIntegerColor) {
+ // unsure whether and how non-normalized
+ // integer formats map to the screen
+ continue;
+ }
+
+ DYNAMIC_SECTION(tp.imageFormatName)
+ {
+ CAPTURE(tp.imageFormatName);
+
+ SECTION("Custom projection layer format")
+ {
+ INFO("Formats: projection: " << tp.imageFormatName << ", quad: " << defaultTestParameters.imageFormatName
+ << " (default)");
+ doInteractiveRenderTest(imageFormat, tp, defaultFormat, defaultTestParameters);
+ }
+ if (imageFormat == defaultFormat) {
+ // compare proj to quad, but no point doing it twice
+ continue;
+ }
+ SECTION("Custom quad layer format")
+ {
+ INFO("Formats: projection: " << defaultTestParameters.imageFormatName << " (default), quad: " << tp.imageFormatName);
+ doInteractiveRenderTest(defaultFormat, defaultTestParameters, imageFormat, tp);
+ }
+ }
+
+ // SwapchainScoped will have xrDestroySwapchain
+ // now we need to flush
+ GetGlobalData().graphicsPlugin->ClearSwapchainCache();
+ GetGlobalData().graphicsPlugin->Flush();
+ }
+ }
+} // namespace Conformance
diff --git a/src/conformance/conformance_test/test_SessionState.cpp b/src/conformance/conformance_test/test_SessionState.cpp
index 43a24ccc..da379cf4 100644
--- a/src/conformance/conformance_test/test_SessionState.cpp
+++ b/src/conformance/conformance_test/test_SessionState.cpp
@@ -16,8 +16,7 @@
#include "conformance_utils.h"
#include "conformance_framework.h"
-#include "matchers.h"
-#include "utilities/utils.h"
+#include "utilities/types_and_constants.h"
#include "utilities/throw_helpers.h"
#include
@@ -26,168 +25,182 @@
#include
#include
-#include
#include
-#include
-#include
-#include
#include
-#include
-
-#define AS_LIST(name, val) name,
-constexpr XrViewConfigurationType KnownViewTypes[] = {XR_LIST_ENUM_XrViewConfigurationType(AS_LIST)};
-#undef AS_LIST
namespace Conformance
{
+ static bool tryReadEvent(XrInstance instance, XrEventDataBuffer* evt)
+ {
+ *evt = {XR_TYPE_EVENT_DATA_BUFFER};
+ XrResult res;
+ XRC_CHECK_THROW_XRCMD(res = xrPollEvent(instance, evt));
+ return res == XR_SUCCESS;
+ }
- TEST_CASE("SessionState", "")
+ static bool tryGetNextSessionState(XrInstance instance, XrEventDataSessionStateChanged* evt)
{
- AutoBasicSession session(AutoBasicSession::createSession);
- REQUIRE_MSG(session != XR_NULL_HANDLE_CPP,
- "If this (XrSession creation) fails, ensure the runtime is configured and the AR/VR device is present.");
-
- XrInstance instance = session.GetInstance();
- XrSystemId systemId = session.GetSystemId();
-
- auto tryReadEvent = [&](XrEventDataBuffer* evt) {
- *evt = {XR_TYPE_EVENT_DATA_BUFFER};
- XrResult res;
- XRC_CHECK_THROW_XRCMD(res = xrPollEvent(session.GetInstance(), evt));
- return res == XR_SUCCESS;
- };
-
- auto tryGetNextSessionState = [&](XrEventDataSessionStateChanged* evt) {
- XrEventDataBuffer buffer;
- while (tryReadEvent(&buffer)) {
- if (buffer.type == XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
- *evt = *reinterpret_cast(&buffer);
- return true;
- }
+ XrEventDataBuffer buffer;
+ while (tryReadEvent(instance, &buffer)) {
+ if (buffer.type == XR_TYPE_EVENT_DATA_SESSION_STATE_CHANGED) {
+ *evt = *reinterpret_cast(&buffer);
+ return true;
}
+ }
+ return false;
+ }
- return false;
- };
+ static bool waitForNextSessionState(XrInstance instance, XrEventDataSessionStateChanged* evt, std::chrono::nanoseconds duration = 1s)
+ {
+ CountdownTimer countdown(duration);
+ while (!countdown.IsTimeUp()) {
+ if (tryGetNextSessionState(instance, evt)) {
+ return true;
+ }
- auto waitForNextSessionState = [&](XrEventDataSessionStateChanged* evt, std::chrono::nanoseconds duration = 1s) {
- CountdownTimer countdown(duration);
- while (!countdown.IsTimeUp()) {
- if (tryGetNextSessionState(evt)) {
- return true;
- }
+ std::this_thread::sleep_for(5ms);
+ }
- std::this_thread::sleep_for(5ms);
- }
+ return false;
+ }
- return false;
- };
+ static void submitFrame(XrSession session)
+ {
+ XrFrameState frameState{XR_TYPE_FRAME_STATE};
+ XRC_CHECK_THROW_XRCMD(xrWaitFrame(session, nullptr, &frameState));
+ XRC_CHECK_THROW_XRCMD(xrBeginFrame(session, nullptr));
+
+ XrFrameEndInfo frameEndInfo{XR_TYPE_FRAME_END_INFO};
+ frameEndInfo.displayTime = frameState.predictedDisplayTime;
+ frameEndInfo.environmentBlendMode = GetGlobalData().GetOptions().environmentBlendModeValue;
+ XRC_CHECK_THROW_XRCMD(xrEndFrame(session, &frameEndInfo));
+ }
+
+ static void submitFramesUntilSessionState(XrInstance instance, XrSession session, XrSessionState expectedSessionState,
+ std::chrono::nanoseconds duration = 30s)
+ {
+ CAPTURE(expectedSessionState);
+
+ CountdownTimer countdown(duration);
+ while (!countdown.IsTimeUp()) {
+ XrEventDataSessionStateChanged evt;
+ if (tryGetNextSessionState(instance, &evt)) {
+ REQUIRE(evt.state == expectedSessionState);
+ return;
+ }
+ submitFrame(session);
+ }
- XrEventDataSessionStateChanged evt{};
- REQUIRE(waitForNextSessionState(&evt) == true);
- REQUIRE_MSG(evt.state == XR_SESSION_STATE_IDLE, "Unexpected session state " << evt.state);
+ FAIL("Failed to reach expected session state");
+ }
- REQUIRE(waitForNextSessionState(&evt) == true);
- REQUIRE_MSG(evt.state == XR_SESSION_STATE_READY, "Unexpected session state " << evt.state);
+ TEST_CASE("SessionState", "")
+ {
+ AutoBasicInstance instance;
- // Ensure unsupported view configuration types fail.
+ SECTION("Cycle through all states")
{
- // Get the list of supported view configurations
- uint32_t viewCount = 0;
- REQUIRE(XR_SUCCESS == xrEnumerateViewConfigurations(instance, systemId, 0, &viewCount, nullptr));
- std::vector runtimeViewTypes(viewCount);
- REQUIRE(XR_SUCCESS == xrEnumerateViewConfigurations(instance, systemId, viewCount, &viewCount, runtimeViewTypes.data()));
+ AutoBasicSession session(AutoBasicSession::createSession, instance);
- for (XrViewConfigurationType viewType : KnownViewTypes) {
- CAPTURE(viewType);
+ REQUIRE(session != XR_NULL_HANDLE_CPP);
- // Is this enum valid, check against enabled extensions.
- bool valid = IsViewConfigurationTypeEnumValid(viewType);
+ XrEventDataSessionStateChanged evt{};
+ REQUIRE(waitForNextSessionState(instance, &evt) == true);
+ REQUIRE_MSG(evt.state == XR_SESSION_STATE_IDLE, "Unexpected session state " << evt.state);
- if (!IsViewConfigurationTypeEnumValid(viewType)) {
- INFO("Must not enumerate invalid view configuration type");
- CHECK_THAT(runtimeViewTypes, !Catch::Matchers::VectorContains(viewType));
- }
+ REQUIRE(waitForNextSessionState(instance, &evt) == true);
+ REQUIRE_MSG(evt.state == XR_SESSION_STATE_READY, "Unexpected session state " << evt.state);
- // Skip this view config if it is supported, since we cannot test correct handling of unsupported values with it.
- if (Catch::Matchers::VectorContains(viewType).match(runtimeViewTypes)) {
- continue;
- }
+ XrSessionBeginInfo beginInfo{XR_TYPE_SESSION_BEGIN_INFO};
+ beginInfo.primaryViewConfigurationType = GetGlobalData().GetOptions().viewConfigurationValue;
+ REQUIRE(XR_SUCCESS == xrBeginSession(session, &beginInfo));
- XrSessionBeginInfo beginInfo{XR_TYPE_SESSION_BEGIN_INFO};
- beginInfo.primaryViewConfigurationType = viewType;
- XrResult result = xrBeginSession(session, &beginInfo);
- REQUIRE_THAT(result, In({XR_ERROR_VALIDATION_FAILURE, XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED}));
- if (!valid && result == XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED) {
- WARN(
- "On receiving an 'invalid' enum value "
- << viewType
- << ", the runtime returned as XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED instead of XR_ERROR_VALIDATION_FAILURE, which may make it harder for apps to reason about the error.");
- }
- else if (valid && result == XR_ERROR_VALIDATION_FAILURE) {
- WARN(
- "On receiving a 'valid' but not supported enum value "
- << viewType
- << ", the runtime returned as XR_ERROR_VALIDATION_FAILURE instead of XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, which may make it harder for apps to reason about the error.");
- }
- }
- }
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_SYNCHRONIZED);
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_VISIBLE);
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_FOCUSED);
- XrSessionBeginInfo beginInfo{XR_TYPE_SESSION_BEGIN_INFO};
- beginInfo.primaryViewConfigurationType = GetGlobalData().GetOptions().viewConfigurationValue;
- XRC_CHECK_THROW_XRCMD(xrBeginSession(session, &beginInfo));
+ // Runtime should only allow ending a session in the STOPPING state.
+ REQUIRE(XR_ERROR_SESSION_NOT_STOPPING == xrEndSession(session));
- if (GetGlobalData().IsUsingGraphicsPlugin()) {
- // Runtime should not transition from READY to SYNCHRONIZED until one or more frames have been submitted.
- // The exception is if the runtime is transitioning to STOPPING, which should not happen
- // during conformance testing. This will wait 1 second before assuming no such incorrect event will come.
- REQUIRE_MSG(tryGetNextSessionState(&evt) == false, "Premature progression from READY to SYNCHRONIZED state");
+ REQUIRE(XR_SUCCESS == xrRequestExitSession(session));
+
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_VISIBLE);
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_SYNCHRONIZED);
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_STOPPING);
+
+ // Runtime should not transition from STOPPING to IDLE until the session has been ended.
+ // This will wait 1 second before assuming no such incorrect event will come.
+ REQUIRE_MSG(waitForNextSessionState(instance, &evt) == false, "Premature progression from STOPPING to IDLE state");
+
+ REQUIRE(XR_SUCCESS == xrEndSession(session));
+
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_IDLE);
+
+ // https://registry.khronos.org/OpenXR/specs/1.1/html/xrspec.html#session-lifecycle
+ // If the runtime determines that its use of this XR session has
+ // concluded, it will transition the session state from
+ // XR_SESSION_STATE_IDLE to XR_SESSION_STATE_EXITING.
+ submitFramesUntilSessionState(instance, session, XR_SESSION_STATE_EXITING);
+
+ // When the application receives the XR_SESSION_STATE_EXITING
+ // event, it releases the resources related to the session and
+ // calls xrDestroySession.
}
- auto submitFrame = [&]() {
- XrFrameState frameState{XR_TYPE_FRAME_STATE};
- XRC_CHECK_THROW_XRCMD(xrWaitFrame(session, nullptr, &frameState));
- XRC_CHECK_THROW_XRCMD(xrBeginFrame(session, nullptr));
-
- XrFrameEndInfo frameEndInfo{XR_TYPE_FRAME_END_INFO};
- frameEndInfo.displayTime = frameState.predictedDisplayTime;
- frameEndInfo.environmentBlendMode = GetGlobalData().GetOptions().environmentBlendModeValue;
- XRC_CHECK_THROW_XRCMD(xrEndFrame(session, &frameEndInfo));
- };
-
- auto submitFramesUntilSessionState = [&](XrSessionState expectedSessionState, std::chrono::nanoseconds duration = 30s) {
- CAPTURE(expectedSessionState);
-
- CountdownTimer countdown(duration);
- while (!countdown.IsTimeUp()) {
- if (tryGetNextSessionState(&evt)) {
- REQUIRE(evt.state == expectedSessionState);
- return;
- }
- submitFrame();
+ SECTION("xrRequestExitSession Session Not Running")
+ {
+ SECTION("Session not running before starting")
+ {
+ AutoBasicSession session(AutoBasicSession::createSession, instance);
+
+ REQUIRE(XR_ERROR_SESSION_NOT_RUNNING == xrRequestExitSession(session));
}
- FAIL("Failed to reach expected session state");
- };
+ SECTION("Session not running after ending")
+ {
+ // A session is considered running after a successful call to
+ // xrBeginSession and remains running until any call is made to
+ // xrEndSession. Certain functions are only valid to call when
+ // a session is running, such as xrWaitFrame, or else the
+ // XR_ERROR_SESSION_NOT_RUNNING error must be returned by the
+ // runtime.
- submitFramesUntilSessionState(XR_SESSION_STATE_SYNCHRONIZED);
- submitFramesUntilSessionState(XR_SESSION_STATE_VISIBLE);
- submitFramesUntilSessionState(XR_SESSION_STATE_FOCUSED);
+ // If session is not running when xrRequestExitSession is
+ // called, XR_ERROR_SESSION_NOT_RUNNING must be returned.
- // Runtime should only allow ending a session in the STOPPING state.
- REQUIRE(XR_ERROR_SESSION_NOT_STOPPING == xrEndSession(session));
+ AutoBasicSession session(
+ AutoBasicSession::beginSession | AutoBasicSession::createSpaces | AutoBasicSession::createSwapchains, instance);
+ REQUIRE(XR_SUCCESS == xrRequestExitSession(session));
- XRC_CHECK_THROW_XRCMD(xrRequestExitSession(session));
+ FrameIterator frameIterator(&session);
+ frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING);
+ REQUIRE(XR_SUCCESS == xrEndSession(session));
- submitFramesUntilSessionState(XR_SESSION_STATE_VISIBLE);
- submitFramesUntilSessionState(XR_SESSION_STATE_SYNCHRONIZED);
- submitFramesUntilSessionState(XR_SESSION_STATE_STOPPING);
+ // Actually test what we want to test!
+ REQUIRE(XR_ERROR_SESSION_NOT_RUNNING == xrRequestExitSession(session));
+ }
+ }
- // Runtime should not transition from STOPPING to IDLE until the session has been ended.
- REQUIRE_MSG(tryGetNextSessionState(&evt) == false, "Premature progression from STOPPING to IDLE state");
+ // Runtime should not transition from READY to SYNCHRONIZED until one
+ // or more frames have been submitted.
+ // The exception is if the runtime is transitioning to STOPPING, which
+ // should not happen during conformance testing.
+ if (GetGlobalData().IsUsingGraphicsPlugin()) {
+ SECTION("Advance without frame submission")
+ {
+ AutoBasicSession session(AutoBasicSession::createSession, instance);
- XRC_CHECK_THROW_XRCMD(xrEndSession(session));
+ FrameIterator frameIterator(&session);
+ frameIterator.RunToSessionState(XR_SESSION_STATE_READY);
- submitFramesUntilSessionState(XR_SESSION_STATE_IDLE);
- submitFramesUntilSessionState(XR_SESSION_STATE_EXITING);
+ XrSessionBeginInfo beginInfo{XR_TYPE_SESSION_BEGIN_INFO};
+ beginInfo.primaryViewConfigurationType = GetGlobalData().GetOptions().viewConfigurationValue;
+ REQUIRE(XR_SUCCESS == xrBeginSession(session, &beginInfo));
+
+ // This will wait 1 second before assuming no such incorrect event will come.
+ XrEventDataSessionStateChanged evt;
+ REQUIRE_MSG(waitForNextSessionState(instance, &evt) == false, "Premature progression from READY to SYNCHRONIZED state");
+ }
+ }
}
} // namespace Conformance
diff --git a/src/conformance/conformance_test/test_ViewConfigurations.cpp b/src/conformance/conformance_test/test_ViewConfigurations.cpp
index 14d80dc4..46de14bc 100644
--- a/src/conformance/conformance_test/test_ViewConfigurations.cpp
+++ b/src/conformance/conformance_test/test_ViewConfigurations.cpp
@@ -19,6 +19,8 @@
#include "matchers.h"
#include
+#include
+#include
#include
#include
@@ -29,7 +31,6 @@
namespace Conformance
{
-
TEST_CASE("ViewConfigurations", "")
{
// XrResult xrEnumerateViewConfigurations(XrInstance instance, XrSystemId systemId, uint32_t viewConfigurationTypeCapacityInput,
@@ -71,6 +72,59 @@ namespace Conformance
}
}
+ // Ensure unsupported view configuration types fail.
+ {
+#define AS_LIST(name, val) name,
+ constexpr XrViewConfigurationType KnownViewTypes[] = {XR_LIST_ENUM_XrViewConfigurationType(AS_LIST)};
+#undef AS_LIST
+
+ XrSystemId systemId = instance.systemId;
+
+ // Get the list of supported view configurations
+ uint32_t viewCount = 0;
+ REQUIRE(XR_SUCCESS == xrEnumerateViewConfigurations(instance, systemId, 0, &viewCount, nullptr));
+ std::vector runtimeViewTypes(viewCount);
+ REQUIRE(XR_SUCCESS == xrEnumerateViewConfigurations(instance, systemId, viewCount, &viewCount, runtimeViewTypes.data()));
+
+ AutoBasicSession session(AutoBasicSession::createSession, instance);
+ FrameIterator frameIterator(&session);
+ frameIterator.RunToSessionState(XR_SESSION_STATE_READY);
+
+ for (XrViewConfigurationType viewType : KnownViewTypes) {
+ CAPTURE(viewType);
+
+ // Is this enum valid, check against enabled extensions.
+ bool valid = IsViewConfigurationTypeEnumValid(viewType);
+
+ if (!IsViewConfigurationTypeEnumValid(viewType)) {
+ INFO("Must not enumerate invalid view configuration type");
+ CHECK_THAT(runtimeViewTypes, !Catch::Matchers::VectorContains(viewType));
+ }
+
+ // Skip this view config if it is supported, since we cannot test correct handling of unsupported values with it.
+ if (Catch::Matchers::VectorContains(viewType).match(runtimeViewTypes)) {
+ continue;
+ }
+
+ XrSessionBeginInfo beginInfo{XR_TYPE_SESSION_BEGIN_INFO};
+ beginInfo.primaryViewConfigurationType = viewType;
+ XrResult result = xrBeginSession(session, &beginInfo);
+ REQUIRE_THAT(result, In({XR_ERROR_VALIDATION_FAILURE, XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED}));
+ if (!valid && result == XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED) {
+ WARN(
+ "On receiving an 'invalid' enum value "
+ << viewType
+ << ", the runtime returned as XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED instead of XR_ERROR_VALIDATION_FAILURE, which may make it harder for apps to reason about the error.");
+ }
+ else if (valid && result == XR_ERROR_VALIDATION_FAILURE) {
+ WARN(
+ "On receiving a 'valid' but not supported enum value "
+ << viewType
+ << ", the runtime returned as XR_ERROR_VALIDATION_FAILURE instead of XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED, which may make it harder for apps to reason about the error.");
+ }
+ }
+ }
+
// xrGetViewConfigurationProperties
{
// XrResult xrGetViewConfigurationProperties(XrInstance instance, XrSystemId systemId, XrViewConfigurationType
diff --git a/src/conformance/conformance_test/test_XR_FB_space_warp.cpp b/src/conformance/conformance_test/test_XR_FB_space_warp.cpp
index 11d9e275..945bfc53 100644
--- a/src/conformance/conformance_test/test_XR_FB_space_warp.cpp
+++ b/src/conformance/conformance_test/test_XR_FB_space_warp.cpp
@@ -95,28 +95,43 @@ namespace Conformance
float maxDepth;
float nearZ;
float farZ;
+ XrResult result;
};
constexpr float minimum_useful_z = 0.01f;
std::vector varyingInfoTestArray{
- SpaceWarpVaryingInfo{0, 0.0f, 1.0f, minimum_useful_z, 100.0f},
- SpaceWarpVaryingInfo{0, 0.5f, 0.6f, minimum_useful_z, 100.0f},
- SpaceWarpVaryingInfo{0, 0.0f, 1.0f, minimum_useful_z, std::numeric_limits::infinity()},
- SpaceWarpVaryingInfo{0, 0.0f, 1.0f, 100.0f, minimum_useful_z},
- SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::infinity(), minimum_useful_z},
- SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::max(), minimum_useful_z},
- SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::max(), minimum_useful_z},
- SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, minimum_useful_z, 100.0f},
- SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.5f, 0.6f, minimum_useful_z, 100.0f},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, minimum_useful_z, 100.0f, XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.5f, 0.6f, minimum_useful_z, 100.0f, XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, minimum_useful_z, std::numeric_limits::infinity(), XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, 100.0f, minimum_useful_z, XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::infinity(), minimum_useful_z, XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::max(), minimum_useful_z, XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::max(), minimum_useful_z, XR_SUCCESS},
+ SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, minimum_useful_z, 100.0f,
+ XR_SUCCESS},
+ SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.5f, 0.6f, minimum_useful_z, 100.0f,
+ XR_SUCCESS},
SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, minimum_useful_z,
- std::numeric_limits::infinity()},
- SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, 100.0f, minimum_useful_z},
+ std::numeric_limits::infinity(), XR_SUCCESS},
+ SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, 100.0f, minimum_useful_z,
+ XR_SUCCESS},
SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f,
- std::numeric_limits::infinity(), minimum_useful_z},
+ std::numeric_limits::infinity(), minimum_useful_z, XR_SUCCESS},
SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, std::numeric_limits::max(),
- minimum_useful_z},
+ minimum_useful_z, XR_SUCCESS},
SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, std::numeric_limits::max(),
- minimum_useful_z}};
+ minimum_useful_z, XR_SUCCESS},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, minimum_useful_z, minimum_useful_z, XR_ERROR_VALIDATION_FAILURE},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, 100.0f, 100.0f, XR_ERROR_VALIDATION_FAILURE},
+ SpaceWarpVaryingInfo{0, 0.0f, 1.0f, std::numeric_limits::infinity(), std::numeric_limits::infinity(),
+ XR_ERROR_VALIDATION_FAILURE},
+ SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, minimum_useful_z, minimum_useful_z,
+ XR_ERROR_VALIDATION_FAILURE},
+ SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f, 100.0f, 100.0f,
+ XR_ERROR_VALIDATION_FAILURE},
+ SpaceWarpVaryingInfo{XR_COMPOSITION_LAYER_SPACE_WARP_INFO_FRAME_SKIP_BIT_FB, 0.0f, 1.0f,
+ std::numeric_limits::infinity(), std::numeric_limits::infinity(),
+ XR_ERROR_VALIDATION_FAILURE}};
for (const SpaceWarpVaryingInfo& varyingInfo : varyingInfoTestArray) {
REQUIRE(frameIterator.PrepareSubmitFrame() == FrameIterator::RunResult::Success);
@@ -160,7 +175,7 @@ namespace Conformance
// xrEndFrame requires the XR_FB_space_warp extension to be
// enabled or else it must return XR_ERROR_LAYER_INVALID.
XrResult result = xrEndFrame(session.GetSession(), &frameIterator.frameEndInfo);
- CHECK(result == XR_SUCCESS);
+ CHECK(result == varyingInfo.result);
}
}
diff --git a/src/conformance/conformance_test/test_actions.cpp b/src/conformance/conformance_test/test_actions.cpp
index 344efb63..b4bc19a1 100644
--- a/src/conformance/conformance_test/test_actions.cpp
+++ b/src/conformance/conformance_test/test_actions.cpp
@@ -34,7 +34,9 @@
#include
#include
#include
+#include
#include
+#include
#include
#include
@@ -1047,19 +1049,18 @@ namespace Conformance
XrBoundSourcesForActionEnumerateInfo info{XR_TYPE_BOUND_SOURCES_FOR_ACTION_ENUMERATE_INFO};
info.action = selectAction;
uint32_t sourceCountOutput;
- XrPath buffer;
- REQUIRE_RESULT(xrEnumerateBoundSourcesForAction(session, &info, 0, &sourceCountOutput, &buffer),
- XR_ERROR_ACTIONSET_NOT_ATTACHED);
- }
- SECTION("Get localized source name")
- {
- XrInputSourceLocalizedNameGetInfo getInfo{XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO};
- getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT;
- getInfo.sourcePath = StringToPath(instance, "/user/hand/left/input/select/click");
- uint32_t sourceCountOutput;
- char buffer;
- REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, &buffer),
+ REQUIRE_RESULT(xrEnumerateBoundSourcesForAction(session, &info, 0, &sourceCountOutput, nullptr),
XR_ERROR_ACTIONSET_NOT_ATTACHED);
+
+ REQUIRE_RESULT(xrAttachSessionActionSets(session, &attachInfo), XR_SUCCESS);
+
+ std::vector boundSourcesPaths = REQUIRE_TWO_CALL(XrPath, {}, xrEnumerateBoundSourcesForAction, session, &info);
+ sourceCountOutput = static_cast(boundSourcesPaths.size());
+
+ // should not get a null path, not really much else we can assert here.
+ REQUIRE_THAT(boundSourcesPaths, !Catch::Matchers::VectorContains(XrPath{}));
+ // Can we assert that we don't enumerate duplicates? Would be weird to return duplicates but may not be strictly forbidden.
+ REQUIRE_THAT(boundSourcesPaths, VectorHasOnlyUniqueElements{});
}
}
SECTION("Unattached action sets")
@@ -3925,65 +3926,94 @@ namespace Conformance
REQUIRE(enumerateResult.size() > 0);
+ // should not get a null path, not really much else we can assert here.
+ REQUIRE_THAT(enumerateResult, !Catch::Matchers::VectorContains(XrPath{}));
+ // Can we assert that we don't enumerate duplicates? Would be weird to return duplicates but may not be strictly forbidden.
+ REQUIRE_THAT(enumerateResult, VectorHasOnlyUniqueElements{});
+
XrInputSourceLocalizedNameGetInfo getInfo{XR_TYPE_INPUT_SOURCE_LOCALIZED_NAME_GET_INFO};
+ getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT;
getInfo.sourcePath = enumerateResult[0];
- SECTION("xrGetInputSourceLocalizedName")
+
+ uint32_t sourceCountOutput;
+ SECTION("Invalid components")
+ {
+ getInfo.whichComponents = 0;
+ REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, nullptr),
+ XR_ERROR_VALIDATION_FAILURE);
+ }
+ SECTION("Invalid path")
{
- getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT;
- std::vector localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
-
- getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT;
- localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
-
- getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
- localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
-
- getInfo.whichComponents =
- XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT;
- localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
-
- getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
- localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
-
- getInfo.whichComponents =
- XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
- localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
-
- getInfo.whichComponents = XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
- XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
- XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT;
- localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
- CHECK(localizedStringResult.size() > 1); // more than null terminator
- CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ getInfo.sourcePath = XR_NULL_PATH;
+ REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, nullptr), XR_ERROR_PATH_INVALID);
+ getInfo.sourcePath = (XrPath)0x1234;
+ REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, nullptr), XR_ERROR_PATH_INVALID);
+ }
- uint32_t sourceCountOutput;
- char buffer;
- SECTION("Invalid components")
- {
- getInfo.whichComponents = 0;
- REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, &buffer),
- XR_ERROR_VALIDATION_FAILURE);
- }
- SECTION("Invalid path")
- {
- getInfo.sourcePath = XR_NULL_PATH;
- REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, &buffer),
- XR_ERROR_PATH_INVALID);
- getInfo.sourcePath = (XrPath)0x1234;
- REQUIRE_RESULT(xrGetInputSourceLocalizedName(session, &getInfo, 0, &sourceCountOutput, &buffer),
- XR_ERROR_PATH_INVALID);
+ SECTION("xrGetInputSourceLocalizedName-on-each")
+ {
+ for (size_t i = 0; i < enumerateResult.size(); ++i) {
+ getInfo.sourcePath = enumerateResult[i];
+ CAPTURE(i);
+
+ auto s = PathToString(instance, getInfo.sourcePath);
+ CHECK(!s.empty());
+ CAPTURE(s);
+ std::vector localizedStringResult;
+
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
+ XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT | XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
+ XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
+ {
+ CAPTURE(XrInputSourceLocalizedNameFlagsRefCPP(getInfo.whichComponents) =
+ XR_INPUT_SOURCE_LOCALIZED_NAME_USER_PATH_BIT |
+ XR_INPUT_SOURCE_LOCALIZED_NAME_INTERACTION_PROFILE_BIT |
+ XR_INPUT_SOURCE_LOCALIZED_NAME_COMPONENT_BIT);
+ localizedStringResult = REQUIRE_TWO_CALL(char, {}, xrGetInputSourceLocalizedName, session, &getInfo);
+ CHECK(localizedStringResult.size() > 1); // more than null terminator
+ CHECK_THAT(localizedStringResult, NullTerminatedVec());
+ }
}
}
}
diff --git a/src/conformance/conformance_test/test_xrLocateViews.cpp b/src/conformance/conformance_test/test_xrLocateViews.cpp
index 2fbc527e..8466527c 100644
--- a/src/conformance/conformance_test/test_xrLocateViews.cpp
+++ b/src/conformance/conformance_test/test_xrLocateViews.cpp
@@ -33,84 +33,95 @@ namespace Conformance
{
GlobalData& globalData = GetGlobalData();
- // 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.RunToSessionState(XR_SESSION_STATE_FOCUSED);
-
- // Render one frame to get a predicted display time for the xrLocateViews calls.
- FrameIterator::RunResult runResult = frameIterator.SubmitFrame();
- REQUIRE(runResult == FrameIterator::RunResult::Success);
-
- XrResult result;
+ // Get a session, but do not start it yet, we might pick a different view config type.
+ // Swapchain will be sized based on default view config type, but that is OK.
+ AutoBasicSession session(AutoBasicSession::createInstance | AutoBasicSession::createSession | AutoBasicSession::createSwapchains |
+ AutoBasicSession::createSpaces);
XrViewLocateInfo locateInfo{XR_TYPE_VIEW_LOCATE_INFO};
locateInfo.space = session.spaceVector.front();
- XrTime time = frameIterator.frameState.predictedDisplayTime;
- CHECK(time != 0);
- locateInfo.displayTime = time;
- locateInfo.viewConfigurationType = globalData.GetOptions().viewConfigurationValue;
-
- XrViewState viewState{XR_TYPE_VIEW_STATE};
- uint32_t viewCount = (uint32_t)session.viewConfigurationViewVector.size();
+ auto viewConfigDependentSetup = [&](XrViewConfigurationType configType) {
+ locateInfo.viewConfigurationType = configType;
+ session.viewConfigurationType = configType;
+ {
+ CAPTURE(configType);
+ session.BeginSession();
+ }
- CAPTURE(viewCount);
- SECTION("valid inputs")
- {
- std::vector views(viewCount, {XR_TYPE_VIEW});
- uint32_t viewCountOut = 0;
+ // Get frames iterating to the point of app focused state. This will draw frames along the way.
+ FrameIterator frameIterator(&session);
+ frameIterator.RunToSessionState(XR_SESSION_STATE_FOCUSED);
- CAPTURE(locateInfo.displayTime);
- CHECK(XR_SUCCESS == xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()));
+ // Render one frame to get a predicted display time for the xrLocateViews calls.
+ // FrameIterator::RunResult runResult = frameIterator.SubmitFrame();
+ // REQUIRE(runResult == FrameIterator::RunResult::Success);
- CHECK(viewCountOut == viewCount);
- }
- SECTION("invalid inputs")
+ const XrTime time = frameIterator.frameState.predictedDisplayTime;
+ REQUIRE(time != 0);
+ locateInfo.displayTime = time;
+ };
+ SECTION("Selected view config")
{
- std::vector views(viewCount, {XR_TYPE_VIEW});
- uint32_t viewCountOut = 0;
+ viewConfigDependentSetup(globalData.GetOptions().viewConfigurationValue);
- OPTIONAL_INVALID_HANDLE_VALIDATION_SECTION
- {
- // Exercise NULL session handle.
- CHECK(xrLocateViews(XR_NULL_HANDLE_CPP, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()) ==
- XR_ERROR_HANDLE_INVALID);
-
- // Exercise invalid session handle.
- CHECK(xrLocateViews(GlobalData().invalidSession, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()) ==
- XR_ERROR_HANDLE_INVALID);
- }
+ XrViewState viewState{XR_TYPE_VIEW_STATE};
+ uint32_t viewCount = (uint32_t)session.viewConfigurationViewVector.size();
- SECTION("Exercise 0 as an invalid time")
+ CAPTURE(viewCount);
+ SECTION("valid inputs")
{
- locateInfo.displayTime = 0;
- CAPTURE(locateInfo.displayTime);
- CHECK(XR_ERROR_TIME_INVALID == xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()));
- }
+ std::vector views(viewCount, {XR_TYPE_VIEW});
+ uint32_t viewCountOut = 0;
- SECTION("Exercise negative values as an invalid time")
- {
- locateInfo.displayTime = (XrTime)-42;
CAPTURE(locateInfo.displayTime);
- CHECK(XR_ERROR_TIME_INVALID == xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()));
- }
+ CHECK(XR_SUCCESS == xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()));
- OPTIONAL_INVALID_TYPE_VALIDATION_SECTION
+ CHECK(viewCountOut == viewCount);
+ }
+ SECTION("invalid inputs")
{
- std::vector invalidViews(viewCount, {XR_TYPE_UNKNOWN});
- REQUIRE(xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, invalidViews.data()) ==
- XR_ERROR_VALIDATION_FAILURE);
+ std::vector views(viewCount, {XR_TYPE_VIEW});
+ uint32_t viewCountOut = 0;
+
+ OPTIONAL_INVALID_HANDLE_VALIDATION_SECTION
+ {
+ // Exercise NULL session handle.
+ CHECK(xrLocateViews(XR_NULL_HANDLE_CPP, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()) ==
+ XR_ERROR_HANDLE_INVALID);
+
+ // Exercise invalid session handle.
+ CHECK(xrLocateViews(GlobalData().invalidSession, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()) ==
+ XR_ERROR_HANDLE_INVALID);
+ }
+
+ SECTION("Exercise 0 as an invalid time")
+ {
+ locateInfo.displayTime = 0;
+ CAPTURE(locateInfo.displayTime);
+ CHECK(XR_ERROR_TIME_INVALID == xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()));
+ }
+
+ SECTION("Exercise negative values as an invalid time")
+ {
+ locateInfo.displayTime = (XrTime)-42;
+ CAPTURE(locateInfo.displayTime);
+ CHECK(XR_ERROR_TIME_INVALID == xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data()));
+ }
+
+ OPTIONAL_INVALID_TYPE_VALIDATION_SECTION
+ {
+ std::vector invalidViews(viewCount, {XR_TYPE_UNKNOWN});
+ REQUIRE(xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, invalidViews.data()) ==
+ XR_ERROR_VALIDATION_FAILURE);
+ }
}
}
SECTION("all known view types")
{
// Ensure unsupported view configuration types fail and supported types pass
- XrInstance instance = session.GetInstance();
- XrSystemId systemId = session.GetSystemId();
+ const XrInstance instance = session.GetInstance();
+ const XrSystemId systemId = session.GetSystemId();
// Get the list of supported view configurations
uint32_t viewConfigCount = 0;
@@ -119,61 +130,65 @@ namespace Conformance
REQUIRE(XR_SUCCESS ==
xrEnumerateViewConfigurations(instance, systemId, viewConfigCount, &viewConfigCount, runtimeViewTypes.data()));
- CAPTURE(locateInfo.displayTime);
-
+ XrViewState viewState{XR_TYPE_VIEW_STATE};
for (auto viewTypeAndName : KnownViewTypes) {
- XrViewConfigurationType viewType = viewTypeAndName.first;
- CAPTURE(viewType);
- CAPTURE(viewTypeAndName.second);
+ DYNAMIC_SECTION("View type " << viewTypeAndName.second)
+ {
+ XrViewConfigurationType viewType = viewTypeAndName.first;
+ CAPTURE(viewType);
+ CAPTURE(viewTypeAndName.second);
+
+ // Is this enum valid, check against enabled extensions.
+ bool valid = IsViewConfigurationTypeEnumValid(viewType);
+
+ const bool isSupportedType = Catch::Matchers::VectorContains(viewType).match(runtimeViewTypes);
+ CAPTURE(valid);
+ CAPTURE(isSupportedType);
+
+ if (!valid) {
+ INFO("Not a valid view configuration type given the enabled extensions");
+ CHECK_MSG(!isSupportedType, "Cannot support invalid view configuration type");
+ }
- // Is this enum valid, check against enabled extensions.
- bool valid = IsViewConfigurationTypeEnumValid(viewType);
+ if (isSupportedType) {
- const bool isSupportedType = Catch::Matchers::VectorContains(viewType).match(runtimeViewTypes);
- CAPTURE(valid);
- CAPTURE(isSupportedType);
+ // Supported but we don't have the corresponding view count immediately at hand
+ // So, we look it up.
+ uint32_t expectedViewCount = 0;
+ REQUIRE(XR_SUCCESS == xrEnumerateViewConfigurationViews(session.GetInstance(), session.GetSystemId(), viewType, 0,
+ &expectedViewCount, nullptr));
- if (!valid) {
- INFO("Not a valid view configuration type given the enabled extensions");
- CHECK_MSG(!isSupportedType, "Cannot support invalid view configuration type");
- }
+ viewConfigDependentSetup(viewType);
- locateInfo.viewConfigurationType = viewType;
- if (isSupportedType) {
- // Supported but we don't have the corresponding view count immediately at hand
- // So, we look it up.
- uint32_t expectedViewCount = 0;
- REQUIRE(XR_SUCCESS == xrEnumerateViewConfigurationViews(session.GetInstance(), session.GetSystemId(), viewType, 0,
- &expectedViewCount, nullptr));
- INFO("Calling xrLocateViews with the noted viewType, which is claimed to be supported");
- uint32_t viewCountOut = 0;
- std::vector views(expectedViewCount, {XR_TYPE_VIEW});
- CHECK(XR_SUCCESS == xrLocateViews(session, &locateInfo, &viewState, expectedViewCount, &viewCountOut, views.data()));
- }
- else {
- // Not a supported type, so call should fail, regardless of the array size.
- INFO("Calling xrLocateViews with the noted viewType, which is claimed to be not supported");
- uint32_t viewCountOut = 0;
- std::vector views(viewCount, {XR_TYPE_VIEW});
-
- result = xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data());
- REQUIRE_THAT(result, In({XR_ERROR_VALIDATION_FAILURE, XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED}));
- if (!valid && result == XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED) {
- WARN(
- "Runtime accepted an invalid enum value as unsupported, which makes it harder for apps to reason about the error.");
+ CAPTURE(locateInfo.displayTime);
+
+ INFO("Calling xrLocateViews with the noted viewType, which is claimed to be supported");
+ uint32_t viewCountOut = 0;
+ std::vector views(expectedViewCount, {XR_TYPE_VIEW});
+ CHECK(XR_SUCCESS ==
+ xrLocateViews(session, &locateInfo, &viewState, expectedViewCount, &viewCountOut, views.data()));
}
- else if (valid && result == XR_ERROR_VALIDATION_FAILURE) {
- WARN(
- "Runtime accepted an valid but unsupported enum value as unsupported, which makes it harder for apps to reason about the error.");
+ else {
+ // Not a supported type, so call should fail, regardless of the array size.
+ INFO("Calling xrLocateViews with the noted viewType, which is claimed to be not supported");
+ uint32_t viewCount = static_cast(session.viewConfigurationViewVector.size());
+ uint32_t viewCountOut = 0;
+ std::vector views(viewCount, {XR_TYPE_VIEW});
+
+ XrResult result = xrLocateViews(session, &locateInfo, &viewState, viewCount, &viewCountOut, views.data());
+ REQUIRE_THAT(result, In({XR_ERROR_VALIDATION_FAILURE, XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED}));
+ if (!valid && result == XR_ERROR_VIEW_CONFIGURATION_TYPE_UNSUPPORTED) {
+ WARN(
+ "Runtime accepted an invalid enum value as unsupported, which makes it harder for apps to reason about the error.");
+ }
+ else if (valid && result == XR_ERROR_VALIDATION_FAILURE) {
+ WARN(
+ "Runtime accepted an valid but unsupported enum value as unsupported, which makes it harder for apps to reason about the error.");
+ }
}
}
}
}
-
- // Leave
- result = xrRequestExitSession(session);
- CHECK(result == XR_SUCCESS);
-
- frameIterator.RunToSessionState(XR_SESSION_STATE_STOPPING);
}
+
} // namespace Conformance
diff --git a/src/conformance/conformance_test/test_xrRequestExitSession.cpp b/src/conformance/conformance_test/test_xrRequestExitSession.cpp
deleted file mode 100644
index a9e36175..00000000
--- a/src/conformance/conformance_test/test_xrRequestExitSession.cpp
+++ /dev/null
@@ -1,36 +0,0 @@
-// Copyright (c) 2019-2024, 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 "conformance_utils.h"
-
-#include
-#include
-
-namespace Conformance
-{
- TEST_CASE("xrRequestExitSession", "")
- {
- AutoBasicSession session(AutoBasicSession::createSession);
-
- SECTION("Session Not Running")
- {
- REQUIRE(XR_ERROR_SESSION_NOT_RUNNING == xrRequestExitSession(session));
- }
-
- // Successful case is tested in test_SessionState.cpp
- }
-
-} // namespace Conformance
diff --git a/src/conformance/framework/CMakeLists.txt b/src/conformance/framework/CMakeLists.txt
index 8adc3a50..9f89b954 100644
--- a/src/conformance/framework/CMakeLists.txt
+++ b/src/conformance/framework/CMakeLists.txt
@@ -50,12 +50,16 @@ run_xr_xml_generate(
${PROJECT_SOURCE_DIR}/src/scripts/template_function_info.cpp
)
run_xr_xml_generate(
- conformance_generator.py interaction_info_generated.cpp
+ conformance_generator.py
+ interaction_info_generated.cpp
"${PROJECT_SOURCE_DIR}/src/scripts/template_interaction_info_generated.cpp"
+ "${PROJECT_SOURCE_DIR}/src/scripts/interaction_profile_processor.py"
)
run_xr_xml_generate(
- conformance_generator.py interaction_info_generated.h
+ conformance_generator.py
+ interaction_info_generated.h
"${PROJECT_SOURCE_DIR}/src/scripts/template_interaction_info_generated.h"
+ "${PROJECT_SOURCE_DIR}/src/scripts/interaction_profile_processor.py"
)
add_library(
diff --git a/src/conformance/framework/conformance_framework.cpp b/src/conformance/framework/conformance_framework.cpp
index 6738032e..fce1ff4c 100644
--- a/src/conformance/framework/conformance_framework.cpp
+++ b/src/conformance/framework/conformance_framework.cpp
@@ -133,12 +133,46 @@ namespace Conformance
AppendSprintf(reportString, "Handle invalidation tested: %s\n", globalData.options.invalidHandleValidation ? "yes" : "no");
AppendSprintf(reportString, "Type invalidation tested: %s\n", globalData.options.invalidTypeValidation ? "yes" : "no");
AppendSprintf(reportString, "Non-disconnectable devices: %s\n", globalData.options.nonDisconnectableDevices ? "yes" : "no");
- AppendSprintf(reportString, "Test Success Count: %d\n", (int)testSuccessCount);
- AppendSprintf(reportString, "Test Failure Count: %d\n", (int)testFailureCount);
+ AppendSprintf(reportString, "Test Success Count: %zu\n", TestSuccessCount());
+ AppendSprintf(reportString, "Test Failure Count: %zu\n", TestFailureCount());
+ if (TestFailureCount() > 0) {
+ AppendSprintf(reportString, "Tests with failures:\n");
+ for (auto const& pair : results) {
+ const auto& name = pair.first;
+ const auto& score = pair.second;
+ if (score.testFailureCount > 0) {
+ AppendSprintf(reportString, " %s\n", name.c_str());
+ }
+ }
+ }
+ if (!unmatchedTestSpecs.empty()) {
+ AppendSprintf(reportString, "Unmatched Test Specs:\n");
+ for (auto const& spec : unmatchedTestSpecs) {
+ AppendSprintf(reportString, " %s\n", spec.c_str());
+ }
+ }
return reportString;
}
+ uint64_t ConformanceReport::TestSuccessCount() const
+ {
+ uint64_t success{};
+ for (auto const& pair : results) {
+ success += pair.second.testSuccessCount;
+ }
+ return success;
+ }
+
+ uint64_t ConformanceReport::TestFailureCount() const
+ {
+ uint64_t failure{};
+ for (auto const& pair : results) {
+ failure += pair.second.testFailureCount;
+ }
+ return failure;
+ }
+
bool GlobalData::Initialize()
{
// NOTE: Runs *after* population of command-line options.
@@ -301,49 +335,6 @@ namespace Conformance
}
}
}
- // Fill out the functions in functionInfoMap.
- // Keep trying all functions, only failing out at end if one of them failed.
- bool functionMapInitialized = true;
- const FunctionInfoMap& functionInfoMap = GetFunctionInfoMap();
- for (auto& functionInfo : functionInfoMap) {
- // We need to poke the address pointer into map entries.
- result = xrGetInstanceProcAddr(autoInstance, functionInfo.first.c_str(),
- &const_cast(functionInfo.second).functionPtr);
-
- if (XR_SUCCEEDED(result)) {
- // This doesn't actually prove the pointer is correct. However, we will exercise that later.
- if (functionInfo.second.functionPtr == nullptr) {
- ReportF("GlobalData::Initialize: xrGetInstanceProcAddr for '%s' failed to return valid addr.",
- functionInfo.first.c_str());
- functionMapInitialized = false;
- }
- }
- else {
- if (!ValidateResultAllowed("xrGetInstanceProcAddr", result)) {
- ReportF("GlobalData::Initialize: xrGetInstanceProcAddr for '%s' returned invalid XrResult.",
- functionInfo.first.c_str());
- functionMapInitialized = false;
- }
-
- // If we could not get a pointer to this function, then it should be because we didn't
- // enable the extension required by the function.
- if (result != XR_ERROR_FUNCTION_UNSUPPORTED) {
- ReportF("GlobalData::Initialize: xrGetInstanceProcAddr for '%s' failed with result: %s.", functionInfo.first.c_str(),
- ResultToString(result));
- functionMapInitialized = false;
- }
-
- // At this point, result is XR_ERROR_FUNCTION_UNSUPPORTED.
- // Verify that the extension was *not* enabled.
- // functionInfo.second.requiredExtension
- // To do.
- }
- }
-
- if (!functionMapInitialized) {
- ReportF("GlobalData::Initialize: xrGetInstanceProcAddr failed for one or more functions.");
- return false;
- }
// Find XrSystemId (for later use and to ensure device is connected/available for whatever that means in a given runtime)
XrSystemId systemId = XR_NULL_SYSTEM_ID;
diff --git a/src/conformance/framework/conformance_framework.h b/src/conformance/framework/conformance_framework.h
index 6febb8d0..55faa770 100644
--- a/src/conformance/framework/conformance_framework.h
+++ b/src/conformance/framework/conformance_framework.h
@@ -167,7 +167,7 @@ namespace Conformance
/// or 0 when auto skip is disabled.
std::chrono::milliseconds autoSkipTimeout{0};
- /// Options include "stereo" "mono". See enum XrViewConfigurationType.
+ /// Options include "stereo" "mono" "foveatedInset" "firstPersonObserver". See enum XrViewConfigurationType.
/// Default is stereo.
std::string viewConfiguration{"Stereo"};
XrViewConfigurationType viewConfigurationValue{XR_VIEW_CONFIGURATION_TYPE_PRIMARY_STEREO};
@@ -310,10 +310,21 @@ namespace Conformance
std::string GetReportString() const;
public:
+ class Score
+ {
+ public:
+ uint64_t testSuccessCount{};
+ uint64_t testFailureCount{};
+ };
+ /// The total successful test case runs across all test cases.
+ uint64_t TestSuccessCount() const;
+
+ /// The total failed test case runs across all test cases.
+ uint64_t TestFailureCount() const;
+
XrVersion apiVersion{XR_CURRENT_API_VERSION};
- uint64_t testSuccessCount{};
- uint64_t testFailureCount{};
- bool unmatchedTestSpecs{false};
+ std::unordered_map results;
+ std::vector unmatchedTestSpecs;
Catch::Totals totals{};
TimedSubmissionResults timedSubmission;
std::vector> swapchainFormats;
diff --git a/src/conformance/framework/conformance_utils.cpp b/src/conformance/framework/conformance_utils.cpp
index 99fa2cd2..412f57dd 100644
--- a/src/conformance/framework/conformance_utils.cpp
+++ b/src/conformance/framework/conformance_utils.cpp
@@ -440,12 +440,13 @@ namespace Conformance
////////////////////////////////////////////////////////////////////////////////////////////////
// AutoBasicSession
////////////////////////////////////////////////////////////////////////////////////////////////
- AutoBasicSession::AutoBasicSession(int optionFlags_, XrInstance instance_) : optionFlags(optionFlags_)
+ AutoBasicSession::AutoBasicSession(int optionFlags_, XrInstance instance_, XrViewConfigurationType viewConfigType_)
+ : optionFlags(optionFlags_)
{
- Init(optionFlags_, instance_);
+ Init(optionFlags_, instance_, viewConfigType_);
}
- void AutoBasicSession::Init(int optionFlags_, XrInstance instance_)
+ void AutoBasicSession::Init(int optionFlags_, XrInstance instance_, XrViewConfigurationType viewConfigType_)
{
GlobalData& globalData = GetGlobalData();
@@ -467,6 +468,8 @@ namespace Conformance
instance = instance_;
optionFlags = optionFlags_;
+ viewConfigurationType =
+ viewConfigType_ == XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM ? globalData.options.viewConfigurationValue : viewConfigType_;
if ((optionFlags & createInstance) == 0) {
// cannot proceed further without an instance
@@ -503,16 +506,13 @@ namespace Conformance
XRC_CHECK_THROW_XRCMD(xrStringToPath(instance, "/user/hand/left", &handSubactionArray[0]));
XRC_CHECK_THROW_XRCMD(xrStringToPath(instance, "/user/hand/right", &handSubactionArray[1]));
- // Note that while we are enumerating this, normally our testing is done via a pre-chosen one (globalData.options.viewConfigurationValue).
- XRC_CHECK_THROW_XRCMD(doTwoCallInPlace(viewConfigurationTypeVector, xrEnumerateViewConfigurations, instance, systemId));
-
- // We use globalData.options.viewConfigurationValue as the type we enumerate with, despite that the runtime may support others.
+ // We use viewConfigurationType as the type we enumerate with, despite that the runtime may support others.
XRC_CHECK_THROW_XRCMD(doTwoCallInPlaceWithEmptyElement(viewConfigurationViewVector, {XR_TYPE_VIEW_CONFIGURATION_VIEW},
xrEnumerateViewConfigurationViews, instance, systemId,
- globalData.options.viewConfigurationValue));
+ viewConfigurationType));
- XRC_CHECK_THROW_XRCMD(doTwoCallInPlace(environmentBlendModeVector, xrEnumerateEnvironmentBlendModes, instance, systemId,
- globalData.options.viewConfigurationValue));
+ XRC_CHECK_THROW_XRCMD(
+ doTwoCallInPlace(environmentBlendModeVector, xrEnumerateEnvironmentBlendModes, instance, systemId, viewConfigurationType));
if ((optionFlags & createSwapchains) && globalData.IsUsingGraphicsPlugin()) {
auto graphicsPlugin = globalData.GetGraphicsPlugin();
@@ -604,8 +604,13 @@ namespace Conformance
XrSessionBeginInfo sessionBeginInfo{XR_TYPE_SESSION_BEGIN_INFO,
globalData.GetPlatformPlugin()->PopulateNextFieldForStruct(XR_TYPE_SESSION_BEGIN_INFO),
- globalData.options.viewConfigurationValue};
+ viewConfigurationType};
XRC_CHECK_THROW_XRCMD(xrBeginSession(session, &sessionBeginInfo));
+
+ // We potentially changed the view configuration so we need to update the viewConfigurationViewVector
+ XRC_CHECK_THROW_XRCMD(doTwoCallInPlaceWithEmptyElement(viewConfigurationViewVector, {XR_TYPE_VIEW_CONFIGURATION_VIEW},
+ xrEnumerateViewConfigurationViews, instance, systemId,
+ viewConfigurationType));
}
AutoBasicSession::~AutoBasicSession()
@@ -626,9 +631,11 @@ namespace Conformance
actionSet = XR_NULL_HANDLE; // Let parent session destroy this.
actionVector.clear(); // Let parent session destroy this.
spaceTypeVector.clear(); // Let parent session destroy this.
- viewConfigurationTypeVector.clear();
+ spaceVector.clear();
viewConfigurationViewVector.clear();
environmentBlendModeVector.clear();
+ viewConfigurationType = XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM;
+ sessionState = XR_SESSION_STATE_UNKNOWN;
if (session != XR_NULL_HANDLE) {
xrDestroySession(session);
@@ -675,7 +682,6 @@ namespace Conformance
XRC_CHECK_THROW(autoBasicSession);
XRC_CHECK_THROW(autoBasicSession->GetInstance());
XRC_CHECK_THROW(autoBasicSession->GetSession());
- XRC_CHECK_THROW(!autoBasicSession->viewConfigurationTypeVector.empty());
XRC_CHECK_THROW(!autoBasicSession->environmentBlendModeVector.empty());
}
@@ -762,7 +768,7 @@ namespace Conformance
return RunResult::Error;
XrViewLocateInfo viewLocateInfo{XR_TYPE_VIEW_LOCATE_INFO};
- viewLocateInfo.viewConfigurationType = GetGlobalData().options.viewConfigurationValue;
+ viewLocateInfo.viewConfigurationType = autoBasicSession->viewConfigurationType;
viewLocateInfo.displayTime = frameState.predictedDisplayTime;
viewLocateInfo.space = autoBasicSession->spaceVector[0];
XrViewState viewState{XR_TYPE_VIEW_STATE};
@@ -906,7 +912,7 @@ namespace Conformance
GlobalData& globalData = GetGlobalData();
XrSessionBeginInfo sessionBeginInfo{
XR_TYPE_SESSION_BEGIN_INFO, globalData.GetPlatformPlugin()->PopulateNextFieldForStruct(XR_TYPE_SESSION_BEGIN_INFO),
- globalData.options.viewConfigurationValue};
+ autoBasicSession->viewConfigurationType};
REQUIRE(xrBeginSession(autoBasicSession->GetSession(), &sessionBeginInfo) == XR_SUCCESS);
}
diff --git a/src/conformance/framework/conformance_utils.h b/src/conformance/framework/conformance_utils.h
index 43340daf..1f4d6d06 100644
--- a/src/conformance/framework/conformance_utils.h
+++ b/src/conformance/framework/conformance_utils.h
@@ -582,15 +582,17 @@ namespace Conformance
};
/// If instance is valid then we inherit it instead of create one ourselves.
- AutoBasicSession(int optionFlags = 0, XrInstance instance = XR_NULL_HANDLE);
+ AutoBasicSession(int optionFlags = 0, XrInstance instance = XR_NULL_HANDLE,
+ XrViewConfigurationType viewConfigType_ = XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM);
/// Calls Shutdown if not shut down already.
~AutoBasicSession();
/// If instance is valid then we inherit it instead of create one ourselves.
- void Init(int optionFlags, XrInstance instance = XR_NULL_HANDLE);
+ void Init(int optionFlags, XrInstance instance = XR_NULL_HANDLE,
+ XrViewConfigurationType viewConfigType_ = XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM);
- /// Begin the session.
+ /// Begin the session with specific view configuration type
void BeginSession();
/// Restores the class instance to a pre-initialized state.
@@ -666,9 +668,9 @@ namespace Conformance
// Enumerated types.
std::vector swapchainFormatVector;
std::vector spaceTypeVector;
- std::vector viewConfigurationTypeVector;
std::vector viewConfigurationViewVector;
std::vector environmentBlendModeVector;
+ XrViewConfigurationType viewConfigurationType{XR_VIEW_CONFIGURATION_TYPE_MAX_ENUM};
};
/// Output operator for the `XrSession` handle in a @ref AutoBasicSession
@@ -685,17 +687,13 @@ namespace Conformance
/// Identifies conformance-related information about individual OpenXR functions.
struct FunctionInfo
{
- PFN_xrVoidFunction functionPtr;
bool nullInstanceOk;
const char* requiredExtension;
std::vector validResults;
- FunctionInfo(PFN_xrVoidFunction functionPtr = nullptr, bool nullInstanceOk = false, const char* requiredExtension = nullptr,
+ FunctionInfo(bool nullInstanceOk = false, const char* requiredExtension = nullptr,
std::vector validResults = std::vector())
- : functionPtr(functionPtr)
- , nullInstanceOk(nullInstanceOk)
- , requiredExtension(requiredExtension)
- , validResults(std::move(validResults))
+ : nullInstanceOk(nullInstanceOk), requiredExtension(requiredExtension), validResults(std::move(validResults))
{
}
};
diff --git a/src/conformance/framework/cts_tinygltf.cpp b/src/conformance/framework/cts_tinygltf.cpp
index 6150d106..8e893f7e 100644
--- a/src/conformance/framework/cts_tinygltf.cpp
+++ b/src/conformance/framework/cts_tinygltf.cpp
@@ -9,9 +9,4 @@
#pragma warning(disable : 4189) // local variable is initialized but not referenced
#endif // defined(_MSC_VER)
-#if defined(__GNUC__) || defined(__clang__)
-#pragma GCC diagnostic ignored "-Wunused-variable"
-#pragma GCC diagnostic ignored "-Wtautological-constant-out-of-range-compare"
-#endif
-
#include "cts_tinygltf.h"
diff --git a/src/conformance/framework/graphics_plugin_metal.cpp b/src/conformance/framework/graphics_plugin_metal.cpp
index 4f261f03..ae18e64d 100644
--- a/src/conformance/framework/graphics_plugin_metal.cpp
+++ b/src/conformance/framework/graphics_plugin_metal.cpp
@@ -427,76 +427,78 @@ namespace Conformance
static const SwapchainFormatDataMap& GetSwapchainFormatData()
{
+ using namespace SwapchainFormat;
+
// Add SwapchainCreateTestParameters for other Vulkan formats if they are supported by a runtime
static SwapchainFormatDataMap map{{
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Unorm_sRGB).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGRA8Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGRA8Unorm_sRGB).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Unorm).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Unorm_sRGB).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGRA8Unorm).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGRA8Unorm_sRGB).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Unorm_sRGB).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Unorm).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Unorm_sRGB).rg().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Unorm_sRGB).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Unorm).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Unorm_sRGB).r().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Snorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Snorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Snorm).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Snorm).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Snorm).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Snorm).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Sint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Sint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Sint).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Uint).r().Int(ColorIntegerRange::u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Uint).rg().Int(ColorIntegerRange::u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Uint).rgba().Int(ColorIntegerRange::u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR8Sint).r().Int(ColorIntegerRange::s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG8Sint).rg().Int(ColorIntegerRange::s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA8Sint).rgba().Int(ColorIntegerRange::s8).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Snorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Snorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Snorm).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Unorm).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Unorm).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Unorm).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Snorm).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Snorm).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Snorm).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Uint).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Uint).r().Int(ColorIntegerRange::u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Uint).rg().Int(ColorIntegerRange::u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Uint).rgba().Int(ColorIntegerRange::u16).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Sint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Sint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Sint).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Sint).r().Int(ColorIntegerRange::s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Sint).rg().Int(ColorIntegerRange::s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Sint).rgba().Int(ColorIntegerRange::s16).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Float).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Float).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Float).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR16Float).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG16Float).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Float).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR32Sint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG32Sint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA32Sint).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR32Sint).r().Int(ColorIntegerRange::s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG32Sint).rg().Int(ColorIntegerRange::s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA32Sint).rgba().Int(ColorIntegerRange::s32).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR32Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG32Uint).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA32Uint).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR32Uint).r().Int(ColorIntegerRange::u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG32Uint).rg().Int(ColorIntegerRange::u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA32Uint).rgba().Int(ColorIntegerRange::u32).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR32Float).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG32Float).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA32Float).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatR32Float).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG32Float).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA32Float).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatB5G6R5Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatA1BGR5Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGR5A1Unorm).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatB5G6R5Unorm).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatA1BGR5Unorm).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGR5A1Unorm).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatABGR4Unorm).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatABGR4Unorm).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGB10A2Unorm).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGR10A2Unorm).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGB10A2Unorm).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBGR10A2Unorm).rgba().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGB10A2Uint).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGB10A2Uint).rgba().Int(ColorIntegerRange::uRGB10A2).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG11B10Float).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGB9E5Float).ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Float).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRG11B10Float).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGB9E5Float).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatRGBA16Float).rgba().ToPair(),
XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatDepth16Unorm).Depth().ToPair(),
XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatDepth24Unorm_Stencil8).DepthStencil().ToPair(),
@@ -504,77 +506,77 @@ namespace Conformance
XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatDepth32Float).Depth().ToPair(),
XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatDepth32Float_Stencil8).DepthStencil().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8A1).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8A1_sRGB).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_R11Unorm).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RG11Unorm).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_R11Snorm).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RG11Snorm).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RGBA8).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RGBA8_sRGB).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_4x4_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x4_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x5_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x5_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x6_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x5_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x6_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x8_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x5_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x6_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x10_sRGB).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x12_sRGB).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_4x4_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x4_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x5_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x5_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x6_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x5_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x6_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x8_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x5_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x6_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x10_LDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x12_LDR).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_4x4_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x4_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x5_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x5_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x6_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x5_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x6_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x8_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x5_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x6_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x10_HDR).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x12_HDR).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC1_RGBA).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC1_RGBA_sRGB).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC2_RGBA).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC2_RGBA_sRGB).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC3_RGBA).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC3_RGBA_sRGB).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC6H_RGBFloat).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC6H_RGBUfloat).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC7_RGBAUnorm).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC7_RGBAUnorm_sRGB).Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8).rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8A1).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8_sRGB).rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatETC2_RGB8A1_sRGB).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_R11Unorm).r().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RG11Unorm).rg().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_R11Snorm).r().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RG11Snorm).rg().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RGBA8).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatEAC_RGBA8_sRGB).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_4x4_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x4_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x5_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x5_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x6_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x5_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x6_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x8_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x5_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x6_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x10_sRGB).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x12_sRGB).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_4x4_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x4_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x5_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x5_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x6_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x5_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x6_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x8_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x5_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x6_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x10_LDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x12_LDR).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_4x4_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x4_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_5x5_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x5_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_6x6_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x5_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x6_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_8x8_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x5_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x6_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_10x10_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x10_HDR).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatASTC_12x12_HDR).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC1_RGBA).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC1_RGBA_sRGB).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC2_RGBA).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC2_RGBA_sRGB).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC3_RGBA).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC3_RGBA_sRGB).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC6H_RGBFloat).rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC6H_RGBUfloat).rgb().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC7_RGBAUnorm).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(MTL::PixelFormatBC7_RGBAUnorm_sRGB).rgba().Compressed().ToPair(),
}};
return map;
}
@@ -941,36 +943,35 @@ namespace Conformance
using NS::StringEncoding::UTF8StringEncoding;
const char* shaderSrc = R"(
- #include
+#include
using namespace metal;
- struct VertexBuffer {
- float4 position;
- float4 color;
- };
+ struct VertexBuffer
+ {
+ float4 position;
+ float4 color;
+ };
- struct v2f
- {
- float4 position [[position]];
- half4 color;
- };
+ struct v2f
+ {
+ float4 position [[position]];
+ half4 color;
+ };
- v2f vertex vertexMain( uint vertexId [[vertex_id]],
- uint instanceId [[instance_id]],
- device const VertexBuffer* vertexBuffer [[buffer(0)]],
- device const float4x4* matricesBuffer [[buffer(1)]] )
- {
- v2f o;
- float4 pos = vertexBuffer[vertexId].position;
- o.position = matricesBuffer[instanceId] * pos;
- o.color = half4(vertexBuffer[vertexId].color);
- return o;
- }
+ v2f vertex vertexMain(uint vertexId [[vertex_id]], uint instanceId [[instance_id]],
+ device const VertexBuffer* vertexBuffer [[buffer(0)]], device const float4x4* matricesBuffer [[buffer(1)]])
+ {
+ v2f o;
+ float4 pos = vertexBuffer[vertexId].position;
+ o.position = matricesBuffer[instanceId] * pos;
+ o.color = half4(vertexBuffer[vertexId].color);
+ return o;
+ }
- half4 fragment fragmentMain( v2f in [[stage_in]] )
- {
- return in.color;
- }
+ half4 fragment fragmentMain(v2f in [[stage_in]])
+ {
+ return in.color;
+ }
)";
NS::Error* pError = nullptr;
diff --git a/src/conformance/framework/graphics_plugin_opengl.cpp b/src/conformance/framework/graphics_plugin_opengl.cpp
index 5a510f10..95f4d5d2 100644
--- a/src/conformance/framework/graphics_plugin_opengl.cpp
+++ b/src/conformance/framework/graphics_plugin_opengl.cpp
@@ -93,54 +93,56 @@ namespace Conformance
#define WORKAROUND NotMutable()
static const SwapchainFormatDataMap& GetSwapchainFormatData()
{
+ using namespace SwapchainFormat;
+
static SwapchainFormatDataMap map{
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2).WORKAROUND.ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(GL_R8).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R16).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG8).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG16).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R16F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG16F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGB16F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R32F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG32F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA32F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R11F_G11F_B10F).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R8_SNORM).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG8_SNORM).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGB8_SNORM).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8_SNORM).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R8I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R8UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R16I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R16UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R32I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_R32UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG8I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG8UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG16I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG16UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG32I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RG32UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16UI).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA32I).WORKAROUND.ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGBA32UI).WORKAROUND.ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(GL_RGBA4).WORKAROUND.NotMutable().NoUnorderedAccess().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_RGB5_A1).WORKAROUND.NotMutable().NoUnorderedAccess().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(GL_SRGB8).WORKAROUND.NoUnorderedAccess().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_SRGB8_ALPHA8).WORKAROUND.NoUnorderedAccess().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(GL_RGB565).WORKAROUND.NotMutable().NoUnorderedAccess().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8).WORKAROUND.rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16).WORKAROUND.rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2).WORKAROUND.rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(GL_R8).WORKAROUND.r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R16).WORKAROUND.r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG8).WORKAROUND.rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG16).WORKAROUND.rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2UI).WORKAROUND.rgba().Int(uRGB10A2).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R16F).WORKAROUND.r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG16F).WORKAROUND.rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGB16F).WORKAROUND.rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16F).WORKAROUND.rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R32F).WORKAROUND.r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG32F).WORKAROUND.rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA32F).WORKAROUND.rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R11F_G11F_B10F).WORKAROUND.rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R8_SNORM).WORKAROUND.r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG8_SNORM).WORKAROUND.rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGB8_SNORM).WORKAROUND.rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8_SNORM).WORKAROUND.rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R8I).WORKAROUND.r().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R8UI).WORKAROUND.r().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R16I).WORKAROUND.r().Int(s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R16UI).WORKAROUND.r().Int(u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R32I).WORKAROUND.r().Int(s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_R32UI).WORKAROUND.r().Int(u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG8I).WORKAROUND.rg().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG8UI).WORKAROUND.rg().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG16I).WORKAROUND.rg().Int(s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG16UI).WORKAROUND.rg().Int(u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG32I).WORKAROUND.rg().Int(s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RG32UI).WORKAROUND.rg().Int(u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8I).WORKAROUND.rgba().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8UI).WORKAROUND.rgba().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16I).WORKAROUND.rgba().Int(s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16UI).WORKAROUND.rgba().Int(u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA32I).WORKAROUND.rgba().Int(s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA32UI).WORKAROUND.rgba().Int(u32).ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA4).WORKAROUND.rgba().NotMutable().NoUnorderedAccess().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_RGB5_A1).WORKAROUND.rgba().NotMutable().NoUnorderedAccess().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(GL_SRGB8).WORKAROUND.rgb().NoUnorderedAccess().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_SRGB8_ALPHA8).WORKAROUND.rgba().NoUnorderedAccess().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(GL_RGB565).WORKAROUND.rgb().NotMutable().NoUnorderedAccess().ToPair(),
XRC_SWAPCHAIN_FORMAT(GL_DEPTH_COMPONENT16).WORKAROUND.Depth().ToPair(),
XRC_SWAPCHAIN_FORMAT(GL_DEPTH_COMPONENT24).WORKAROUND.Depth().ToPair(),
@@ -150,25 +152,25 @@ namespace Conformance
XRC_SWAPCHAIN_FORMAT(GL_DEPTH32F_STENCIL8).WORKAROUND.DepthStencil().ToPair(),
XRC_SWAPCHAIN_FORMAT(GL_STENCIL_INDEX8).WORKAROUND.Stencil().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RED_RGTC1).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RED_RGTC1).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RG_RGTC2).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RG_RGTC2).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_BPTC_UNORM).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT).WORKAROUND.Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT).WORKAROUND.Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB8_ETC2).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ETC2).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA8_ETC2_EAC).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_R11_EAC).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_R11_EAC).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RG11_EAC).WORKAROUND.Compressed().NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RG11_EAC).WORKAROUND.Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RED_RGTC1).WORKAROUND.r().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RED_RGTC1).WORKAROUND.r().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RG_RGTC2).WORKAROUND.rg().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RG_RGTC2).WORKAROUND.rg().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_BPTC_UNORM).WORKAROUND.rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM).WORKAROUND.rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT).WORKAROUND.rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT).WORKAROUND.rgb().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB8_ETC2).WORKAROUND.rgb().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ETC2).WORKAROUND.rgb().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2).WORKAROUND.rgba().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2).WORKAROUND.rgba().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA8_ETC2_EAC).WORKAROUND.rgba().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC).WORKAROUND.rgba().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_R11_EAC).WORKAROUND.r().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_R11_EAC).WORKAROUND.r().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RG11_EAC).WORKAROUND.rg().Compressed().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RG11_EAC).WORKAROUND.rg().Compressed().NotMutable().ToPair(),
};
return map;
}
diff --git a/src/conformance/framework/graphics_plugin_opengles.cpp b/src/conformance/framework/graphics_plugin_opengles.cpp
index 10bb7335..e6255159 100644
--- a/src/conformance/framework/graphics_plugin_opengles.cpp
+++ b/src/conformance/framework/graphics_plugin_opengles.cpp
@@ -620,204 +620,243 @@ namespace Conformance
static const SwapchainFormatDataMap& GetSwapchainFormatData()
{
+ using namespace SwapchainFormat;
+ using C = SwapchainFormat::RawColorComponents;
+
static SwapchainFormatDataMap map{
//
// 8 bits per component
//
- XRC_SWAPCHAIN_FORMAT(GL_R8).WORKAROUND.ToPair(), // 1-component, 8-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RG8).WORKAROUND.ToPair(), // 2-component, 8-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB8).WORKAROUND.ToPair(), // 3-component, 8-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8).WORKAROUND.ToPair(), // 4-component, 8-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_R8_SNORM).WORKAROUND.ToPair(), // 1-component, 8-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_RG8_SNORM).WORKAROUND.ToPair(), // 2-component, 8-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB8_SNORM).WORKAROUND.ToPair(), // 3-component, 8-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8_SNORM).WORKAROUND.ToPair(), // 4-component, 8-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_R8UI).WORKAROUND.ToPair(), // 1-component, 8-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RG8UI).WORKAROUND.ToPair(), // 2-component, 8-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RGB8UI).WORKAROUND.ToPair(), // 3-component, 8-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8UI).WORKAROUND.ToPair(), // 4-component, 8-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_R8I).WORKAROUND.ToPair(), // 1-component, 8-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RG8I).WORKAROUND.ToPair(), // 2-component, 8-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RGB8I).WORKAROUND.ToPair(), // 3-component, 8-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RGBA8I).WORKAROUND.ToPair(), // 4-component, 8-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_SR8).WORKAROUND.ToPair(), // 1-component, 8-bit sRGB
- XRC_SWAPCHAIN_FORMAT(GL_SRG8).WORKAROUND.ToPair(), // 2-component, 8-bit sRGB
- XRC_SWAPCHAIN_FORMAT(GL_SRGB8).WORKAROUND.ToPair(), // 3-component, 8-bit sRGB
- XRC_SWAPCHAIN_FORMAT(GL_SRGB8_ALPHA8).WORKAROUND.ToPair(), // 4-component, 8-bit sRGB
+ XRC_SWAPCHAIN_FORMAT(GL_R8).WORKAROUND.r().ToPair(), // 1-component, 8-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RG8).WORKAROUND.rg().ToPair(), // 2-component, 8-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB8).WORKAROUND.rgb().ToPair(), // 3-component, 8-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8).WORKAROUND.rgba().ToPair(), // 4-component, 8-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_R8_SNORM).WORKAROUND.r().ToPair(), // 1-component, 8-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RG8_SNORM).WORKAROUND.rg().ToPair(), // 2-component, 8-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB8_SNORM).WORKAROUND.rgb().ToPair(), // 3-component, 8-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8_SNORM).WORKAROUND.rgba().ToPair(), // 4-component, 8-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_R8UI).WORKAROUND.r().Int(u8).ToPair(), // 1-component, 8-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RG8UI).WORKAROUND.rg().Int(u8).ToPair(), // 2-component, 8-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGB8UI).WORKAROUND.rgb().Int(u8).ToPair(), // 3-component, 8-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8UI).WORKAROUND.rgba().Int(u8).ToPair(), // 4-component, 8-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_R8I).WORKAROUND.r().Int(s8).ToPair(), // 1-component, 8-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RG8I).WORKAROUND.rg().Int(s8).ToPair(), // 2-component, 8-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGB8I).WORKAROUND.rgb().Int(s8).ToPair(), // 3-component, 8-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA8I).WORKAROUND.rgba().Int(s8).ToPair(), // 4-component, 8-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_SR8).WORKAROUND.r().ToPair(), // 1-component, 8-bit sRGB
+ XRC_SWAPCHAIN_FORMAT(GL_SRG8).WORKAROUND.rg().ToPair(), // 2-component, 8-bit sRGB
+ XRC_SWAPCHAIN_FORMAT(GL_SRGB8).WORKAROUND.rgb().ToPair(), // 3-component, 8-bit sRGB
+ XRC_SWAPCHAIN_FORMAT(GL_SRGB8_ALPHA8).WORKAROUND.rgba().ToPair(), // 4-component, 8-bit sRGB
//
// 16 bits per component
//
- XRC_SWAPCHAIN_FORMAT(GL_R16).WORKAROUND.ToPair(), // 1-component, 16-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RG16).WORKAROUND.ToPair(), // 2-component, 16-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB16).WORKAROUND.ToPair(), // 3-component, 16-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16).WORKAROUND.ToPair(), // 4-component, 16-bit unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_R16_SNORM).WORKAROUND.ToPair(), // 1-component, 16-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_RG16_SNORM).WORKAROUND.ToPair(), // 2-component, 16-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB16_SNORM).WORKAROUND.ToPair(), // 3-component, 16-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16_SNORM).WORKAROUND.ToPair(), // 4-component, 16-bit signed normalized
- XRC_SWAPCHAIN_FORMAT(GL_R16UI).WORKAROUND.ToPair(), // 1-component, 16-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RG16UI).WORKAROUND.ToPair(), // 2-component, 16-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RGB16UI).WORKAROUND.ToPair(), // 3-component, 16-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16UI).WORKAROUND.ToPair(), // 4-component, 16-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_R16I).WORKAROUND.ToPair(), // 1-component, 16-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RG16I).WORKAROUND.ToPair(), // 2-component, 16-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RGB16I).WORKAROUND.ToPair(), // 3-component, 16-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16I).WORKAROUND.ToPair(), // 4-component, 16-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_R16F).WORKAROUND.ToPair(), // 1-component, 16-bit floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RG16F).WORKAROUND.ToPair(), // 2-component, 16-bit floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RGB16F).WORKAROUND.ToPair(), // 3-component, 16-bit floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RGBA16F).WORKAROUND.ToPair(), // 4-component, 16-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_R16).WORKAROUND.r().ToPair(), // 1-component, 16-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RG16).WORKAROUND.rg().ToPair(), // 2-component, 16-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB16).WORKAROUND.rgb().ToPair(), // 3-component, 16-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16).WORKAROUND.rgba().ToPair(), // 4-component, 16-bit unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_R16_SNORM).WORKAROUND.r().ToPair(), // 1-component, 16-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RG16_SNORM).WORKAROUND.rg().ToPair(), // 2-component, 16-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB16_SNORM).WORKAROUND.rgb().ToPair(), // 3-component, 16-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16_SNORM).WORKAROUND.rgba().ToPair(), // 4-component, 16-bit signed normalized
+ XRC_SWAPCHAIN_FORMAT(GL_R16UI).WORKAROUND.r().Int(u16).ToPair(), // 1-component, 16-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RG16UI).WORKAROUND.rg().Int(u16).ToPair(), // 2-component, 16-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGB16UI).WORKAROUND.rgb().Int(u16).ToPair(), // 3-component, 16-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16UI).WORKAROUND.rgba().Int(u16).ToPair(), // 4-component, 16-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_R16I).WORKAROUND.r().Int(s16).ToPair(), // 1-component, 16-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RG16I).WORKAROUND.rg().Int(s16).ToPair(), // 2-component, 16-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGB16I).WORKAROUND.rgb().Int(s16).ToPair(), // 3-component, 16-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16I).WORKAROUND.rgba().Int(s16).ToPair(), // 4-component, 16-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_R16F).WORKAROUND.r().ToPair(), // 1-component, 16-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RG16F).WORKAROUND.rg().ToPair(), // 2-component, 16-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RGB16F).WORKAROUND.rgb().ToPair(), // 3-component, 16-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA16F).WORKAROUND.rgba().ToPair(), // 4-component, 16-bit floating-point
//
// 32 bits per component
//
- XRC_SWAPCHAIN_FORMAT(GL_R32UI).WORKAROUND.ToPair(), // 1-component, 32-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RG32UI).WORKAROUND.ToPair(), // 2-component, 32-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RGB32UI).WORKAROUND.ToPair(), // 3-component, 32-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_RGBA32UI).WORKAROUND.ToPair(), // 4-component, 32-bit unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_R32I).WORKAROUND.ToPair(), // 1-component, 32-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RG32I).WORKAROUND.ToPair(), // 2-component, 32-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RGB32I).WORKAROUND.ToPair(), // 3-component, 32-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_RGBA32I).WORKAROUND.ToPair(), // 4-component, 32-bit signed integer
- XRC_SWAPCHAIN_FORMAT(GL_R32F).WORKAROUND.ToPair(), // 1-component, 32-bit floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RG32F).WORKAROUND.ToPair(), // 2-component, 32-bit floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RGB32F).WORKAROUND.ToPair(), // 3-component, 32-bit floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RGBA32F).WORKAROUND.ToPair(), // 4-component, 32-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_R32UI).WORKAROUND.r().Int(u32).ToPair(), // 1-component, 32-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RG32UI).WORKAROUND.rg().Int(u32).ToPair(), // 2-component, 32-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGB32UI).WORKAROUND.rgb().Int(u32).ToPair(), // 3-component, 32-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA32UI).WORKAROUND.rgba().Int(u32).ToPair(), // 4-component, 32-bit unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_R32I).WORKAROUND.r().Int(s32).ToPair(), // 1-component, 32-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RG32I).WORKAROUND.rg().Int(s32).ToPair(), // 2-component, 32-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGB32I).WORKAROUND.rgb().Int(s32).ToPair(), // 3-component, 32-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA32I).WORKAROUND.rgba().Int(s32).ToPair(), // 4-component, 32-bit signed integer
+ XRC_SWAPCHAIN_FORMAT(GL_R32F).WORKAROUND.r().ToPair(), // 1-component, 32-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RG32F).WORKAROUND.rg().ToPair(), // 2-component, 32-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RGB32F).WORKAROUND.rgb().ToPair(), // 3-component, 32-bit floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA32F).WORKAROUND.rgba().ToPair(), // 4-component, 32-bit floating-point
//
// Packed
//
- XRC_SWAPCHAIN_FORMAT(GL_RGB5).WORKAROUND.ToPair(), // 3-component 5:5:5, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB565).WORKAROUND.ToPair(), // 3-component 5:6:5, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB10).WORKAROUND.ToPair(), // 3-component 10:10:10, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGBA4).WORKAROUND.ToPair(), // 4-component 4:4:4:4, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB5_A1).WORKAROUND.ToPair(), // 4-component 5:5:5:1, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2).WORKAROUND.ToPair(), // 4-component 10:10:10:2, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2UI).WORKAROUND.ToPair(), // 4-component 10:10:10:2, unsigned integer
- XRC_SWAPCHAIN_FORMAT(GL_R11F_G11F_B10F).WORKAROUND.ToPair(), // 3-component 11:11:10, floating-point
- XRC_SWAPCHAIN_FORMAT(GL_RGB9_E5).WORKAROUND.ToPair(), // 3-component/exp 9:9:9/5, floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RGB5).WORKAROUND.rgb().ToPair(), // 3-component 5:5:5, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB565).WORKAROUND.rgb().ToPair(), // 3-component 5:6:5, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB10).WORKAROUND.rgb().ToPair(), // 3-component 10:10:10, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGBA4).WORKAROUND.rgba().ToPair(), // 4-component 4:4:4:4, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB5_A1).WORKAROUND.rgba().ToPair(), // 4-component 5:5:5:1, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2).WORKAROUND.rgba().ToPair(), // 4-component 10:10:10:2, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_RGB10_A2UI).WORKAROUND.rgba().Int(uRGB10A2).ToPair(), // 4-component 10:10:10:2, unsigned integer
+ XRC_SWAPCHAIN_FORMAT(GL_R11F_G11F_B10F).WORKAROUND.rgb().ToPair(), // 3-component 11:11:10, floating-point
+ XRC_SWAPCHAIN_FORMAT(GL_RGB9_E5).WORKAROUND.rgb().ToPair(), // 3-component/exp 9:9:9/5, floating-point
//
// S3TC/DXT/BC
//
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_S3TC_DXT1_EXT)
+ .rgb()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT1_EXT)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space plus 1-bit alpha, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT5_EXT)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space plus line through 1D space, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_S3TC_DXT3_EXT)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space plus 4-bit alpha, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_S3TC_DXT1_EXT)
+ .rgb()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space plus 1-bit alpha, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space plus line through 1D space, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // line through 3D space plus 4-bit alpha, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_LUMINANCE_LATC1_EXT)
+ .r()
.Compressed()
.NotMutable()
.ToPair(), // line through 1D space, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_LUMINANCE_ALPHA_LATC2_EXT)
+ .Color(C(r | a))
.Compressed()
.NotMutable()
.ToPair(), // two lines through 1D space, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_LUMINANCE_LATC1_EXT)
+ .r()
.Compressed()
.NotMutable()
.ToPair(), // line through 1D space, 4x4 blocks, signed normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_LUMINANCE_ALPHA_LATC2_EXT)
+ .Color(C(r | a))
.Compressed()
.NotMutable()
.ToPair(), // two lines through 1D space, 4x4 blocks, signed normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RED_RGTC1)
+ .r()
.Compressed()
.NotMutable()
.ToPair(), // line through 1D space, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RG_RGTC2)
+ .rg()
.Compressed()
.NotMutable()
.ToPair(), // two lines through 1D space, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RED_RGTC1)
+ .r()
.Compressed()
.NotMutable()
.ToPair(), // line through 1D space, 4x4 blocks, signed normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RG_RGTC2)
+ .rg()
.Compressed()
.NotMutable()
.ToPair(), // two lines through 1D space, 4x4 blocks, signed normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT)
+ .rgb()
.Compressed()
.NotMutable()
.ToPair(), // 3-component, 4x4 blocks, unsigned floating-point
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT)
+ .rgb()
.Compressed()
.NotMutable()
.ToPair(), // 3-component, 4x4 blocks, signed floating-point
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_BPTC_UNORM)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component, 4x4 blocks, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM).Compressed().NotMutable().ToPair(), // 4-component, 4x4 blocks, sRGB
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM)
+ .rgba()
+ .Compressed()
+ .NotMutable()
+ .ToPair(), // 4-component, 4x4 blocks, sRGB
//
// ETC
//
- XRC_SWAPCHAIN_FORMAT(GL_ETC1_RGB8_OES).Compressed().NotMutable().ToPair(), // 3-component ETC1, 4x4 blocks, unsigned normalized
+ XRC_SWAPCHAIN_FORMAT(GL_ETC1_RGB8_OES)
+ .rgb()
+ .Compressed()
+ .NotMutable()
+ .ToPair(), // 3-component ETC1, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB8_ETC2)
+ .rgb()
.Compressed()
.NotMutable()
.ToPair(), // 3-component ETC2, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ETC2 with 1-bit alpha, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA8_ETC2_EAC)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ETC2, 4x4 blocks, unsigned normalized
- XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ETC2).Compressed().NotMutable().ToPair(), // 3-component ETC2, 4x4 blocks, sRGB
+ XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ETC2).rgb().Compressed().NotMutable().ToPair(), // 3-component ETC2, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ETC2 with 1-bit alpha, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ETC2, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_R11_EAC)
+ .r()
.Compressed()
.NotMutable()
.ToPair(), // 1-component ETC, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RG11_EAC)
+ .rg()
.Compressed()
.NotMutable()
.ToPair(), // 2-component ETC, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_R11_EAC)
+ .r()
.Compressed()
.NotMutable()
.ToPair(), // 1-component ETC, 4x4 blocks, signed normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SIGNED_RG11_EAC)
+ .rg()
.Compressed()
.NotMutable()
.ToPair(), // 2-component ETC, 4x4 blocks, signed normalized
@@ -826,114 +865,142 @@ namespace Conformance
// ASTC
//
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_4x4_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 4x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_5x4_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 5x4 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_5x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 5x5 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_6x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 6x5 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_6x6_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 6x6 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_8x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 8x5 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_8x6_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 8x6 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_8x8_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 8x8 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_10x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x5 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_10x6_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x6 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_10x8_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x8 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_10x10_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x10 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_12x10_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 12x10 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_RGBA_ASTC_12x12_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 12x12 blocks, unsigned normalized
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 4x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 5x4 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 5x5 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 6x5 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 6x6 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 8x5 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 8x6 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 8x8 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x5 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x6 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x8 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 10x10 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 12x10 blocks, sRGB
XRC_SWAPCHAIN_FORMAT(GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR)
+ .rgba()
.Compressed()
.NotMutable()
.ToPair(), // 4-component ASTC, 12x12 blocks, sRGB
diff --git a/src/conformance/framework/graphics_plugin_vulkan.cpp b/src/conformance/framework/graphics_plugin_vulkan.cpp
index 987a5c68..657abf20 100644
--- a/src/conformance/framework/graphics_plugin_vulkan.cpp
+++ b/src/conformance/framework/graphics_plugin_vulkan.cpp
@@ -1429,97 +1429,98 @@ namespace Conformance
static const SwapchainFormatDataMap& GetSwapchainFormatData()
{
+ using namespace SwapchainFormat;
// Add SwapchainCreateTestParameters for other Vulkan formats if they are supported by a runtime
static SwapchainFormatDataMap map{{
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_SRGB).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8A8_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8A8_SRGB).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_SRGB).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8_SRGB).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_UNORM).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_UNORM).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_SNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_SNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_SNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_SNORM).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_SRGB).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_SRGB).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_UNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_UNORM).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_SNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_SNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_SNORM).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SNORM).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_UINT).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SINT).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_SFLOAT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_SFLOAT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_SFLOAT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SFLOAT).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32_SINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32A32_SINT).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32_UINT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32A32_UINT).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32_SFLOAT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32_SFLOAT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32_SFLOAT).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32A32_SFLOAT).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R5G5B5A1_UNORM_PACK16).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R5G6B5_UNORM_PACK16).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2B10G10R10_UNORM_PACK32).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R4G4B4A4_UNORM_PACK16).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A1R5G5B5_UNORM_PACK16).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2R10G10B10_UNORM_PACK32).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2R10G10B10_UINT_PACK32).ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2B10G10R10_UNORM_PACK32).ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2B10G10R10_UINT_PACK32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_UNORM).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_SRGB).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8A8_UNORM).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8A8_SRGB).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_UNORM).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_SRGB).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8_UNORM).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B8G8R8_SRGB).rgb().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_UNORM).rg().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_UNORM).r().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_SNORM).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_SNORM).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_SNORM).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_SNORM).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_UINT).r().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_UINT).rg().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_UINT).rgb().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_UINT).rgba().Int(u8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_SINT).r().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_SINT).rg().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8_SINT).rgb().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_UNORM).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8B8A8_SINT).rgba().Int(s8).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8_SRGB).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R8G8_SRGB).rg().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_UNORM).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_UNORM).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_UNORM).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_UNORM).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_SNORM).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_SNORM).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_SNORM).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SNORM).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_UINT).r().Int(u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_UINT).rg().Int(u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_UINT).rgb().Int(u16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_UINT).rgba().Int(u16).ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_SINT).r().Int(s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_SINT).rg().Int(s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_SINT).rgb().Int(s16).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SINT).rgba().Int(s16).ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16_SFLOAT).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16_SFLOAT).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16_SFLOAT).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SFLOAT).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32_SINT).r().Int(s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32_SINT).rg().Int(s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32_SINT).rgb().Int(s32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32A32_SINT).rgba().Int(s32).ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32_UINT).r().Int(u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32_UINT).rg().Int(u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32_UINT).rgb().Int(u32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32A32_UINT).rgba().Int(u32).ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32_SFLOAT).r().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32_SFLOAT).rg().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32_SFLOAT).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R32G32B32A32_SFLOAT).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R5G5B5A1_UNORM_PACK16).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R5G6B5_UNORM_PACK16).rgb().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2B10G10R10_UNORM_PACK32).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R4G4B4A4_UNORM_PACK16).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A1R5G5B5_UNORM_PACK16).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2R10G10B10_UNORM_PACK32).rgba().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2R10G10B10_UINT_PACK32).rgba().Int(uRGB10A2).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2B10G10R10_UNORM_PACK32).rgba().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_A2B10G10R10_UINT_PACK32).rgba().Int(uRGB10A2).ToPair(),
// Runtimes with D3D11 back-ends map VK_FORMAT_B10G11R11_UFLOAT_PACK32 to DXGI_FORMAT_R11G11B10_FLOAT and that format doesn't have a TYPELESS equivalent.
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B10G11R11_UFLOAT_PACK32).NotMutable().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_B10G11R11_UFLOAT_PACK32).rgb().NotMutable().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_E5B9G9R9_UFLOAT_PACK32).rgb().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SFLOAT).ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_R16G16B16A16_SFLOAT).rgba().ToPair(),
XRC_SWAPCHAIN_FORMAT(VK_FORMAT_D16_UNORM).Depth().ToPair(),
XRC_SWAPCHAIN_FORMAT(VK_FORMAT_D24_UNORM_S8_UINT).DepthStencil().ToPair(),
@@ -1530,62 +1531,62 @@ namespace Conformance
XRC_SWAPCHAIN_FORMAT(VK_FORMAT_D32_SFLOAT).Depth().ToPair(),
XRC_SWAPCHAIN_FORMAT(VK_FORMAT_D32_SFLOAT_S8_UINT).DepthStencil().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11G11_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11_SNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11G11_SNORM_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_4x4_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x4_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x5_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x5_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x6_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x5_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x6_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x8_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x5_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x6_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x8_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x10_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x10_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x12_UNORM_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_4x4_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x4_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x5_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x5_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x6_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x5_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x6_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x8_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x5_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x6_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x8_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x10_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x10_SRGB_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x12_SRGB_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC1_RGBA_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC1_RGBA_SRGB_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC2_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC2_SRGB_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC3_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC3_SRGB_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC6H_UFLOAT_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC6H_SFLOAT_BLOCK).Compressed().ToPair(),
-
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC7_UNORM_BLOCK).Compressed().ToPair(),
- XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC7_SRGB_BLOCK).Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK).rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK).rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11_UNORM_BLOCK).r().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11G11_UNORM_BLOCK).rg().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11_SNORM_BLOCK).r().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_EAC_R11G11_SNORM_BLOCK).rg().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_4x4_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x4_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x5_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x5_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x6_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x5_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x6_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x8_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x5_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x6_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x8_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x10_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x10_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x12_UNORM_BLOCK).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_4x4_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x4_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_5x5_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x5_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_6x6_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x5_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x6_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_8x8_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x5_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x6_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x8_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_10x10_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x10_SRGB_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_ASTC_12x12_SRGB_BLOCK).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC1_RGBA_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC1_RGBA_SRGB_BLOCK).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC2_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC2_SRGB_BLOCK).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC3_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC3_SRGB_BLOCK).rgba().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC6H_UFLOAT_BLOCK).rgb().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC6H_SFLOAT_BLOCK).rgb().Compressed().ToPair(),
+
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC7_UNORM_BLOCK).rgba().Compressed().ToPair(),
+ XRC_SWAPCHAIN_FORMAT(VK_FORMAT_BC7_SRGB_BLOCK).rgba().Compressed().ToPair(),
}};
return map;
}
diff --git a/src/conformance/framework/input_testinputdevice.cpp b/src/conformance/framework/input_testinputdevice.cpp
index 6aabb4e1..0ea05a63 100644
--- a/src/conformance/framework/input_testinputdevice.cpp
+++ b/src/conformance/framework/input_testinputdevice.cpp
@@ -76,6 +76,7 @@ namespace Conformance
m_actionSet = actionSet;
m_actionMap = actionMap;
m_firstBooleanAction = firstBooleanAction; // will be used for testing active controller
+ m_firstTrackerAction = XR_NULL_HANDLE; // will be used for testing active controller if m_firstBooleanAction is not set
m_shouldDestroyActionSet = false; // actions and action sets are handled by the test, so do not destroy
}
@@ -129,6 +130,9 @@ namespace Conformance
if (m_firstBooleanAction == XR_NULL_PATH && inputSourceData.Type == XR_ACTION_TYPE_BOOLEAN_INPUT) {
m_firstBooleanAction = action;
}
+ if (m_firstTrackerAction == XR_NULL_PATH && inputSourceData.Type == XR_ACTION_TYPE_POSE_INPUT) {
+ m_firstTrackerAction = action;
+ }
const XrPath bindingPath = StringToPath(instance, inputSourceData.Path);
m_actionMap.insert({bindingPath, action});
@@ -182,6 +186,10 @@ namespace Conformance
XrActionSet detectionActionSet{waitCondition.detectionActionSet};
XrAction detectionBoolAction{waitCondition.detectionBoolAction};
+ // The selected controller has no boolean actions so...
+ XRC_CHECK_THROW(detectionBoolAction != XR_NULL_HANDLE || m_firstBooleanAction != XR_NULL_HANDLE ||
+ m_firstTrackerAction != XR_NULL_HANDLE);
+
// Checks the isActive on a boolean action to determine if a controller is on
auto findController = [&]() -> ControllerState {
XrActiveActionSet activeActionSets[] = {
@@ -201,15 +209,28 @@ namespace Conformance
}
}
- XrActionStateBoolean booleanActionData{XR_TYPE_ACTION_STATE_BOOLEAN};
- XrActionStateGetInfo getInfo{XR_TYPE_ACTION_STATE_GET_INFO};
- getInfo.action = detectionBoolAction == XR_NULL_HANDLE ? m_firstBooleanAction : detectionBoolAction;
- const XrResult res = xrGetActionStateBoolean(m_session, &getInfo, &booleanActionData);
- if (res != XR_SUCCESS) {
- XRC_THROW_XRRESULT(res, xrGetActionStateBoolean);
+ if (detectionBoolAction != XR_NULL_HANDLE || m_firstBooleanAction != XR_NULL_HANDLE) {
+ XrActionStateBoolean booleanActionData{XR_TYPE_ACTION_STATE_BOOLEAN};
+ XrActionStateGetInfo getInfo{XR_TYPE_ACTION_STATE_GET_INFO};
+ getInfo.action = detectionBoolAction != XR_NULL_HANDLE ? detectionBoolAction : m_firstBooleanAction;
+ const XrResult res = xrGetActionStateBoolean(m_session, &getInfo, &booleanActionData);
+ if (res != XR_SUCCESS) {
+ XRC_THROW_XRRESULT(res, xrGetActionStateBoolean);
+ }
+
+ return booleanActionData.isActive ? ControllerState::Active : ControllerState::Inactive;
}
+ else {
+ XrActionStatePose trackerActionData{XR_TYPE_ACTION_STATE_POSE};
+ XrActionStateGetInfo getInfo{XR_TYPE_ACTION_STATE_GET_INFO};
+ getInfo.action = m_firstTrackerAction;
+ const XrResult res = xrGetActionStatePose(m_session, &getInfo, &trackerActionData);
+ if (res != XR_SUCCESS) {
+ XRC_THROW_XRRESULT(res, xrGetActionStatePose);
+ }
- return booleanActionData.isActive ? ControllerState::Active : ControllerState::Inactive;
+ return trackerActionData.isActive ? ControllerState::Active : ControllerState::Inactive;
+ }
};
const ControllerState desiredControllerState = state ? ControllerState::Active : ControllerState::Inactive;
@@ -532,6 +553,7 @@ namespace Conformance
std::map m_actionMap;
XrAction m_firstBooleanAction{XR_NULL_PATH}; // Used to detect controller state
+ XrAction m_firstTrackerAction{XR_NULL_PATH}; // Used to detect controller state
bool m_shouldDestroyActionSet = true; // Don't destroy the action set if the test provided one
};
diff --git a/src/conformance/framework/xml_test_environment.cpp b/src/conformance/framework/xml_test_environment.cpp
index af10edf2..802076bf 100644
--- a/src/conformance/framework/xml_test_environment.cpp
+++ b/src/conformance/framework/xml_test_environment.cpp
@@ -31,8 +31,8 @@ namespace Conformance
.writeAttribute("patch", XR_VERSION_PATCH(cr.apiVersion))
.writeText(to_hex(cr.apiVersion));
xml.scopedElement(CTS_XML_NS_PREFIX_QUALIFIER "results")
- .writeAttribute("testSuccessCount", cr.testSuccessCount)
- .writeAttribute("testFailureCount", cr.testFailureCount);
+ .writeAttribute("testSuccessCount", cr.TestSuccessCount())
+ .writeAttribute("testFailureCount", cr.TestFailureCount());
if (cr.timedSubmission.IsValid()) {
const auto& timing = cr.timedSubmission;
using ms = std::chrono::duration;
diff --git a/src/conformance/usage/Makefile b/src/conformance/usage/Makefile
index 17ebd9eb..067ef105 100644
--- a/src/conformance/usage/Makefile
+++ b/src/conformance/usage/Makefile
@@ -85,7 +85,7 @@ reflow:
################################################
# Meta builds for releases. Also copies into approximately the right layout for the OpenXR-Registry repo.
-REGISTRYOUTDIR = $(GENDIR)/out/registry-release/cts-usage
+REGISTRYOUTDIR := $(GENDIR)/out/registry-release/conformance
$(REGISTRYOUTDIR)/cts_usage.pdf: $(CTSUSAGEPDF)
$(ECHO) "[hexapdf] $(call MAKE_RELATIVE,$@)"
diff --git a/src/conformance/usage/asciidoctor-targets.mk b/src/conformance/usage/asciidoctor-targets.mk
index 7c81eda0..c14319d8 100644
--- a/src/conformance/usage/asciidoctor-targets.mk
+++ b/src/conformance/usage/asciidoctor-targets.mk
@@ -14,7 +14,7 @@ ADOCOPTS = --doctype book \
$(ADOC_FAILURE_LEVEL) \
$(ATTRIBOPTS)
-SPECREVISION = 1.1.41
+SPECREVISION = 1.1.42
ifneq (,$(strip $(RELEASE)))
# No dates or internal commit hashes in release builds for reproducibility
diff --git a/src/conformance/usage/selftests.adoc b/src/conformance/usage/selftests.adoc
index 222f33f5..bece57e9 100644
--- a/src/conformance/usage/selftests.adoc
+++ b/src/conformance/usage/selftests.adoc
@@ -14,8 +14,8 @@ with tests that build on them, submission of a CTS results package does not
require them.
Currently, the only self-tests tagged in this way are for the PBR/glTF
rendering subsystem.
-They synchronously load very large, artificial test assets, originally from
-the "glTF-Sample-Models" repository, to test specific details of the
+They (asynchronously) load very large, artificial test assets, originally
+from the "glTF-Sample-Models" repository, to test specific details of the
renderer.
To run the self-tests, commands similar to the following can be used:
@@ -50,3 +50,60 @@ conformance_cli "[self_test][interactive]" -G opengl --apiVersion 1.1 --reporter
----
====
+.Corresponding ADB commands to launch on Android for OpenXR 1.0
+[%collapsible]
+====
+Omit any graphics API binding extensions your runtime does not support.
+These commands do not match one-to-one with the desktop examples due to
+different graphics API availability on Android.
+
+[source,sh]
+----
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[self_test][interactive]" -e graphicsPlugin vulkan -e apiVersion 1.0 -e xmlFilename interactive_self_test_vulkan_1_0.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_self_test_vulkan_1_0.xml
+
+
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[self_test][interactive]" -e graphicsPlugin vulkan2 -e apiVersion 1.0 -e xmlFilename interactive_self_test_vulkan2_1_0.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_self_test_vulkan2_1_0.xml
+
+
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[self_test][interactive]" -e graphicsPlugin opengles -e apiVersion 1.0 -e xmlFilename interactive_self_test_opengles_1_0.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_self_test_opengles_1_0.xml
+
+----
+====
+
+.Corresponding ADB commands to launch on Android for OpenXR 1.1
+[%collapsible]
+====
+Omit any graphics API binding extensions your runtime does not support.
+These commands do not match one-to-one with the desktop examples due to
+different graphics API availability on Android.
+
+[source,sh]
+----
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[self_test][interactive]" -e graphicsPlugin vulkan -e apiVersion 1.1 -e xmlFilename interactive_self_test_vulkan_1_1.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_self_test_vulkan_1_1.xml
+
+
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[self_test][interactive]" -e graphicsPlugin vulkan2 -e apiVersion 1.1 -e xmlFilename interactive_self_test_vulkan2_1_1.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_self_test_vulkan2_1_1.xml
+
+
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[self_test][interactive]" -e graphicsPlugin opengles -e apiVersion 1.1 -e xmlFilename interactive_self_test_opengles_1_1.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_self_test_opengles_1_1.xml
+
+----
+====
diff --git a/src/conformance/usage/submissions_criteria.adoc b/src/conformance/usage/submissions_criteria.adoc
index 415bc112..532e22e5 100644
--- a/src/conformance/usage/submissions_criteria.adoc
+++ b/src/conformance/usage/submissions_criteria.adoc
@@ -33,14 +33,14 @@ or
[source,xml]
----
-
+
----
or
[source,xml]
----
-
+
----
With the results of the entire run summarized in `testsuite` tag (listing
@@ -59,8 +59,11 @@ the number of top level test cases):
----
-**Any error or failure when testing core or KHR extension functionality
-means your runtime is not conformant.**
+[IMPORTANT]
+====
+Any error or failure when testing **core or KHR extension** functionality
+means your runtime is **not conformant**.
Any warnings **may** indicate non-conformance and **must** be explained in
the submission package.
+====
diff --git a/src/conformance/usage/submissions_package.adoc b/src/conformance/usage/submissions_package.adoc
index 6093b7b4..cecb382a 100644
--- a/src/conformance/usage/submissions_package.adoc
+++ b/src/conformance/usage/submissions_package.adoc
@@ -7,10 +7,10 @@
The submission package **must** include each of the following:
-. <>
+. <>
. The console output produced by the CTS runs above.
-. <>
-. <>
+. <>
+. <>
When you submit for OpenXR 1.1 conformance, you **must** also submit for
each earlier OpenXR minor version that your runtime supports in the same
@@ -95,15 +95,14 @@ Can we drop this requirement?
====
Each test suite run starts by printing test configuration data, and ends by
-printing a ``Report'' showing details of the runtime and environment
+printing a "Report" showing details of the runtime and environment
(extensions, etc) used in that run.
A few tests produce console output in-between that does not show up in the
result XML.
It is important to have this data for the interpretation of the results.
[[submissions-package-build-info]]
-=== Information on the build of conformance used in generating the
-results
+=== Information on the build of conformance used in generating the results
Files containing the result of the commands `git status` and `git log` from
the CTS directory:
diff --git a/src/conformance/usage/submissions_testing_steps.adoc b/src/conformance/usage/submissions_testing_steps.adoc
index a58a6b6f..52d8ba12 100644
--- a/src/conformance/usage/submissions_testing_steps.adoc
+++ b/src/conformance/usage/submissions_testing_steps.adoc
@@ -354,6 +354,12 @@ For any supported interaction profiles that are valid for `/user/gamepad`
rather than `/user/hand/left` and `/user/hand/right`, further filter the
tests by specifying the tag `[gamepad]`.
+To clarify, if you support providing input for all components of one of the
+following interaction profiles, specify them as well.
+
+* `/interaction_profiles/khr/simple_controller`
+* `/interaction_profiles/ext/hand_interaction_ext`
+* `/interaction_profiles/ext/eye_gaze_interaction`
.Example command lines for OpenXR 1.0
[%collapsible]
@@ -362,9 +368,14 @@ Select the interaction profiles to test based on the preceding description.
[source,sh]
----
-# Generic profile
+## Generic: Simple controller
conformance_cli "[actions][interactive]" -G d3d11 -I "khr/simple_controller" --apiVersion 1.0 --reporter ctsxml::out=interactive_action_simple_controller_1_0.xml
+## Generic: Hand interaction (whether via hand tracking or controller)
+conformance_cli "[actions][interactive]" -G d3d11 -I "ext/hand_interaction_ext" --apiVersion 1.0 --reporter ctsxml::out=interactive_action_ext_hand_interaction_interaction_1_0.xml
+
+## Generic: Eye gaze
+conformance_cli "[actions][interactive]" -G d3d11 -I "ext/eye_gaze_interaction" --apiVersion 1.0 --reporter ctsxml::out=interactive_action_ext_eye_gaze_interaction_1_0.xml
# Sample device-associated profiles
conformance_cli "[actions][interactive]" -G d3d11 -I "microsoft/motion_controller" --apiVersion 1.0 --reporter ctsxml::out=interactive_action_microsoft_motion_controller_1_0.xml
@@ -382,9 +393,14 @@ conformance_cli "[actions][interactive]" -G d3d11 -I "htc/vive_controller" --api
Select the interaction profiles to test based on the preceding description.
[source,sh]
----
-# Generic profile
+## Generic: Simple controller
conformance_cli "[actions][interactive]" -G d3d11 -I "khr/simple_controller" --apiVersion 1.1 --reporter ctsxml::out=interactive_action_simple_controller_1_1.xml
+## Generic: Hand interaction (whether via hand tracking or controller)
+conformance_cli "[actions][interactive]" -G d3d11 -I "ext/hand_interaction_ext" --apiVersion 1.1 --reporter ctsxml::out=interactive_action_ext_hand_interaction_interaction_1_1.xml
+
+## Generic: Eye gaze
+conformance_cli "[actions][interactive]" -G d3d11 -I "ext/eye_gaze_interaction" --apiVersion 1.1 --reporter ctsxml::out=interactive_action_ext_eye_gaze_interaction_1_1.xml
# Sample device-associated profiles
conformance_cli "[actions][interactive]" -G d3d11 -I "microsoft/motion_controller" --apiVersion 1.1 --reporter ctsxml::out=interactive_action_microsoft_motion_controller_1_1.xml
@@ -423,13 +439,27 @@ Select the interaction profiles to test based on the preceding description.
[source,sh]
----
-## Generic profile
+## Generic: Simple controller
adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,khr/simple_controller" -e apiVersion 1.0 -e xmlFilename interactive_action_simple_controller_1_0.xml
# Wait until tests complete, then retrieve results with
adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_simple_controller_1_0.xml
+## Generic: Hand interaction (whether via hand tracking or controller)
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,ext/hand_interaction_ext" -e apiVersion 1.0 -e xmlFilename interactive_action_ext_hand_interaction_1_0.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_ext_hand_interaction_1_0.xml
+
+
+## Generic: Eye gaze interaction
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,ext/eye_gaze_interaction" -e apiVersion 1.0 -e xmlFilename interactive_action_ext_eye_gaze_interaction_1_0.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_ext_eye_gaze_interaction_1_0.xml
+
+
## Sample device-associated profile
adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,oculus/touch_controller" -e apiVersion 1.0 -e xmlFilename interactive_action_oculus_touch_controller_1_0.xml
@@ -451,13 +481,27 @@ adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_mi
====
[source,sh]
----
-## Generic profile
+## Generic: Simple controller
adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,khr/simple_controller" -e apiVersion 1.1 -e xmlFilename interactive_action_simple_controller_1_1.xml
# Wait until tests complete, then retrieve results with
adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_simple_controller_1_1.xml
+## Generic: Hand interaction (whether via hand tracking or controller)
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,ext/hand_interaction_ext" -e apiVersion 1.1 -e xmlFilename interactive_action_ext_hand_interaction_1_1.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_ext_hand_interaction_1_1.xml
+
+
+## Generic: Eye gaze interaction
+adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,ext/eye_gaze_interaction" -e apiVersion 1.1 -e xmlFilename interactive_action_ext_eye_gaze_interaction_1_1.xml
+
+# Wait until tests complete, then retrieve results with
+adb pull /sdcard/Android/data/org.khronos.openxr.cts/files/interactive_action_ext_eye_gaze_interaction_1_1.xml
+
+
## Sample device-associated profile
adb shell am start-activity -S -n org.khronos.openxr.cts/android.app.NativeActivity --esa args "[actions][interactive],-I,oculus/touch_controller" -e apiVersion 1.1 -e xmlFilename interactive_action_oculus_touch_controller_1_1.xml
diff --git a/src/conformance/utilities/CMakeLists.txt b/src/conformance/utilities/CMakeLists.txt
index aa539975..9a5e4ea1 100644
--- a/src/conformance/utilities/CMakeLists.txt
+++ b/src/conformance/utilities/CMakeLists.txt
@@ -59,6 +59,7 @@ add_library(
string_utils.cpp
stringification.cpp
swapchain_format_data.cpp
+ swapchain_parameters.cpp
throw_helpers.cpp
types_and_constants.cpp
utils.cpp
diff --git a/src/conformance/utilities/bitmask_to_string.h b/src/conformance/utilities/bitmask_to_string.h
index 06dec935..1b69bc85 100644
--- a/src/conformance/utilities/bitmask_to_string.h
+++ b/src/conformance/utilities/bitmask_to_string.h
@@ -22,7 +22,8 @@ namespace Conformance
_(XrSwapchainUsageFlags) \
_(XrCompositionLayerFlags) \
_(XrViewStateFlags) \
- _(XrSpaceLocationFlags)
+ _(XrSpaceLocationFlags) \
+ _(XrInputSourceLocalizedNameFlags)
namespace detail
{
diff --git a/src/conformance/utilities/d3d_common.cpp b/src/conformance/utilities/d3d_common.cpp
index e4268e5d..82876409 100644
--- a/src/conformance/utilities/d3d_common.cpp
+++ b/src/conformance/utilities/d3d_common.cpp
@@ -90,141 +90,152 @@ namespace Conformance
SwapchainTestMap& GetDxgiSwapchainTestMap()
{
+ using namespace SwapchainFormat;
+
static SwapchainTestMap dxgiSwapchainTestMap{
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_FLOAT).ExpectedFormat(DXGI_FORMAT_R32G32B32A32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_UINT).ExpectedFormat(DXGI_FORMAT_R32G32B32A32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_SINT).ExpectedFormat(DXGI_FORMAT_R32G32B32A32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_TYPELESS).rgba().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_FLOAT).rgba().ExpectedFormat(DXGI_FORMAT_R32G32B32A32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_UINT).rgba().Int(u32).ExpectedFormat(DXGI_FORMAT_R32G32B32A32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32A32_SINT).rgba().Int(s32).ExpectedFormat(DXGI_FORMAT_R32G32B32A32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_FLOAT).ExpectedFormat(DXGI_FORMAT_R32G32B32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_UINT).ExpectedFormat(DXGI_FORMAT_R32G32B32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_SINT).ExpectedFormat(DXGI_FORMAT_R32G32B32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_TYPELESS).rgb().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_FLOAT).rgb().ExpectedFormat(DXGI_FORMAT_R32G32B32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_UINT).rgb().Int(u32).ExpectedFormat(DXGI_FORMAT_R32G32B32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32B32_SINT).rgb().Int(s32).ExpectedFormat(DXGI_FORMAT_R32G32B32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_FLOAT).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_UINT).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_SINT).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_UNORM).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_SNORM).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_TYPELESS).rgba().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_FLOAT).rgba().ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_UINT).rgba().Int(u16).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_SINT).rgba().Int(s16).ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_UNORM).rgba().ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16B16A16_SNORM).rgba().ExpectedFormat(DXGI_FORMAT_R16G16B16A16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_FLOAT).ExpectedFormat(DXGI_FORMAT_R32G32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_UINT).ExpectedFormat(DXGI_FORMAT_R32G32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_SINT).ExpectedFormat(DXGI_FORMAT_R32G32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_TYPELESS).rg().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_FLOAT).rg().ExpectedFormat(DXGI_FORMAT_R32G32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_UINT).rg().Int(u32).ExpectedFormat(DXGI_FORMAT_R32G32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G32_SINT).rg().Int(s32).ExpectedFormat(DXGI_FORMAT_R32G32_TYPELESS).Build(),
// 32bit channel, 8bit channel, 24bit ignored. All typeless.
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G8X24_TYPELESS).Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32G8X24_TYPELESS).rg().Typeless().Build(),
// 32bit float depth, 8 bit uint stencil, 24bit ignored.
XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_D32_FLOAT_S8X24_UINT).ExpectedFormat(DXGI_FORMAT_R32G8X24_TYPELESS).DepthStencil().Build(),
// 32bit float red, 8bit ignored, 24bit ignored. Not typeless because used parts are typed?
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS).Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS).r().Typeless().Build(),
// typeless unused 32bit component, 8bit uint green, and 24bit unused. Not typeless because used parts are typed?
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT).ExpectedFormat(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS).Build(),
-
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10A2_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10A2_UNORM).ExpectedFormat(DXGI_FORMAT_R10G10B10A2_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10A2_UINT).ExpectedFormat(DXGI_FORMAT_R10G10B10A2_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_X32_TYPELESS_G8X24_UINT)
+ .Color(g)
+ .Int(u8)
+ .ExpectedFormat(DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS)
+ .Build(),
+
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10A2_TYPELESS).rgba().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10A2_UNORM).rgba().ExpectedFormat(DXGI_FORMAT_R10G10B10A2_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10A2_UINT)
+ .rgba()
+ .Int(uRGB10A2)
+ .ExpectedFormat(DXGI_FORMAT_R10G10B10A2_TYPELESS)
+ .Build(),
// This doesn't have a typeless equivalent, so it's created as-is by the runtime.
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R11G11B10_FLOAT).NotMutable().Build(),
-
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_UNORM).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_UINT).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_SINT).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_SNORM).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
-
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_FLOAT).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_UINT).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_SINT).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_UNORM).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_SNORM).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
-
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_FLOAT).ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R11G11B10_FLOAT).rgb().NotMutable().Build(),
+
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_TYPELESS).rgba().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_UNORM).rgba().ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_UNORM_SRGB).rgba().ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_UINT).rgba().Int(u8).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_SINT).rgba().Int(s8).ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8B8A8_SNORM).rgba().ExpectedFormat(DXGI_FORMAT_R8G8B8A8_TYPELESS).Build(),
+
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_TYPELESS).rg().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_FLOAT).rg().ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_UINT).rg().Int(u16).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_SINT).rg().Int(s16).ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_UNORM).rg().ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16G16_SNORM).rg().ExpectedFormat(DXGI_FORMAT_R16G16_TYPELESS).Build(),
+
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_TYPELESS).r().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_FLOAT).r().ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Build(),
XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_D32_FLOAT).ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Depth().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_UINT).ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_SINT).ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_UINT).r().Int(u32).ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R32_SINT).r().Int(s32).ExpectedFormat(DXGI_FORMAT_R32_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R24G8_TYPELESS).Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R24G8_TYPELESS).rg().Typeless().Build(),
XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_D24_UNORM_S8_UINT).ExpectedFormat(DXGI_FORMAT_R24G8_TYPELESS).Depth().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R24_UNORM_X8_TYPELESS).ExpectedFormat(DXGI_FORMAT_R24G8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_X24_TYPELESS_G8_UINT).ExpectedFormat(DXGI_FORMAT_R24G8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R24_UNORM_X8_TYPELESS).r().ExpectedFormat(DXGI_FORMAT_R24G8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_X24_TYPELESS_G8_UINT).Color(g).Int(u8).ExpectedFormat(DXGI_FORMAT_R24G8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_UINT).ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_SINT).ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_UNORM).ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_SNORM).ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_TYPELESS).rg().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_UINT).rg().Int(u8).ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_SINT).rg().Int(s8).ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_UNORM).rg().ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_SNORM).rg().ExpectedFormat(DXGI_FORMAT_R8G8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_FLOAT).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_TYPELESS).r().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_FLOAT).r().ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_D16_UNORM).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Depth().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_UINT).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_SINT).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_UNORM).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_SNORM).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
-
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_UINT).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_SINT).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_UNORM).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_SNORM).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_A8_UNORM).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_UINT).r().Int(u16).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_SINT).r().Int(s16).ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_UNORM).r().ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R16_SNORM).r().ExpectedFormat(DXGI_FORMAT_R16_TYPELESS).Build(),
+
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_TYPELESS).r().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_UINT).r().Int(u8).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_SINT).r().Int(s8).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_UNORM).r().ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8_SNORM).r().ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_A8_UNORM).Color(a).ExpectedFormat(DXGI_FORMAT_R8_TYPELESS).Build(),
// These don't have typeless equivalents, so they are created as-is by the runtime.
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R1_UNORM).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R9G9B9E5_SHAREDEXP).NotMutable().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_B8G8_UNORM).NotMutable().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_G8R8_G8B8_UNORM).NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R1_UNORM).r().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R9G9B9E5_SHAREDEXP).rgb().NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R8G8_B8G8_UNORM).rgb().NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_G8R8_G8B8_UNORM).rgb().NotMutable().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC1_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC1_UNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC1_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC1_UNORM_SRGB).Compressed().ExpectedFormat(DXGI_FORMAT_BC1_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC1_TYPELESS).rgba().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC1_UNORM).rgba().Compressed().ExpectedFormat(DXGI_FORMAT_BC1_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC1_UNORM_SRGB).rgba().Compressed().ExpectedFormat(DXGI_FORMAT_BC1_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC2_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC2_UNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC2_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC2_UNORM_SRGB).Compressed().ExpectedFormat(DXGI_FORMAT_BC2_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC2_TYPELESS).rgba().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC2_UNORM).rgba().Compressed().ExpectedFormat(DXGI_FORMAT_BC2_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC2_UNORM_SRGB).rgba().Compressed().ExpectedFormat(DXGI_FORMAT_BC2_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC3_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC3_UNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC3_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC3_UNORM_SRGB).Compressed().ExpectedFormat(DXGI_FORMAT_BC3_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC3_TYPELESS).rgba().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC3_UNORM).rgba().Compressed().ExpectedFormat(DXGI_FORMAT_BC3_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC3_UNORM_SRGB).rgba().Compressed().ExpectedFormat(DXGI_FORMAT_BC3_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC4_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC4_UNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC4_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC4_SNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC4_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC4_TYPELESS).r().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC4_UNORM).r().Compressed().ExpectedFormat(DXGI_FORMAT_BC4_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC4_SNORM).r().Compressed().ExpectedFormat(DXGI_FORMAT_BC4_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC5_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC5_UNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC5_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC5_SNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC5_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC5_TYPELESS).rg().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC5_UNORM).rg().Compressed().ExpectedFormat(DXGI_FORMAT_BC5_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC5_SNORM).rg().Compressed().ExpectedFormat(DXGI_FORMAT_BC5_TYPELESS).Build(),
// These don't have typeless equivalents, so they are created as-is by the runtime.
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B5G6R5_UNORM).NotMutable().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B5G5R5A1_UNORM).NotMutable().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM).NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B5G6R5_UNORM).rgb().NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B5G5R5A1_UNORM).rgba().NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM).rgba().NotMutable().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8A8_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8A8_UNORM).ExpectedFormat(DXGI_FORMAT_B8G8R8A8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB).ExpectedFormat(DXGI_FORMAT_B8G8R8A8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8A8_TYPELESS).rgba().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8A8_UNORM).rgba().ExpectedFormat(DXGI_FORMAT_B8G8R8A8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8A8_UNORM_SRGB).rgba().ExpectedFormat(DXGI_FORMAT_B8G8R8A8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8X8_TYPELESS).Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8X8_UNORM).ExpectedFormat(DXGI_FORMAT_B8G8R8X8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB).ExpectedFormat(DXGI_FORMAT_B8G8R8X8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8X8_TYPELESS).rgb().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8X8_UNORM).rgb().ExpectedFormat(DXGI_FORMAT_B8G8R8X8_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B8G8R8X8_UNORM_SRGB).rgb().ExpectedFormat(DXGI_FORMAT_B8G8R8X8_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC6H_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC6H_UF16).Compressed().ExpectedFormat(DXGI_FORMAT_BC6H_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC6H_SF16).Compressed().ExpectedFormat(DXGI_FORMAT_BC6H_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC6H_TYPELESS).rgb().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC6H_UF16).rgb().Compressed().ExpectedFormat(DXGI_FORMAT_BC6H_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC6H_SF16).rgb().Compressed().ExpectedFormat(DXGI_FORMAT_BC6H_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC7_TYPELESS).Compressed().Typeless().Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC7_UNORM).Compressed().ExpectedFormat(DXGI_FORMAT_BC7_TYPELESS).Build(),
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC7_UNORM_SRGB).Compressed().ExpectedFormat(DXGI_FORMAT_BC7_TYPELESS).Build(),
+ // The alpha channel is optional for these
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC7_TYPELESS).rgb().Compressed().Typeless().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC7_UNORM).rgb().Compressed().ExpectedFormat(DXGI_FORMAT_BC7_TYPELESS).Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_BC7_UNORM_SRGB).rgb().Compressed().ExpectedFormat(DXGI_FORMAT_BC7_TYPELESS).Build(),
// This doesn't have a typeless equivalent, so it's created as-is by the runtime.
- XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B4G4R4A4_UNORM).NotMutable().Build(),
+ XRC_SWAPCHAIN_FORMAT(DXGI_FORMAT_B4G4R4A4_UNORM).rgba().NotMutable().Build(),
};
diff --git a/src/conformance/utilities/swapchain_format_data.cpp b/src/conformance/utilities/swapchain_format_data.cpp
index 49ffcb8f..59be12ae 100644
--- a/src/conformance/utilities/swapchain_format_data.cpp
+++ b/src/conformance/utilities/swapchain_format_data.cpp
@@ -246,6 +246,13 @@ namespace Conformance
SwapchainCreateTestParameters SwapchainFormatData::ToTestParameters() const
{
+ if (!m_colorFormat && !m_depthFormat && !m_stencilFormat) {
+ std::ostringstream oss;
+ oss << "Format " << m_imageFormatName << " (" << to_hex(m_imageFormat) << ")"
+ << "has no known aspect (color, depth, stencil);"
+ " if this is correct, code may need to be updated.";
+ throw std::logic_error(oss.str());
+ }
span mipCountVector{kArrayOf1.begin(), kArrayOf1.end()};
if (m_colorFormat && !m_compressedFormat) {
@@ -253,16 +260,17 @@ namespace Conformance
}
span arrayCountVector{kArrayOf1And2.begin(), kArrayOf1And2.end()};
+ namespace FormatFlags = SwapchainFormat::Flags;
return SwapchainCreateTestParameters{
- std::string{m_imageFormatName}, //
- m_isTypeless ? SwapchainFormatMutability::MUTABLE : SwapchainFormatMutability::IMMUTABLE, //
- m_supportsMutableFormat ? SwapchainFormatSupportsMutability::MUT_SUPPORT
- : SwapchainFormatSupportsMutability::NO_MUT_SUPPORT, //
- m_colorFormat ? SwapchainFormatIsColor::COLOR : SwapchainFormatIsColor::NON_COLOR,
- m_compressedFormat ? SwapchainFormatIsCompressed::COMPRESSED : SwapchainFormatIsCompressed::UNCOMPRESSED,
- m_compressedFormat ? SwapchainFormatSupportsRendering::NO_RENDERING_SUPPORT
- : SwapchainFormatSupportsRendering::RENDERING_SUPPORT,
+ std::string{m_imageFormatName}, //
+ m_isTypeless ? FormatFlags::Mutability::MUTABLE : FormatFlags::Mutability::IMMUTABLE, //
+ m_supportsMutableFormat ? FormatFlags::SupportsMutability::MUT_SUPPORT : FormatFlags::SupportsMutability::NO_MUT_SUPPORT, //
+ m_colorFormat ? FormatFlags::IsColor::COLOR : FormatFlags::IsColor::NON_COLOR,
+ m_compressedFormat ? FormatFlags::IsCompressed::COMPRESSED : FormatFlags::IsCompressed::UNCOMPRESSED,
+ m_compressedFormat ? FormatFlags::SupportsRendering::NO_RENDERING_SUPPORT : FormatFlags::SupportsRendering::RENDERING_SUPPORT,
m_expectedCreatedImageFormat,
+ m_colorComponents,
+ m_integerRange,
{m_usageFlagsVector.begin(), m_usageFlagsVector.end()},
{m_createFlagsVector.begin(), m_createFlagsVector.end()},
{arrayCountVector.begin(), arrayCountVector.end()},
diff --git a/src/conformance/utilities/swapchain_format_data.h b/src/conformance/utilities/swapchain_format_data.h
index 46bac4a0..18be78a6 100644
--- a/src/conformance/utilities/swapchain_format_data.h
+++ b/src/conformance/utilities/swapchain_format_data.h
@@ -30,7 +30,6 @@
namespace Conformance
{
using nonstd::span;
-
/// Minimal data structure storing details about a swapchain image format.
///
/// May eventually replace @ref SwapchainImageTestParam
@@ -145,7 +144,10 @@ namespace Conformance
bool m_supportsMutableFormat = true;
/// Whether the format is a color-specific format
- bool m_colorFormat = true;
+ bool m_colorFormat = false;
+
+ /// Which color components the format resolves to (including alpha)
+ SwapchainFormat::RawColorComponents m_colorComponents = SwapchainFormat::RawColorComponents::Unknown;
/// Whether the format can be use as a depth buffer: implies not color
bool m_depthFormat = false;
@@ -156,6 +158,9 @@ namespace Conformance
/// Whether the format is a compressed format (and thus cannot be rendered to)
bool m_compressedFormat = false;
+ /// The signed-ness and integer range of this format.
+ SwapchainFormat::ColorIntegerRange m_integerRange = SwapchainFormat::ColorIntegerRange::NoIntegerColor;
+
/// XrSwapchainUsageFlags to exercise for this format.
/// Defaults to all combinations, including 0, of the core flags.
/// @todo Stop making so many copies of this, generate it from the other data instead
@@ -188,6 +193,60 @@ namespace Conformance
using Self = SwapchainCreateTestParametersBuilder;
+ /// Mark this as supporting color buffer usage with the channels/components @param components
+ ///
+ /// Also sets some default usage flags.
+ Self& Color(SwapchainFormat::RawColorComponents components)
+ {
+ m_data.m_colorFormat = true;
+ m_data.m_colorComponents = components;
+ UpdateDefaultUsageFlagVector();
+ return *this;
+ }
+
+ /// Mark this as supporting color buffer usage with the channels R
+ ///
+ /// Also sets some default usage flags.
+ Self& r()
+ {
+ using C = SwapchainFormat::RawColorComponents;
+ return Color(C::r);
+ }
+
+ /// Mark this as supporting color buffer usage with the channels R, G
+ ///
+ /// Also sets some default usage flags.
+ Self& rg()
+ {
+ using C = SwapchainFormat::RawColorComponents;
+ return Color((C)(C::r | C::g));
+ }
+
+ /// Mark this as supporting color buffer usage with the channels R, G, B
+ ///
+ /// Also sets some default usage flags.
+ Self& rgb()
+ {
+ using C = SwapchainFormat::RawColorComponents;
+ return Color((C)(C::r | C::g | C::b));
+ }
+
+ /// Mark this as supporting color buffer usage with the channels R, G, B, A
+ ///
+ /// Also sets some default usage flags.
+ Self& rgba()
+ {
+ using C = SwapchainFormat::RawColorComponents;
+ return Color((C)(C::r | C::g | C::b | C::a));
+ }
+
+ /// Mark this as a color integer format with the color/alpha depth specified
+ Self& Int(SwapchainFormat::ColorIntegerRange range)
+ {
+ m_data.m_integerRange = range;
+ return *this;
+ }
+
/// Mark this as not supporting "unordered access"
Self& NoUnorderedAccess()
{
@@ -214,7 +273,7 @@ namespace Conformance
Self& Depth()
{
m_data.m_depthFormat = true;
- NotColor();
+ UpdateDefaultUsageFlagVector();
return *this;
}
@@ -224,7 +283,7 @@ namespace Conformance
Self& Stencil()
{
m_data.m_stencilFormat = true;
- NotColor();
+ UpdateDefaultUsageFlagVector();
return *this;
}
@@ -237,7 +296,7 @@ namespace Conformance
{
m_data.m_stencilFormat = true;
m_data.m_depthFormat = true;
- NotColor();
+ UpdateDefaultUsageFlagVector();
return *this;
}
@@ -292,12 +351,6 @@ namespace Conformance
std::string ToString() const;
private:
- void NotColor()
- {
- m_data.m_colorFormat = false;
- UpdateDefaultUsageFlagVector();
- }
-
void UpdateDefaultUsageFlagVector();
SwapchainFormatData m_data;
};
diff --git a/src/conformance/utilities/swapchain_parameters.cpp b/src/conformance/utilities/swapchain_parameters.cpp
new file mode 100644
index 00000000..8f93d0df
--- /dev/null
+++ b/src/conformance/utilities/swapchain_parameters.cpp
@@ -0,0 +1,63 @@
+// Copyright (c) 2019-2024, 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 "swapchain_parameters.h"
+
+namespace Conformance
+{
+ namespace SwapchainFormat
+ {
+ uint8_t ColorIntegerRangeBits(ColorIntegerRange colorIntegerRange)
+ {
+ switch (colorIntegerRange) {
+ case ColorIntegerRange::NoIntegerColor:
+ throw std::logic_error("ColorIntegerRangeBits only valid for integer colors");
+ case ColorIntegerRange::u8:
+ case ColorIntegerRange::s8:
+ return 8;
+ case ColorIntegerRange::u16:
+ case ColorIntegerRange::s16:
+ return 16;
+ case ColorIntegerRange::u32:
+ case ColorIntegerRange::s32:
+ return 32;
+ case ColorIntegerRange::uRGB10A2:
+ return 10;
+ default:
+ throw std::logic_error("Missing case in implementation of ColorIntegerRangeBits");
+ }
+ }
+
+ bool ColorIntegerRangeIsSigned(ColorIntegerRange colorIntegerRange)
+ {
+ switch (colorIntegerRange) {
+ case ColorIntegerRange::NoIntegerColor:
+ throw std::logic_error("ColorIntegerRangeIsSigned only valid for integer colors");
+ case ColorIntegerRange::u8:
+ case ColorIntegerRange::u16:
+ case ColorIntegerRange::u32:
+ case ColorIntegerRange::uRGB10A2:
+ return false;
+ case ColorIntegerRange::s8:
+ case ColorIntegerRange::s16:
+ case ColorIntegerRange::s32:
+ return true;
+ default:
+ throw std::logic_error("Missing case in implementation of ColorIntegerRangeIsSigned");
+ }
+ }
+ } // namespace SwapchainFormat
+} // namespace Conformance
diff --git a/src/conformance/utilities/swapchain_parameters.h b/src/conformance/utilities/swapchain_parameters.h
index a16db1c7..b9c61dd6 100644
--- a/src/conformance/utilities/swapchain_parameters.h
+++ b/src/conformance/utilities/swapchain_parameters.h
@@ -22,31 +22,66 @@
namespace Conformance
{
- enum SwapchainFormatMutability
+ namespace SwapchainFormat
{
- IMMUTABLE,
- MUTABLE,
- };
- enum SwapchainFormatSupportsMutability
- {
- NO_MUT_SUPPORT,
- MUT_SUPPORT,
- };
- enum SwapchainFormatIsColor
- {
- NON_COLOR,
- COLOR,
- };
- enum SwapchainFormatIsCompressed
- {
- UNCOMPRESSED,
- COMPRESSED,
- };
- enum SwapchainFormatSupportsRendering
- {
- NO_RENDERING_SUPPORT,
- RENDERING_SUPPORT,
- };
+ namespace Flags
+ {
+ enum Mutability
+ {
+ IMMUTABLE,
+ MUTABLE,
+ };
+ enum SupportsMutability
+ {
+ NO_MUT_SUPPORT,
+ MUT_SUPPORT,
+ };
+ enum IsColor
+ {
+ NON_COLOR,
+ COLOR,
+ };
+ enum IsCompressed
+ {
+ UNCOMPRESSED,
+ COMPRESSED,
+ };
+ enum SupportsRendering
+ {
+ NO_RENDERING_SUPPORT,
+ RENDERING_SUPPORT,
+ };
+ } // namespace Flags
+
+ /// The components defined by the texture during sampling
+ /// (i.e. not just returned as the default value)
+ enum RawColorComponents : uint8_t
+ {
+ Unknown = 0,
+ r = 1 << 0,
+ g = 1 << 1,
+ b = 1 << 2,
+ a = 1 << 3,
+ };
+
+ /// Textures whose output is interpreted as an integer
+ /// and not mapped to a fixed- or floating-point value.
+ /// This does not yet account for integer aspects of
+ /// non-color formats, but could be renamed and extended.
+ enum ColorIntegerRange
+ {
+ NoIntegerColor = 0,
+ u8,
+ s8,
+ u16,
+ s16,
+ u32,
+ s32,
+ uRGB10A2,
+ };
+ uint8_t ColorIntegerRangeBits(ColorIntegerRange colorIntegerRange);
+ bool ColorIntegerRangeIsSigned(ColorIntegerRange colorIntegerRange);
+ } // namespace SwapchainFormat
/// Defines XrSwapchainCreateInfo test parameters for a single given image format.
/// Sometimes values are zeroed, for the case that use of them is invalid or unsupportable.
@@ -58,23 +93,29 @@ namespace Conformance
std::string imageFormatName;
/// Whether the image format is a mutable (a.k.a. typeless) type.
- SwapchainFormatMutability mutableFormat;
+ SwapchainFormat::Flags::Mutability mutableFormat;
/// Whether the image format supports creation with XR_SWAPCHAIN_USAGE_MUTABLE_FORMAT_BIT.
- SwapchainFormatSupportsMutability supportsMutableFormat;
+ SwapchainFormat::Flags::SupportsMutability supportsMutableFormat;
/// Whether the format is a color-specific format, as opposed to a depth-specific format.
- SwapchainFormatIsColor colorFormat;
+ SwapchainFormat::Flags::IsColor colorFormat;
/// Whether the format is a compressed format.
- SwapchainFormatIsCompressed compressedFormat;
+ SwapchainFormat::Flags::IsCompressed compressedFormat;
/// Whether the image format can be rendered to.
- SwapchainFormatSupportsRendering supportsRendering;
+ SwapchainFormat::Flags::SupportsRendering supportsRendering;
/// The graphics-specific created image format returned by xrCreateSwapchain, may be different from imageFormat in some cases.
int64_t expectedCreatedImageFormat;
+ /// The color components that, when sampled, will not just be set to default values.
+ SwapchainFormat::RawColorComponents colorComponents;
+
+ /// For integer (not floating point or normalised) color images, the bit depth of each color/alpha component.
+ SwapchainFormat::ColorIntegerRange colorIntegerRange;
+
/// XrSwapchainUsageFlags to exercise for this format.
std::vector usageFlagsVector;
diff --git a/src/external/stb/stb_image.h b/src/external/stb/stb_image.h
index d60371b9..9eedabed 100644
--- a/src/external/stb/stb_image.h
+++ b/src/external/stb/stb_image.h
@@ -1,4 +1,4 @@
-/* stb_image - v2.27 - public domain image loader - http://nothings.org/stb
+/* stb_image - v2.30 - public domain image loader - http://nothings.org/stb
no warranty implied; use at your own risk
Do this:
@@ -48,6 +48,9 @@ LICENSE
RECENT REVISION HISTORY:
+ 2.30 (2024-05-31) avoid erroneous gcc warning
+ 2.29 (2023-05-xx) optimizations
+ 2.28 (2023-01-29) many error fixes, security errors, just tons of stuff
2.27 (2021-07-11) document stbi_info better, 16-bit PNM support, bug fixes
2.26 (2020-07-13) many minor fixes
2.25 (2020-02-02) fix warnings
@@ -108,7 +111,7 @@ RECENT REVISION HISTORY:
Cass Everitt Ryamond Barbiero github:grim210
Paul Du Bois Engin Manap Aldo Culquicondor github:sammyhw
Philipp Wiesemann Dale Weiler Oriol Ferrer Mesia github:phprus
- Josh Tobin Matthew Gregan github:poppolopoppo
+ Josh Tobin Neil Bickford Matthew Gregan github:poppolopoppo
Julian Raschke Gregory Mullen Christian Floisand github:darealshinji
Baldur Karlsson Kevin Schmidt JR Smith github:Michaelangel007
Brad Weinberger Matvey Cherevko github:mosra
@@ -140,7 +143,7 @@ RECENT REVISION HISTORY:
// // ... x = width, y = height, n = # 8-bit components per pixel ...
// // ... replace '0' with '1'..'4' to force that many components per pixel
// // ... but 'n' will always be the number that it would have been if you said 0
-// stbi_image_free(data)
+// stbi_image_free(data);
//
// Standard parameters:
// int *x -- outputs image width in pixels
@@ -635,7 +638,7 @@ STBIDEF int stbi_zlib_decode_noheader_buffer(char *obuffer, int olen, const ch
#endif
#endif
-#ifdef _MSC_VER
+#if defined(_MSC_VER) || defined(__SYMBIAN32__)
typedef unsigned short stbi__uint16;
typedef signed short stbi__int16;
typedef unsigned int stbi__uint32;
@@ -1063,6 +1066,23 @@ static void *stbi__malloc_mad4(int a, int b, int c, int d, int add)
}
#endif
+// returns 1 if the sum of two signed ints is valid (between -2^31 and 2^31-1 inclusive), 0 on overflow.
+static int stbi__addints_valid(int a, int b)
+{
+ if ((a >= 0) != (b >= 0)) return 1; // a and b have different signs, so no overflow
+ if (a < 0 && b < 0) return a >= INT_MIN - b; // same as a + b >= INT_MIN; INT_MIN - b cannot overflow since b < 0.
+ return a <= INT_MAX - b;
+}
+
+// returns 1 if the product of two ints fits in a signed short, 0 on overflow.
+static int stbi__mul2shorts_valid(int a, int b)
+{
+ if (b == 0 || b == -1) return 1; // multiplication by 0 is always 0; check for -1 so SHRT_MIN/b doesn't overflow
+ if ((a >= 0) == (b >= 0)) return a <= SHRT_MAX/b; // product is positive, so similar to mul2sizes_valid
+ if (b < 0) return a <= SHRT_MIN / b; // same as a * b >= SHRT_MIN
+ return a >= SHRT_MIN / b;
+}
+
// stbi__err - error
// stbi__errpf - error returning pointer to float
// stbi__errpuc - error returning pointer to unsigned char
@@ -1985,9 +2005,12 @@ static int stbi__build_huffman(stbi__huffman *h, int *count)
int i,j,k=0;
unsigned int code;
// build size list for each symbol (from JPEG spec)
- for (i=0; i < 16; ++i)
- for (j=0; j < count[i]; ++j)
+ for (i=0; i < 16; ++i) {
+ for (j=0; j < count[i]; ++j) {
h->size[k++] = (stbi_uc) (i+1);
+ if(k >= 257) return stbi__err("bad size list","Corrupt JPEG");
+ }
+ }
h->size[k] = 0;
// compute actual symbols (from jpeg spec)
@@ -2112,6 +2135,8 @@ stbi_inline static int stbi__jpeg_huff_decode(stbi__jpeg *j, stbi__huffman *h)
// convert the huffman code to the symbol id
c = ((j->code_buffer >> (32 - k)) & stbi__bmask[k]) + h->delta[k];
+ if(c < 0 || c >= 256) // symbol id out of bounds!
+ return -1;
STBI_ASSERT((((j->code_buffer) >> (32 - h->size[c])) & stbi__bmask[h->size[c]]) == h->code[c]);
// convert the id to a symbol
@@ -2130,6 +2155,7 @@ stbi_inline static int stbi__extend_receive(stbi__jpeg *j, int n)
unsigned int k;
int sgn;
if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+ if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
sgn = j->code_buffer >> 31; // sign bit always in MSB; 0 if MSB clear (positive), 1 if MSB set (negative)
k = stbi_lrot(j->code_buffer, n);
@@ -2144,6 +2170,7 @@ stbi_inline static int stbi__jpeg_get_bits(stbi__jpeg *j, int n)
{
unsigned int k;
if (j->code_bits < n) stbi__grow_buffer_unsafe(j);
+ if (j->code_bits < n) return 0; // ran out of bits from stream, return 0s intead of continuing
k = stbi_lrot(j->code_buffer, n);
j->code_buffer = k & ~stbi__bmask[n];
k &= stbi__bmask[n];
@@ -2155,6 +2182,7 @@ stbi_inline static int stbi__jpeg_get_bit(stbi__jpeg *j)
{
unsigned int k;
if (j->code_bits < 1) stbi__grow_buffer_unsafe(j);
+ if (j->code_bits < 1) return 0; // ran out of bits from stream, return 0s intead of continuing
k = j->code_buffer;
j->code_buffer <<= 1;
--j->code_bits;
@@ -2192,8 +2220,10 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
memset(data,0,64*sizeof(data[0]));
diff = t ? stbi__extend_receive(j, t) : 0;
+ if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta","Corrupt JPEG");
dc = j->img_comp[b].dc_pred + diff;
j->img_comp[b].dc_pred = dc;
+ if (!stbi__mul2shorts_valid(dc, dequant[0])) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
data[0] = (short) (dc * dequant[0]);
// decode AC components, see JPEG spec
@@ -2207,6 +2237,7 @@ static int stbi__jpeg_decode_block(stbi__jpeg *j, short data[64], stbi__huffman
if (r) { // fast-AC path
k += (r >> 4) & 15; // run
s = r & 15; // combined length
+ if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
j->code_buffer <<= s;
j->code_bits -= s;
// decode into unzigzag'd location
@@ -2246,8 +2277,10 @@ static int stbi__jpeg_decode_block_prog_dc(stbi__jpeg *j, short data[64], stbi__
if (t < 0 || t > 15) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
diff = t ? stbi__extend_receive(j, t) : 0;
+ if (!stbi__addints_valid(j->img_comp[b].dc_pred, diff)) return stbi__err("bad delta", "Corrupt JPEG");
dc = j->img_comp[b].dc_pred + diff;
j->img_comp[b].dc_pred = dc;
+ if (!stbi__mul2shorts_valid(dc, 1 << j->succ_low)) return stbi__err("can't merge dc and ac", "Corrupt JPEG");
data[0] = (short) (dc * (1 << j->succ_low));
} else {
// refinement scan for DC coefficient
@@ -2282,6 +2315,7 @@ static int stbi__jpeg_decode_block_prog_ac(stbi__jpeg *j, short data[64], stbi__
if (r) { // fast-AC path
k += (r >> 4) & 15; // run
s = r & 15; // combined length
+ if (s > j->code_bits) return stbi__err("bad huffman code", "Combined length longer than code bits available");
j->code_buffer <<= s;
j->code_bits -= s;
zig = stbi__jpeg_dezigzag[k++];
@@ -3102,6 +3136,7 @@ static int stbi__process_marker(stbi__jpeg *z, int m)
sizes[i] = stbi__get8(z->s);
n += sizes[i];
}
+ if(n > 256) return stbi__err("bad DHT header","Corrupt JPEG"); // Loop over i < n would write past end of values!
L -= 17;
if (tc == 0) {
if (!stbi__build_huffman(z->huff_dc+th, sizes)) return 0;
@@ -3351,6 +3386,28 @@ static int stbi__decode_jpeg_header(stbi__jpeg *z, int scan)
return 1;
}
+static stbi_uc stbi__skip_jpeg_junk_at_end(stbi__jpeg *j)
+{
+ // some JPEGs have junk at end, skip over it but if we find what looks
+ // like a valid marker, resume there
+ while (!stbi__at_eof(j->s)) {
+ stbi_uc x = stbi__get8(j->s);
+ while (x == 0xff) { // might be a marker
+ if (stbi__at_eof(j->s)) return STBI__MARKER_none;
+ x = stbi__get8(j->s);
+ if (x != 0x00 && x != 0xff) {
+ // not a stuffed zero or lead-in to another marker, looks
+ // like an actual marker, return it
+ return x;
+ }
+ // stuffed zero has x=0 now which ends the loop, meaning we go
+ // back to regular scan loop.
+ // repeated 0xff keeps trying to read the next byte of the marker.
+ }
+ }
+ return STBI__MARKER_none;
+}
+
// decode image to YCbCr format
static int stbi__decode_jpeg_image(stbi__jpeg *j)
{
@@ -3367,25 +3424,22 @@ static int stbi__decode_jpeg_image(stbi__jpeg *j)
if (!stbi__process_scan_header(j)) return 0;
if (!stbi__parse_entropy_coded_data(j)) return 0;
if (j->marker == STBI__MARKER_none ) {
- // handle 0s at the end of image data from IP Kamera 9060
- while (!stbi__at_eof(j->s)) {
- int x = stbi__get8(j->s);
- if (x == 255) {
- j->marker = stbi__get8(j->s);
- break;
- }
- }
+ j->marker = stbi__skip_jpeg_junk_at_end(j);
// if we reach eof without hitting a marker, stbi__get_marker() below will fail and we'll eventually return 0
}
+ m = stbi__get_marker(j);
+ if (STBI__RESTART(m))
+ m = stbi__get_marker(j);
} else if (stbi__DNL(m)) {
int Ld = stbi__get16be(j->s);
stbi__uint32 NL = stbi__get16be(j->s);
if (Ld != 4) return stbi__err("bad DNL len", "Corrupt JPEG");
if (NL != j->s->img_y) return stbi__err("bad DNL height", "Corrupt JPEG");
+ m = stbi__get_marker(j);
} else {
- if (!stbi__process_marker(j, m)) return 0;
+ if (!stbi__process_marker(j, m)) return 1;
+ m = stbi__get_marker(j);
}
- m = stbi__get_marker(j);
}
if (j->progressive)
stbi__jpeg_finish(j);
@@ -3976,6 +4030,7 @@ static void *stbi__jpeg_load(stbi__context *s, int *x, int *y, int *comp, int re
unsigned char* result;
stbi__jpeg* j = (stbi__jpeg*) stbi__malloc(sizeof(stbi__jpeg));
if (!j) return stbi__errpuc("outofmem", "Out of memory");
+ memset(j, 0, sizeof(stbi__jpeg));
STBI_NOTUSED(ri);
j->s = s;
stbi__setup_jpeg(j);
@@ -3989,6 +4044,7 @@ static int stbi__jpeg_test(stbi__context *s)
int r;
stbi__jpeg* j = (stbi__jpeg*)stbi__malloc(sizeof(stbi__jpeg));
if (!j) return stbi__err("outofmem", "Out of memory");
+ memset(j, 0, sizeof(stbi__jpeg));
j->s = s;
stbi__setup_jpeg(j);
r = stbi__decode_jpeg_header(j, STBI__SCAN_type);
@@ -4014,6 +4070,7 @@ static int stbi__jpeg_info(stbi__context *s, int *x, int *y, int *comp)
int result;
stbi__jpeg* j = (stbi__jpeg*) (stbi__malloc(sizeof(stbi__jpeg)));
if (!j) return stbi__err("outofmem", "Out of memory");
+ memset(j, 0, sizeof(stbi__jpeg));
j->s = s;
result = stbi__jpeg_info_raw(j, x, y, comp);
STBI_FREE(j);
@@ -4121,6 +4178,7 @@ typedef struct
{
stbi_uc *zbuffer, *zbuffer_end;
int num_bits;
+ int hit_zeof_once;
stbi__uint32 code_buffer;
char *zout;
@@ -4187,9 +4245,20 @@ stbi_inline static int stbi__zhuffman_decode(stbi__zbuf *a, stbi__zhuffman *z)
int b,s;
if (a->num_bits < 16) {
if (stbi__zeof(a)) {
- return -1; /* report error for unexpected end of data. */
+ if (!a->hit_zeof_once) {
+ // This is the first time we hit eof, insert 16 extra padding btis
+ // to allow us to keep going; if we actually consume any of them
+ // though, that is invalid data. This is caught later.
+ a->hit_zeof_once = 1;
+ a->num_bits += 16; // add 16 implicit zero bits
+ } else {
+ // We already inserted our extra 16 padding bits and are again
+ // out, this stream is actually prematurely terminated.
+ return -1;
+ }
+ } else {
+ stbi__fill_bits(a);
}
- stbi__fill_bits(a);
}
b = z->fast[a->code_buffer & STBI__ZFAST_MASK];
if (b) {
@@ -4254,17 +4323,25 @@ static int stbi__parse_huffman_block(stbi__zbuf *a)
int len,dist;
if (z == 256) {
a->zout = zout;
+ if (a->hit_zeof_once && a->num_bits < 16) {
+ // The first time we hit zeof, we inserted 16 extra zero bits into our bit
+ // buffer so the decoder can just do its speculative decoding. But if we
+ // actually consumed any of those bits (which is the case when num_bits < 16),
+ // the stream actually read past the end so it is malformed.
+ return stbi__err("unexpected end","Corrupt PNG");
+ }
return 1;
}
+ if (z >= 286) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, length codes 286 and 287 must not appear in compressed data
z -= 257;
len = stbi__zlength_base[z];
if (stbi__zlength_extra[z]) len += stbi__zreceive(a, stbi__zlength_extra[z]);
z = stbi__zhuffman_decode(a, &a->z_distance);
- if (z < 0) return stbi__err("bad huffman code","Corrupt PNG");
+ if (z < 0 || z >= 30) return stbi__err("bad huffman code","Corrupt PNG"); // per DEFLATE, distance codes 30 and 31 must not appear in compressed data
dist = stbi__zdist_base[z];
if (stbi__zdist_extra[z]) dist += stbi__zreceive(a, stbi__zdist_extra[z]);
if (zout - a->zout_start < dist) return stbi__err("bad dist","Corrupt PNG");
- if (zout + len > a->zout_end) {
+ if (len > a->zout_end - zout) {
if (!stbi__zexpand(a, zout, len)) return 0;
zout = a->zout;
}
@@ -4408,6 +4485,7 @@ static int stbi__parse_zlib(stbi__zbuf *a, int parse_header)
if (!stbi__parse_zlib_header(a)) return 0;
a->num_bits = 0;
a->code_buffer = 0;
+ a->hit_zeof_once = 0;
do {
final = stbi__zreceive(a,1);
type = stbi__zreceive(a,2);
@@ -4563,9 +4641,8 @@ enum {
STBI__F_up=2,
STBI__F_avg=3,
STBI__F_paeth=4,
- // synthetic filters used for first scanline to avoid needing a dummy row of 0s
- STBI__F_avg_first,
- STBI__F_paeth_first
+ // synthetic filter used for first scanline to avoid needing a dummy row of 0s
+ STBI__F_avg_first
};
static stbi_uc first_row_filter[5] =
@@ -4574,29 +4651,56 @@ static stbi_uc first_row_filter[5] =
STBI__F_sub,
STBI__F_none,
STBI__F_avg_first,
- STBI__F_paeth_first
+ STBI__F_sub // Paeth with b=c=0 turns out to be equivalent to sub
};
static int stbi__paeth(int a, int b, int c)
{
- int p = a + b - c;
- int pa = abs(p-a);
- int pb = abs(p-b);
- int pc = abs(p-c);
- if (pa <= pb && pa <= pc) return a;
- if (pb <= pc) return b;
- return c;
+ // This formulation looks very different from the reference in the PNG spec, but is
+ // actually equivalent and has favorable data dependencies and admits straightforward
+ // generation of branch-free code, which helps performance significantly.
+ int thresh = c*3 - (a + b);
+ int lo = a < b ? a : b;
+ int hi = a < b ? b : a;
+ int t0 = (hi <= thresh) ? lo : c;
+ int t1 = (thresh <= lo) ? hi : t0;
+ return t1;
}
static const stbi_uc stbi__depth_scale_table[9] = { 0, 0xff, 0x55, 0, 0x11, 0,0,0, 0x01 };
+// adds an extra all-255 alpha channel
+// dest == src is legal
+// img_n must be 1 or 3
+static void stbi__create_png_alpha_expand8(stbi_uc *dest, stbi_uc *src, stbi__uint32 x, int img_n)
+{
+ int i;
+ // must process data backwards since we allow dest==src
+ if (img_n == 1) {
+ for (i=x-1; i >= 0; --i) {
+ dest[i*2+1] = 255;
+ dest[i*2+0] = src[i];
+ }
+ } else {
+ STBI_ASSERT(img_n == 3);
+ for (i=x-1; i >= 0; --i) {
+ dest[i*4+3] = 255;
+ dest[i*4+2] = src[i*3+2];
+ dest[i*4+1] = src[i*3+1];
+ dest[i*4+0] = src[i*3+0];
+ }
+ }
+}
+
// create the png data from post-deflated data
static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 raw_len, int out_n, stbi__uint32 x, stbi__uint32 y, int depth, int color)
{
- int bytes = (depth == 16? 2 : 1);
+ int bytes = (depth == 16 ? 2 : 1);
stbi__context *s = a->s;
stbi__uint32 i,j,stride = x*out_n*bytes;
stbi__uint32 img_len, img_width_bytes;
+ stbi_uc *filter_buf;
+ int all_ok = 1;
int k;
int img_n = s->img_n; // copy it into a local for later
@@ -4608,8 +4712,11 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
a->out = (stbi_uc *) stbi__malloc_mad3(x, y, output_bytes, 0); // extra bytes to write off the end into
if (!a->out) return stbi__err("outofmem", "Out of memory");
+ // note: error exits here don't need to clean up a->out individually,
+ // stbi__do_png always does on error.
if (!stbi__mad3sizes_valid(img_n, x, depth, 7)) return stbi__err("too large", "Corrupt PNG");
img_width_bytes = (((img_n * x * depth) + 7) >> 3);
+ if (!stbi__mad2sizes_valid(img_width_bytes, y, img_width_bytes)) return stbi__err("too large", "Corrupt PNG");
img_len = (img_width_bytes + 1) * y;
// we used to check for exact match between raw_len and img_len on non-interlaced PNGs,
@@ -4617,189 +4724,137 @@ static int stbi__create_png_image_raw(stbi__png *a, stbi_uc *raw, stbi__uint32 r
// so just check for raw_len < img_len always.
if (raw_len < img_len) return stbi__err("not enough pixels","Corrupt PNG");
+ // Allocate two scan lines worth of filter workspace buffer.
+ filter_buf = (stbi_uc *) stbi__malloc_mad2(img_width_bytes, 2, 0);
+ if (!filter_buf) return stbi__err("outofmem", "Out of memory");
+
+ // Filtering for low-bit-depth images
+ if (depth < 8) {
+ filter_bytes = 1;
+ width = img_width_bytes;
+ }
+
for (j=0; j < y; ++j) {
- stbi_uc *cur = a->out + stride*j;
- stbi_uc *prior;
+ // cur/prior filter buffers alternate
+ stbi_uc *cur = filter_buf + (j & 1)*img_width_bytes;
+ stbi_uc *prior = filter_buf + (~j & 1)*img_width_bytes;
+ stbi_uc *dest = a->out + stride*j;
+ int nk = width * filter_bytes;
int filter = *raw++;
- if (filter > 4)
- return stbi__err("invalid filter","Corrupt PNG");
-
- if (depth < 8) {
- if (img_width_bytes > x) return stbi__err("invalid width","Corrupt PNG");
- cur += x*out_n - img_width_bytes; // store output to the rightmost img_len bytes, so we can decode in place
- filter_bytes = 1;
- width = img_width_bytes;
+ // check filter type
+ if (filter > 4) {
+ all_ok = stbi__err("invalid filter","Corrupt PNG");
+ break;
}
- prior = cur - stride; // bugfix: need to compute this after 'cur +=' computation above
// if first row, use special filter that doesn't sample previous row
if (j == 0) filter = first_row_filter[filter];
- // handle first byte explicitly
- for (k=0; k < filter_bytes; ++k) {
- switch (filter) {
- case STBI__F_none : cur[k] = raw[k]; break;
- case STBI__F_sub : cur[k] = raw[k]; break;
- case STBI__F_up : cur[k] = STBI__BYTECAST(raw[k] + prior[k]); break;
- case STBI__F_avg : cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1)); break;
- case STBI__F_paeth : cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(0,prior[k],0)); break;
- case STBI__F_avg_first : cur[k] = raw[k]; break;
- case STBI__F_paeth_first: cur[k] = raw[k]; break;
- }
- }
-
- if (depth == 8) {
- if (img_n != out_n)
- cur[img_n] = 255; // first pixel
- raw += img_n;
- cur += out_n;
- prior += out_n;
- } else if (depth == 16) {
- if (img_n != out_n) {
- cur[filter_bytes] = 255; // first pixel top byte
- cur[filter_bytes+1] = 255; // first pixel bottom byte
- }
- raw += filter_bytes;
- cur += output_bytes;
- prior += output_bytes;
- } else {
- raw += 1;
- cur += 1;
- prior += 1;
+ // perform actual filtering
+ switch (filter) {
+ case STBI__F_none:
+ memcpy(cur, raw, nk);
+ break;
+ case STBI__F_sub:
+ memcpy(cur, raw, filter_bytes);
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]);
+ break;
+ case STBI__F_up:
+ for (k = 0; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]);
+ break;
+ case STBI__F_avg:
+ for (k = 0; k < filter_bytes; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + (prior[k]>>1));
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1));
+ break;
+ case STBI__F_paeth:
+ for (k = 0; k < filter_bytes; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + prior[k]); // prior[k] == stbi__paeth(0,prior[k],0)
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes], prior[k], prior[k-filter_bytes]));
+ break;
+ case STBI__F_avg_first:
+ memcpy(cur, raw, filter_bytes);
+ for (k = filter_bytes; k < nk; ++k)
+ cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1));
+ break;
}
- // this is a little gross, so that we don't switch per-pixel or per-component
- if (depth < 8 || img_n == out_n) {
- int nk = (width - 1)*filter_bytes;
- #define STBI__CASE(f) \
- case f: \
- for (k=0; k < nk; ++k)
- switch (filter) {
- // "none" filter turns into a memcpy here; make that explicit.
- case STBI__F_none: memcpy(cur, raw, nk); break;
- STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k-filter_bytes]); } break;
- STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
- STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k-filter_bytes])>>1)); } break;
- STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],prior[k],prior[k-filter_bytes])); } break;
- STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k-filter_bytes] >> 1)); } break;
- STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k-filter_bytes],0,0)); } break;
- }
- #undef STBI__CASE
- raw += nk;
- } else {
- STBI_ASSERT(img_n+1 == out_n);
- #define STBI__CASE(f) \
- case f: \
- for (i=x-1; i >= 1; --i, cur[filter_bytes]=255,raw+=filter_bytes,cur+=output_bytes,prior+=output_bytes) \
- for (k=0; k < filter_bytes; ++k)
- switch (filter) {
- STBI__CASE(STBI__F_none) { cur[k] = raw[k]; } break;
- STBI__CASE(STBI__F_sub) { cur[k] = STBI__BYTECAST(raw[k] + cur[k- output_bytes]); } break;
- STBI__CASE(STBI__F_up) { cur[k] = STBI__BYTECAST(raw[k] + prior[k]); } break;
- STBI__CASE(STBI__F_avg) { cur[k] = STBI__BYTECAST(raw[k] + ((prior[k] + cur[k- output_bytes])>>1)); } break;
- STBI__CASE(STBI__F_paeth) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],prior[k],prior[k- output_bytes])); } break;
- STBI__CASE(STBI__F_avg_first) { cur[k] = STBI__BYTECAST(raw[k] + (cur[k- output_bytes] >> 1)); } break;
- STBI__CASE(STBI__F_paeth_first) { cur[k] = STBI__BYTECAST(raw[k] + stbi__paeth(cur[k- output_bytes],0,0)); } break;
- }
- #undef STBI__CASE
-
- // the loop above sets the high byte of the pixels' alpha, but for
- // 16 bit png files we also need the low byte set. we'll do that here.
- if (depth == 16) {
- cur = a->out + stride*j; // start at the beginning of the row again
- for (i=0; i < x; ++i,cur+=output_bytes) {
- cur[filter_bytes+1] = 255;
- }
- }
- }
- }
+ raw += nk;
- // we make a separate pass to expand bits to pixels; for performance,
- // this could run two scanlines behind the above code, so it won't
- // intefere with filtering but will still be in the cache.
- if (depth < 8) {
- for (j=0; j < y; ++j) {
- stbi_uc *cur = a->out + stride*j;
- stbi_uc *in = a->out + stride*j + x*out_n - img_width_bytes;
- // unpack 1/2/4-bit into a 8-bit buffer. allows us to keep the common 8-bit path optimal at minimal cost for 1/2/4-bit
- // png guarante byte alignment, if width is not multiple of 8/4/2 we'll decode dummy trailing data that will be skipped in the later loop
+ // expand decoded bits in cur to dest, also adding an extra alpha channel if desired
+ if (depth < 8) {
stbi_uc scale = (color == 0) ? stbi__depth_scale_table[depth] : 1; // scale grayscale values to 0..255 range
+ stbi_uc *in = cur;
+ stbi_uc *out = dest;
+ stbi_uc inb = 0;
+ stbi__uint32 nsmp = x*img_n;
- // note that the final byte might overshoot and write more data than desired.
- // we can allocate enough data that this never writes out of memory, but it
- // could also overwrite the next scanline. can it overwrite non-empty data
- // on the next scanline? yes, consider 1-pixel-wide scanlines with 1-bit-per-pixel.
- // so we need to explicitly clamp the final ones
-
+ // expand bits to bytes first
if (depth == 4) {
- for (k=x*img_n; k >= 2; k-=2, ++in) {
- *cur++ = scale * ((*in >> 4) );
- *cur++ = scale * ((*in ) & 0x0f);
+ for (i=0; i < nsmp; ++i) {
+ if ((i & 1) == 0) inb = *in++;
+ *out++ = scale * (inb >> 4);
+ inb <<= 4;
}
- if (k > 0) *cur++ = scale * ((*in >> 4) );
} else if (depth == 2) {
- for (k=x*img_n; k >= 4; k-=4, ++in) {
- *cur++ = scale * ((*in >> 6) );
- *cur++ = scale * ((*in >> 4) & 0x03);
- *cur++ = scale * ((*in >> 2) & 0x03);
- *cur++ = scale * ((*in ) & 0x03);
+ for (i=0; i < nsmp; ++i) {
+ if ((i & 3) == 0) inb = *in++;
+ *out++ = scale * (inb >> 6);
+ inb <<= 2;
}
- if (k > 0) *cur++ = scale * ((*in >> 6) );
- if (k > 1) *cur++ = scale * ((*in >> 4) & 0x03);
- if (k > 2) *cur++ = scale * ((*in >> 2) & 0x03);
- } else if (depth == 1) {
- for (k=x*img_n; k >= 8; k-=8, ++in) {
- *cur++ = scale * ((*in >> 7) );
- *cur++ = scale * ((*in >> 6) & 0x01);
- *cur++ = scale * ((*in >> 5) & 0x01);
- *cur++ = scale * ((*in >> 4) & 0x01);
- *cur++ = scale * ((*in >> 3) & 0x01);
- *cur++ = scale * ((*in >> 2) & 0x01);
- *cur++ = scale * ((*in >> 1) & 0x01);
- *cur++ = scale * ((*in ) & 0x01);
+ } else {
+ STBI_ASSERT(depth == 1);
+ for (i=0; i < nsmp; ++i) {
+ if ((i & 7) == 0) inb = *in++;
+ *out++ = scale * (inb >> 7);
+ inb <<= 1;
}
- if (k > 0) *cur++ = scale * ((*in >> 7) );
- if (k > 1) *cur++ = scale * ((*in >> 6) & 0x01);
- if (k > 2) *cur++ = scale * ((*in >> 5) & 0x01);
- if (k > 3) *cur++ = scale * ((*in >> 4) & 0x01);
- if (k > 4) *cur++ = scale * ((*in >> 3) & 0x01);
- if (k > 5) *cur++ = scale * ((*in >> 2) & 0x01);
- if (k > 6) *cur++ = scale * ((*in >> 1) & 0x01);
}
- if (img_n != out_n) {
- int q;
- // insert alpha = 255
- cur = a->out + stride*j;
+
+ // insert alpha=255 values if desired
+ if (img_n != out_n)
+ stbi__create_png_alpha_expand8(dest, dest, x, img_n);
+ } else if (depth == 8) {
+ if (img_n == out_n)
+ memcpy(dest, cur, x*img_n);
+ else
+ stbi__create_png_alpha_expand8(dest, cur, x, img_n);
+ } else if (depth == 16) {
+ // convert the image data from big-endian to platform-native
+ stbi__uint16 *dest16 = (stbi__uint16*)dest;
+ stbi__uint32 nsmp = x*img_n;
+
+ if (img_n == out_n) {
+ for (i = 0; i < nsmp; ++i, ++dest16, cur += 2)
+ *dest16 = (cur[0] << 8) | cur[1];
+ } else {
+ STBI_ASSERT(img_n+1 == out_n);
if (img_n == 1) {
- for (q=x-1; q >= 0; --q) {
- cur[q*2+1] = 255;
- cur[q*2+0] = cur[q];
+ for (i = 0; i < x; ++i, dest16 += 2, cur += 2) {
+ dest16[0] = (cur[0] << 8) | cur[1];
+ dest16[1] = 0xffff;
}
} else {
STBI_ASSERT(img_n == 3);
- for (q=x-1; q >= 0; --q) {
- cur[q*4+3] = 255;
- cur[q*4+2] = cur[q*3+2];
- cur[q*4+1] = cur[q*3+1];
- cur[q*4+0] = cur[q*3+0];
+ for (i = 0; i < x; ++i, dest16 += 4, cur += 6) {
+ dest16[0] = (cur[0] << 8) | cur[1];
+ dest16[1] = (cur[2] << 8) | cur[3];
+ dest16[2] = (cur[4] << 8) | cur[5];
+ dest16[3] = 0xffff;
}
}
}
}
- } else if (depth == 16) {
- // force the image data from big-endian to platform-native.
- // this is done in a separate pass due to the decoding relying
- // on the data being untouched, but could probably be done
- // per-line during decode if care is taken.
- stbi_uc *cur = a->out;
- stbi__uint16 *cur16 = (stbi__uint16*)cur;
-
- for(i=0; i < x*y*out_n; ++i,cur16++,cur+=2) {
- *cur16 = (cur[0] << 8) | cur[1];
- }
}
+ STBI_FREE(filter_buf);
+ if (!all_ok) return 0;
+
return 1;
}
@@ -4955,7 +5010,7 @@ STBIDEF void stbi_convert_iphone_png_to_rgb(int flag_true_if_should_convert)
static STBI_THREAD_LOCAL int stbi__unpremultiply_on_load_local, stbi__unpremultiply_on_load_set;
static STBI_THREAD_LOCAL int stbi__de_iphone_flag_local, stbi__de_iphone_flag_set;
-STBIDEF void stbi__unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
+STBIDEF void stbi_set_unpremultiply_on_load_thread(int flag_true_if_should_unpremultiply)
{
stbi__unpremultiply_on_load_local = flag_true_if_should_unpremultiply;
stbi__unpremultiply_on_load_set = 1;
@@ -5064,14 +5119,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!pal_img_n) {
s->img_n = (color & 2 ? 3 : 1) + (color & 4 ? 1 : 0);
if ((1 << 30) / s->img_x / s->img_n < s->img_y) return stbi__err("too large", "Image too large to decode");
- if (scan == STBI__SCAN_header) return 1;
} else {
// if paletted, then pal_n is our final components, and
// img_n is # components to decompress/filter.
s->img_n = 1;
if ((1 << 30) / s->img_x / 4 < s->img_y) return stbi__err("too large","Corrupt PNG");
- // if SCAN_header, have to scan to see if we have a tRNS
}
+ // even with SCAN_header, have to scan to see if we have a tRNS
break;
}
@@ -5103,10 +5157,14 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
if (!(s->img_n & 1)) return stbi__err("tRNS with alpha","Corrupt PNG");
if (c.length != (stbi__uint32) s->img_n*2) return stbi__err("bad tRNS len","Corrupt PNG");
has_trans = 1;
+ // non-paletted with tRNS = constant alpha. if header-scanning, we can stop now.
+ if (scan == STBI__SCAN_header) { ++s->img_n; return 1; }
if (z->depth == 16) {
- for (k = 0; k < s->img_n; ++k) tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
+ for (k = 0; k < s->img_n && k < 3; ++k) // extra loop test to suppress false GCC warning
+ tc16[k] = (stbi__uint16)stbi__get16be(s); // copy the values as-is
} else {
- for (k = 0; k < s->img_n; ++k) tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
+ for (k = 0; k < s->img_n && k < 3; ++k)
+ tc[k] = (stbi_uc)(stbi__get16be(s) & 255) * stbi__depth_scale_table[z->depth]; // non 8-bit images will be larger
}
}
break;
@@ -5115,7 +5173,13 @@ static int stbi__parse_png_file(stbi__png *z, int scan, int req_comp)
case STBI__PNG_TYPE('I','D','A','T'): {
if (first) return stbi__err("first not IHDR", "Corrupt PNG");
if (pal_img_n && !pal_len) return stbi__err("no PLTE","Corrupt PNG");
- if (scan == STBI__SCAN_header) { s->img_n = pal_img_n; return 1; }
+ if (scan == STBI__SCAN_header) {
+ // header scan definitely stops at first IDAT
+ if (pal_img_n)
+ s->img_n = pal_img_n;
+ return 1;
+ }
+ if (c.length > (1u << 30)) return stbi__err("IDAT size limit", "IDAT section larger than 2^30 bytes");
if ((int)(ioff + c.length) < (int)ioff) return 0;
if (ioff + c.length > idata_limit) {
stbi__uint32 idata_limit_old = idata_limit;
@@ -5498,8 +5562,22 @@ static void *stbi__bmp_load(stbi__context *s, int *x, int *y, int *comp, int req
psize = (info.offset - info.extra_read - info.hsz) >> 2;
}
if (psize == 0) {
- if (info.offset != s->callback_already_read + (s->img_buffer - s->img_buffer_original)) {
- return stbi__errpuc("bad offset", "Corrupt BMP");
+ // accept some number of extra bytes after the header, but if the offset points either to before
+ // the header ends or implies a large amount of extra data, reject the file as malformed
+ int bytes_read_so_far = s->callback_already_read + (int)(s->img_buffer - s->img_buffer_original);
+ int header_limit = 1024; // max we actually read is below 256 bytes currently.
+ int extra_data_limit = 256*4; // what ordinarily goes here is a palette; 256 entries*4 bytes is its max size.
+ if (bytes_read_so_far <= 0 || bytes_read_so_far > header_limit) {
+ return stbi__errpuc("bad header", "Corrupt BMP");
+ }
+ // we established that bytes_read_so_far is positive and sensible.
+ // the first half of this test rejects offsets that are either too small positives, or
+ // negative, and guarantees that info.offset >= bytes_read_so_far > 0. this in turn
+ // ensures the number computed in the second half of the test can't overflow.
+ if (info.offset < bytes_read_so_far || info.offset - bytes_read_so_far > extra_data_limit) {
+ return stbi__errpuc("bad offset", "Corrupt BMP");
+ } else {
+ stbi__skip(s, info.offset - bytes_read_so_far);
}
}
@@ -7187,12 +7265,12 @@ static float *stbi__hdr_load(stbi__context *s, int *x, int *y, int *comp, int re
// Run
value = stbi__get8(s);
count -= 128;
- if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+ if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = value;
} else {
// Dump
- if (count > nleft) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
+ if ((count == 0) || (count > nleft)) { STBI_FREE(hdr_data); STBI_FREE(scanline); return stbi__errpf("corrupt", "bad RLE data in HDR"); }
for (z = 0; z < count; ++z)
scanline[i++ * 4 + k] = stbi__get8(s);
}
@@ -7446,10 +7524,17 @@ static void *stbi__pnm_load(stbi__context *s, int *x, int *y, int *comp, int req
out = (stbi_uc *) stbi__malloc_mad4(s->img_n, s->img_x, s->img_y, ri->bits_per_channel / 8, 0);
if (!out) return stbi__errpuc("outofmem", "Out of memory");
- stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8));
+ if (!stbi__getn(s, out, s->img_n * s->img_x * s->img_y * (ri->bits_per_channel / 8))) {
+ STBI_FREE(out);
+ return stbi__errpuc("bad PNM", "PNM file truncated");
+ }
if (req_comp && req_comp != s->img_n) {
- out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+ if (ri->bits_per_channel == 16) {
+ out = (stbi_uc *) stbi__convert_format16((stbi__uint16 *) out, s->img_n, req_comp, s->img_x, s->img_y);
+ } else {
+ out = stbi__convert_format(out, s->img_n, req_comp, s->img_x, s->img_y);
+ }
if (out == NULL) return out; // stbi__convert_format frees input on failure
}
return out;
@@ -7486,6 +7571,8 @@ static int stbi__pnm_getinteger(stbi__context *s, char *c)
while (!stbi__at_eof(s) && stbi__pnm_isdigit(*c)) {
value = value*10 + (*c - '0');
*c = (char) stbi__get8(s);
+ if((value > 214748364) || (value == 214748364 && *c > '7'))
+ return stbi__err("integer parse overflow", "Parsing an integer in the PPM header overflowed a 32-bit int");
}
return value;
@@ -7516,9 +7603,13 @@ static int stbi__pnm_info(stbi__context *s, int *x, int *y, int *comp)
stbi__pnm_skip_whitespace(s, &c);
*x = stbi__pnm_getinteger(s, &c); // read width
+ if(*x == 0)
+ return stbi__err("invalid width", "PPM image header had zero or overflowing width");
stbi__pnm_skip_whitespace(s, &c);
*y = stbi__pnm_getinteger(s, &c); // read height
+ if (*y == 0)
+ return stbi__err("invalid width", "PPM image header had zero or overflowing width");
stbi__pnm_skip_whitespace(s, &c);
maxv = stbi__pnm_getinteger(s, &c); // read max value
diff --git a/src/external/stb/stb_truetype.h b/src/external/stb/stb_truetype.h
index bbf2284b..90a5c2e2 100644
--- a/src/external/stb/stb_truetype.h
+++ b/src/external/stb/stb_truetype.h
@@ -54,7 +54,7 @@
// Hou Qiming Derek Vinyard
// Rob Loach Cort Stratton
// Kenney Phillis Jr. Brian Costabile
-// Ken Voskuil (kaesve)
+// Ken Voskuil (kaesve) Yakov Galka
//
// VERSION HISTORY
//
@@ -4604,6 +4604,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
scale_y = -scale_y;
{
+ // distance from singular values (in the same units as the pixel grid)
+ const float eps = 1./1024, eps2 = eps*eps;
int x,y,i,j;
float *precompute;
stbtt_vertex *verts;
@@ -4616,15 +4618,15 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float x0 = verts[i].x*scale_x, y0 = verts[i].y*scale_y;
float x1 = verts[j].x*scale_x, y1 = verts[j].y*scale_y;
float dist = (float) STBTT_sqrt((x1-x0)*(x1-x0) + (y1-y0)*(y1-y0));
- precompute[i] = (dist == 0) ? 0.0f : 1.0f / dist;
+ precompute[i] = (dist < eps) ? 0.0f : 1.0f / dist;
} else if (verts[i].type == STBTT_vcurve) {
float x2 = verts[j].x *scale_x, y2 = verts[j].y *scale_y;
float x1 = verts[i].cx*scale_x, y1 = verts[i].cy*scale_y;
float x0 = verts[i].x *scale_x, y0 = verts[i].y *scale_y;
float bx = x0 - 2*x1 + x2, by = y0 - 2*y1 + y2;
float len2 = bx*bx + by*by;
- if (len2 != 0.0f)
- precompute[i] = 1.0f / (bx*bx + by*by);
+ if (len2 >= eps2)
+ precompute[i] = 1.0f / len2;
else
precompute[i] = 0.0f;
} else
@@ -4689,8 +4691,8 @@ STBTT_DEF unsigned char * stbtt_GetGlyphSDF(const stbtt_fontinfo *info, float sc
float a = 3*(ax*bx + ay*by);
float b = 2*(ax*ax + ay*ay) + (mx*bx+my*by);
float c = mx*ax+my*ay;
- if (a == 0.0) { // if a is 0, it's linear
- if (b != 0.0) {
+ if (STBTT_fabs(a) < eps2) { // if a is 0, it's linear
+ if (STBTT_fabs(b) >= eps2) {
res[num++] = -c/b;
}
} else {
diff --git a/src/external/tinygltf/README.md b/src/external/tinygltf/README.md
index 557734a1..5e706d9c 100644
--- a/src/external/tinygltf/README.md
+++ b/src/external/tinygltf/README.md
@@ -9,7 +9,7 @@ If you are looking for old, C++03 version, please use `devel-picojson` branch (b
## Status
Currently TinyGLTF is stable and maintenance mode. No drastic changes and feature additions planned.
-
+ - v2.9.0 Various fixes and improvements. Filesystem callback API change.
- v2.8.0 Add URICallbacks for custom URI handling in Buffer and Image. PR#397
- v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393
- v2.6.0 Support serializing sparse accessor(Thanks to @fynv).
@@ -26,8 +26,6 @@ Currently TinyGLTF is stable and maintenance mode. No drastic changes and featur
## Builds
-[![Build Status](https://travis-ci.org/syoyo/tinygltf.svg?branch=devel)](https://travis-ci.org/syoyo/tinygltf)
-
[![Build status](https://ci.appveyor.com/api/projects/status/warngenu9wjjhlm8?svg=true)](https://ci.appveyor.com/project/syoyo/tinygltf)
![C/C++ CI](https://github.com/syoyo/tinygltf/workflows/C/C++%20CI/badge.svg)
@@ -109,6 +107,7 @@ WASI build example is located in [wasm](wasm) .
* [SanityEngine](https://github.com/DethRaid/SanityEngine) - A C++/D3D12 renderer focused on the personal and professional development of its developer
* [Open3D](http://www.open3d.org/) - A Modern Library for 3D Data Processing
* [Supernova Engine](https://github.com/supernovaengine/supernova) - Game engine for 2D and 3D projects with Lua or C++ in data oriented design.
+* [Wicked Engine](https://github.com/turanszkij/WickedEngine) - 3D engine with modern graphics
* Your projects here! (Please send PR)
## TODOs
@@ -197,6 +196,7 @@ if (!ret) {
* `TINYGLTF_USE_RAPIDJSON` : Use RapidJSON as a JSON parser/serializer. RapidJSON files are not included in TinyGLTF repo. Please set an include path to RapidJSON if you enable this feature.
* `TINYGLTF_USE_CPP14` : Use C++14 feature(requires C++14 compiler). This may give better performance than C++11.
+
## CMake options
You can add tinygltf using `add_subdirectory` feature.
diff --git a/src/external/tinygltf/tiny_gltf.h b/src/external/tinygltf/tiny_gltf.h
index 0f69ad27..6d8c3ffb 100644
--- a/src/external/tinygltf/tiny_gltf.h
+++ b/src/external/tinygltf/tiny_gltf.h
@@ -25,32 +25,8 @@
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
-// Version:
-// - v2.8.1 Missed serialization texture sampler name fixed. PR#399.
-// - v2.8.0 Add URICallbacks for custom URI handling in Buffer and Image. PR#397.
-// - v2.7.0 Change WriteImageDataFunction user callback function signature. PR#393.
-// - v2.6.3 Fix GLB file with empty BIN chunk was not handled. PR#382 and PR#383.
-// - v2.6.2 Fix out-of-bounds access of accessors. PR#379.
-// - v2.6.1 Better GLB validation check when loading.
-// - v2.6.0 Support serializing sparse accessor(Thanks to @fynv).
-// Disable expanding file path for security(no use of awkward `wordexp` anymore).
-// - v2.5.0 Add SetPreserveImageChannels() option to load image data as is.
-// - v2.4.3 Fix null object output when material has all default
-// parameters.
-// - v2.4.2 Decode percent-encoded URI.
-// - v2.4.1 Fix some glTF object class does not have `extensions` and/or
-// `extras` property.
-// - v2.4.0 Experimental RapidJSON and C++14 support(Thanks to @jrkoone).
-// - v2.3.1 Set default value of minFilter and magFilter in Sampler to -1.
-// - v2.3.0 Modified Material representation according to glTF 2.0 schema
-// (and introduced TextureInfo class)
-// Change the behavior of `Value::IsNumber`. It return true either the
-// value is int or real.
-// - v2.2.0 Add loading 16bit PNG support. Add Sparse accessor support(Thanks
-// to @Ybalrid)
-// - v2.1.0 Add draco compression.
-// - v2.0.1 Add comparison feature(Thanks to @Selmar).
-// - v2.0.0 glTF 2.0!.
+// Version: - v2.9.*
+// See https://github.com/syoyo/tinygltf/releases for release history.
//
// Tiny glTF loader is using following third party libraries:
//
@@ -67,20 +43,19 @@
#include
#include
#include
+#include
#include
#include