File: vk_safe_struct_utils.hpp

package info (click to toggle)
vulkan-utility-libraries 1.4.341.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 8,636 kB
  • sloc: cpp: 109,126; ansic: 17,113; python: 2,220; sh: 23; makefile: 6
file content (126 lines) | stat: -rw-r--r-- 4,464 bytes parent folder | download | duplicates (8)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
/***************************************************************************
 *
 * Copyright (c) 2015-2024 The Khronos Group Inc.
 * Copyright (c) 2015-2024 Valve Corporation
 * Copyright (c) 2015-2024 LunarG, Inc.
 * Copyright (c) 2015-2024 Google Inc.
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 ****************************************************************************/

#pragma once
#include <vulkan/vulkan.h>
#include <cassert>
#include <cstdlib>
#include <cstring>
#include <functional>
#include <vector>

namespace vku {

// State that elements in a pNext chain may need to be aware of
struct PNextCopyState {
    // Custom initialization function. Returns true if the structure passed to init was initialized, false otherwise
    std::function<bool(VkBaseOutStructure* /* safe_sruct */, const VkBaseOutStructure* /* in_struct */)> init;
};

void* SafePnextCopy(const void* pNext, PNextCopyState* copy_state = {});
void FreePnextChain(const void* pNext);
char* SafeStringCopy(const char* in_string);

template <typename Base, typename T>
bool AddToPnext(Base& base, const T& data) {
    assert(base.ptr());  // All safe struct have a ptr() method. Prevent use with non-safe structs.
    auto** prev = reinterpret_cast<VkBaseOutStructure**>(const_cast<void**>(&base.pNext));
    auto* current = *prev;
    while (current) {
        if (data.sType == current->sType) {
            return false;
        }
        prev = reinterpret_cast<VkBaseOutStructure**>(&current->pNext);
        current = *prev;
    }
    *prev = reinterpret_cast<VkBaseOutStructure*>(SafePnextCopy(&data));
    return true;
}

template <typename Base>
bool RemoveFromPnext(Base& base, VkStructureType t) {
    assert(base.ptr());  // All safe struct have a ptr() method. Prevent use with non-safe structs.
    auto** prev = reinterpret_cast<VkBaseOutStructure**>(const_cast<void**>(&base.pNext));
    auto* current = *prev;
    while (current) {
        if (t == current->sType) {
            *prev = current->pNext;
            current->pNext = nullptr;
            FreePnextChain(current);
            return true;
        }
        prev = reinterpret_cast<VkBaseOutStructure**>(&current->pNext);
        current = *prev;
    }
    return false;
}

template <typename CreateInfo>
uint32_t FindExtension(CreateInfo& ci, const char* extension_name) {
    assert(ci.ptr());  // All safe struct have a ptr() method. Prevent use with non-safe structs.
    for (uint32_t i = 0; i < ci.enabledExtensionCount; i++) {
        if (strcmp(ci.ppEnabledExtensionNames[i], extension_name) == 0) {
            return i;
        }
    }
    return ci.enabledExtensionCount;
}

template <typename CreateInfo>
bool AddExtension(CreateInfo& ci, const char* extension_name) {
    assert(ci.ptr());  // All safe struct have a ptr() method. Prevent use with non-safe structs.
    uint32_t pos = FindExtension(ci, extension_name);
    if (pos < ci.enabledExtensionCount) {
        // already present
        return false;
    }
    char** exts = new char*[ci.enabledExtensionCount + 1];
    if (ci.ppEnabledExtensionNames) {
        memcpy(exts, ci.ppEnabledExtensionNames, sizeof(char*) * ci.enabledExtensionCount);
    }
    exts[ci.enabledExtensionCount] = SafeStringCopy(extension_name);
    delete[] ci.ppEnabledExtensionNames;
    ci.ppEnabledExtensionNames = exts;
    ci.enabledExtensionCount++;
    return true;
}

template <typename CreateInfo>
bool RemoveExtension(CreateInfo& ci, const char* extension_name) {
    assert(ci.ptr());  // All safe struct have a ptr() method. Prevent use with non-safe structs.
    uint32_t pos = FindExtension(ci, extension_name);
    if (pos >= ci.enabledExtensionCount) {
        // not present
        return false;
    }
    if (ci.enabledExtensionCount == 1) {
        delete[] ci.ppEnabledExtensionNames[0];
        delete[] ci.ppEnabledExtensionNames;
        ci.ppEnabledExtensionNames = nullptr;
        ci.enabledExtensionCount = 0;
        return true;
    }
    uint32_t out_pos = 0;
    char** exts = new char*[ci.enabledExtensionCount - 1];
    for (uint32_t i = 0; i < ci.enabledExtensionCount; i++) {
        if (i == pos) {
            delete[] ci.ppEnabledExtensionNames[i];
        } else {
            exts[out_pos++] = const_cast<char*>(ci.ppEnabledExtensionNames[i]);
        }
    }
    delete[] ci.ppEnabledExtensionNames;
    ci.ppEnabledExtensionNames = exts;
    ci.enabledExtensionCount--;
    return true;
}

}  // namespace vku