blob: 0b9c97beede0374a7a6f1c38b05aadeaa3718285 [file] [log] [blame]
John Zulauf3d84f1b2020-03-09 13:33:25 -06001/*
2 * Copyright (c) 2019-2020 Valve Corporation
3 * Copyright (c) 2019-2020 LunarG, Inc.
John Zulauf9cb530d2019-09-30 14:14:10 -06004 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 *
17 * Author: John Zulauf <jzulauf@lunarg.com>
18 */
19
20#pragma once
21
22#include <map>
23#include <memory>
24#include <unordered_map>
25#include <vulkan/vulkan.h>
26
27#include "synchronization_validation_types.h"
28#include "state_tracker.h"
29
John Zulauf355e49b2020-04-24 15:11:15 -060030class SyncValidator;
31
John Zulauf2f952d22020-02-10 11:34:51 -070032enum SyncHazard {
33 NONE = 0,
34 READ_AFTER_WRITE,
35 WRITE_AFTER_READ,
36 WRITE_AFTER_WRITE,
37 READ_RACING_WRITE,
38 WRITE_RACING_WRITE,
39 WRITE_RACING_READ,
40};
John Zulauf9cb530d2019-09-30 14:14:10 -060041
42// Useful Utilites for manipulating StageAccess parameters, suitable as base class to save typing
43struct SyncStageAccess {
44 static SyncStageAccessFlagBits FlagBit(SyncStageAccessIndex stage_access) {
45 return syncStageAccessInfoByStageAccessIndex[stage_access].stage_access_bit;
46 }
47
48 static bool IsRead(SyncStageAccessFlagBits stage_access_bit) { return 0 != (stage_access_bit & syncStageAccessReadMask); }
49 static bool IsRead(SyncStageAccessIndex stage_access_index) { return IsRead(FlagBit(stage_access_index)); }
50
51 static bool IsWrite(SyncStageAccessFlagBits stage_access_bit) { return 0 != (stage_access_bit & syncStageAccessWriteMask); }
52 static bool IsWrite(SyncStageAccessIndex stage_access_index) { return IsWrite(FlagBit(stage_access_index)); }
53 static VkPipelineStageFlagBits PipelineStageBit(SyncStageAccessIndex stage_access_index) {
54 return syncStageAccessInfoByStageAccessIndex[stage_access_index].stage_mask;
55 }
56 static SyncStageAccessFlags AccessScopeByStage(VkPipelineStageFlags stages);
57 static SyncStageAccessFlags AccessScopeByAccess(VkAccessFlags access);
58 static SyncStageAccessFlags AccessScope(VkPipelineStageFlags stages, VkAccessFlags access);
59 static SyncStageAccessFlags AccessScope(SyncStageAccessFlags stage_scope, VkAccessFlags accesses) {
60 return stage_scope & AccessScopeByAccess(accesses);
61 }
62};
63
John Zulauf5f13a792020-03-10 07:31:21 -060064struct ResourceUsageTag {
65 uint64_t index;
66 ResourceUsageTag &operator++() {
67 index++;
68 return *this;
69 }
70 bool IsBefore(const ResourceUsageTag &rhs) const { return index < rhs.index; }
John Zulaufe5da6e52020-03-18 15:32:18 -060071 bool operator==(const ResourceUsageTag &rhs) const { return (index == rhs.index); }
72 bool operator!=(const ResourceUsageTag &rhs) const { return !(*this == rhs); }
John Zulauf355e49b2020-04-24 15:11:15 -060073 ResourceUsageTag() : index(0) {}
John Zulauf5f13a792020-03-10 07:31:21 -060074};
75
John Zulauf9cb530d2019-09-30 14:14:10 -060076struct HazardResult {
77 SyncHazard hazard = NONE;
78 ResourceUsageTag tag = ResourceUsageTag();
79 void Set(SyncHazard hazard_, const ResourceUsageTag &tag_) {
80 hazard = hazard_;
81 tag = tag_;
82 }
83};
84
John Zulauf3d84f1b2020-03-09 13:33:25 -060085struct SyncBarrier {
86 VkPipelineStageFlags src_exec_scope;
87 SyncStageAccessFlags src_access_scope;
88 VkPipelineStageFlags dst_exec_scope;
89 SyncStageAccessFlags dst_access_scope;
90 SyncBarrier() = default;
91 SyncBarrier &operator=(const SyncBarrier &) = default;
92 SyncBarrier(VkQueueFlags gueue_flags, const VkSubpassDependency2 &sub_pass_barrier);
93};
94using SyncBarrierStack = std::vector<const SyncBarrier *>;
95
John Zulauf9cb530d2019-09-30 14:14:10 -060096class ResourceAccessState : public SyncStageAccess {
97 protected:
98 // Mutliple read operations can be simlutaneously (and independently) synchronized,
99 // given the only the second execution scope creates a dependency chain, we have to track each,
100 // but only up to one per pipeline stage (as another read from the *same* stage become more recent,
101 // and applicable one for hazard detection
102 struct ReadState {
103 VkPipelineStageFlagBits stage; // The stage of this read
104 VkPipelineStageFlags barriers; // all applicable barriered stages
105 ResourceUsageTag tag;
John Zulaufe5da6e52020-03-18 15:32:18 -0600106 bool operator==(const ReadState &rhs) const {
107 bool same = (stage == rhs.stage) && (barriers == rhs.barriers) && (tag == rhs.tag);
108 return same;
109 }
110 bool operator!=(const ReadState &rhs) const { return !(*this == rhs); }
John Zulauf9cb530d2019-09-30 14:14:10 -0600111 };
112
113 public:
114 HazardResult DetectHazard(SyncStageAccessIndex usage_index) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600115
John Zulauf0cb5be22020-01-23 12:18:22 -0700116 HazardResult DetectBarrierHazard(SyncStageAccessIndex usage_index, VkPipelineStageFlags src_stage_mask,
117 SyncStageAccessFlags source_scope) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600118 HazardResult DetectAsyncHazard(SyncStageAccessIndex usage_index) const;
119
John Zulauf9cb530d2019-09-30 14:14:10 -0600120 void Update(SyncStageAccessIndex usage_index, const ResourceUsageTag &tag);
John Zulauf5f13a792020-03-10 07:31:21 -0600121 void Resolve(const ResourceAccessState &other);
122 void ApplyBarrier(const SyncBarrier &barrier);
John Zulauf9cb530d2019-09-30 14:14:10 -0600123 void ApplyExecutionBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask);
124 void ApplyMemoryAccessBarrier(VkPipelineStageFlags src_stage_mask, SyncStageAccessFlags src_scope,
125 VkPipelineStageFlags dst_stage_mask, SyncStageAccessFlags dst_scope);
126
127 ResourceAccessState()
John Zulauf355e49b2020-04-24 15:11:15 -0600128 : write_barriers(~SyncStageAccessFlags(0)),
129 write_dependency_chain(0),
130 last_read_count(0),
131 last_read_stages(0),
132 write_tag(),
133 last_write(0) {}
John Zulauf9cb530d2019-09-30 14:14:10 -0600134
John Zulauf3d84f1b2020-03-09 13:33:25 -0600135 bool HasWriteOp() const { return last_write != 0; }
John Zulaufe5da6e52020-03-18 15:32:18 -0600136 bool operator==(const ResourceAccessState &rhs) const {
137 bool same = (write_barriers == rhs.write_barriers) && (write_dependency_chain == rhs.write_dependency_chain) &&
138 (last_read_count == rhs.last_read_count) && (last_read_stages == rhs.last_read_stages) &&
139 (write_tag == rhs.write_tag);
140 for (uint32_t i = 0; same && i < last_read_count; i++) {
141 same |= last_reads[i] == rhs.last_reads[i];
142 }
143 return same;
144 }
145 bool operator!=(const ResourceAccessState &rhs) const { return !(*this == rhs); }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600146
John Zulauf9cb530d2019-09-30 14:14:10 -0600147 private:
148 bool IsWriteHazard(SyncStageAccessFlagBits usage) const { return 0 != (usage & ~write_barriers); }
149 bool IsReadHazard(VkPipelineStageFlagBits stage, const ReadState &read_access) const {
150 return 0 != (stage & ~read_access.barriers);
151 }
John Zulauf0cb5be22020-01-23 12:18:22 -0700152 bool IsReadHazard(VkPipelineStageFlags stage_mask, const ReadState &read_access) const {
153 return stage_mask != (stage_mask & read_access.barriers);
154 }
John Zulauf9cb530d2019-09-30 14:14:10 -0600155 // With reads, each must be "safe" relative to it's prior write, so we need only
156 // save the most recent write operation (as anything *transitively* unsafe would arleady
157 // be included
158 SyncStageAccessFlags write_barriers; // union of applicable barrier masks since last write
159 VkPipelineStageFlags write_dependency_chain; // intiially zero, but accumulating the dstStages of barriers if they chain.
160 uint32_t last_read_count;
161 VkPipelineStageFlags last_read_stages;
162
163 ResourceUsageTag write_tag;
John Zulauf355e49b2020-04-24 15:11:15 -0600164 // TODO: Add a NONE (zero) enum to SyncStageAccessFlagBits
165 SyncStageAccessFlags last_write; // only the most recent write
John Zulauf9cb530d2019-09-30 14:14:10 -0600166
167 std::array<ReadState, 8 * sizeof(VkPipelineStageFlags)> last_reads;
John Zulauf9cb530d2019-09-30 14:14:10 -0600168};
169
John Zulauf16adfc92020-04-08 10:28:33 -0600170using ResourceAccessRangeMap = sparse_container::range_map<VkDeviceSize, ResourceAccessState>;
John Zulauf5c5e88d2019-12-26 11:22:02 -0700171using ResourceAccessRange = typename ResourceAccessRangeMap::key_type;
John Zulauf355e49b2020-04-24 15:11:15 -0600172using ResourceRangeMergeIterator = sparse_container::parallel_iterator<ResourceAccessRangeMap, const ResourceAccessRangeMap>;
John Zulauf9cb530d2019-09-30 14:14:10 -0600173
John Zulauf540266b2020-04-06 18:54:53 -0600174class AccessContext {
John Zulauf5c5e88d2019-12-26 11:22:02 -0700175 public:
John Zulauf355e49b2020-04-24 15:11:15 -0600176 enum AddressType : int { kLinearAddress = 0, kIdealizedAddress = 1, kMaxAddressType = 1 };
177 enum DetectOptions : unsigned int {
178 kDetectPrevious = 1U << 0,
179 kDetectAsync = 1U << 1,
180 kDetectAll = (kDetectPrevious | kDetectAsync)
John Zulauf16adfc92020-04-08 10:28:33 -0600181 };
182
John Zulauf3d84f1b2020-03-09 13:33:25 -0600183 struct TrackBack {
184 SyncBarrier barrier;
John Zulauf540266b2020-04-06 18:54:53 -0600185 AccessContext *context;
186 TrackBack(AccessContext *context_, VkQueueFlags queue_flags_, const VkSubpassDependency2 &subpass_barrier_)
John Zulauf3d84f1b2020-03-09 13:33:25 -0600187 : barrier(queue_flags_, subpass_barrier_), context(context_) {}
188 TrackBack &operator=(const TrackBack &) = default;
189 TrackBack() = default;
190 };
John Zulauf5c5e88d2019-12-26 11:22:02 -0700191
John Zulauf355e49b2020-04-24 15:11:15 -0600192 HazardResult DetectHazard(const BUFFER_STATE &buffer, SyncStageAccessIndex usage_index, const ResourceAccessRange &range) const;
John Zulauf540266b2020-04-06 18:54:53 -0600193 HazardResult DetectHazard(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
John Zulauf3d84f1b2020-03-09 13:33:25 -0600194 const VkImageSubresourceLayers &subresource, const VkOffset3D &offset,
195 const VkExtent3D &extent) const;
John Zulauf355e49b2020-04-24 15:11:15 -0600196 HazardResult DetectImageBarrierHazard(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope,
197 SyncStageAccessFlags src_access_scope, const VkImageSubresourceRange &subresource_range,
198 DetectOptions options) const;
199 HazardResult DetectImageBarrierHazard(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope,
200 SyncStageAccessFlags src_stage_accesses, const VkImageMemoryBarrier &barrier) const;
201 HazardResult DetectSubpassTransitionHazard(const RENDER_PASS_STATE::AttachmentTransition &transitions,
202 const std::vector<const IMAGE_VIEW_STATE *> &attachments) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600203
John Zulaufe5da6e52020-03-18 15:32:18 -0600204 const TrackBack &GetDstExternalTrackBack() const { return dst_external_; }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600205 void Reset() {
John Zulauf3d84f1b2020-03-09 13:33:25 -0600206 prev_.clear();
John Zulauf355e49b2020-04-24 15:11:15 -0600207 prev_by_subpass_.clear();
John Zulauf3d84f1b2020-03-09 13:33:25 -0600208 async_.clear();
John Zulaufe5da6e52020-03-18 15:32:18 -0600209 src_external_ = TrackBack();
John Zulauf16adfc92020-04-08 10:28:33 -0600210 for (auto &map : access_state_maps_) {
211 map.clear();
212 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600213 }
John Zulauf5f13a792020-03-10 07:31:21 -0600214 // TODO: See if returning the lower_bound would be useful from a performance POV -- look at the lower_bound overhead
215 // Would need to add a "hint" overload to parallel_iterator::invalidate_[AB] call, if so.
John Zulauf355e49b2020-04-24 15:11:15 -0600216 void ResolvePreviousAccess(AddressType type, const ResourceAccessRange &range, ResourceAccessRangeMap *descent_map,
217 const ResourceAccessState *infill_state) const;
John Zulauf540266b2020-04-06 18:54:53 -0600218 void ResolvePreviousAccess(const IMAGE_STATE &image_state, const VkImageSubresourceRange &subresource_range,
John Zulauf355e49b2020-04-24 15:11:15 -0600219 AddressType address_type, ResourceAccessRangeMap *descent_map,
220 const ResourceAccessState *infill_state) const;
221 void ResolveAccessRange(AddressType type, const ResourceAccessRange &range, const SyncBarrier *barrier,
222 ResourceAccessRangeMap *resolve_map, const ResourceAccessState *infill_state,
223 bool recur_to_infill = true) const;
224 void UpdateAccessState(const BUFFER_STATE &buffer, SyncStageAccessIndex current_usage, const ResourceAccessRange &range,
225 const ResourceUsageTag &tag);
226 void UpdateAccessState(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
227 const VkImageSubresourceRange &subresource_range, const VkOffset3D &offset, const VkExtent3D &extent,
228 const ResourceUsageTag &tag);
John Zulauf540266b2020-04-06 18:54:53 -0600229 void UpdateAccessState(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
John Zulauf3d84f1b2020-03-09 13:33:25 -0600230 const VkImageSubresourceLayers &subresource, const VkOffset3D &offset, const VkExtent3D &extent,
231 const ResourceUsageTag &tag);
232
John Zulauf540266b2020-04-06 18:54:53 -0600233 void ResolveChildContexts(const std::vector<AccessContext> &contexts);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600234
John Zulauf355e49b2020-04-24 15:11:15 -0600235 void ApplyImageBarrier(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope, SyncStageAccessFlags src_access_scope,
236 VkPipelineStageFlags dst_exec_scope, SyncStageAccessFlags dst_accesse_scope,
237 const VkImageSubresourceRange &subresource_range);
238
239 void ApplyImageBarrier(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope, SyncStageAccessFlags src_access_scope,
240 VkPipelineStageFlags dst_exec_scope, SyncStageAccessFlags dst_access_scope,
241 const VkImageSubresourceRange &subresource_range, bool layout_transition, const ResourceUsageTag &tag);
242 void ApplyImageBarrier(const IMAGE_STATE &image, const SyncBarrier &barrier, const VkImageSubresourceRange &subresource_range,
243 bool layout_transition, const ResourceUsageTag &tag);
244
John Zulauf540266b2020-04-06 18:54:53 -0600245 template <typename Action>
246 void UpdateMemoryAccess(const BUFFER_STATE &buffer, const ResourceAccessRange &range, const Action action);
247 template <typename Action>
248 void UpdateMemoryAccess(const IMAGE_STATE &image, const VkImageSubresourceRange &subresource_range, const Action action);
249
250 template <typename Action>
251 void ApplyGlobalBarriers(const Action &barrier_action);
252
John Zulauf16adfc92020-04-08 10:28:33 -0600253 static AddressType ImageAddressType(const IMAGE_STATE &image);
John Zulauf355e49b2020-04-24 15:11:15 -0600254 static VkDeviceSize ResourceBaseAddress(const BINDABLE &bindable);
John Zulauf16adfc92020-04-08 10:28:33 -0600255
John Zulauf540266b2020-04-06 18:54:53 -0600256 AccessContext(uint32_t subpass, VkQueueFlags queue_flags, const std::vector<SubpassDependencyGraphNode> &dependencies,
257 const std::vector<AccessContext> &contexts, AccessContext *external_context);
258
259 AccessContext() { Reset(); }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600260
John Zulauf16adfc92020-04-08 10:28:33 -0600261 ResourceAccessRangeMap &GetAccessStateMap(AddressType type) { return access_state_maps_[type]; }
262 const ResourceAccessRangeMap &GetAccessStateMap(AddressType type) const { return access_state_maps_[type]; }
263 ResourceAccessRangeMap &GetLinearMap() { return GetAccessStateMap(AddressType::kLinearAddress); }
264 const ResourceAccessRangeMap &GetLinearMap() const { return GetAccessStateMap(AddressType::kLinearAddress); }
265 ResourceAccessRangeMap &GetIdealizedMap() { return GetAccessStateMap(AddressType::kIdealizedAddress); }
266 const ResourceAccessRangeMap &GetIdealizedMap() const { return GetAccessStateMap(AddressType::kIdealizedAddress); }
John Zulauf355e49b2020-04-24 15:11:15 -0600267 const TrackBack *GetTrackBackFromSubpass(uint32_t subpass) const {
268 if (subpass == VK_SUBPASS_EXTERNAL) {
269 return &src_external_;
270 } else {
271 assert(subpass < prev_by_subpass_.size());
272 return prev_by_subpass_[subpass];
273 }
274 }
John Zulauf16adfc92020-04-08 10:28:33 -0600275
John Zulauf3d84f1b2020-03-09 13:33:25 -0600276 private:
John Zulauf355e49b2020-04-24 15:11:15 -0600277 HazardResult DetectHazard(AddressType type, SyncStageAccessIndex usage_index, const ResourceAccessRange &range) const;
278 HazardResult DetectBarrierHazard(AddressType type, SyncStageAccessIndex current_usage, VkPipelineStageFlags src_exec_scope,
279 SyncStageAccessFlags src_access_scope, const ResourceAccessRange &range,
280 DetectOptions options) const;
John Zulauf16adfc92020-04-08 10:28:33 -0600281
John Zulauf3d84f1b2020-03-09 13:33:25 -0600282 template <typename Detector>
John Zulauf355e49b2020-04-24 15:11:15 -0600283 HazardResult DetectHazard(AddressType type, const Detector &detector, const ResourceAccessRange &range,
284 DetectOptions options) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600285 template <typename Detector>
John Zulauf355e49b2020-04-24 15:11:15 -0600286 HazardResult DetectAsyncHazard(AddressType type, const Detector &detector, const ResourceAccessRange &range) const;
John Zulauf5f13a792020-03-10 07:31:21 -0600287 template <typename Detector>
John Zulauf355e49b2020-04-24 15:11:15 -0600288 HazardResult DetectPreviousHazard(AddressType type, const Detector &detector, const ResourceAccessRange &range) const;
John Zulauf16adfc92020-04-08 10:28:33 -0600289 void UpdateAccessState(AddressType type, SyncStageAccessIndex current_usage, const ResourceAccessRange &range,
290 const ResourceUsageTag &tag);
291 constexpr static int kAddressTypeCount = AddressType::kMaxAddressType + 1;
292 static const std::array<AddressType, kAddressTypeCount> kAddressTypes;
293 std::array<ResourceAccessRangeMap, kAddressTypeCount> access_state_maps_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600294 std::vector<TrackBack> prev_;
John Zulauf355e49b2020-04-24 15:11:15 -0600295 std::vector<TrackBack *> prev_by_subpass_;
John Zulauf540266b2020-04-06 18:54:53 -0600296 std::vector<AccessContext *> async_;
John Zulaufe5da6e52020-03-18 15:32:18 -0600297 TrackBack src_external_;
298 TrackBack dst_external_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600299};
300
John Zulauf355e49b2020-04-24 15:11:15 -0600301class RenderPassAccessContext {
302 public:
303 RenderPassAccessContext(AccessContext *external_context)
304 : external_context_(external_context), rp_state_(nullptr), current_subpass_(0) {}
305
306 bool ValidateNextSubpassLayoutTransitions(const SyncValidator &sync_state, const char *command_name) const;
307 bool ValidateFinalSubpassLayoutTransitions(const SyncValidator &sync_state, const char *func_name) const;
308
309 void RecordLayoutTransitions(const ResourceUsageTag &tag);
310 void RecordBeginRenderPass(const SyncValidator &state, const CMD_BUFFER_STATE &cb_state, VkQueueFlags queue_flags,
311 const ResourceUsageTag &tag);
312 void RecordNextSubpass(const ResourceUsageTag &tag);
313 void RecordEndRenderPass(const ResourceUsageTag &tag);
314
John Zulauf540266b2020-04-06 18:54:53 -0600315 AccessContext &CurrentContext() { return subpass_contexts_[current_subpass_]; }
316 const AccessContext &CurrentContext() const { return subpass_contexts_[current_subpass_]; }
John Zulauf355e49b2020-04-24 15:11:15 -0600317 const std::vector<AccessContext> &GetContexts() const { return subpass_contexts_; }
318 uint32_t GetCurrentSubpass() const { return current_subpass_; }
319 const RENDER_PASS_STATE *GetRenderPassState() const { return rp_state_; }
320
321 private:
322 AccessContext *external_context_;
323 const RENDER_PASS_STATE *rp_state_;
324 uint32_t current_subpass_;
325 std::vector<AccessContext> subpass_contexts_;
326 std::vector<const IMAGE_VIEW_STATE *> attachment_views_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600327};
328
329class CommandBufferAccessContext {
330 public:
331 CommandBufferAccessContext()
John Zulauf355e49b2020-04-24 15:11:15 -0600332 : command_number_(0),
333 reset_count_(0),
334 render_pass_contexts_(),
335 cb_access_context_(),
336 current_context_(&cb_access_context_),
John Zulauf3d84f1b2020-03-09 13:33:25 -0600337 current_renderpass_context_(),
338 cb_state_(),
339 queue_flags_() {}
John Zulauf355e49b2020-04-24 15:11:15 -0600340 CommandBufferAccessContext(SyncValidator &sync_validator, std::shared_ptr<CMD_BUFFER_STATE> &cb_state, VkQueueFlags queue_flags)
John Zulauf3d84f1b2020-03-09 13:33:25 -0600341 : CommandBufferAccessContext() {
342 cb_state_ = cb_state;
John Zulauf355e49b2020-04-24 15:11:15 -0600343 sync_state_ = &sync_validator;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600344 queue_flags_ = queue_flags;
345 }
John Zulauf5c5e88d2019-12-26 11:22:02 -0700346
347 void Reset() {
John Zulauf355e49b2020-04-24 15:11:15 -0600348 command_number_ = 0;
349 reset_count_++;
350 cb_access_context_.Reset();
John Zulauf3d84f1b2020-03-09 13:33:25 -0600351 render_pass_contexts_.clear();
John Zulauf355e49b2020-04-24 15:11:15 -0600352 current_context_ = &cb_access_context_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600353 current_renderpass_context_ = nullptr;
John Zulauf5c5e88d2019-12-26 11:22:02 -0700354 }
355
John Zulauf540266b2020-04-06 18:54:53 -0600356 AccessContext *GetCurrentAccessContext() { return current_context_; }
357 const AccessContext *GetCurrentAccessContext() const { return current_context_; }
John Zulauf355e49b2020-04-24 15:11:15 -0600358 void RecordBeginRenderPass(const ResourceUsageTag &tag);
359 bool ValidateBeginRenderPass(const RENDER_PASS_STATE &render_pass, const VkRenderPassBeginInfo *pRenderPassBegin,
360 const VkSubpassBeginInfoKHR *pSubpassBeginInfo, const char *func_name) const;
361 bool ValidateNextSubpass(const char *func_name) const;
362 bool ValidateEndRenderpass(const char *func_name) const;
363 void RecordNextSubpass(const RENDER_PASS_STATE &render_pass, const ResourceUsageTag &tag);
364 void RecordEndRenderPass(const RENDER_PASS_STATE &render_pass, const ResourceUsageTag &tag);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600365 CMD_BUFFER_STATE *GetCommandBufferState() { return cb_state_.get(); }
366 const CMD_BUFFER_STATE *GetCommandBufferState() const { return cb_state_.get(); }
367 VkQueueFlags GetQueueFlags() const { return queue_flags_; }
John Zulauf355e49b2020-04-24 15:11:15 -0600368 inline ResourceUsageTag NextCommandTag(CMD_TYPE command) {
369 // TODO: add command encoding to ResourceUsageTag.
370 // What else we what to include. Do we want some sort of "parent" or global sequence number
371 command_number_++;
372 ResourceUsageTag next;
373 next.index = (static_cast<uint64_t>(reset_count_) << 32) | command_number_;
374 return next;
375 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600376
377 private:
John Zulauf355e49b2020-04-24 15:11:15 -0600378 uint32_t command_number_;
379 uint32_t reset_count_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600380 std::vector<RenderPassAccessContext> render_pass_contexts_;
John Zulauf355e49b2020-04-24 15:11:15 -0600381 AccessContext cb_access_context_;
John Zulauf540266b2020-04-06 18:54:53 -0600382 AccessContext *current_context_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600383 RenderPassAccessContext *current_renderpass_context_;
384 std::shared_ptr<CMD_BUFFER_STATE> cb_state_;
John Zulauf355e49b2020-04-24 15:11:15 -0600385 SyncValidator *sync_state_;
386
John Zulauf3d84f1b2020-03-09 13:33:25 -0600387 VkQueueFlags queue_flags_;
John Zulauf9cb530d2019-09-30 14:14:10 -0600388};
389
390class SyncValidator : public ValidationStateTracker, public SyncStageAccess {
391 public:
392 SyncValidator() { container_type = LayerObjectTypeSyncValidation; }
393 using StateTracker = ValidationStateTracker;
394
395 using StateTracker::AccessorTraitsTypes;
John Zulauf5f13a792020-03-10 07:31:21 -0600396 ResourceUsageTag tag; // Find a better tagging scheme...
John Zulauf3d84f1b2020-03-09 13:33:25 -0600397 std::unordered_map<VkCommandBuffer, std::unique_ptr<CommandBufferAccessContext>> cb_access_state;
398 CommandBufferAccessContext *GetAccessContextImpl(VkCommandBuffer command_buffer, bool do_insert) {
John Zulauf9cb530d2019-09-30 14:14:10 -0600399 auto found_it = cb_access_state.find(command_buffer);
400 if (found_it == cb_access_state.end()) {
401 if (!do_insert) return nullptr;
402 // If we don't have one, make it.
John Zulauf3d84f1b2020-03-09 13:33:25 -0600403 auto cb_state = GetShared<CMD_BUFFER_STATE>(command_buffer);
404 assert(cb_state.get());
405 auto queue_flags = GetQueueFlags(*cb_state);
John Zulauf355e49b2020-04-24 15:11:15 -0600406 std::unique_ptr<CommandBufferAccessContext> context(new CommandBufferAccessContext(*this, cb_state, queue_flags));
John Zulauf3d84f1b2020-03-09 13:33:25 -0600407 auto insert_pair = cb_access_state.insert(std::make_pair(command_buffer, std::move(context)));
John Zulauf9cb530d2019-09-30 14:14:10 -0600408 found_it = insert_pair.first;
409 }
410 return found_it->second.get();
411 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600412 CommandBufferAccessContext *GetAccessContext(VkCommandBuffer command_buffer) {
413 return GetAccessContextImpl(command_buffer, true); // true -> do_insert on not found
John Zulauf9cb530d2019-09-30 14:14:10 -0600414 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600415 CommandBufferAccessContext *GetAccessContextNoInsert(VkCommandBuffer command_buffer) {
416 return GetAccessContextImpl(command_buffer, false); // false -> don't do_insert on not found
John Zulauf9cb530d2019-09-30 14:14:10 -0600417 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600418
419 const CommandBufferAccessContext *GetAccessContext(VkCommandBuffer command_buffer) const {
John Zulauf9cb530d2019-09-30 14:14:10 -0600420 const auto found_it = cb_access_state.find(command_buffer);
421 if (found_it == cb_access_state.end()) {
422 return nullptr;
423 }
424 return found_it->second.get();
425 }
426
John Zulauf540266b2020-04-06 18:54:53 -0600427 void ApplyGlobalBarriers(AccessContext *context, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
John Zulauf9cb530d2019-09-30 14:14:10 -0600428 SyncStageAccessFlags src_stage_scope, SyncStageAccessFlags dst_stage_scope,
429 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers);
John Zulauf540266b2020-04-06 18:54:53 -0600430 void ApplyBufferBarriers(AccessContext *context, VkPipelineStageFlags src_stage_mask, SyncStageAccessFlags src_stage_scope,
431 VkPipelineStageFlags dst_stage_mask, SyncStageAccessFlags dst_stage_scope, uint32_t barrier_count,
432 const VkBufferMemoryBarrier *barriers);
433 void ApplyImageBarriers(AccessContext *context, VkPipelineStageFlags src_stage_mask, SyncStageAccessFlags src_stage_scope,
434 VkPipelineStageFlags dst_stage_mask, SyncStageAccessFlags dst_stage_scope, uint32_t barrier_count,
John Zulauf355e49b2020-04-24 15:11:15 -0600435 const VkImageMemoryBarrier *barriers, const ResourceUsageTag &tag);
John Zulauf9cb530d2019-09-30 14:14:10 -0600436
John Zulaufd1f85d42020-04-15 12:23:15 -0600437 void ResetCommandBufferCallback(VkCommandBuffer command_buffer);
438 void FreeCommandBufferCallback(VkCommandBuffer command_buffer);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600439 void RecordCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
John Zulauf355e49b2020-04-24 15:11:15 -0600440 const VkSubpassBeginInfo *pSubpassBeginInfo, CMD_TYPE command);
441 void RecordCmdNextSubpass(VkCommandBuffer commandBuffer,
442
443 const VkSubpassBeginInfo *pSubpassBeginInfo, const VkSubpassEndInfo *pSubpassEndInfo,
444 CMD_TYPE command);
445 void RecordCmdEndRenderPass(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo, CMD_TYPE command);
John Zulauf9cb530d2019-09-30 14:14:10 -0600446
447 void PostCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
448 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result);
449
John Zulauf355e49b2020-04-24 15:11:15 -0600450 bool ValidateBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
451 const VkSubpassBeginInfoKHR *pSubpassBeginInfo, const char *func_name) const;
452
453 bool PreCallValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
454 VkSubpassContents contents) const;
455
456 bool PreCallValidateCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
457 const VkSubpassBeginInfoKHR *pSubpassBeginInfo) const;
458
459 bool PreCallValidateCmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
460 const VkSubpassBeginInfoKHR *pSubpassBeginInfo) const;
461
John Zulauf9cb530d2019-09-30 14:14:10 -0600462 bool PreCallValidateCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount,
463 const VkBufferCopy *pRegions) const;
464
465 void PreCallRecordCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount,
466 const VkBufferCopy *pRegions);
467
John Zulauf5c5e88d2019-12-26 11:22:02 -0700468 bool PreCallValidateCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
469 VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
470 const VkImageCopy *pRegions) const;
471
472 void PreCallRecordCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
473 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions);
474
John Zulauf9cb530d2019-09-30 14:14:10 -0600475 bool PreCallValidateCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
476 VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
477 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
478 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
479 uint32_t imageMemoryBarrierCount,
480 const VkImageMemoryBarrier *pImageMemoryBarriers) const;
481
482 void PreCallRecordCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
483 VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
484 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
485 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
486 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600487
488 void PostCallRecordBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo,
489 VkResult result);
490
491 void PostCallRecordCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
492 VkSubpassContents contents);
493 void PostCallRecordCmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
494 const VkSubpassBeginInfo *pSubpassBeginInfo);
495 void PostCallRecordCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
496 const VkSubpassBeginInfo *pSubpassBeginInfo);
497
John Zulauf355e49b2020-04-24 15:11:15 -0600498 bool ValidateCmdNextSubpass(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
499 const VkSubpassEndInfoKHR *pSubpassEndInfo, const char *func_name) const;
500 bool PreCallValidateCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) const;
501 bool PreCallValidateCmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
502 const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
503 bool PreCallValidateCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
504 const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
505
John Zulauf3d84f1b2020-03-09 13:33:25 -0600506 void PostCallRecordCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
507 void PostCallRecordCmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
508 const VkSubpassEndInfo *pSubpassEndInfo);
509 void PostCallRecordCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
510 const VkSubpassEndInfo *pSubpassEndInfo);
511
John Zulauf355e49b2020-04-24 15:11:15 -0600512 bool ValidateCmdEndRenderPass(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo,
513 const char *func_name) const;
514 bool PreCallValidateCmdEndRenderPass(VkCommandBuffer commandBuffer) const;
515 bool PreCallValidateCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
516 bool PreCallValidateCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
517
John Zulauf3d84f1b2020-03-09 13:33:25 -0600518 void PostCallRecordCmdEndRenderPass(VkCommandBuffer commandBuffer);
519 void PostCallRecordCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo);
520 void PostCallRecordCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo);
locke-lunarga19c71d2020-03-02 18:17:04 -0700521 bool PreCallValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
522 VkImageLayout dstImageLayout, uint32_t regionCount,
523 const VkBufferImageCopy *pRegions) const;
524
525 void PreCallRecordCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
526 VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *pRegions);
527
528 bool PreCallValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
529 VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) const;
530
531 void PreCallRecordCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
532 VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions);
533
534 bool PreCallValidateCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
535 VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
536 const VkImageBlit *pRegions, VkFilter filter) const;
537
538 void PreCallRecordCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
539 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions,
540 VkFilter filter);
John Zulauf9cb530d2019-09-30 14:14:10 -0600541};