File: state_object.cpp

package info (click to toggle)
vulkan-validationlayers 1.4.321.0-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid
  • size: 47,412 kB
  • sloc: cpp: 594,175; python: 11,321; sh: 24; makefile: 20; xml: 14
file content (99 lines) | stat: -rw-r--r-- 3,408 bytes parent folder | download | duplicates (10)
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
/* 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.
 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
 *
 * 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 "state_tracker/state_object.h"

vvl::StateObject::~StateObject() { Destroy(); }

void vvl::StateObject::Destroy() {
    Invalidate();
    destroyed_ = true;
}

const VulkanTypedHandle* vvl::StateObject::InUse() const {
    // NOTE: for performance reasons, this method calls up the tree
    // with the read lock held.
    auto guard = ReadLockTree();
    for (auto& item : parent_nodes_) {
        auto node = item.second.lock();
        if (!node) {
            continue;
        }
        if (node->InUse()) {
            return &node->Handle();
        }
    }
    return nullptr;
}

bool vvl::StateObject::AddParent(StateObject* parent_node) {
    auto guard = WriteLockTree();
    auto result = parent_nodes_.emplace(parent_node->Handle(), std::weak_ptr<StateObject>(parent_node->shared_from_this()));
    return result.second;
}

void vvl::StateObject::RemoveParent(StateObject* parent_node) {
    assert(parent_node);
    auto guard = WriteLockTree();
    parent_nodes_.erase(parent_node->Handle());
}

// copy the current set of parents so that we don't need to hold the lock
// while calling NotifyInvalidate on them, as that would lead to recursive locking.
vvl::StateObject::NodeMap vvl::StateObject::GetParentsForInvalidate(bool unlink) {
    NodeMap result;
    if (unlink) {
        auto guard = WriteLockTree();
        result = std::move(parent_nodes_);
        parent_nodes_.clear();
    } else {
        auto guard = ReadLockTree();
        result = parent_nodes_;
    }
    return result;
}

vvl::StateObject::NodeMap vvl::StateObject::ObjectBindings() const {
    auto guard = ReadLockTree();
    return parent_nodes_;
}

void vvl::StateObject::Invalidate(bool unlink) {
    NodeList empty;
    // We do not want to call the virtual method here because any special handling
    // in an overriden NotifyInvalidate() is for when a child node has become invalid.
    // But calling Invalidate() indicates the current node is invalid.
    // Calling the default implementation directly here avoids duplicating it inline.
    StateObject::NotifyInvalidate(empty, unlink);
}

void vvl::StateObject::NotifyInvalidate(const NodeList& invalid_nodes, bool unlink) {
    auto current_parents = GetParentsForInvalidate(unlink);
    if (current_parents.empty()) {
        return;
    }

    NodeList up_nodes = invalid_nodes;
    up_nodes.emplace_back(shared_from_this());
    for (auto& item : current_parents) {
        auto node = item.second.lock();
        if (node && !node->Destroyed()) {
            node->NotifyInvalidate(up_nodes, unlink);
        }
    }
}