1 /*-------------------------------------------------------------------------
2 * Vulkan CTS Framework
3 * --------------------
4 *
5 * Copyright (c) 2015 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief Vulkan api version.
22 *//*--------------------------------------------------------------------*/
23
24 #include "vkApiVersion.hpp"
25 #include <vector>
26 #include <set>
27 #include <algorithm>
28
29 namespace vk
30 {
31
unpackVersion(uint32_t version)32 ApiVersion unpackVersion(uint32_t version)
33 {
34 return ApiVersion(VK_API_VERSION_VARIANT(version), VK_API_VERSION_MAJOR(version), VK_API_VERSION_MINOR(version),
35 VK_API_VERSION_PATCH(version));
36 }
37
pack(const ApiVersion & version)38 uint32_t pack(const ApiVersion &version)
39 {
40 DE_ASSERT((version.variantNum & ~0x7) == 0);
41 DE_ASSERT((version.majorNum & ~0x7F) == 0);
42 DE_ASSERT((version.minorNum & ~0x3FF) == 0);
43 DE_ASSERT((version.patchNum & ~0xFFF) == 0);
44
45 return (version.variantNum << 29) | (version.majorNum << 22) | (version.minorNum << 12) | version.patchNum;
46 }
47
apiVersionClearPatch(uint32_t version)48 uint32_t apiVersionClearPatch(uint32_t version)
49 {
50 return version & ~0xFFF;
51 }
52
53 // Direct acyclic graph of Vulkan API versions and its predecessors.
54 // At the moment it's linear ( 0.1.0.0 < 0.1.1.0 < 0.1.2.0 < 1.1.0.0 ).
55 // But with the introduction of Vulkan 1.3 it won't be, because Vulkan 1.2 will have 2 successors orthogonal to each other.
56 // Moreover - when in the future new Vulkan SC 1.1 version will be created - it's possible that
57 // it will have 2 predecessors : Vulkan SC 1.0 and Vulkan 1.3 ( or later version - it's just example )
58 // When it happens : two new predecessors will look like this:
59 // { VK_MAKE_API_VERSION(1, 1, 1, 0), VK_MAKE_API_VERSION(1, 1, 0, 0) },
60 // { VK_MAKE_API_VERSION(1, 1, 1, 0), VK_MAKE_API_VERSION(0, 1, 3, 0) },
61
62 const static std::vector<std::pair<uint32_t, uint32_t>> apiVersionPredecessors = {
63 {VK_MAKE_API_VERSION(0, 1, 0, 0), 0},
64 {VK_MAKE_API_VERSION(0, 1, 1, 0), VK_MAKE_API_VERSION(0, 1, 0, 0)},
65 {VK_MAKE_API_VERSION(0, 1, 2, 0), VK_MAKE_API_VERSION(0, 1, 1, 0)},
66 {VK_MAKE_API_VERSION(1, 1, 0, 0), VK_MAKE_API_VERSION(0, 1, 2, 0)},
67 {VK_MAKE_API_VERSION(0, 1, 3, 0), VK_MAKE_API_VERSION(0, 1, 2, 0)},
68 };
69
isApiVersionEqual(uint32_t lhs,uint32_t rhs)70 bool isApiVersionEqual(uint32_t lhs, uint32_t rhs)
71 {
72 uint32_t lhsp = apiVersionClearPatch(lhs);
73 uint32_t rhsp = apiVersionClearPatch(rhs);
74 return lhsp == rhsp;
75 }
76
isApiVersionPredecessor(uint32_t version,uint32_t predVersion)77 bool isApiVersionPredecessor(uint32_t version, uint32_t predVersion)
78 {
79 std::vector<uint32_t> versions;
80 versions.push_back(apiVersionClearPatch(version));
81
82 uint32_t p = apiVersionClearPatch(predVersion);
83
84 while (!versions.empty())
85 {
86 uint32_t v = versions.back();
87 versions.pop_back();
88
89 for (auto it = begin(apiVersionPredecessors); it != end(apiVersionPredecessors); ++it)
90 {
91 if (it->first != v)
92 continue;
93 if (it->second == p)
94 return true;
95 versions.push_back(it->second);
96 }
97 }
98 return false;
99 }
100
isApiVersionSupported(uint32_t yourVersion,uint32_t versionInQuestion)101 bool isApiVersionSupported(uint32_t yourVersion, uint32_t versionInQuestion)
102 {
103 if (isApiVersionEqual(yourVersion, versionInQuestion))
104 return true;
105 return isApiVersionPredecessor(yourVersion, versionInQuestion);
106 }
107
minVulkanAPIVersion(uint32_t lhs,uint32_t rhs)108 uint32_t minVulkanAPIVersion(uint32_t lhs, uint32_t rhs)
109 {
110 uint32_t lhsp = apiVersionClearPatch(lhs);
111 uint32_t rhsp = apiVersionClearPatch(rhs);
112 if (lhsp == rhsp)
113 return de::min(lhs, rhs);
114 if (isApiVersionPredecessor(rhs, lhs))
115 return lhs;
116 if (isApiVersionPredecessor(lhs, rhs))
117 return rhs;
118 // both versions are located in different DAG paths - we will return common predecessor
119 static std::vector<uint32_t> commonPredecessors;
120 if (commonPredecessors.empty())
121 {
122 std::set<uint32_t> pred;
123 for (auto it = begin(apiVersionPredecessors); it != end(apiVersionPredecessors); ++it)
124 {
125 if (pred.find(it->second) != end(pred))
126 commonPredecessors.push_back(it->second);
127 pred.insert(it->second);
128 }
129 std::sort(begin(commonPredecessors), end(commonPredecessors),
130 [](uint32_t xlhs, uint32_t xrhs) { return isApiVersionPredecessor(xrhs, xlhs); });
131 }
132 for (auto it = begin(commonPredecessors); it != end(commonPredecessors); ++it)
133 if (isApiVersionPredecessor(rhs, *it) && isApiVersionPredecessor(lhs, *it))
134 return *it;
135 return 0;
136 }
137
138 } // namespace vk
139