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 29namespace vk 30{ 31 32ApiVersion unpackVersion (deUint32 version) 33{ 34 return ApiVersion(VK_API_VERSION_VARIANT(version), 35 VK_API_VERSION_MAJOR(version), 36 VK_API_VERSION_MINOR(version), 37 VK_API_VERSION_PATCH(version)); 38} 39 40deUint32 pack (const ApiVersion& version) 41{ 42 DE_ASSERT((version.variantNum & ~0x7) == 0); 43 DE_ASSERT((version.majorNum & ~0x7F) == 0); 44 DE_ASSERT((version.minorNum & ~0x3FF) == 0); 45 DE_ASSERT((version.patchNum & ~0xFFF) == 0); 46 47 return (version.variantNum << 29) | (version.majorNum << 22) | (version.minorNum << 12) | version.patchNum; 48} 49 50deUint32 apiVersionClearPatch(deUint32 version) 51{ 52 return version & ~0xFFF; 53} 54 55// Direct acyclic graph of Vulkan API versions and its predecessors. 56// At the moment it's linear ( 0.1.0.0 < 0.1.1.0 < 0.1.2.0 < 1.1.0.0 ). 57// But with the introduction of Vulkan 1.3 it won't be, because Vulkan 1.2 will have 2 successors orthogonal to each other. 58// Moreover - when in the future new Vulkan SC 1.1 version will be created - it's possible that 59// it will have 2 predecessors : Vulkan SC 1.0 and Vulkan 1.3 ( or later version - it's just example ) 60// When it happens : two new predecessors will look like this: 61// { VK_MAKE_API_VERSION(1, 1, 1, 0), VK_MAKE_API_VERSION(1, 1, 0, 0) }, 62// { VK_MAKE_API_VERSION(1, 1, 1, 0), VK_MAKE_API_VERSION(0, 1, 3, 0) }, 63 64const static std::vector<std::pair<deUint32,deUint32>> apiVersionPredecessors = 65{ 66 { VK_MAKE_API_VERSION(0, 1, 0, 0), 0 }, 67 { VK_MAKE_API_VERSION(0, 1, 1, 0), VK_MAKE_API_VERSION(0, 1, 0, 0) }, 68 { VK_MAKE_API_VERSION(0, 1, 2, 0), VK_MAKE_API_VERSION(0, 1, 1, 0) }, 69 { VK_MAKE_API_VERSION(1, 1, 0, 0), VK_MAKE_API_VERSION(0, 1, 2, 0) }, 70 { VK_MAKE_API_VERSION(0, 1, 3, 0), VK_MAKE_API_VERSION(0, 1, 2, 0) }, 71}; 72 73bool isApiVersionEqual(deUint32 lhs, deUint32 rhs) 74{ 75 deUint32 lhsp = apiVersionClearPatch(lhs); 76 deUint32 rhsp = apiVersionClearPatch(rhs); 77 return lhsp == rhsp; 78} 79 80bool isApiVersionPredecessor(deUint32 version, deUint32 predVersion) 81{ 82 std::vector<deUint32> versions; 83 versions.push_back(apiVersionClearPatch(version)); 84 85 deUint32 p = apiVersionClearPatch(predVersion); 86 87 while (!versions.empty()) 88 { 89 deUint32 v = versions.back(); 90 versions.pop_back(); 91 92 for (auto it = begin(apiVersionPredecessors); it != end(apiVersionPredecessors); ++it) 93 { 94 if (it->first != v) 95 continue; 96 if (it->second == p) 97 return true; 98 versions.push_back(it->second); 99 } 100 } 101 return false; 102} 103 104bool isApiVersionSupported(deUint32 yourVersion, deUint32 versionInQuestion) 105{ 106 if (isApiVersionEqual(yourVersion, versionInQuestion)) 107 return true; 108 return isApiVersionPredecessor(yourVersion, versionInQuestion); 109} 110 111deUint32 minVulkanAPIVersion(deUint32 lhs, deUint32 rhs) 112{ 113 deUint32 lhsp = apiVersionClearPatch(lhs); 114 deUint32 rhsp = apiVersionClearPatch(rhs); 115 if (lhsp == rhsp) 116 return de::min(lhs, rhs); 117 if (isApiVersionPredecessor(rhs, lhs)) 118 return lhs; 119 if (isApiVersionPredecessor(lhs, rhs)) 120 return rhs; 121 // both versions are located in different DAG paths - we will return common predecessor 122 static std::vector<deUint32> commonPredecessors; 123 if (commonPredecessors.empty()) 124 { 125 std::set<deUint32> pred; 126 for (auto it = begin(apiVersionPredecessors); it != end(apiVersionPredecessors); ++it) 127 { 128 if (pred.find(it->second) != end(pred)) 129 commonPredecessors.push_back(it->second); 130 pred.insert(it->second); 131 } 132 std::sort(begin(commonPredecessors), end(commonPredecessors), [](deUint32 xlhs, deUint32 xrhs) { return isApiVersionPredecessor(xrhs, xlhs); }); 133 } 134 for (auto it = begin(commonPredecessors); it != end(commonPredecessors); ++it) 135 if (isApiVersionPredecessor(rhs, *it) && isApiVersionPredecessor(lhs, *it)) 136 return *it; 137 return 0; 138} 139 140} // vk 141