blob: 2ed242cbe573d7f2da5f02a2401f6d3adcaf0aa5 [file] [log] [blame]
Jeremy Gebben159b3cc2021-06-03 09:09:03 -06001/* Copyright (c) 2015-2021 The Khronos Group Inc.
2 * Copyright (c) 2015-2021 Valve Corporation
3 * Copyright (c) 2015-2021 LunarG, Inc.
4 * Copyright (C) 2015-2021 Google Inc.
5 * Modifications Copyright (C) 2020 Advanced Micro Devices, Inc. All rights reserved.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 * Author: Courtney Goeltzenleuchter <courtneygo@google.com>
20 * Author: Tobin Ehlis <tobine@google.com>
21 * Author: Chris Forbes <chrisf@ijw.co.nz>
22 * Author: Mark Lobodzinski <mark@lunarg.com>
23 * Author: Dave Houlton <daveh@lunarg.com>
24 * Author: John Zulauf <jzulauf@lunarg.com>
25 * Author: Tobias Hector <tobias.hector@amd.com>
26 */
27#pragma once
28#include "base_node.h"
29#include "query_state.h"
30#include "command_validation.h"
31#include "hash_vk_types.h"
32#include "subresource_adapter.h"
33#include "image_layout_map.h"
34#include "pipeline_state.h"
35#include "device_state.h"
36#include "descriptor_sets.h"
37#include "qfo_transfer.h"
38
39class RENDER_PASS_STATE;
40class CoreChecks;
41class ValidationStateTracker;
42
43class EVENT_STATE : public BASE_NODE {
44 public:
45 int write_in_use;
46 VkPipelineStageFlags2KHR stageMask = VkPipelineStageFlags2KHR(0);
47 VkEventCreateFlags flags;
48
49 EVENT_STATE(VkEvent event_, VkEventCreateFlags flags_)
50 : BASE_NODE(event_, kVulkanObjectTypeEvent), write_in_use(0), flags(flags_) {}
51
52 VkEvent event() const { return handle_.Cast<VkEvent>(); }
53};
54
55// Only CoreChecks uses this, but the state tracker stores it.
56constexpr static auto kInvalidLayout = image_layout_map::kInvalidLayout;
57using ImageSubresourceLayoutMap = image_layout_map::ImageSubresourceLayoutMap;
58typedef layer_data::unordered_map<VkEvent, VkPipelineStageFlags2KHR> EventToStageMap;
59
60// Track command pools and their command buffers
61class COMMAND_POOL_STATE : public BASE_NODE {
62 public:
63 VkCommandPoolCreateFlags createFlags;
64 uint32_t queueFamilyIndex;
65 VkQueueFlags queue_flags;
66 bool unprotected; // can't be used for protected memory
67 // Cmd buffers allocated from this pool
68 layer_data::unordered_set<VkCommandBuffer> commandBuffers;
69
70 COMMAND_POOL_STATE(VkCommandPool cp, const VkCommandPoolCreateInfo *pCreateInfo, VkQueueFlags flags)
71 : BASE_NODE(cp, kVulkanObjectTypeCommandPool),
72 createFlags(pCreateInfo->flags),
73 queueFamilyIndex(pCreateInfo->queueFamilyIndex),
74 queue_flags(flags),
75 unprotected((pCreateInfo->flags & VK_COMMAND_POOL_CREATE_PROTECTED_BIT) == 0) {}
76
77 VkCommandPool commandPool() const { return handle_.Cast<VkCommandPool>(); }
78
79 virtual ~COMMAND_POOL_STATE() { Destroy(); }
80
81 void Destroy() override {
82 commandBuffers.clear();
83 BASE_NODE::Destroy();
84 }
85};
86
87template <typename Barrier, bool assume_transfer = false>
88static bool TempIsReleaseOp(const COMMAND_POOL_STATE *pool, const Barrier &barrier) {
89 return (assume_transfer || IsTransferOp(barrier)) && (pool->queueFamilyIndex == barrier.srcQueueFamilyIndex);
90}
91
92template <typename Barrier, bool assume_transfer = false>
93static bool IsAcquireOp(const COMMAND_POOL_STATE *pool, const Barrier &barrier) {
94 return (assume_transfer || IsTransferOp(barrier)) && (pool->queueFamilyIndex == barrier.dstQueueFamilyIndex);
95}
96
97// Autogenerated as part of the command_validation.h codegen
98const char *CommandTypeString(CMD_TYPE type);
99
100enum CB_STATE {
101 CB_NEW, // Newly created CB w/o any cmds
102 CB_RECORDING, // BeginCB has been called on this CB
103 CB_RECORDED, // EndCB has been called on this CB
104 CB_INVALID_COMPLETE, // had a complete recording, but was since invalidated
105 CB_INVALID_INCOMPLETE, // fouled before recording was completed
106};
107
108// CB Status -- used to track status of various bindings on cmd buffer objects
109typedef uint64_t CBStatusFlags;
110enum CBStatusFlagBits : uint64_t {
111 // clang-format off
112 CBSTATUS_NONE = 0x00000000, // No status is set
113 CBSTATUS_LINE_WIDTH_SET = 0x00000001, // Line width has been set
114 CBSTATUS_DEPTH_BIAS_SET = 0x00000002, // Depth bias has been set
115 CBSTATUS_BLEND_CONSTANTS_SET = 0x00000004, // Blend constants state has been set
116 CBSTATUS_DEPTH_BOUNDS_SET = 0x00000008, // Depth bounds state object has been set
117 CBSTATUS_STENCIL_READ_MASK_SET = 0x00000010, // Stencil read mask has been set
118 CBSTATUS_STENCIL_WRITE_MASK_SET = 0x00000020, // Stencil write mask has been set
119 CBSTATUS_STENCIL_REFERENCE_SET = 0x00000040, // Stencil reference has been set
120 CBSTATUS_VIEWPORT_SET = 0x00000080,
121 CBSTATUS_SCISSOR_SET = 0x00000100,
122 CBSTATUS_INDEX_BUFFER_BOUND = 0x00000200, // Index buffer has been set
123 CBSTATUS_EXCLUSIVE_SCISSOR_SET = 0x00000400,
124 CBSTATUS_SHADING_RATE_PALETTE_SET = 0x00000800,
125 CBSTATUS_LINE_STIPPLE_SET = 0x00001000,
126 CBSTATUS_VIEWPORT_W_SCALING_SET = 0x00002000,
127 CBSTATUS_CULL_MODE_SET = 0x00004000,
128 CBSTATUS_FRONT_FACE_SET = 0x00008000,
129 CBSTATUS_PRIMITIVE_TOPOLOGY_SET = 0x00010000,
130 CBSTATUS_VIEWPORT_WITH_COUNT_SET = 0x00020000,
131 CBSTATUS_SCISSOR_WITH_COUNT_SET = 0x00040000,
132 CBSTATUS_VERTEX_INPUT_BINDING_STRIDE_SET = 0x00080000,
133 CBSTATUS_DEPTH_TEST_ENABLE_SET = 0x00100000,
134 CBSTATUS_DEPTH_WRITE_ENABLE_SET = 0x00200000,
135 CBSTATUS_DEPTH_COMPARE_OP_SET = 0x00400000,
136 CBSTATUS_DEPTH_BOUNDS_TEST_ENABLE_SET = 0x00800000,
137 CBSTATUS_STENCIL_TEST_ENABLE_SET = 0x01000000,
138 CBSTATUS_STENCIL_OP_SET = 0x02000000,
139 CBSTATUS_DISCARD_RECTANGLE_SET = 0x04000000,
140 CBSTATUS_SAMPLE_LOCATIONS_SET = 0x08000000,
141 CBSTATUS_COARSE_SAMPLE_ORDER_SET = 0x10000000,
142 CBSTATUS_PATCH_CONTROL_POINTS_SET = 0x20000000,
143 CBSTATUS_RASTERIZER_DISCARD_ENABLE_SET = 0x40000000,
144 CBSTATUS_DEPTH_BIAS_ENABLE_SET = 0x80000000,
145 CBSTATUS_LOGIC_OP_SET = 0x100000000,
146 CBSTATUS_PRIMITIVE_RESTART_ENABLE_SET = 0x200000000,
147 CBSTATUS_VERTEX_INPUT_SET = 0x400000000,
148 CBSTATUS_ALL_STATE_SET = 0x7FFFFFDFF, // All state set (intentionally exclude index buffer)
149 // clang-format on
150};
151
152VkDynamicState ConvertToDynamicState(CBStatusFlagBits flag);
153CBStatusFlagBits ConvertToCBStatusFlagBits(VkDynamicState state);
154std::string DynamicStateString(CBStatusFlags input_value);
155
156struct BufferBinding {
157 std::shared_ptr<BUFFER_STATE> buffer_state;
158 VkDeviceSize size;
159 VkDeviceSize offset;
160 VkDeviceSize stride;
161
162 BufferBinding() : buffer_state(), size(0), offset(0), stride(0) {}
163 virtual ~BufferBinding() {}
164
165 virtual void reset() { *this = BufferBinding(); }
166};
167
168struct IndexBufferBinding : BufferBinding {
169 VkIndexType index_type;
170
171 IndexBufferBinding() : BufferBinding(), index_type(static_cast<VkIndexType>(0)) {}
172 virtual ~IndexBufferBinding() {}
173
174 virtual void reset() override { *this = IndexBufferBinding(); }
175};
176
177struct CBVertexBufferBindingInfo {
178 std::vector<BufferBinding> vertex_buffer_bindings;
179};
180
181typedef subresource_adapter::BothRangeMap<VkImageLayout, 16> GlobalImageLayoutRangeMap;
182typedef layer_data::unordered_map<VkImage, layer_data::optional<GlobalImageLayoutRangeMap>> GlobalImageLayoutMap;
183
184typedef layer_data::unordered_map<VkImage, layer_data::optional<ImageSubresourceLayoutMap>> CommandBufferImageLayoutMap;
185
186struct SUBPASS_INFO;
187class FRAMEBUFFER_STATE;
188
189class CMD_BUFFER_STATE : public REFCOUNTED_NODE {
190 public:
191 VkCommandBufferAllocateInfo createInfo = {};
192 VkCommandBufferBeginInfo beginInfo;
193 VkCommandBufferInheritanceInfo inheritanceInfo;
194 std::shared_ptr<const COMMAND_POOL_STATE> command_pool;
195 bool hasDrawCmd;
196 bool hasTraceRaysCmd;
197 bool hasBuildAccelerationStructureCmd;
198 bool hasDispatchCmd;
199 bool unprotected; // can't be used for protected memory
200
201 CB_STATE state; // Track cmd buffer update state
202 uint64_t commandCount; // Number of commands recorded. Currently only used with VK_KHR_performance_query
203 uint64_t submitCount; // Number of times CB has been submitted
204 typedef uint64_t ImageLayoutUpdateCount;
205 ImageLayoutUpdateCount image_layout_change_count; // The sequence number for changes to image layout (for cached validation)
206 CBStatusFlags status; // Track status of various bindings on cmd buffer
207 CBStatusFlags static_status; // All state bits provided by current graphics pipeline
208 // rather than dynamic state
209 CBStatusFlags dynamic_status; // dynamic state set up in pipeline
210 // Currently storing "lastBound" objects on per-CB basis
211 // long-term may want to create caches of "lastBound" states and could have
212 // each individual CMD_NODE referencing its own "lastBound" state
213 // Store last bound state for Gfx & Compute pipeline bind points
214 std::array<LAST_BOUND_STATE, BindPoint_Count> lastBound; // index is LvlBindPoint.
215
216 struct CmdDrawDispatchInfo {
217 CMD_TYPE cmd_type;
218 std::string function;
219 std::vector<std::pair<const uint32_t, DescriptorRequirement>> binding_infos;
220 VkFramebuffer framebuffer;
221 std::shared_ptr<std::vector<SUBPASS_INFO>> subpasses;
222 std::shared_ptr<std::vector<IMAGE_VIEW_STATE *>> attachments;
223 };
224 layer_data::unordered_map<VkDescriptorSet, std::vector<CmdDrawDispatchInfo>> validate_descriptorsets_in_queuesubmit;
225
226 // If VK_NV_inherited_viewport_scissor is enabled and VkCommandBufferInheritanceViewportScissorInfoNV::viewportScissor2D is
227 // true, then is the nonempty list of viewports passed in pViewportDepths. Otherwise, this is empty.
228 std::vector<VkViewport> inheritedViewportDepths;
229
230 // For each draw command D recorded to this command buffer, let
231 // * g_D be the graphics pipeline used
232 // * v_G be the viewportCount of g_D (0 if g_D disables rasterization or enables VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT)
233 // * s_G be the scissorCount of g_D (0 if g_D disables rasterization or enables VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT)
234 // Then this value is max(0, max(v_G for all D in cb), max(s_G for all D in cb))
235 uint32_t usedViewportScissorCount;
236 uint32_t pipelineStaticViewportCount; // v_G for currently-bound graphics pipeline.
237 uint32_t pipelineStaticScissorCount; // s_G for currently-bound graphics pipeline.
238
239 uint32_t viewportMask;
240 uint32_t viewportWithCountMask;
241 uint32_t viewportWithCountCount;
242 uint32_t scissorMask;
243 uint32_t scissorWithCountMask;
244 uint32_t scissorWithCountCount;
245
246 // Dynamic viewports set in this command buffer; if bit j of viewportMask is set then dynamicViewports[j] is valid, but the
247 // converse need not be true.
248 std::vector<VkViewport> dynamicViewports;
249
250 // Bits set when binding graphics pipeline defining corresponding static state, or executing any secondary command buffer.
251 // Bits unset by calling a corresponding vkCmdSet[State] cmd.
252 uint32_t trashedViewportMask;
253 uint32_t trashedScissorMask;
254 bool trashedViewportCount;
255 bool trashedScissorCount;
256
257 // True iff any draw command recorded to this command buffer consumes dynamic viewport/scissor with count state.
258 bool usedDynamicViewportCount;
259 bool usedDynamicScissorCount;
260
261 uint32_t initial_device_mask;
262 VkPrimitiveTopology primitiveTopology;
263
264 safe_VkRenderPassBeginInfo activeRenderPassBeginInfo;
265 std::shared_ptr<RENDER_PASS_STATE> activeRenderPass;
266 std::shared_ptr<std::vector<SUBPASS_INFO>> active_subpasses;
267 std::shared_ptr<std::vector<IMAGE_VIEW_STATE *>> active_attachments;
268 std::set<std::shared_ptr<IMAGE_VIEW_STATE>> attachments_view_states;
269
270 VkSubpassContents activeSubpassContents;
271 uint32_t active_render_pass_device_mask;
272 uint32_t activeSubpass;
273 std::shared_ptr<FRAMEBUFFER_STATE> activeFramebuffer;
274 layer_data::unordered_set<std::shared_ptr<FRAMEBUFFER_STATE>> framebuffers;
275 // Unified data structs to track objects bound to this command buffer as well as object
276 // dependencies that have been broken : either destroyed objects, or updated descriptor sets
277 layer_data::unordered_set<VulkanTypedHandle> object_bindings;
278 layer_data::unordered_map<VulkanTypedHandle, LogObjectList> broken_bindings;
279
280 QFOTransferBarrierSets<QFOBufferTransferBarrier> qfo_transfer_buffer_barriers;
281 QFOTransferBarrierSets<QFOImageTransferBarrier> qfo_transfer_image_barriers;
282
283 layer_data::unordered_set<VkEvent> waitedEvents;
284 std::vector<VkEvent> writeEventsBeforeWait;
285 std::vector<VkEvent> events;
286 layer_data::unordered_set<QueryObject> activeQueries;
287 layer_data::unordered_set<QueryObject> startedQueries;
288 layer_data::unordered_set<QueryObject> resetQueries;
289 CommandBufferImageLayoutMap image_layout_map;
290 CBVertexBufferBindingInfo current_vertex_buffer_binding_info;
291 bool vertex_buffer_used; // Track for perf warning to make sure any bound vtx buffer used
292 VkCommandBuffer primaryCommandBuffer;
293 // If primary, the secondary command buffers we will call.
294 // If secondary, the primary command buffers we will be called by.
295 layer_data::unordered_set<CMD_BUFFER_STATE *> linkedCommandBuffers;
296 // Validation functions run at primary CB queue submit time
297 std::vector<std::function<bool(const ValidationStateTracker *device_data, const class QUEUE_STATE *queue_state)>>
298 queue_submit_functions;
299 // Validation functions run when secondary CB is executed in primary
300 std::vector<std::function<bool(const CMD_BUFFER_STATE *, const FRAMEBUFFER_STATE *)>> cmd_execute_commands_functions;
301 std::vector<
302 std::function<bool(const ValidationStateTracker *device_data, bool do_validate, EventToStageMap *localEventToStageMap)>>
303 eventUpdates;
304 std::vector<std::function<bool(const ValidationStateTracker *device_data, bool do_validate, VkQueryPool &firstPerfQueryPool,
305 uint32_t perfQueryPass, QueryMap *localQueryToStateMap)>>
306 queryUpdates;
307 layer_data::unordered_set<cvdescriptorset::DescriptorSet *> validated_descriptor_sets;
308 // Contents valid only after an index buffer is bound (CBSTATUS_INDEX_BUFFER_BOUND set)
309 IndexBufferBinding index_buffer_binding;
310 bool performance_lock_acquired = false;
311 bool performance_lock_released = false;
312
313 // Cache of current insert label...
314 LoggingLabel debug_label;
315
316 std::vector<uint8_t> push_constant_data;
317 PushConstantRangesId push_constant_data_ranges;
318
319 std::map<VkShaderStageFlagBits, std::vector<uint8_t>>
320 push_constant_data_update; // vector's value is enum PushConstantByteState.
321 VkPipelineLayout push_constant_pipeline_layout_set;
322
323 // Used for Best Practices tracking
324 uint32_t small_indexed_draw_call_count;
325
326 bool transform_feedback_active{false};
327
328 CMD_BUFFER_STATE(VkCommandBuffer cb, const VkCommandBufferAllocateInfo *pCreateInfo)
329 : REFCOUNTED_NODE(cb, kVulkanObjectTypeCommandBuffer), createInfo(*pCreateInfo) {}
330
331 ~CMD_BUFFER_STATE() { Destroy(); }
332
333 void Destroy() override;
334
335 VkCommandBuffer commandBuffer() const { return handle_.Cast<VkCommandBuffer>(); }
336
337 int AddReverseBinding(const VulkanTypedHandle &obj);
338
339 IMAGE_VIEW_STATE *GetActiveAttachmentImageViewState(uint32_t index);
340 const IMAGE_VIEW_STATE *GetActiveAttachmentImageViewState(uint32_t index) const;
341
342 void AddChild(BASE_NODE *child_node);
343
344 void RemoveChild(BASE_NODE *child_node);
345
346 void Reset();
347
348 ImageSubresourceLayoutMap *GetImageSubresourceLayoutMap(const IMAGE_STATE &image_state);
349 const ImageSubresourceLayoutMap *GetImageSubresourceLayoutMap(VkImage image) const;
350
351 const QFOTransferBarrierSets<QFOImageTransferBarrier> &GetQFOBarrierSets(const QFOImageTransferBarrier &type_tag) const {
352 return qfo_transfer_image_barriers;
353 }
354
355 const QFOTransferBarrierSets<QFOBufferTransferBarrier> &GetQFOBarrierSets(const QFOBufferTransferBarrier &type_tag) const {
356 return qfo_transfer_buffer_barriers;
357 }
358
359 QFOTransferBarrierSets<QFOImageTransferBarrier> &GetQFOBarrierSets(const QFOImageTransferBarrier &type_tag) {
360 return qfo_transfer_image_barriers;
361 }
362
363 QFOTransferBarrierSets<QFOBufferTransferBarrier> &GetQFOBarrierSets(const QFOBufferTransferBarrier &type_tag) {
364 return qfo_transfer_buffer_barriers;
365 }
366
367 PIPELINE_STATE *GetCurrentPipeline(VkPipelineBindPoint pipelineBindPoint) const {
368 const auto lv_bind_point = ConvertToLvlBindPoint(pipelineBindPoint);
369 return lastBound[lv_bind_point].pipeline_state;
370 }
371
372 void GetCurrentPipelineAndDesriptorSets(VkPipelineBindPoint pipelineBindPoint, const PIPELINE_STATE **rtn_pipe,
373 const std::vector<LAST_BOUND_STATE::PER_SET> **rtn_sets) const {
374 const auto lv_bind_point = ConvertToLvlBindPoint(pipelineBindPoint);
375 const auto &last_bound_it = lastBound[lv_bind_point];
376 if (!last_bound_it.IsUsing()) {
377 return;
378 }
379 *rtn_pipe = last_bound_it.pipeline_state;
380 *rtn_sets = &(last_bound_it.per_set);
381 }
382
383 VkQueueFlags GetQueueFlags() const {
384 return command_pool->queue_flags;
385 }
386
387 protected:
388 void NotifyInvalidate(const LogObjectList &invalid_handles, bool unlink) override;
389};