xref: /aosp_15_r20/external/vulkan-validation-layers/layers/cast_utils.h (revision b7893ccf7851cd6a48cc5a1e965257d8a5cdcc70)
1*b7893ccfSSadaf Ebrahimi /* Copyright (c) 2019 The Khronos Group Inc.
2*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2019 Valve Corporation
3*b7893ccfSSadaf Ebrahimi  * Copyright (c) 2019 LunarG, Inc.
4*b7893ccfSSadaf Ebrahimi  *
5*b7893ccfSSadaf Ebrahimi  * Licensed under the Apache License, Version 2.0 (the "License");
6*b7893ccfSSadaf Ebrahimi  * you may not use this file except in compliance with the License.
7*b7893ccfSSadaf Ebrahimi  * You may obtain a copy of the License at
8*b7893ccfSSadaf Ebrahimi  *
9*b7893ccfSSadaf Ebrahimi  *     http://www.apache.org/licenses/LICENSE-2.0
10*b7893ccfSSadaf Ebrahimi  *
11*b7893ccfSSadaf Ebrahimi  * Unless required by applicable law or agreed to in writing, software
12*b7893ccfSSadaf Ebrahimi  * distributed under the License is distributed on an "AS IS" BASIS,
13*b7893ccfSSadaf Ebrahimi  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*b7893ccfSSadaf Ebrahimi  * See the License for the specific language governing permissions and
15*b7893ccfSSadaf Ebrahimi  * limitations under the License.
16*b7893ccfSSadaf Ebrahimi  *
17*b7893ccfSSadaf Ebrahimi  * Author: John Zulauf <[email protected]>
18*b7893ccfSSadaf Ebrahimi  *
19*b7893ccfSSadaf Ebrahimi  */
20*b7893ccfSSadaf Ebrahimi #pragma once
21*b7893ccfSSadaf Ebrahimi #ifndef CAST_UTILS_H_
22*b7893ccfSSadaf Ebrahimi #define CAST_UTILS_H_
23*b7893ccfSSadaf Ebrahimi 
24*b7893ccfSSadaf Ebrahimi #include <cassert>
25*b7893ccfSSadaf Ebrahimi #include <cstddef>
26*b7893ccfSSadaf Ebrahimi #include <cstdint>
27*b7893ccfSSadaf Ebrahimi #include <functional>
28*b7893ccfSSadaf Ebrahimi 
29*b7893ccfSSadaf Ebrahimi #define CAST_TO_FROM_UTILS
30*b7893ccfSSadaf Ebrahimi // Casts to allow various types of less than 64 bits to be cast to and from uint64_t safely and portably
31*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename Uint>
CastFromUint(Uint untyped_handle)32*b7893ccfSSadaf Ebrahimi static inline HandleType CastFromUint(Uint untyped_handle) {
33*b7893ccfSSadaf Ebrahimi     static_assert(sizeof(HandleType) == sizeof(Uint), "HandleType must be the same size as untyped handle");
34*b7893ccfSSadaf Ebrahimi     return *reinterpret_cast<HandleType *>(&untyped_handle);
35*b7893ccfSSadaf Ebrahimi }
36*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename Uint>
CastToUint(HandleType handle)37*b7893ccfSSadaf Ebrahimi static inline Uint CastToUint(HandleType handle) {
38*b7893ccfSSadaf Ebrahimi     static_assert(sizeof(HandleType) == sizeof(Uint), "HandleType must be the same size as untyped handle");
39*b7893ccfSSadaf Ebrahimi     return *reinterpret_cast<Uint *>(&handle);
40*b7893ccfSSadaf Ebrahimi }
41*b7893ccfSSadaf Ebrahimi 
42*b7893ccfSSadaf Ebrahimi // Ensure that the size changing casts are *static* to ensure portability
43*b7893ccfSSadaf Ebrahimi template <typename HandleType>
CastFromUint64(uint64_t untyped_handle)44*b7893ccfSSadaf Ebrahimi static inline HandleType CastFromUint64(uint64_t untyped_handle) {
45*b7893ccfSSadaf Ebrahimi     static_assert(sizeof(HandleType) <= sizeof(uint64_t), "HandleType must be not larger than the untyped handle size");
46*b7893ccfSSadaf Ebrahimi     typedef
47*b7893ccfSSadaf Ebrahimi         typename std::conditional<sizeof(HandleType) == sizeof(uint8_t), uint8_t,
48*b7893ccfSSadaf Ebrahimi                                   typename std::conditional<sizeof(HandleType) == sizeof(uint16_t), uint16_t,
49*b7893ccfSSadaf Ebrahimi                                                             typename std::conditional<sizeof(HandleType) == sizeof(uint32_t),
50*b7893ccfSSadaf Ebrahimi                                                                                       uint32_t, uint64_t>::type>::type>::type Uint;
51*b7893ccfSSadaf Ebrahimi     return CastFromUint<HandleType, Uint>(static_cast<Uint>(untyped_handle));
52*b7893ccfSSadaf Ebrahimi }
53*b7893ccfSSadaf Ebrahimi 
54*b7893ccfSSadaf Ebrahimi template <typename HandleType>
CastToUint64(HandleType handle)55*b7893ccfSSadaf Ebrahimi static uint64_t CastToUint64(HandleType handle) {
56*b7893ccfSSadaf Ebrahimi     static_assert(sizeof(HandleType) <= sizeof(uint64_t), "HandleType must be not larger than the untyped handle size");
57*b7893ccfSSadaf Ebrahimi     typedef
58*b7893ccfSSadaf Ebrahimi         typename std::conditional<sizeof(HandleType) == sizeof(uint8_t), uint8_t,
59*b7893ccfSSadaf Ebrahimi                                   typename std::conditional<sizeof(HandleType) == sizeof(uint16_t), uint16_t,
60*b7893ccfSSadaf Ebrahimi                                                             typename std::conditional<sizeof(HandleType) == sizeof(uint32_t),
61*b7893ccfSSadaf Ebrahimi                                                                                       uint32_t, uint64_t>::type>::type>::type Uint;
62*b7893ccfSSadaf Ebrahimi     return static_cast<uint64_t>(CastToUint<HandleType, Uint>(handle));
63*b7893ccfSSadaf Ebrahimi }
64*b7893ccfSSadaf Ebrahimi 
65*b7893ccfSSadaf Ebrahimi // Convenience functions to case between handles and the types the handles abstract, reflecting the Vulkan handle scheme, where
66*b7893ccfSSadaf Ebrahimi // Handles are either pointers (dispatchable) or sizeof(uint64_t) (non-dispatchable), s.t. full size-safe casts are used and
67*b7893ccfSSadaf Ebrahimi // we ensure that handles are large enough to contain the underlying type.
68*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename ValueType>
CastToHandle(ValueType value,HandleType * handle)69*b7893ccfSSadaf Ebrahimi void CastToHandle(ValueType value, HandleType *handle) {
70*b7893ccfSSadaf Ebrahimi     static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value");
71*b7893ccfSSadaf Ebrahimi     *handle = CastFromUint64<HandleType>(CastToUint64<ValueType>(value));
72*b7893ccfSSadaf Ebrahimi }
73*b7893ccfSSadaf Ebrahimi // This form is conveniently "inline", you should only need to specify the handle type (the value type being deducible from the arg)
74*b7893ccfSSadaf Ebrahimi template <typename HandleType, typename ValueType>
CastToHandle(ValueType value)75*b7893ccfSSadaf Ebrahimi HandleType CastToHandle(ValueType value) {
76*b7893ccfSSadaf Ebrahimi     HandleType handle;
77*b7893ccfSSadaf Ebrahimi     CastToHandle(value, &handle);
78*b7893ccfSSadaf Ebrahimi     return handle;
79*b7893ccfSSadaf Ebrahimi }
80*b7893ccfSSadaf Ebrahimi 
81*b7893ccfSSadaf Ebrahimi template <typename ValueType, typename HandleType>
CastFromHandle(HandleType handle,ValueType * value)82*b7893ccfSSadaf Ebrahimi void CastFromHandle(HandleType handle, ValueType *value) {
83*b7893ccfSSadaf Ebrahimi     static_assert(sizeof(HandleType) >= sizeof(ValueType), "HandleType must large enough to hold internal value");
84*b7893ccfSSadaf Ebrahimi     *value = CastFromUint64<ValueType>(CastToUint64<HandleType>(handle));
85*b7893ccfSSadaf Ebrahimi }
86*b7893ccfSSadaf Ebrahimi template <typename ValueType, typename HandleType>
CastFromHandle(HandleType handle)87*b7893ccfSSadaf Ebrahimi ValueType CastFromHandle(HandleType handle) {
88*b7893ccfSSadaf Ebrahimi     ValueType value;
89*b7893ccfSSadaf Ebrahimi     CastFromHandle(handle, &value);
90*b7893ccfSSadaf Ebrahimi     return value;
91*b7893ccfSSadaf Ebrahimi }
92*b7893ccfSSadaf Ebrahimi 
93*b7893ccfSSadaf Ebrahimi #endif  // CAST_UTILS_H_
94