blob: e6d04ca0edead56a6b463927fbd824238e329a2d [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 {
John Zulauf1507ee42020-05-18 11:33:09 -060044 static inline SyncStageAccessFlagBits FlagBit(SyncStageAccessIndex stage_access) {
John Zulauf9cb530d2019-09-30 14:14:10 -060045 return syncStageAccessInfoByStageAccessIndex[stage_access].stage_access_bit;
46 }
John Zulauf1507ee42020-05-18 11:33:09 -060047 static inline SyncStageAccessFlags Flags(SyncStageAccessIndex stage_access) {
48 return static_cast<SyncStageAccessFlags>(FlagBit(stage_access));
49 }
John Zulauf9cb530d2019-09-30 14:14:10 -060050
51 static bool IsRead(SyncStageAccessFlagBits stage_access_bit) { return 0 != (stage_access_bit & syncStageAccessReadMask); }
52 static bool IsRead(SyncStageAccessIndex stage_access_index) { return IsRead(FlagBit(stage_access_index)); }
53
54 static bool IsWrite(SyncStageAccessFlagBits stage_access_bit) { return 0 != (stage_access_bit & syncStageAccessWriteMask); }
John Zulauf1507ee42020-05-18 11:33:09 -060055 static bool HasWrite(SyncStageAccessFlags stage_access_mask) { return 0 != (stage_access_mask & syncStageAccessWriteMask); }
John Zulauf9cb530d2019-09-30 14:14:10 -060056 static bool IsWrite(SyncStageAccessIndex stage_access_index) { return IsWrite(FlagBit(stage_access_index)); }
57 static VkPipelineStageFlagBits PipelineStageBit(SyncStageAccessIndex stage_access_index) {
58 return syncStageAccessInfoByStageAccessIndex[stage_access_index].stage_mask;
59 }
60 static SyncStageAccessFlags AccessScopeByStage(VkPipelineStageFlags stages);
61 static SyncStageAccessFlags AccessScopeByAccess(VkAccessFlags access);
62 static SyncStageAccessFlags AccessScope(VkPipelineStageFlags stages, VkAccessFlags access);
63 static SyncStageAccessFlags AccessScope(SyncStageAccessFlags stage_scope, VkAccessFlags accesses) {
64 return stage_scope & AccessScopeByAccess(accesses);
65 }
66};
67
John Zulauf5f13a792020-03-10 07:31:21 -060068struct ResourceUsageTag {
69 uint64_t index;
70 ResourceUsageTag &operator++() {
71 index++;
72 return *this;
73 }
74 bool IsBefore(const ResourceUsageTag &rhs) const { return index < rhs.index; }
John Zulaufe5da6e52020-03-18 15:32:18 -060075 bool operator==(const ResourceUsageTag &rhs) const { return (index == rhs.index); }
76 bool operator!=(const ResourceUsageTag &rhs) const { return !(*this == rhs); }
John Zulauf355e49b2020-04-24 15:11:15 -060077 ResourceUsageTag() : index(0) {}
John Zulauf5f13a792020-03-10 07:31:21 -060078};
79
John Zulauf9cb530d2019-09-30 14:14:10 -060080struct HazardResult {
81 SyncHazard hazard = NONE;
82 ResourceUsageTag tag = ResourceUsageTag();
83 void Set(SyncHazard hazard_, const ResourceUsageTag &tag_) {
84 hazard = hazard_;
85 tag = tag_;
86 }
87};
88
John Zulauf3d84f1b2020-03-09 13:33:25 -060089struct SyncBarrier {
90 VkPipelineStageFlags src_exec_scope;
91 SyncStageAccessFlags src_access_scope;
92 VkPipelineStageFlags dst_exec_scope;
93 SyncStageAccessFlags dst_access_scope;
94 SyncBarrier() = default;
95 SyncBarrier &operator=(const SyncBarrier &) = default;
96 SyncBarrier(VkQueueFlags gueue_flags, const VkSubpassDependency2 &sub_pass_barrier);
97};
98using SyncBarrierStack = std::vector<const SyncBarrier *>;
99
John Zulauf9cb530d2019-09-30 14:14:10 -0600100class ResourceAccessState : public SyncStageAccess {
101 protected:
102 // Mutliple read operations can be simlutaneously (and independently) synchronized,
103 // given the only the second execution scope creates a dependency chain, we have to track each,
104 // but only up to one per pipeline stage (as another read from the *same* stage become more recent,
105 // and applicable one for hazard detection
106 struct ReadState {
107 VkPipelineStageFlagBits stage; // The stage of this read
108 VkPipelineStageFlags barriers; // all applicable barriered stages
109 ResourceUsageTag tag;
John Zulaufe5da6e52020-03-18 15:32:18 -0600110 bool operator==(const ReadState &rhs) const {
111 bool same = (stage == rhs.stage) && (barriers == rhs.barriers) && (tag == rhs.tag);
112 return same;
113 }
114 bool operator!=(const ReadState &rhs) const { return !(*this == rhs); }
John Zulauf9cb530d2019-09-30 14:14:10 -0600115 };
116
117 public:
118 HazardResult DetectHazard(SyncStageAccessIndex usage_index) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600119
John Zulaufc9201222020-05-13 15:13:03 -0600120 HazardResult DetectBarrierHazard(SyncStageAccessIndex usage_index, VkPipelineStageFlags source_exec_scope,
121 SyncStageAccessFlags source_access_scope) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600122 HazardResult DetectAsyncHazard(SyncStageAccessIndex usage_index) const;
123
John Zulauf9cb530d2019-09-30 14:14:10 -0600124 void Update(SyncStageAccessIndex usage_index, const ResourceUsageTag &tag);
John Zulauf5f13a792020-03-10 07:31:21 -0600125 void Resolve(const ResourceAccessState &other);
126 void ApplyBarrier(const SyncBarrier &barrier);
John Zulauf9cb530d2019-09-30 14:14:10 -0600127 void ApplyExecutionBarrier(VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask);
128 void ApplyMemoryAccessBarrier(VkPipelineStageFlags src_stage_mask, SyncStageAccessFlags src_scope,
129 VkPipelineStageFlags dst_stage_mask, SyncStageAccessFlags dst_scope);
130
131 ResourceAccessState()
John Zulauf355e49b2020-04-24 15:11:15 -0600132 : write_barriers(~SyncStageAccessFlags(0)),
133 write_dependency_chain(0),
134 last_read_count(0),
135 last_read_stages(0),
136 write_tag(),
137 last_write(0) {}
John Zulauf9cb530d2019-09-30 14:14:10 -0600138
John Zulauf3d84f1b2020-03-09 13:33:25 -0600139 bool HasWriteOp() const { return last_write != 0; }
John Zulaufe5da6e52020-03-18 15:32:18 -0600140 bool operator==(const ResourceAccessState &rhs) const {
141 bool same = (write_barriers == rhs.write_barriers) && (write_dependency_chain == rhs.write_dependency_chain) &&
142 (last_read_count == rhs.last_read_count) && (last_read_stages == rhs.last_read_stages) &&
143 (write_tag == rhs.write_tag);
144 for (uint32_t i = 0; same && i < last_read_count; i++) {
145 same |= last_reads[i] == rhs.last_reads[i];
146 }
147 return same;
148 }
149 bool operator!=(const ResourceAccessState &rhs) const { return !(*this == rhs); }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600150
John Zulauf9cb530d2019-09-30 14:14:10 -0600151 private:
152 bool IsWriteHazard(SyncStageAccessFlagBits usage) const { return 0 != (usage & ~write_barriers); }
153 bool IsReadHazard(VkPipelineStageFlagBits stage, const ReadState &read_access) const {
154 return 0 != (stage & ~read_access.barriers);
155 }
John Zulauf0cb5be22020-01-23 12:18:22 -0700156 bool IsReadHazard(VkPipelineStageFlags stage_mask, const ReadState &read_access) const {
157 return stage_mask != (stage_mask & read_access.barriers);
158 }
John Zulauf9cb530d2019-09-30 14:14:10 -0600159 // With reads, each must be "safe" relative to it's prior write, so we need only
160 // save the most recent write operation (as anything *transitively* unsafe would arleady
161 // be included
162 SyncStageAccessFlags write_barriers; // union of applicable barrier masks since last write
163 VkPipelineStageFlags write_dependency_chain; // intiially zero, but accumulating the dstStages of barriers if they chain.
164 uint32_t last_read_count;
165 VkPipelineStageFlags last_read_stages;
166
167 ResourceUsageTag write_tag;
John Zulauf355e49b2020-04-24 15:11:15 -0600168 // TODO: Add a NONE (zero) enum to SyncStageAccessFlagBits
169 SyncStageAccessFlags last_write; // only the most recent write
John Zulauf9cb530d2019-09-30 14:14:10 -0600170
171 std::array<ReadState, 8 * sizeof(VkPipelineStageFlags)> last_reads;
John Zulauf9cb530d2019-09-30 14:14:10 -0600172};
173
John Zulauf16adfc92020-04-08 10:28:33 -0600174using ResourceAccessRangeMap = sparse_container::range_map<VkDeviceSize, ResourceAccessState>;
John Zulauf5c5e88d2019-12-26 11:22:02 -0700175using ResourceAccessRange = typename ResourceAccessRangeMap::key_type;
John Zulauf355e49b2020-04-24 15:11:15 -0600176using ResourceRangeMergeIterator = sparse_container::parallel_iterator<ResourceAccessRangeMap, const ResourceAccessRangeMap>;
John Zulauf9cb530d2019-09-30 14:14:10 -0600177
John Zulauf540266b2020-04-06 18:54:53 -0600178class AccessContext {
John Zulauf5c5e88d2019-12-26 11:22:02 -0700179 public:
John Zulauf355e49b2020-04-24 15:11:15 -0600180 enum AddressType : int { kLinearAddress = 0, kIdealizedAddress = 1, kMaxAddressType = 1 };
181 enum DetectOptions : unsigned int {
182 kDetectPrevious = 1U << 0,
183 kDetectAsync = 1U << 1,
184 kDetectAll = (kDetectPrevious | kDetectAsync)
John Zulauf16adfc92020-04-08 10:28:33 -0600185 };
186
John Zulauf3d84f1b2020-03-09 13:33:25 -0600187 struct TrackBack {
188 SyncBarrier barrier;
John Zulauf540266b2020-04-06 18:54:53 -0600189 AccessContext *context;
190 TrackBack(AccessContext *context_, VkQueueFlags queue_flags_, const VkSubpassDependency2 &subpass_barrier_)
John Zulauf3d84f1b2020-03-09 13:33:25 -0600191 : barrier(queue_flags_, subpass_barrier_), context(context_) {}
192 TrackBack &operator=(const TrackBack &) = default;
193 TrackBack() = default;
194 };
John Zulauf5c5e88d2019-12-26 11:22:02 -0700195
John Zulauf355e49b2020-04-24 15:11:15 -0600196 HazardResult DetectHazard(const BUFFER_STATE &buffer, SyncStageAccessIndex usage_index, const ResourceAccessRange &range) const;
John Zulauf540266b2020-04-06 18:54:53 -0600197 HazardResult DetectHazard(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
John Zulauf3d84f1b2020-03-09 13:33:25 -0600198 const VkImageSubresourceLayers &subresource, const VkOffset3D &offset,
199 const VkExtent3D &extent) const;
John Zulauf1507ee42020-05-18 11:33:09 -0600200 HazardResult DetectHazard(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
201 const VkImageSubresourceRange &subresource_range, const VkOffset3D &offset,
202 const VkExtent3D &extent) const;
John Zulauf355e49b2020-04-24 15:11:15 -0600203 HazardResult DetectImageBarrierHazard(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope,
204 SyncStageAccessFlags src_access_scope, const VkImageSubresourceRange &subresource_range,
205 DetectOptions options) const;
206 HazardResult DetectImageBarrierHazard(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope,
207 SyncStageAccessFlags src_stage_accesses, const VkImageMemoryBarrier &barrier) const;
208 HazardResult DetectSubpassTransitionHazard(const RENDER_PASS_STATE::AttachmentTransition &transitions,
209 const std::vector<const IMAGE_VIEW_STATE *> &attachments) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600210
John Zulaufe5da6e52020-03-18 15:32:18 -0600211 const TrackBack &GetDstExternalTrackBack() const { return dst_external_; }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600212 void Reset() {
John Zulauf3d84f1b2020-03-09 13:33:25 -0600213 prev_.clear();
John Zulauf355e49b2020-04-24 15:11:15 -0600214 prev_by_subpass_.clear();
John Zulauf3d84f1b2020-03-09 13:33:25 -0600215 async_.clear();
John Zulaufe5da6e52020-03-18 15:32:18 -0600216 src_external_ = TrackBack();
John Zulauf16adfc92020-04-08 10:28:33 -0600217 for (auto &map : access_state_maps_) {
218 map.clear();
219 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600220 }
John Zulauf5f13a792020-03-10 07:31:21 -0600221 // TODO: See if returning the lower_bound would be useful from a performance POV -- look at the lower_bound overhead
222 // Would need to add a "hint" overload to parallel_iterator::invalidate_[AB] call, if so.
John Zulauf355e49b2020-04-24 15:11:15 -0600223 void ResolvePreviousAccess(AddressType type, const ResourceAccessRange &range, ResourceAccessRangeMap *descent_map,
224 const ResourceAccessState *infill_state) const;
John Zulauf540266b2020-04-06 18:54:53 -0600225 void ResolvePreviousAccess(const IMAGE_STATE &image_state, const VkImageSubresourceRange &subresource_range,
John Zulauf355e49b2020-04-24 15:11:15 -0600226 AddressType address_type, ResourceAccessRangeMap *descent_map,
227 const ResourceAccessState *infill_state) const;
228 void ResolveAccessRange(AddressType type, const ResourceAccessRange &range, const SyncBarrier *barrier,
229 ResourceAccessRangeMap *resolve_map, const ResourceAccessState *infill_state,
230 bool recur_to_infill = true) const;
231 void UpdateAccessState(const BUFFER_STATE &buffer, SyncStageAccessIndex current_usage, const ResourceAccessRange &range,
232 const ResourceUsageTag &tag);
233 void UpdateAccessState(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
234 const VkImageSubresourceRange &subresource_range, const VkOffset3D &offset, const VkExtent3D &extent,
235 const ResourceUsageTag &tag);
John Zulauf540266b2020-04-06 18:54:53 -0600236 void UpdateAccessState(const IMAGE_STATE &image, SyncStageAccessIndex current_usage,
John Zulauf3d84f1b2020-03-09 13:33:25 -0600237 const VkImageSubresourceLayers &subresource, const VkOffset3D &offset, const VkExtent3D &extent,
238 const ResourceUsageTag &tag);
239
John Zulauf540266b2020-04-06 18:54:53 -0600240 void ResolveChildContexts(const std::vector<AccessContext> &contexts);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600241
John Zulauf355e49b2020-04-24 15:11:15 -0600242 void ApplyImageBarrier(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope, SyncStageAccessFlags src_access_scope,
243 VkPipelineStageFlags dst_exec_scope, SyncStageAccessFlags dst_accesse_scope,
244 const VkImageSubresourceRange &subresource_range);
245
246 void ApplyImageBarrier(const IMAGE_STATE &image, VkPipelineStageFlags src_exec_scope, SyncStageAccessFlags src_access_scope,
247 VkPipelineStageFlags dst_exec_scope, SyncStageAccessFlags dst_access_scope,
248 const VkImageSubresourceRange &subresource_range, bool layout_transition, const ResourceUsageTag &tag);
249 void ApplyImageBarrier(const IMAGE_STATE &image, const SyncBarrier &barrier, const VkImageSubresourceRange &subresource_range,
250 bool layout_transition, const ResourceUsageTag &tag);
251
John Zulauf540266b2020-04-06 18:54:53 -0600252 template <typename Action>
253 void UpdateMemoryAccess(const BUFFER_STATE &buffer, const ResourceAccessRange &range, const Action action);
254 template <typename Action>
255 void UpdateMemoryAccess(const IMAGE_STATE &image, const VkImageSubresourceRange &subresource_range, const Action action);
256
257 template <typename Action>
258 void ApplyGlobalBarriers(const Action &barrier_action);
259
John Zulauf16adfc92020-04-08 10:28:33 -0600260 static AddressType ImageAddressType(const IMAGE_STATE &image);
John Zulauf355e49b2020-04-24 15:11:15 -0600261 static VkDeviceSize ResourceBaseAddress(const BINDABLE &bindable);
John Zulauf16adfc92020-04-08 10:28:33 -0600262
John Zulauf540266b2020-04-06 18:54:53 -0600263 AccessContext(uint32_t subpass, VkQueueFlags queue_flags, const std::vector<SubpassDependencyGraphNode> &dependencies,
264 const std::vector<AccessContext> &contexts, AccessContext *external_context);
265
266 AccessContext() { Reset(); }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600267
John Zulauf16adfc92020-04-08 10:28:33 -0600268 ResourceAccessRangeMap &GetAccessStateMap(AddressType type) { return access_state_maps_[type]; }
269 const ResourceAccessRangeMap &GetAccessStateMap(AddressType type) const { return access_state_maps_[type]; }
270 ResourceAccessRangeMap &GetLinearMap() { return GetAccessStateMap(AddressType::kLinearAddress); }
271 const ResourceAccessRangeMap &GetLinearMap() const { return GetAccessStateMap(AddressType::kLinearAddress); }
272 ResourceAccessRangeMap &GetIdealizedMap() { return GetAccessStateMap(AddressType::kIdealizedAddress); }
273 const ResourceAccessRangeMap &GetIdealizedMap() const { return GetAccessStateMap(AddressType::kIdealizedAddress); }
John Zulauf355e49b2020-04-24 15:11:15 -0600274 const TrackBack *GetTrackBackFromSubpass(uint32_t subpass) const {
275 if (subpass == VK_SUBPASS_EXTERNAL) {
276 return &src_external_;
277 } else {
278 assert(subpass < prev_by_subpass_.size());
279 return prev_by_subpass_[subpass];
280 }
281 }
John Zulauf16adfc92020-04-08 10:28:33 -0600282
John Zulauf1507ee42020-05-18 11:33:09 -0600283 bool ValidateLayoutTransitions(const SyncValidator &sync_state, const RENDER_PASS_STATE &rp_state,
284 const std::vector<const IMAGE_VIEW_STATE *> &attachment_views, const char *func_name,
285 uint32_t subpass) const;
286 bool ValidateLoadOperation(const SyncValidator &sync_state, const RENDER_PASS_STATE &rp_state, const VkRect2D &render_area,
287 const std::vector<const IMAGE_VIEW_STATE *> &attachment_views, const char *func_name,
288 uint32_t subpass) const;
289
John Zulauf3d84f1b2020-03-09 13:33:25 -0600290 private:
John Zulauf355e49b2020-04-24 15:11:15 -0600291 HazardResult DetectHazard(AddressType type, SyncStageAccessIndex usage_index, const ResourceAccessRange &range) const;
292 HazardResult DetectBarrierHazard(AddressType type, SyncStageAccessIndex current_usage, VkPipelineStageFlags src_exec_scope,
293 SyncStageAccessFlags src_access_scope, const ResourceAccessRange &range,
294 DetectOptions options) const;
John Zulauf16adfc92020-04-08 10:28:33 -0600295
John Zulauf3d84f1b2020-03-09 13:33:25 -0600296 template <typename Detector>
John Zulauf355e49b2020-04-24 15:11:15 -0600297 HazardResult DetectHazard(AddressType type, const Detector &detector, const ResourceAccessRange &range,
298 DetectOptions options) const;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600299 template <typename Detector>
John Zulauf355e49b2020-04-24 15:11:15 -0600300 HazardResult DetectAsyncHazard(AddressType type, const Detector &detector, const ResourceAccessRange &range) const;
John Zulauf5f13a792020-03-10 07:31:21 -0600301 template <typename Detector>
John Zulauf355e49b2020-04-24 15:11:15 -0600302 HazardResult DetectPreviousHazard(AddressType type, const Detector &detector, const ResourceAccessRange &range) const;
John Zulauf16adfc92020-04-08 10:28:33 -0600303 void UpdateAccessState(AddressType type, SyncStageAccessIndex current_usage, const ResourceAccessRange &range,
304 const ResourceUsageTag &tag);
305 constexpr static int kAddressTypeCount = AddressType::kMaxAddressType + 1;
306 static const std::array<AddressType, kAddressTypeCount> kAddressTypes;
307 std::array<ResourceAccessRangeMap, kAddressTypeCount> access_state_maps_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600308 std::vector<TrackBack> prev_;
John Zulauf355e49b2020-04-24 15:11:15 -0600309 std::vector<TrackBack *> prev_by_subpass_;
John Zulauf540266b2020-04-06 18:54:53 -0600310 std::vector<AccessContext *> async_;
John Zulaufe5da6e52020-03-18 15:32:18 -0600311 TrackBack src_external_;
312 TrackBack dst_external_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600313};
314
John Zulauf355e49b2020-04-24 15:11:15 -0600315class RenderPassAccessContext {
316 public:
317 RenderPassAccessContext(AccessContext *external_context)
318 : external_context_(external_context), rp_state_(nullptr), current_subpass_(0) {}
319
John Zulauf1507ee42020-05-18 11:33:09 -0600320 bool ValidateNextSubpass(const SyncValidator &sync_state, const VkRect2D &render_area, const char *command_name) const;
John Zulauf355e49b2020-04-24 15:11:15 -0600321 bool ValidateFinalSubpassLayoutTransitions(const SyncValidator &sync_state, const char *func_name) const;
322
323 void RecordLayoutTransitions(const ResourceUsageTag &tag);
John Zulauf1507ee42020-05-18 11:33:09 -0600324 void RecordLoadOperations(const VkRect2D &render_area, const ResourceUsageTag &tag);
John Zulauf355e49b2020-04-24 15:11:15 -0600325 void RecordBeginRenderPass(const SyncValidator &state, const CMD_BUFFER_STATE &cb_state, VkQueueFlags queue_flags,
326 const ResourceUsageTag &tag);
John Zulauf1507ee42020-05-18 11:33:09 -0600327 void RecordNextSubpass(const VkRect2D &render_area, const ResourceUsageTag &tag);
John Zulauf355e49b2020-04-24 15:11:15 -0600328 void RecordEndRenderPass(const ResourceUsageTag &tag);
329
John Zulauf540266b2020-04-06 18:54:53 -0600330 AccessContext &CurrentContext() { return subpass_contexts_[current_subpass_]; }
331 const AccessContext &CurrentContext() const { return subpass_contexts_[current_subpass_]; }
John Zulauf355e49b2020-04-24 15:11:15 -0600332 const std::vector<AccessContext> &GetContexts() const { return subpass_contexts_; }
333 uint32_t GetCurrentSubpass() const { return current_subpass_; }
334 const RENDER_PASS_STATE *GetRenderPassState() const { return rp_state_; }
335
336 private:
337 AccessContext *external_context_;
338 const RENDER_PASS_STATE *rp_state_;
339 uint32_t current_subpass_;
340 std::vector<AccessContext> subpass_contexts_;
341 std::vector<const IMAGE_VIEW_STATE *> attachment_views_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600342};
343
344class CommandBufferAccessContext {
345 public:
346 CommandBufferAccessContext()
John Zulauf355e49b2020-04-24 15:11:15 -0600347 : command_number_(0),
348 reset_count_(0),
349 render_pass_contexts_(),
350 cb_access_context_(),
351 current_context_(&cb_access_context_),
John Zulauf3d84f1b2020-03-09 13:33:25 -0600352 current_renderpass_context_(),
353 cb_state_(),
354 queue_flags_() {}
John Zulauf355e49b2020-04-24 15:11:15 -0600355 CommandBufferAccessContext(SyncValidator &sync_validator, std::shared_ptr<CMD_BUFFER_STATE> &cb_state, VkQueueFlags queue_flags)
John Zulauf3d84f1b2020-03-09 13:33:25 -0600356 : CommandBufferAccessContext() {
357 cb_state_ = cb_state;
John Zulauf355e49b2020-04-24 15:11:15 -0600358 sync_state_ = &sync_validator;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600359 queue_flags_ = queue_flags;
360 }
John Zulauf5c5e88d2019-12-26 11:22:02 -0700361
362 void Reset() {
John Zulauf355e49b2020-04-24 15:11:15 -0600363 command_number_ = 0;
364 reset_count_++;
365 cb_access_context_.Reset();
John Zulauf3d84f1b2020-03-09 13:33:25 -0600366 render_pass_contexts_.clear();
John Zulauf355e49b2020-04-24 15:11:15 -0600367 current_context_ = &cb_access_context_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600368 current_renderpass_context_ = nullptr;
John Zulauf5c5e88d2019-12-26 11:22:02 -0700369 }
370
John Zulauf540266b2020-04-06 18:54:53 -0600371 AccessContext *GetCurrentAccessContext() { return current_context_; }
372 const AccessContext *GetCurrentAccessContext() const { return current_context_; }
John Zulauf355e49b2020-04-24 15:11:15 -0600373 void RecordBeginRenderPass(const ResourceUsageTag &tag);
374 bool ValidateBeginRenderPass(const RENDER_PASS_STATE &render_pass, const VkRenderPassBeginInfo *pRenderPassBegin,
375 const VkSubpassBeginInfoKHR *pSubpassBeginInfo, const char *func_name) const;
376 bool ValidateNextSubpass(const char *func_name) const;
377 bool ValidateEndRenderpass(const char *func_name) const;
378 void RecordNextSubpass(const RENDER_PASS_STATE &render_pass, const ResourceUsageTag &tag);
379 void RecordEndRenderPass(const RENDER_PASS_STATE &render_pass, const ResourceUsageTag &tag);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600380 CMD_BUFFER_STATE *GetCommandBufferState() { return cb_state_.get(); }
381 const CMD_BUFFER_STATE *GetCommandBufferState() const { return cb_state_.get(); }
382 VkQueueFlags GetQueueFlags() const { return queue_flags_; }
John Zulauf355e49b2020-04-24 15:11:15 -0600383 inline ResourceUsageTag NextCommandTag(CMD_TYPE command) {
384 // TODO: add command encoding to ResourceUsageTag.
385 // What else we what to include. Do we want some sort of "parent" or global sequence number
386 command_number_++;
387 ResourceUsageTag next;
388 next.index = (static_cast<uint64_t>(reset_count_) << 32) | command_number_;
389 return next;
390 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600391
392 private:
John Zulauf355e49b2020-04-24 15:11:15 -0600393 uint32_t command_number_;
394 uint32_t reset_count_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600395 std::vector<RenderPassAccessContext> render_pass_contexts_;
John Zulauf355e49b2020-04-24 15:11:15 -0600396 AccessContext cb_access_context_;
John Zulauf540266b2020-04-06 18:54:53 -0600397 AccessContext *current_context_;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600398 RenderPassAccessContext *current_renderpass_context_;
399 std::shared_ptr<CMD_BUFFER_STATE> cb_state_;
John Zulauf355e49b2020-04-24 15:11:15 -0600400 SyncValidator *sync_state_;
401
John Zulauf3d84f1b2020-03-09 13:33:25 -0600402 VkQueueFlags queue_flags_;
John Zulauf9cb530d2019-09-30 14:14:10 -0600403};
404
405class SyncValidator : public ValidationStateTracker, public SyncStageAccess {
406 public:
407 SyncValidator() { container_type = LayerObjectTypeSyncValidation; }
408 using StateTracker = ValidationStateTracker;
409
410 using StateTracker::AccessorTraitsTypes;
John Zulauf3d84f1b2020-03-09 13:33:25 -0600411 std::unordered_map<VkCommandBuffer, std::unique_ptr<CommandBufferAccessContext>> cb_access_state;
412 CommandBufferAccessContext *GetAccessContextImpl(VkCommandBuffer command_buffer, bool do_insert) {
John Zulauf9cb530d2019-09-30 14:14:10 -0600413 auto found_it = cb_access_state.find(command_buffer);
414 if (found_it == cb_access_state.end()) {
415 if (!do_insert) return nullptr;
416 // If we don't have one, make it.
John Zulauf3d84f1b2020-03-09 13:33:25 -0600417 auto cb_state = GetShared<CMD_BUFFER_STATE>(command_buffer);
418 assert(cb_state.get());
419 auto queue_flags = GetQueueFlags(*cb_state);
John Zulauf355e49b2020-04-24 15:11:15 -0600420 std::unique_ptr<CommandBufferAccessContext> context(new CommandBufferAccessContext(*this, cb_state, queue_flags));
John Zulauf3d84f1b2020-03-09 13:33:25 -0600421 auto insert_pair = cb_access_state.insert(std::make_pair(command_buffer, std::move(context)));
John Zulauf9cb530d2019-09-30 14:14:10 -0600422 found_it = insert_pair.first;
423 }
424 return found_it->second.get();
425 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600426 CommandBufferAccessContext *GetAccessContext(VkCommandBuffer command_buffer) {
427 return GetAccessContextImpl(command_buffer, true); // true -> do_insert on not found
John Zulauf9cb530d2019-09-30 14:14:10 -0600428 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600429 CommandBufferAccessContext *GetAccessContextNoInsert(VkCommandBuffer command_buffer) {
430 return GetAccessContextImpl(command_buffer, false); // false -> don't do_insert on not found
John Zulauf9cb530d2019-09-30 14:14:10 -0600431 }
John Zulauf3d84f1b2020-03-09 13:33:25 -0600432
433 const CommandBufferAccessContext *GetAccessContext(VkCommandBuffer command_buffer) const {
John Zulauf9cb530d2019-09-30 14:14:10 -0600434 const auto found_it = cb_access_state.find(command_buffer);
435 if (found_it == cb_access_state.end()) {
436 return nullptr;
437 }
438 return found_it->second.get();
439 }
440
John Zulauf540266b2020-04-06 18:54:53 -0600441 void ApplyGlobalBarriers(AccessContext *context, VkPipelineStageFlags srcStageMask, VkPipelineStageFlags dstStageMask,
John Zulauf9cb530d2019-09-30 14:14:10 -0600442 SyncStageAccessFlags src_stage_scope, SyncStageAccessFlags dst_stage_scope,
443 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers);
John Zulauf540266b2020-04-06 18:54:53 -0600444 void ApplyBufferBarriers(AccessContext *context, VkPipelineStageFlags src_stage_mask, SyncStageAccessFlags src_stage_scope,
445 VkPipelineStageFlags dst_stage_mask, SyncStageAccessFlags dst_stage_scope, uint32_t barrier_count,
446 const VkBufferMemoryBarrier *barriers);
447 void ApplyImageBarriers(AccessContext *context, VkPipelineStageFlags src_stage_mask, SyncStageAccessFlags src_stage_scope,
448 VkPipelineStageFlags dst_stage_mask, SyncStageAccessFlags dst_stage_scope, uint32_t barrier_count,
John Zulauf355e49b2020-04-24 15:11:15 -0600449 const VkImageMemoryBarrier *barriers, const ResourceUsageTag &tag);
John Zulauf9cb530d2019-09-30 14:14:10 -0600450
John Zulaufd1f85d42020-04-15 12:23:15 -0600451 void ResetCommandBufferCallback(VkCommandBuffer command_buffer);
452 void FreeCommandBufferCallback(VkCommandBuffer command_buffer);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600453 void RecordCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
John Zulauf355e49b2020-04-24 15:11:15 -0600454 const VkSubpassBeginInfo *pSubpassBeginInfo, CMD_TYPE command);
455 void RecordCmdNextSubpass(VkCommandBuffer commandBuffer,
456
457 const VkSubpassBeginInfo *pSubpassBeginInfo, const VkSubpassEndInfo *pSubpassEndInfo,
458 CMD_TYPE command);
459 void RecordCmdEndRenderPass(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo, CMD_TYPE command);
John Zulauf9cb530d2019-09-30 14:14:10 -0600460
461 void PostCallRecordCreateDevice(VkPhysicalDevice gpu, const VkDeviceCreateInfo *pCreateInfo,
462 const VkAllocationCallbacks *pAllocator, VkDevice *pDevice, VkResult result);
463
John Zulauf355e49b2020-04-24 15:11:15 -0600464 bool ValidateBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
465 const VkSubpassBeginInfoKHR *pSubpassBeginInfo, const char *func_name) const;
466
467 bool PreCallValidateCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
468 VkSubpassContents contents) const;
469
470 bool PreCallValidateCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
471 const VkSubpassBeginInfoKHR *pSubpassBeginInfo) const;
472
473 bool PreCallValidateCmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
474 const VkSubpassBeginInfoKHR *pSubpassBeginInfo) const;
475
John Zulauf9cb530d2019-09-30 14:14:10 -0600476 bool PreCallValidateCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount,
477 const VkBufferCopy *pRegions) const;
478
479 void PreCallRecordCmdCopyBuffer(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkBuffer dstBuffer, uint32_t regionCount,
480 const VkBufferCopy *pRegions);
481
John Zulauf5c5e88d2019-12-26 11:22:02 -0700482 bool PreCallValidateCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
483 VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
484 const VkImageCopy *pRegions) const;
485
486 void PreCallRecordCmdCopyImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
487 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageCopy *pRegions);
488
John Zulauf9cb530d2019-09-30 14:14:10 -0600489 bool PreCallValidateCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
490 VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
491 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
492 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
493 uint32_t imageMemoryBarrierCount,
494 const VkImageMemoryBarrier *pImageMemoryBarriers) const;
495
496 void PreCallRecordCmdPipelineBarrier(VkCommandBuffer commandBuffer, VkPipelineStageFlags srcStageMask,
497 VkPipelineStageFlags dstStageMask, VkDependencyFlags dependencyFlags,
498 uint32_t memoryBarrierCount, const VkMemoryBarrier *pMemoryBarriers,
499 uint32_t bufferMemoryBarrierCount, const VkBufferMemoryBarrier *pBufferMemoryBarriers,
500 uint32_t imageMemoryBarrierCount, const VkImageMemoryBarrier *pImageMemoryBarriers);
John Zulauf3d84f1b2020-03-09 13:33:25 -0600501
502 void PostCallRecordBeginCommandBuffer(VkCommandBuffer commandBuffer, const VkCommandBufferBeginInfo *pBeginInfo,
503 VkResult result);
504
505 void PostCallRecordCmdBeginRenderPass(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
506 VkSubpassContents contents);
507 void PostCallRecordCmdBeginRenderPass2(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
508 const VkSubpassBeginInfo *pSubpassBeginInfo);
509 void PostCallRecordCmdBeginRenderPass2KHR(VkCommandBuffer commandBuffer, const VkRenderPassBeginInfo *pRenderPassBegin,
510 const VkSubpassBeginInfo *pSubpassBeginInfo);
511
John Zulauf355e49b2020-04-24 15:11:15 -0600512 bool ValidateCmdNextSubpass(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
513 const VkSubpassEndInfoKHR *pSubpassEndInfo, const char *func_name) const;
514 bool PreCallValidateCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents) const;
515 bool PreCallValidateCmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
516 const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
517 bool PreCallValidateCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfoKHR *pSubpassBeginInfo,
518 const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
519
John Zulauf3d84f1b2020-03-09 13:33:25 -0600520 void PostCallRecordCmdNextSubpass(VkCommandBuffer commandBuffer, VkSubpassContents contents);
521 void PostCallRecordCmdNextSubpass2(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
522 const VkSubpassEndInfo *pSubpassEndInfo);
523 void PostCallRecordCmdNextSubpass2KHR(VkCommandBuffer commandBuffer, const VkSubpassBeginInfo *pSubpassBeginInfo,
524 const VkSubpassEndInfo *pSubpassEndInfo);
525
John Zulauf355e49b2020-04-24 15:11:15 -0600526 bool ValidateCmdEndRenderPass(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo,
527 const char *func_name) const;
528 bool PreCallValidateCmdEndRenderPass(VkCommandBuffer commandBuffer) const;
529 bool PreCallValidateCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
530 bool PreCallValidateCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfoKHR *pSubpassEndInfo) const;
531
John Zulauf3d84f1b2020-03-09 13:33:25 -0600532 void PostCallRecordCmdEndRenderPass(VkCommandBuffer commandBuffer);
533 void PostCallRecordCmdEndRenderPass2(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo);
534 void PostCallRecordCmdEndRenderPass2KHR(VkCommandBuffer commandBuffer, const VkSubpassEndInfo *pSubpassEndInfo);
locke-lunarga19c71d2020-03-02 18:17:04 -0700535 bool PreCallValidateCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
536 VkImageLayout dstImageLayout, uint32_t regionCount,
537 const VkBufferImageCopy *pRegions) const;
538
539 void PreCallRecordCmdCopyBufferToImage(VkCommandBuffer commandBuffer, VkBuffer srcBuffer, VkImage dstImage,
540 VkImageLayout dstImageLayout, uint32_t regionCount, const VkBufferImageCopy *pRegions);
541
542 bool PreCallValidateCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
543 VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions) const;
544
545 void PreCallRecordCmdCopyImageToBuffer(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
546 VkBuffer dstBuffer, uint32_t regionCount, const VkBufferImageCopy *pRegions);
547
548 bool PreCallValidateCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout,
549 VkImage dstImage, VkImageLayout dstImageLayout, uint32_t regionCount,
550 const VkImageBlit *pRegions, VkFilter filter) const;
551
552 void PreCallRecordCmdBlitImage(VkCommandBuffer commandBuffer, VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage,
553 VkImageLayout dstImageLayout, uint32_t regionCount, const VkImageBlit *pRegions,
554 VkFilter filter);
John Zulauf9cb530d2019-09-30 14:14:10 -0600555};