forked from KhronosGroup/Vulkan-ValidationLayers
-
Notifications
You must be signed in to change notification settings - Fork 1
/
qfo_transfer.h
182 lines (164 loc) · 9.22 KB
/
qfo_transfer.h
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
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
/* Copyright (c) 2015-2021 The Khronos Group Inc.
* Copyright (c) 2015-2021 Valve Corporation
* Copyright (c) 2015-2021 LunarG, Inc.
* Copyright (C) 2015-2021 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.
*
* Author: Courtney Goeltzenleuchter <[email protected]>
* Author: Tobin Ehlis <[email protected]>
* Author: Chris Forbes <[email protected]>
* Author: Mark Lobodzinski <[email protected]>
* Author: Dave Houlton <[email protected]>
* Author: John Zulauf <[email protected]>
* Author: Tobias Hector <[email protected]>
*/
#pragma once
#include "vk_layer_data.h"
#include "hash_util.h"
// Types to store queue family ownership (QFO) Transfers
class COMMAND_POOL_STATE;
template <typename Barrier>
static bool IsTransferOp(const Barrier &barrier) {
return barrier.srcQueueFamilyIndex != barrier.dstQueueFamilyIndex;
}
static inline bool QueueFamilyIsExternal(const uint32_t queue_family_index) {
return (queue_family_index == VK_QUEUE_FAMILY_EXTERNAL) || (queue_family_index == VK_QUEUE_FAMILY_FOREIGN_EXT);
}
// Caution: Section 7.7.4 states that "If the values of srcQueueFamilyIndex and dstQueueFamilyIndex are equal, no ownership transfer
// is performed, and the barrier operates as if they were both set to VK_QUEUE_FAMILY_IGNORED."; this does not handle that case.
static inline bool QueueFamilyIsIgnored(uint32_t queue_family_index) { return queue_family_index == VK_QUEUE_FAMILY_IGNORED; }
enum BarrierOperationsType {
kAllAcquire, // All Barrier operations are "ownership acquire" operations
kAllRelease, // All Barrier operations are "ownership release" operations
kGeneral, // Either no ownership operations or a mix of ownership operation types and/or non-ownership operations
};
// Common to image and buffer memory barriers
template <typename Handle>
struct QFOTransferBarrierBase {
using HandleType = Handle;
Handle handle = VK_NULL_HANDLE;
uint32_t srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
uint32_t dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED;
QFOTransferBarrierBase() = default;
QFOTransferBarrierBase(const Handle &resource_handle, uint32_t src, uint32_t dst)
: handle(resource_handle), srcQueueFamilyIndex(src), dstQueueFamilyIndex(dst) {}
hash_util::HashCombiner base_hash_combiner() const {
hash_util::HashCombiner hc;
hc << srcQueueFamilyIndex << dstQueueFamilyIndex << handle;
return hc;
}
bool operator==(const QFOTransferBarrierBase<Handle> &rhs) const {
return (srcQueueFamilyIndex == rhs.srcQueueFamilyIndex) && (dstQueueFamilyIndex == rhs.dstQueueFamilyIndex) &&
(handle == rhs.handle);
}
};
// Image barrier specific implementation
struct QFOImageTransferBarrier : public QFOTransferBarrierBase<VkImage> {
using BaseType = QFOTransferBarrierBase<VkImage>;
VkImageLayout oldLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageLayout newLayout = VK_IMAGE_LAYOUT_UNDEFINED;
VkImageSubresourceRange subresourceRange;
QFOImageTransferBarrier() = default;
QFOImageTransferBarrier(const VkImageMemoryBarrier &barrier)
: BaseType(barrier.image, barrier.srcQueueFamilyIndex, barrier.dstQueueFamilyIndex),
oldLayout(barrier.oldLayout),
newLayout(barrier.newLayout),
subresourceRange(barrier.subresourceRange) {}
QFOImageTransferBarrier(const VkImageMemoryBarrier2KHR &barrier)
: BaseType(barrier.image, barrier.srcQueueFamilyIndex, barrier.dstQueueFamilyIndex),
oldLayout(barrier.oldLayout),
newLayout(barrier.newLayout),
subresourceRange(barrier.subresourceRange) {}
size_t hash() const {
// Ignoring the layout information for the purpose of the hash, as we're interested in QFO release/acquisition w.r.t.
// the subresource affected, an layout transitions are current validated on another path
auto hc = base_hash_combiner() << subresourceRange;
return hc.Value();
}
bool operator==(const QFOImageTransferBarrier &rhs) const {
// Ignoring layout w.r.t. equality. See comment in hash above.
return (static_cast<BaseType>(*this) == static_cast<BaseType>(rhs)) && (subresourceRange == rhs.subresourceRange);
}
// TODO: codegen a comprehensive complie time type -> string (and or other traits) template family
static const char *BarrierName() { return "VkImageMemoryBarrier"; }
static const char *HandleName() { return "VkImage"; }
// UNASSIGNED-VkImageMemoryBarrier-image-00001 QFO transfer image barrier must not duplicate QFO recorded in command buffer
static const char *ErrMsgDuplicateQFOInCB() { return "UNASSIGNED-VkImageMemoryBarrier-image-00001"; }
// UNASSIGNED-VkImageMemoryBarrier-image-00002 QFO transfer image barrier must not duplicate QFO submitted in batch
static const char *ErrMsgDuplicateQFOInSubmit() { return "UNASSIGNED-VkImageMemoryBarrier-image-00002"; }
// UNASSIGNED-VkImageMemoryBarrier-image-00003 QFO transfer image barrier must not duplicate QFO submitted previously
static const char *ErrMsgDuplicateQFOSubmitted() { return "UNASSIGNED-VkImageMemoryBarrier-image-00003"; }
// UNASSIGNED-VkImageMemoryBarrier-image-00004 QFO acquire image barrier must have matching QFO release submitted previously
static const char *ErrMsgMissingQFOReleaseInSubmit() { return "UNASSIGNED-VkImageMemoryBarrier-image-00004"; }
};
// Buffer barrier specific implementation
struct QFOBufferTransferBarrier : public QFOTransferBarrierBase<VkBuffer> {
using BaseType = QFOTransferBarrierBase<VkBuffer>;
VkDeviceSize offset = 0;
VkDeviceSize size = 0;
QFOBufferTransferBarrier() = default;
QFOBufferTransferBarrier(const VkBufferMemoryBarrier &barrier)
: BaseType(barrier.buffer, barrier.srcQueueFamilyIndex, barrier.dstQueueFamilyIndex),
offset(barrier.offset),
size(barrier.size) {}
QFOBufferTransferBarrier(const VkBufferMemoryBarrier2KHR &barrier)
: BaseType(barrier.buffer, barrier.srcQueueFamilyIndex, barrier.dstQueueFamilyIndex),
offset(barrier.offset),
size(barrier.size) {}
size_t hash() const {
auto hc = base_hash_combiner() << offset << size;
return hc.Value();
}
bool operator==(const QFOBufferTransferBarrier &rhs) const {
return (static_cast<BaseType>(*this) == static_cast<BaseType>(rhs)) && (offset == rhs.offset) && (size == rhs.size);
}
static const char *BarrierName() { return "VkBufferMemoryBarrier"; }
static const char *HandleName() { return "VkBuffer"; }
// UNASSIGNED-VkImageMemoryBarrier-buffer-00001 QFO transfer buffer barrier must not duplicate QFO recorded in command buffer
static const char *ErrMsgDuplicateQFOInCB() { return "UNASSIGNED-VkBufferMemoryBarrier-buffer-00001"; }
// UNASSIGNED-VkBufferMemoryBarrier-buffer-00002 QFO transfer buffer barrier must not duplicate QFO submitted in batch
static const char *ErrMsgDuplicateQFOInSubmit() { return "UNASSIGNED-VkBufferMemoryBarrier-buffer-00002"; }
// UNASSIGNED-VkBufferMemoryBarrier-buffer-00003 QFO transfer buffer barrier must not duplicate QFO submitted previously
static const char *ErrMsgDuplicateQFOSubmitted() { return "UNASSIGNED-VkBufferMemoryBarrier-buffer-00003"; }
// UNASSIGNED-VkBufferMemoryBarrier-buffer-00004 QFO acquire buffer barrier must have matching QFO release submitted previously
static const char *ErrMsgMissingQFOReleaseInSubmit() { return "UNASSIGNED-VkBufferMemoryBarrier-buffer-00004"; }
};
template <typename TransferBarrier>
using QFOTransferBarrierHash = hash_util::HasHashMember<TransferBarrier>;
// Command buffers store the set of barriers recorded
template <typename TransferBarrier>
using QFOTransferBarrierSet = layer_data::unordered_set<TransferBarrier, QFOTransferBarrierHash<TransferBarrier>>;
template <typename TransferBarrier>
struct QFOTransferBarrierSets {
QFOTransferBarrierSet<TransferBarrier> release;
QFOTransferBarrierSet<TransferBarrier> acquire;
void Reset() {
acquire.clear();
release.clear();
}
};
// The layer_data stores the map of pending release barriers
template <typename TransferBarrier>
using GlobalQFOTransferBarrierMap =
layer_data::unordered_map<typename TransferBarrier::HandleType, QFOTransferBarrierSet<TransferBarrier>>;
// Submit queue uses the Scoreboard to track all release/acquire operations in a batch.
template <typename TransferBarrier>
using QFOTransferCBScoreboard =
layer_data::unordered_map<TransferBarrier, const CMD_BUFFER_STATE *, QFOTransferBarrierHash<TransferBarrier>>;
template <typename TransferBarrier>
struct QFOTransferCBScoreboards {
QFOTransferCBScoreboard<TransferBarrier> acquire;
QFOTransferCBScoreboard<TransferBarrier> release;
};