blob: e9db2639b0d2d0fd5cb1f7ffec10b7788a70b92e [file] [log] [blame]
/* Copyright (c) 2015-2026 The Khronos Group Inc.
* Copyright (c) 2015-2026 Valve Corporation
* Copyright (c) 2015-2026 LunarG, Inc.
* Copyright (C) 2015-2026 Google Inc.
* Copyright (C) 2025 Arm Limited.
* Modifications Copyright (C) 2020,2025-2026 Advanced Micro Devices, Inc. All rights reserved.
* Modifications Copyright (C) 2022 RasterGrid Kft.
*
* 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.
*/
#pragma once
#include "state_tracker/state_object.h"
#include "state_tracker/image_layout_map.h"
#include "state_tracker/pipeline_library_state.h"
#include "state_tracker/video_session_state.h"
#include "state_tracker/last_bound_state.h"
#include "state_tracker/bind_point.h"
#include "state_tracker/query_state.h"
#include "state_tracker/vertex_index_buffer_state.h"
#include "error_message/error_location.h"
#include "utils/sync_utils.h"
#include "generated/dynamic_state_helper.h"
#include "containers/range_map.h"
struct Location;
namespace vvl {
class Bindable;
class Buffer;
class CommandBufferSubState;
class DeviceMemory;
class DeviceState;
class Pipeline;
class Framebuffer;
class Queue;
class RenderPass;
class VideoSession;
class VideoSessionParameters;
} // namespace vvl
enum class CbState {
New, // Newly created CB w/o any cmds
Recording, // BeginCB has been called on this CB
Recorded, // EndCB has been called on this CB
InvalidComplete, // had a complete recording, but was since invalidated
InvalidIncomplete, // fouled before recording was completed
};
static inline bool IsRecorded(CbState state) { return state == CbState::Recorded || state == CbState::InvalidComplete; }
static inline bool IsRecording(CbState state) { return state == CbState::Recording || state == CbState::InvalidIncomplete; }
bool HasActionOrSyncCommandBeforeBeginRendering(vvl::Func first_action_or_sync_command);
enum class AttachmentSource {
Empty = 0,
RenderPass,
DynamicRendering,
Inheritance, // secondary command buffer VkCommandBufferInheritanceInfo
};
struct AttachmentInfo {
enum class Type {
Empty = 0,
Input,
Color,
ColorResolve,
DepthStencil,
// Dynamic rendering split DepthStencil up
Depth,
DepthResolve,
Stencil,
StencilResolve,
// pNext extended attachment types
FragmentDensityMap,
FragmentShadingRate,
};
vvl::ImageView *image_view;
Type type;
VkImageLayout layout;
// Only for VkRenderPass with VK_KHR_separate_depth_stencil_layouts
VkImageLayout separate_stencil_layout;
// When dealing with color attachments, need to know the index for things such as
// VkPipelineColorBlendStateCreateInfo::pAttachments or vkCmdSetColorBlendEnableEXT
//
// This index is tied to a Attachment::Type and will line up to the index in either:
// VkRenderingInfo::pColorAttachments
// VkSubpassDescription::pColorAttachments
// VkSubpassDescription::pInputAttachments
// VkSubpassDescription::pResolveAttachments
uint32_t type_index;
AttachmentInfo()
: image_view(nullptr),
type(Type::Empty),
layout(VK_IMAGE_LAYOUT_UNDEFINED),
separate_stencil_layout(VK_IMAGE_LAYOUT_UNDEFINED),
type_index(0) {}
bool IsResolve() const { return type == Type::ColorResolve || type == Type::DepthResolve || type == Type::StencilResolve; }
bool IsInput() const { return type == Type::Input; }
bool IsColor() const { return type == Type::Color; }
bool IsDepth() const;
bool IsStencil() const;
bool IsDepthOrStencil() const { return type == Type::DepthStencil || type == Type::Depth || type == Type::Stencil; }
bool IsFragmentDensityMap() const { return type == Type::FragmentDensityMap; }
bool IsFragmentShadingRate() const { return type == Type::FragmentShadingRate; }
std::string Describe(const vvl::CommandBuffer &cb_state, uint32_t rp_index) const;
};
struct SubpassInfo {
bool used;
VkImageUsageFlagBits usage;
VkImageAspectFlags aspectMask;
SubpassInfo() : used(false), usage(VkImageUsageFlagBits(0)), aspectMask(VkImageAspectFlags(0)) {}
};
namespace vvl {
class Event : public StateObject {
public:
Event(VkEvent handle, const VkEventCreateInfo *create_info);
VkEvent VkHandle() const { return handle_.Cast<VkEvent>(); }
const VkEventCreateFlags flags;
#ifdef VK_USE_PLATFORM_METAL_EXT
const bool metal_event_export;
#endif // VK_USE_PLATFORM_METAL_EXT
// Signaling state.
// Gets updated at queue submission granularity or when signaled from the host.
bool signaled = false;
vku::safe_VkDependencyInfo dependency_info = {};
// Source stage specified by the "set event" command.
// Gets updated at queue submission granularity.
VkPipelineStageFlags2 signal_src_stage_mask = VK_PIPELINE_STAGE_2_NONE;
// Queue that signaled this event. It's null if event was signaled from the host.
VkQueue signaling_queue = VK_NULL_HANDLE;
};
// Track command pools and their command buffers
class CommandPool : public StateObject {
public:
DeviceState &dev_data;
const VkCommandPoolCreateFlags createFlags;
const uint32_t queueFamilyIndex;
const VkQueueFlags queue_flags;
const bool unprotected; // can't be used for protected memory
// Cmd buffers allocated from this pool
vvl::unordered_map<VkCommandBuffer, CommandBuffer *> commandBuffers;
CommandPool(DeviceState &dev, VkCommandPool handle, const VkCommandPoolCreateInfo *create_info, VkQueueFlags flags);
virtual ~CommandPool() { Destroy(); }
VkCommandPool VkHandle() const { return handle_.Cast<VkCommandPool>(); }
void Allocate(const VkCommandBufferAllocateInfo *allocate_info, const VkCommandBuffer *command_buffers);
void Free(uint32_t count, const VkCommandBuffer *command_buffers);
void Reset(const Location &loc);
void Destroy() override;
};
// This struct is not used to store label inserted with vkCmdInsertDebugUtilsLabelEXT
struct LabelCommand {
bool begin = false; // vkCmdBeginDebugUtilsLabelEXT or vkCmdEndDebugUtilsLabelEXT
std::string label_name; // used when begin == true
};
class CommandBuffer : public RefcountedStateObject, public SubStateManager<CommandBufferSubState> {
using Func = vvl::Func;
public:
using AliasedLayoutMap = vvl::unordered_map<const ImageLayoutMap *, std::shared_ptr<CommandBufferImageLayoutMap>>;
VkCommandBufferAllocateInfo allocate_info;
VkCommandBufferUsageFlags begin_info_flags;
bool has_inheritance;
vku::safe_VkCommandBufferInheritanceInfo inheritance_info;
vku::safe_VkCommandBufferInheritanceDescriptorHeapInfoEXT inheritance_descriptor_heap_info;
// since command buffers can only be destroyed by their command pool, this does not need to be a shared_ptr
const vvl::CommandPool *command_pool;
DeviceState &dev_data;
const bool unprotected; // can't be used for protected memory
CbState state; // Track cmd buffer update state
uint64_t command_count; // Number of commands recorded. Currently only used with VK_KHR_performance_query
uint64_t submit_count; // Number of times CB has been submitted
uint64_t image_layout_change_count; // The sequence number for changes to image layout (for cached validation)
// Track status of all vkCmdSet* calls, if 1, means it was set
struct DynamicStateStatus {
CBDynamicFlags cb; // for lifetime of CommandBuffer (invalidated if static pipeline is bound)
CBDynamicFlags pipeline; // for lifetime since last bound pipeline
CBDynamicFlags history; // for lifetime of CommandBuffer, regardless if invalidated, used for better error messages
// There is currently only a single non-graphics dynamic state, for now manage manually to save memory
bool rtx_stack_size_cb; // for lifetime of CommandBuffer
bool rtx_stack_size_pipeline; // for lifetime since last bound pipeline
} dynamic_state_status;
// used to mark which pipeline invalidated dynamic state so error message knows
// Note that index zero is not used due to the enum size being bitset friendly
VkPipeline invalidated_state_pipe[CB_DYNAMIC_STATE_STATUS_NUM];
std::string DescribeInvalidatedState(CBDynamicState dynamic_state) const;
// Return true if the corresponding vkCmdSet* call has occured in the command buffer.
// Used for calls like vkCmdSetColorBlendEnableEXT where we have both a VU for
// - it was called it at all
// - it was called for every attachment
// And this is used to not give double error
bool IsDynamicStateSet(CBDynamicState state) const { return dynamic_state_status.cb[state]; }
// These are values that are being set with vkCmdSet* tied to a command buffer
struct DynamicStateValue {
// VK_DYNAMIC_STATE_STENCIL_WRITE_MASK
uint32_t write_mask_front{};
uint32_t write_mask_back{};
// VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE
bool depth_write_enable{};
// VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE
bool depth_test_enable{};
// VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE
bool depth_bounds_test_enable{};
// VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE
bool stencil_test_enable{};
// VK_DYNAMIC_STATE_STENCIL_OP
VkStencilOp fail_op_front{};
VkStencilOp pass_op_front{};
VkStencilOp depth_fail_op_front{};
VkStencilOp fail_op_back{};
VkStencilOp pass_op_back{};
VkStencilOp depth_fail_op_back{};
// VK_DYNAMIC_STATE_CULL_MODE
VkCullModeFlags cull_mode{};
// VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY
VkPrimitiveTopology primitive_topology{};
// VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT
VkSampleLocationsInfoEXT sample_locations_info{};
// VK_DYNAMIC_STATE_DISCARD_RECTANGLE_ENABLE_EXT
bool discard_rectangle_enable{};
// VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT
// maxDiscardRectangles is at max 8 on all known implementations currently
std::bitset<32> discard_rectangles{};
// VK_DYNAMIC_STATE_POLYGON_MODE_EXT
VkPolygonMode polygon_mode{};
// VK_DYNAMIC_STATE_RASTERIZATION_SAMPLES_EXT
VkSampleCountFlagBits rasterization_samples{};
// VK_DYNAMIC_STATE_RASTERIZATION_STREAM_EXT
uint32_t rasterization_stream{};
// VK_DYNAMIC_STATE_SAMPLE_MASK_EXT
VkSampleCountFlagBits samples_mask_samples{};
// VK_DYNAMIC_STATE_LINE_RASTERIZATION_MODE_KHR
VkLineRasterizationMode line_rasterization_mode{};
// VK_DYNAMIC_STATE_LINE_STIPPLE_ENABLE_EXT
bool stippled_line_enable{};
// VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_ENABLE_NV
bool coverage_to_color_enable{};
// VK_DYNAMIC_STATE_COVERAGE_TO_COLOR_LOCATION_NV
uint32_t coverage_to_color_location{};
// VK_DYNAMIC_STATE_COVERAGE_MODULATION_MODE_NV
VkCoverageModulationModeNV coverage_modulation_mode{};
// VK_DYNAMIC_STATE_COVERAGE_MODULATION_TABLE_ENABLE_NV
bool coverage_modulation_table_enable{};
// VK_DYNAMIC_STATE_SHADING_RATE_IMAGE_ENABLE_NV
bool shading_rate_image_enable{};
// VK_DYNAMIC_STATE_RASTERIZER_DISCARD_ENABLE
bool rasterizer_discard_enable{};
// VK_DYNAMIC_STATE_DEPTH_BIAS_ENABLE
bool depth_bias_enable{};
// VK_DYNAMIC_STATE_DEPTH_CLAMP_ENABLE_EXT
bool depth_clamp_enable{};
// VK_DYNAMIC_STATE_ALPHA_TO_COVERAGE_ENABLE_EXT
bool alpha_to_coverage_enable{};
// VK_DYNAMIC_STATE_ALPHA_TO_ONE_ENABLE_EXT
bool alpha_to_one_enable{};
// VK_DYNAMIC_STATE_LOGIC_OP_ENABLE_EXT
bool logic_op_enable{};
// VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR
VkExtent2D fragment_size{};
// VK_DYNAMIC_STATE_PRIMITIVE_RESTART_ENABLE
bool primitive_restart_enable{};
uint32_t color_write_enable_attachment_count{};
// maxColorAttachments is at max 8 on all known implementations currently
std::bitset<32> color_blend_enable_attachments{}; // VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT
std::bitset<32> color_blend_enabled{}; // VK_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT
std::bitset<32> color_blend_equation_attachments{}; // VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT
std::bitset<32> color_write_mask_attachments{}; // VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT
std::bitset<32> color_blend_advanced_attachments{}; // VK_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT
std::bitset<32> color_write_enabled{}; // VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT
std::vector<VkColorBlendEquationEXT> color_blend_equations; // VK_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT
std::vector<VkColorComponentFlags> color_write_masks; // VK_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT
// VK_DYNAMIC_STATE_VERTEX_INPUT_EXT, key is binding number
vvl::unordered_map<uint32_t, VertexBindingState> vertex_bindings;
// VK_DYNAMIC_STATE_CONSERVATIVE_RASTERIZATION_MODE_EXT
VkConservativeRasterizationModeEXT conservative_rasterization_mode{};
// VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_ENABLE_EXT
bool sample_locations_enable{};
// VK_DYNAMIC_STATE_ATTACHMENT_FEEDBACK_LOOP_ENABLE_EXT
VkImageAspectFlags attachment_feedback_loop_enable{};
// VK_DYNAMIC_STATE_VIEWPORT
std::vector<VkViewport> viewports;
// and VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT
uint32_t viewport_count{};
// VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT
uint32_t scissor_count{};
// VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV
std::vector<VkViewportWScalingNV> viewport_w_scalings;
uint32_t viewport_w_scaling_first{};
uint32_t viewport_w_scaling_count{};
// VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_ENABLE
bool viewport_w_scaling_enable{};
// VK_DYNAMIC_STATE_VIEWPORT_SWIZZLE_NV
uint32_t viewport_swizzle_count{};
// VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV
uint32_t shading_rate_palette_count{};
// VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV
uint32_t exclusive_scissor_enable_first{};
uint32_t exclusive_scissor_enable_count{};
std::vector<VkBool32> exclusive_scissor_enables{};
// VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV
uint32_t exclusive_scissor_first{};
uint32_t exclusive_scissor_count{};
std::vector<VkRect2D> exclusive_scissors;
// When the Command Buffer resets, the value most things in this struct don't matter because if they are read without
// setting the state, it will fail in ValidateDynamicStateIsSet() for us. Some values (ex. the bitset) are tracking in
// replacement for static_status/dynamic_status so this needs to reset along with those.
//
// The only time this is reset is when the command buffer is reset, and vkCmdBindPipeline for static state
void reset(CBDynamicFlags mask) {
// Mask tells which things to reset
if (mask[CB_DYNAMIC_STATE_VIEWPORT]) {
viewports.clear();
}
if (mask[CB_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT]) {
discard_rectangles.reset();
}
if (mask[CB_DYNAMIC_STATE_COLOR_BLEND_ENABLE_EXT]) {
color_blend_enable_attachments.reset();
color_blend_enabled.reset();
}
if (mask[CB_DYNAMIC_STATE_COLOR_BLEND_EQUATION_EXT]) {
color_blend_equation_attachments.reset();
color_blend_equations.clear();
}
if (mask[CB_DYNAMIC_STATE_COLOR_WRITE_MASK_EXT]) {
color_write_mask_attachments.reset();
color_write_masks.clear();
}
if (mask[CB_DYNAMIC_STATE_COLOR_BLEND_ADVANCED_EXT]) {
color_blend_advanced_attachments.reset();
}
if (mask[CB_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT]) {
color_write_enabled.reset();
color_write_enable_attachment_count = 0u;
}
if (mask[CB_DYNAMIC_STATE_VERTEX_INPUT_EXT]) {
vertex_bindings.clear();
}
if (mask[CB_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV]) {
viewport_w_scalings.clear();
}
if (mask[CB_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_ENABLE_NV]) {
exclusive_scissor_enables.clear();
}
if (mask[CB_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV]) {
exclusive_scissors.clear();
}
// There are special because the Secondary CB Inheritance is tracking these defaults
if (mask[CB_DYNAMIC_STATE_VIEWPORT_WITH_COUNT]) {
viewport_count = 0u;
}
if (mask[CB_DYNAMIC_STATE_SCISSOR_WITH_COUNT]) {
scissor_count = 0u;
}
}
} dynamic_state_value;
// Currently storing "lastBound" objects on per-CB basis
// long-term may want to create caches of "lastBound" states and could have
// each individual CMD_NODE referencing its own "lastBound" state
// Store last bound state for Gfx & Compute pipeline bind points
std::array<LastBound, vvl::BindPointCount> lastBound;
const LastBound &GetLastBoundGraphics() const { return lastBound[vvl::BindPointGraphics]; }
const LastBound &GetLastBoundCompute() const { return lastBound[vvl::BindPointCompute]; }
const LastBound &GetLastBoundRayTracing() const { return lastBound[vvl::BindPointRayTracing]; }
const LastBound &GetLastBoundDataGraph() const { return lastBound[vvl::BindPointDataGraph]; }
// Use the casting boilerplate from StateObject to implement the derived shared_from_this
std::shared_ptr<const CommandBuffer> shared_from_this() const { return SharedFromThisImpl(this); }
std::shared_ptr<CommandBuffer> shared_from_this() { return SharedFromThisImpl(this); }
// Track if any dynamic state is set that is static in the currently bound pipeline
bool dirty_static_state;
// Device Mask at start of command buffer
uint32_t initial_device_mask;
// Device mask from vkCmdBeginRenderPass/vkCmdBeginRendering
uint32_t render_pass_device_mask;
// Set to true when the first render pass instance is encountered during recording.
// When recording is finished, it indicates if command buffer has render pass instances.
bool has_render_pass_instance;
// True if the *first* render pass instance specifies VK_RENDERING_RESUMING_BIT
bool resumes_render_pass_instance;
// During recording, this tracks the current suspension state of the command buffer.
// When recording ends, this is the suspension state at the end of the command buffer.
// Render pass instances without RESUMING/SUSPENDING do not modify the suspension state.
enum class SuspendState { Empty, Suspended, Resumed };
SuspendState last_suspend_state;
// Used by submit time validation to check for invalild commands when render pass instance is suspended.
vvl::Func first_action_or_sync_command;
// Rendering info from the first/last vkCmdBeginRendering.
std::optional<vku::safe_VkRenderingInfo> first_rendering_info;
std::unique_ptr<LocationCapture> first_rendering_info_loc;
std::optional<vku::safe_VkRenderingInfo> last_rendering_info;
// This is null if we are outside a renderPass/rendering
//
// There are 4 ways we populate this pointer
// 1. vkCmdBeginRenderPass this becomes a reference to the state created a vkCreateRenderPass time.
// 2. VkCommandBufferInheritanceInfo same as (1) but for secondary command buffers.
// 3. vkCmdBeginRendering we create the state object and store it here.
// 4. VkCommandBufferInheritanceRenderingInfo same as (3) but for secondary command buffers.
std::shared_ptr<vvl::RenderPass> active_render_pass;
// Used for both type of renderPass
AttachmentSource attachment_source;
// There is no concept of "attachment index" with dynamic rendering, we use this for both dynamic/non-dynamic rendering though.
// The attachments are packed the following: | color | color resolve | depth | depth resolve | stencil | stencil resolve |
std::vector<AttachmentInfo> active_attachments;
// Used for checking all color attachments, values will be [0, colorAttachmentCount - 1] from either VkRenderingInfo or the
// current subpass. The "active" part means the imageView was not VK_NULL_HANDLE/VK_ATTACHMENT_UNUSED
vvl::unordered_set<uint32_t> active_color_attachments_index;
bool has_render_pass_striped;
uint32_t striped_count;
VkRect2D render_area;
// only when not using dynamic rendering
vku::safe_VkRenderPassSampleLocationsBeginInfoEXT sample_locations_begin_info;
std::vector<SubpassInfo> active_subpasses;
const char *DescribeActiveColorAttachment() const;
VkSubpassContents active_subpass_contents;
uint32_t GetActiveSubpass() const { return active_subpass_; }
void SetActiveSubpass(uint32_t subpass);
std::optional<VkSampleCountFlagBits> GetActiveSubpassRasterizationSampleCount() const { return active_subpass_sample_count_; }
void SetActiveSubpassRasterizationSampleCount(VkSampleCountFlagBits rasterization_sample_count) {
active_subpass_sample_count_ = rasterization_sample_count;
}
std::shared_ptr<vvl::Framebuffer> active_framebuffer;
// Unified data structs to track objects bound to this command buffer as well as object
// dependencies that have been broken : either destroyed objects, or updated descriptor sets
vvl::unordered_set<std::shared_ptr<StateObject>> object_bindings;
vvl::unordered_map<VulkanTypedHandle, LogObjectList> broken_bindings;
std::vector<TensorBarrier> tensor_barriers;
// VK_KHR_dynamic_rendering_local_read works like dynamic state, but lives for the rendering lifetime only
struct RenderingAttachment {
// VkRenderingAttachmentLocationInfo
bool set_color_locations = false;
std::vector<uint32_t> color_locations;
// VkRenderingInputAttachmentIndexInfo
bool set_color_indexes = false;
std::vector<uint32_t> color_indexes;
const uint32_t *depth_index = nullptr;
const uint32_t *stencil_index = nullptr;
uint32_t depth_index_storage;
uint32_t stencil_index_storage;
void Reset() {
color_locations.clear();
color_indexes.clear();
depth_index = nullptr;
stencil_index = nullptr;
}
} rendering_attachments;
vvl::unordered_set<VkEvent> waited_events;
std::vector<VkEvent> write_events_before_wait;
std::vector<VkEvent> events;
vvl::unordered_set<QueryObject> active_queries;
vvl::unordered_set<QueryObject> started_queries;
vvl::unordered_set<QueryObject> updated_queries;
vvl::unordered_set<QueryObject> render_pass_queries;
ImageLayoutRegistry image_layout_registry;
AliasedLayoutMap aliased_image_layout_map; // storage for potentially aliased images
vvl::unordered_map<uint32_t, vvl::VertexBufferBinding> current_vertex_buffer_binding_info;
vvl::IndexBufferBinding index_buffer_binding;
VkCommandBuffer primary_command_buffer;
// If primary, the secondary command buffers we will call.
vvl::unordered_set<CommandBuffer *> linked_command_buffers;
bool performance_lock_acquired = false;
bool performance_lock_released = false;
PushConstantRangesId push_constant_ranges_layout;
// Video coding related state tracking
std::shared_ptr<vvl::VideoSession> bound_video_session;
std::shared_ptr<vvl::VideoSessionParameters> bound_video_session_parameters;
BoundVideoPictureResources bound_video_picture_resources;
VideoEncodeRateControlState video_encode_rate_control_state{};
std::optional<uint32_t> video_encode_quality_level{};
VideoSessionUpdateMap video_session_updates;
bool transform_feedback_active{false};
uint32_t transform_feedback_buffers_bound;
bool conditional_rendering_active{false};
bool conditional_rendering_inside_render_pass{false};
uint32_t conditional_rendering_subpass{0};
std::shared_ptr<vvl::DeviceMemory> bound_tile_memory;
// VK_EXT_descriptor_buffer
struct DescriptorBuffer {
struct BindingInfo {
VkDeviceAddress address;
VkBufferUsageFlags2 usage;
};
// This information is always tracked
std::vector<BindingInfo> binding_info;
bool ever_bound{false};
void Reset() {
binding_info.clear();
ever_bound = false;
}
} descriptor_buffer;
// VK_EXT_descriptor_heap
struct DescriptorHeap {
// Heap buffer area and for-implementation-reserved-area currently bound by vkCmdBindSamplerHeapEXT
bool sampler_bound;
vvl::range<VkDeviceAddress> sampler_range;
vvl::range<VkDeviceAddress> sampler_reserved;
// Heap buffer area and for-implementation-reserved-area currently bound by vkCmdBindResourceHeapEXT
bool resource_bound;
vvl::range<VkDeviceAddress> resource_range;
vvl::range<VkDeviceAddress> resource_reserved;
// Heap buffer push data assigned with vkCmdPushDataKHR ranges
std::vector<uint8_t> push_data{};
void Reset() {
sampler_bound = false;
sampler_reserved = {};
sampler_range = {};
resource_bound = false;
resource_reserved = {};
resource_range = {};
push_data.clear();
}
} descriptor_heap;
void SetDescriptorMode(vvl::DescriptorMode new_mode, vvl::Func function);
void InvalidateDescriptorMode(vvl::DescriptorMode invalidate_mode, vvl::Func function);
mutable std::shared_mutex lock;
ReadLockGuard ReadLock() const { return ReadLockGuard(lock); }
WriteLockGuard WriteLock() { return WriteLockGuard(lock); }
CommandBuffer(DeviceState &dev, VkCommandBuffer handle, const VkCommandBufferAllocateInfo *allocate_info,
const vvl::CommandPool *cmd_pool);
virtual ~CommandBuffer() { Destroy(); }
void Destroy() override;
VkCommandBuffer VkHandle() const { return handle_.Cast<VkCommandBuffer>(); }
vvl::ImageView *GetActiveAttachmentImageViewState(uint32_t index);
const vvl::ImageView *GetActiveAttachmentImageViewState(uint32_t index) const;
void AddChild(std::shared_ptr<StateObject> &state_object);
template <typename T>
void AddChild(std::shared_ptr<T> &child_node) {
auto base = std::static_pointer_cast<StateObject>(child_node);
AddChild(base);
}
void RemoveChild(std::shared_ptr<StateObject> &state_object);
template <typename T>
void RemoveChild(std::shared_ptr<T> &child_node) {
auto base = std::static_pointer_cast<StateObject>(child_node);
RemoveChild(base);
}
void Reset(const Location &loc);
std::shared_ptr<const CommandBufferImageLayoutMap> GetImageLayoutMap(VkImage image) const;
std::shared_ptr<CommandBufferImageLayoutMap> GetOrCreateImageLayoutMap(const vvl::Image &image_state);
// Used to get error message objects, but overloads depending on what information is known
LogObjectList GetObjectList(VkShaderStageFlagBits stage) const;
LogObjectList GetObjectList(VkPipelineBindPoint pipeline_bind_point) const;
VkQueueFlags GetQueueFlags() const { return command_pool->queue_flags; }
bool IsReleaseOp(const OwnershipTransferBarrier &barrier) const {
return (IsOwnershipTransfer(barrier)) && (command_pool->queueFamilyIndex == barrier.srcQueueFamilyIndex);
}
bool IsAcquireOp(const OwnershipTransferBarrier &barrier) const {
return (IsOwnershipTransfer(barrier)) && (command_pool->queueFamilyIndex == barrier.dstQueueFamilyIndex);
}
void Begin(const VkCommandBufferBeginInfo *pBeginInfo);
void End(VkResult result);
void RecordCommand(const Location &loc);
void RecordBeginQuery(const QueryObject &query_obj, const Location &loc);
void RecordEndQuery(const QueryObject &query_obj, const Location &loc);
void RecordEndQueries(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount);
void RecordWriteTimestamp(VkQueryPool queryPool, uint32_t slot, const Location &loc);
void RecordResetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, const Location &loc);
void RecordCopyQueryPoolResults(VkQueryPool queryPool, VkBuffer dstBuffer, uint32_t firstQuery, uint32_t queryCount,
VkDeviceSize dstOffset, VkDeviceSize stride, VkQueryResultFlags flags, const Location &loc);
void RecordWriteAccelerationStructuresProperties(VkQueryPool queryPool, uint32_t firstQuery,
uint32_t accelerationStructureCount, const Location &loc);
bool UpdatesQuery(const QueryObject &query_obj) const;
void RecordBeginRendering(const VkRenderingInfo &rendering_info, const Location &loc);
void RecordBeginRenderPass(const VkRenderPassBeginInfo &render_pass_begin, const VkSubpassBeginInfo &subpass_begin_info,
const Location &loc);
void RecordNextSubpass(const VkSubpassBeginInfo &subpass_begin_info, const VkSubpassEndInfo *subpass_end_info,
const Location &loc);
void UpdateSubpassAttachments();
void RecordEndRendering(const VkRenderingEndInfoEXT *pRenderingEndInfo, const Location &loc);
void RecordEndRenderPass(const VkSubpassEndInfo *subpass_end_info, const Location &loc);
void RecordBeginCustomResolve(const Location &loc);
void RecordBeginVideoCoding(const VkVideoBeginCodingInfoKHR &begin_info, const Location &loc);
void RecordEndVideoCoding(const Location &loc);
void RecordControlVideoCoding(const VkVideoCodingControlInfoKHR &control_info, const Location &loc);
void RecordDecodeVideo(const VkVideoDecodeInfoKHR &decode_info, const Location &loc);
void RecordEncodeVideo(const VkVideoEncodeInfoKHR &encode_info, const Location &loc);
void RecordExecuteCommands(vvl::span<const VkCommandBuffer> secondary_command_buffers, const Location &loc);
void UpdateLastBoundDescriptorSets(VkPipelineBindPoint pipeline_bind_point,
std::shared_ptr<const vvl::PipelineLayout> pipeline_layout, uint32_t first_set,
uint32_t set_count, const VkDescriptorSet *pDescriptorSets,
std::shared_ptr<vvl::DescriptorSet> &push_descriptor_set, uint32_t dynamic_offset_count,
const uint32_t *p_dynamic_offsets, const Location &loc);
void UpdateLastBoundDescriptorBuffers(VkPipelineBindPoint pipeline_bind_point,
std::shared_ptr<const vvl::PipelineLayout> pipeline_layout, uint32_t first_set,
uint32_t set_count, const uint32_t *buffer_indicies, const VkDeviceSize *buffer_offsets);
void PushDescriptorSetState(VkPipelineBindPoint pipelineBindPoint, std::shared_ptr<const vvl::PipelineLayout> pipeline_layout,
uint32_t set, uint32_t descriptorWriteCount, const VkWriteDescriptorSet *pDescriptorWrites,
const Location &loc);
void RecordDraw(const Location &loc);
void RecordDispatch(const Location &loc);
void RecordTraceRay(const Location &loc);
void RecordStateCmd(CBDynamicState dynamic_state);
void RecordDynamicState(CBDynamicState dynamic_state);
void RecordSetViewport(uint32_t first_viewport, uint32_t viewport_count, const VkViewport *viewports);
void RecordSetViewportWithCount(uint32_t viewport_count, const VkViewport *viewports);
void RecordSetScissor(uint32_t first_scissor, uint32_t scissor_count);
void RecordSetScissorWithCount(uint32_t scissor_count);
void RecordSetDepthCompareOp(VkCompareOp depth_compare_op);
void RecordSetDepthTestEnable(VkBool32 depth_test_enable);
void RecordBindPipeline(VkPipelineBindPoint bind_point, vvl::Pipeline &pipeline);
void RecordCopyBuffer(vvl::Buffer &src_buffer_state, vvl::Buffer &dst_buffer_state, uint32_t region_count,
const VkBufferCopy *regions, const Location &loc);
void RecordCopyBuffer2(vvl::Buffer &src_buffer_state, vvl::Buffer &dst_buffer_state, uint32_t region_count,
const VkBufferCopy2 *regions, const Location &loc);
void RecordCopyImage(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageCopy *regions, const Location &loc);
void RecordCopyImage2(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageCopy2 *regions, const Location &loc);
void RecordCopyBufferToImage(vvl::Buffer &src_buffer_state, vvl::Image &dst_image_state, VkImageLayout dst_image_layout,
uint32_t region_count, const VkBufferImageCopy *regions, const Location &loc);
void RecordCopyBufferToImage2(vvl::Buffer &src_buffer_state, vvl::Image &dst_image_state, VkImageLayout dst_image_layout,
uint32_t region_count, const VkBufferImageCopy2 *regions, const Location &loc);
void RecordCopyImageToBuffer(vvl::Image &src_image_state, vvl::Buffer &dst_buffer_state, VkImageLayout src_image_layout,
uint32_t region_count, const VkBufferImageCopy *regions, const Location &loc);
void RecordCopyImageToBuffer2(vvl::Image &src_image_state, vvl::Buffer &dst_buffer_state, VkImageLayout src_image_layout,
uint32_t region_count, const VkBufferImageCopy2 *regions, const Location &loc);
void RecordBlitImage(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageBlit *regions, const Location &loc);
void RecordBlitImage2(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageBlit2 *regions, const Location &loc);
void RecordResolveImage(vvl::Image &src_image_state, vvl::Image &dst_image_state, uint32_t region_count,
const VkImageResolve *regions, const Location &loc);
void RecordResolveImage2(vvl::Image &src_image_state, vvl::Image &dst_image_state, uint32_t region_count,
const VkImageResolve2 *regions, const Location &loc);
void RecordClearColorImage(vvl::Image &image_state, VkImageLayout image_layout, const VkClearColorValue *color_values,
uint32_t range_count, const VkImageSubresourceRange *ranges, const Location &loc);
void RecordClearDepthStencilImage(vvl::Image &image_state, VkImageLayout image_layout,
const VkClearDepthStencilValue *depth_stencil_values, uint32_t range_count,
const VkImageSubresourceRange *ranges, const Location &loc);
void RecordClearAttachments(uint32_t attachment_count, const VkClearAttachment *pAttachments, uint32_t rect_count,
const VkClearRect *pRects, const Location &loc);
void RecordFillBuffer(vvl::Buffer &buffer_state, VkDeviceSize offset, VkDeviceSize size, const Location &loc);
void RecordUpdateBuffer(vvl::Buffer &buffer_state, VkDeviceSize offset, VkDeviceSize size, const Location &loc);
void RecordSetEvent(VkEvent event, VkPipelineStageFlags2KHR stageMask, const VkDependencyInfo *dependency_info,
const Location &loc);
void RecordResetEvent(VkEvent event, VkPipelineStageFlags2KHR stageMask, const Location &loc);
void RecordWaitEvents(uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags2KHR src_stage_mask,
const VkDependencyInfo *dependency_info, const Location &loc);
void RecordPushConstants(const vvl::PipelineLayout &pipeline_layout_state, VkShaderStageFlags stage_flags, uint32_t offset,
uint32_t size, const void *values);
void RecordCmdPushDataEXT(const VkPushDataInfoEXT& push_data_info, const Location& loc);
void RecordBeginConditionalRendering(const Location &loc);
void RecordEndConditionalRendering(const Location &loc);
void RecordSetRenderingAttachmentLocations(const VkRenderingAttachmentLocationInfo *pLocationInfo, const Location &loc);
void RecordSetRenderingInputAttachmentIndices(const VkRenderingInputAttachmentIndexInfo *pLocationInfo, const Location &loc);
void RecordBarrierObjects(uint32_t buffer_barrier_count, const VkBufferMemoryBarrier *buffer_barriers,
uint32_t image_barrier_count, const VkImageMemoryBarrier *image_barriers,
VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, const Location &loc);
void RecordBarrierObjects(const VkDependencyInfo &dep_info, const Location &loc);
void SetImageViewLayout(const vvl::ImageView &view_state, VkImageLayout layout, VkImageLayout layoutStencil);
void TrackImageViewFirstLayout(const vvl::ImageView &view_state, VkImageLayout layout,
const char *submit_time_layout_mismatch_vuid);
void TrackDepthAttachmentFirstLayout(const vvl::ImageView &view_state, VkImageLayout layout,
const char *submit_time_layout_mismatch_vuid);
void TrackStencilAttachmentFirstLayout(const vvl::ImageView &view_state, VkImageLayout layout,
const char *submit_time_layout_mismatch_vuid);
void SetImageLayout(const vvl::Image &image_state, const VkImageSubresourceRange &normalized_subresource_range,
VkImageLayout layout, VkImageLayout expected_layout = kInvalidLayout);
// This tracks the first known layout of the subresource in the command buffer.
// NOTE: depth_offset/depth_extent parameters are used to support per-slice image layout
// transitions in 3d image. Set depth_extent to zero if API does not specify region with depth information.
void TrackImageFirstLayout(const vvl::Image &image_state, const VkImageSubresourceRange &subresource_range,
int32_t depth_offset, uint32_t depth_extent, VkImageLayout layout);
void SubmitTimeValidate(Queue &queue_state, uint32_t perf_submit_pass, const Location &loc);
// Helpers to offset into |active_attachments|
// [all color, all color resolve, depth, depth resolve, stencil, stencil resolve, FragmentDensityMap]
uint32_t GetDynamicRenderingColorAttachmentCount() const;
// Used to keep naming convention consistent
uint32_t GetDynamicRenderingColorAttachmentIndex(uint32_t index) const { return index; }
uint32_t GetDynamicRenderingColorResolveAttachmentIndex(uint32_t index) const {
return index + GetDynamicRenderingColorAttachmentCount();
}
// used for non-color types
uint32_t GetDynamicRenderingAttachmentIndex(AttachmentInfo::Type type) const;
uint32_t GetViewMask() const;
bool HasExternalFormatResolveAttachment() const;
inline void BindLastBoundPipeline(vvl::BindPoint bind_point, vvl::Pipeline *pipe_state) {
lastBound[bind_point].pipeline_state = pipe_state;
}
void BindShader(VkShaderStageFlagBits shader_stage, vvl::ShaderObject *shader_object_state);
bool IsPrimary() const { return allocate_info.level == VK_COMMAND_BUFFER_LEVEL_PRIMARY; }
bool IsSecondary() const { return allocate_info.level == VK_COMMAND_BUFFER_LEVEL_SECONDARY; }
void BeginLabel(const char *label_name);
void EndLabel();
int32_t GetLabelStackDepth() const { return label_stack_depth_; }
const std::vector<LabelCommand> &GetLabelCommands() const { return label_commands_; }
// Applies label commands to the label_stack: for "begin label" command it pushes
// a label on the stack, and for the "end label" command it removes the top label.
static void ReplayLabelCommands(const vvl::span<const LabelCommand> &label_commands, std::vector<std::string> &label_stack);
// Computes debug region by replaying given commands on top initial label stack.
static std::string GetDebugRegionName(const std::vector<LabelCommand>& label_commands, uint32_t label_command_index,
const std::vector<std::string>& initial_label_stack = {});
private:
void ResetCBState();
// Keep track of how many CmdBeginDebugUtilsLabelEXT calls have been made without a matching CmdEndDebugUtilsLabelEXT.
// Negative value for a secondary command buffer indicates invalid state.
// Negative value for a primary command buffer is allowed. Validation is done at submit time accross all command buffers.
int32_t label_stack_depth_ = 0;
// Used during sumbit time validation.
std::vector<LabelCommand> label_commands_;
uint32_t active_subpass_;
// Stores rasterization samples count obtained from the first pipeline with a pMultisampleState in the active subpass,
// or std::nullopt
std::optional<VkSampleCountFlagBits> active_subpass_sample_count_;
protected:
void NotifyInvalidate(const StateObject::NodeList &invalid_nodes, bool unlink) override;
void UpdateAttachmentsView(const VkRenderPassBeginInfo *pRenderPassBegin);
void RecordVideoInlineQueries(const VkVideoInlineQueryInfoKHR &query_info);
void UnbindResources();
};
class CommandBufferSubState {
public:
explicit CommandBufferSubState(CommandBuffer &cb) : base(cb) {}
CommandBufferSubState(const CommandBufferSubState &) = delete;
CommandBufferSubState &operator=(const CommandBufferSubState &) = delete;
virtual ~CommandBufferSubState() {}
virtual void Begin(const VkCommandBufferBeginInfo &begin_info) {}
virtual void End() {}
virtual void Reset(const Location &loc) {}
virtual void Destroy() {}
virtual void RecordExecuteCommand(vvl::CommandBuffer &secondary_command_buffer, uint32_t cmd_index, const Location &loc) {}
virtual void RecordActionCommand(LastBound &last_bound, const Location &loc) {}
virtual void RecordBindPipeline(VkPipelineBindPoint bind_point, vvl::Pipeline &pipeline) {}
virtual void UpdateLastBoundDescriptorSets(VkPipelineBindPoint bind_point, const Location &loc) {}
virtual void RecordSetViewport(uint32_t first_viewport, uint32_t viewport_count) {}
virtual void RecordSetViewportWithCount(uint32_t viewport_count) {}
virtual void RecordSetScissor(uint32_t first_scissor, uint32_t scissor_count) {}
virtual void RecordSetScissorWithCount(uint32_t scissor_count) {}
virtual void RecordSetDepthCompareOp(VkCompareOp depth_compare_op) {}
virtual void RecordSetDepthTestEnable(VkBool32 depth_test_enable) {}
virtual void RecordCopyBuffer(vvl::Buffer &src_buffer_state, vvl::Buffer &dst_buffer_state, uint32_t region_count,
const VkBufferCopy *regions, const Location &loc) {}
virtual void RecordCopyBuffer2(vvl::Buffer &src_buffer_state, vvl::Buffer &dst_buffer_state, uint32_t region_count,
const VkBufferCopy2 *regions, const Location &loc) {}
virtual void RecordCopyImage(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageCopy *regions,
const Location &loc) {}
virtual void RecordCopyImage2(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageCopy2 *regions,
const Location &loc) {}
virtual void RecordCopyBufferToImage(vvl::Buffer &src_buffer_state, vvl::Image &dst_image_state, VkImageLayout dst_image_layout,
uint32_t region_count, const VkBufferImageCopy *regions, const Location &loc) {}
virtual void RecordCopyBufferToImage2(vvl::Buffer &src_buffer_state, vvl::Image &dst_image_state,
VkImageLayout dst_image_layout, uint32_t region_count, const VkBufferImageCopy2 *regions,
const Location &loc) {}
virtual void RecordCopyImageToBuffer(vvl::Image &src_image_state, vvl::Buffer &dst_buffer_state, VkImageLayout src_image_layout,
uint32_t region_count, const VkBufferImageCopy *regions, const Location &loc) {}
virtual void RecordCopyImageToBuffer2(vvl::Image &src_image_state, vvl::Buffer &dst_buffer_state,
VkImageLayout src_image_layout, uint32_t region_count, const VkBufferImageCopy2 *regions,
const Location &loc) {}
virtual void RecordBlitImage(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageBlit *regions,
const Location &loc) {}
virtual void RecordBlitImage2(vvl::Image &src_image_state, vvl::Image &dst_image_state, VkImageLayout src_image_layout,
VkImageLayout dst_image_layout, uint32_t region_count, const VkImageBlit2 *regions,
const Location &loc) {}
virtual void RecordResolveImage(vvl::Image &src_image_state, vvl::Image &dst_image_state, uint32_t region_count,
const VkImageResolve *regions, const Location &loc) {}
virtual void RecordResolveImage2(vvl::Image &src_image_state, vvl::Image &dst_image_state, uint32_t region_count,
const VkImageResolve2 *regions, const Location &loc) {}
virtual void RecordClearColorImage(vvl::Image &image_state, VkImageLayout image_layout, const VkClearColorValue *color_values,
uint32_t range_count, const VkImageSubresourceRange *ranges, const Location &loc) {}
virtual void RecordClearDepthStencilImage(vvl::Image &image_state, VkImageLayout image_layout,
const VkClearDepthStencilValue *depth_stencil_values, uint32_t range_count,
const VkImageSubresourceRange *ranges, const Location &loc) {}
virtual void RecordClearAttachments(uint32_t attachment_count, const VkClearAttachment *pAttachments, uint32_t rect_count,
const VkClearRect *pRects, const Location &loc) {}
virtual void RecordFillBuffer(vvl::Buffer &buffer_state, VkDeviceSize offset, VkDeviceSize size, const Location &loc) {}
virtual void RecordUpdateBuffer(vvl::Buffer &buffer_state, VkDeviceSize offset, VkDeviceSize size, const Location &loc) {}
virtual void RecordSetEvent(VkEvent event, VkPipelineStageFlags2 stage_mask, const VkDependencyInfo *dependency_info) {}
virtual void RecordResetEvent(VkEvent event, VkPipelineStageFlags2 stage_mask) {}
virtual void RecordWaitEvents(uint32_t eventCount, const VkEvent *pEvents, VkPipelineStageFlags2 src_stage_mask,
const VkDependencyInfo *dependency_info, const Location &loc) {}
virtual void RecordBarriers(uint32_t buffer_barrier_count, const VkBufferMemoryBarrier *buffer_barriers,
uint32_t image_barrier_count, const VkImageMemoryBarrier *image_barriers,
VkPipelineStageFlags src_stage_mask, VkPipelineStageFlags dst_stage_mask, const Location &loc) {}
virtual void RecordBarriers2(const VkDependencyInfo &dep_info, const Location &loc) {}
virtual void RecordPushConstants(VkPipelineLayout layout, VkShaderStageFlags stage_flags, uint32_t offset, uint32_t size,
const void *values) {}
virtual void RecordBeginRendering(const VkRenderingInfo &rendering_info, const Location &loc) {}
virtual void RecordBeginRenderPass(const VkRenderPassBeginInfo &render_pass_begin, const VkSubpassBeginInfo &subpass_begin_info,
const Location &loc) {}
virtual void RecordNextSubpass(const VkSubpassBeginInfo &subpass_begin_info, const VkSubpassEndInfo *subpass_end_info,
const Location &loc) {}
// Note - these are called prior to the renderPass object being destroyed
virtual void RecordEndRendering(const VkRenderingEndInfoEXT *pRenderingEndInfo) {}
virtual void RecordEndRenderPass(const VkSubpassEndInfo *subpass_end_info, const Location &loc) {}
virtual void RecordBeginCustomResolve() {}
virtual void RecordBeginQuery(const QueryObject &query_obj, const Location &loc) {}
virtual void RecordEndQuery(const QueryObject &query_obj, const Location &loc) {}
virtual void RecordEndQueries(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount) {}
virtual void RecordWriteTimestamp(const QueryObject &query_obj, const Location &loc) {}
virtual void RecordResetQueryPool(VkQueryPool queryPool, uint32_t firstQuery, uint32_t queryCount, bool is_perf_query,
const Location &loc) {}
virtual void RecordCopyQueryPoolResults(vvl::QueryPool &pool_state, vvl::Buffer &dst_buffer_state, uint32_t first_query,
uint32_t query_count, VkDeviceSize dst_offset, VkDeviceSize stride,
VkQueryResultFlags flags, const Location &loc) {}
virtual void RecordWriteAccelerationStructuresProperties(VkQueryPool queryPool, uint32_t firstQuery,
uint32_t accelerationStructureCount, const Location &loc) {}
virtual void RecordVideoInlineQueries(const VkVideoInlineQueryInfoKHR &query_info) {}
virtual void RecordBeginVideoCoding(vvl::VideoSession &vs_state, const VkVideoBeginCodingInfoKHR &begin_info,
const Location &loc) {}
virtual void RecordControlVideoCoding(vvl::VideoSession &vs_state, const VkVideoCodingControlInfoKHR &control_info,
const Location &loc) {}
virtual void RecordDecodeVideo(vvl::VideoSession &vs_state, const VkVideoDecodeInfoKHR &decode_info, const Location &loc) {}
virtual void RecordEncodeVideo(vvl::VideoSession &vs_state, const VkVideoEncodeInfoKHR &encode_info, const Location &loc) {}
virtual void ClearPushConstants() {}
virtual void NotifyInvalidate(const StateObject::NodeList &invalid_nodes, bool unlink) {}
virtual void Submit(Queue &queue_state, uint32_t perf_submit_pass, const Location &loc) {}
VulkanTypedHandle Handle() const;
VkCommandBuffer VkHandle() const;
CommandBuffer &base;
};
} // namespace vvl