mesa/src/broadcom/vulkan/v3dv_cmd_buffer.h
Jose Maria Casanova Crespo 2b6b859a22
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run
v3dv: defer tile_alloc creation in meta TLB ops
Remove the allocate_tile_state_now parameter from v3dv_job_start_frame().
So v3dv_job_allocate_tile_state() is explicitly called after
job_emit_binning_flush() as we know the value of job->draw_count instead
of using always 0.

Reviewed-by: Iago Toral Quiroga <itoral@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/40554>
2026-04-13 10:31:21 +00:00

789 lines
27 KiB
C

/*
* Copyright © 2026 Raspberry Pi Ltd
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the "Software"),
* to deal in the Software without restriction, including without limitation
* the rights to use, copy, modify, merge, publish, distribute, sublicense,
* and/or sell copies of the Software, and to permit persons to whom the
* Software is furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice (including the next
* paragraph) shall be included in all copies or substantial portions of the
* Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
* IN THE SOFTWARE.
*/
#ifndef V3DV_CMD_BUFFER_H
#define V3DV_CMD_BUFFER_H
#include "v3dv_common.h"
#include "v3dv_limits.h"
#include "v3dv_pipeline.h"
#include "v3dv_pass.h"
#include "v3dv_query.h"
#include "v3dv_cl.h"
#include "vk_command_buffer.h"
#include "vk_command_pool.h"
#include "vk_sync.h"
#include "util/set.h"
struct v3dv_buffer;
struct v3dv_descriptor_set;
struct v3dv_device;
struct v3dv_image;
struct v3dv_image_view;
enum v3dv_cmd_buffer_status {
V3DV_CMD_BUFFER_STATUS_NEW = 0,
V3DV_CMD_BUFFER_STATUS_INITIALIZED = 1,
V3DV_CMD_BUFFER_STATUS_RECORDING = 2,
V3DV_CMD_BUFFER_STATUS_EXECUTABLE = 3
};
union v3dv_clear_value {
uint32_t color[4];
struct {
float z;
uint8_t s;
};
};
struct v3dv_cmd_buffer_attachment_state {
/* The original clear value as provided by the Vulkan API */
VkClearValue vk_clear_value;
/* The hardware clear value */
union v3dv_clear_value clear_value;
/* The underlying image view (from the framebuffer or, if imageless
* framebuffer is used, from VkRenderPassAttachmentBeginInfo.
*/
struct v3dv_image_view *image_view;
/* If this is a multisampled attachment with a resolve operation. */
bool has_resolve;
/* If this is a multisampled attachment with a resolve operation,
* whether we can use the TLB for the resolve.
*/
bool use_tlb_resolve;
};
enum v3dv_job_type {
V3DV_JOB_TYPE_GPU_CL = 0,
V3DV_JOB_TYPE_GPU_CL_INCOMPLETE,
V3DV_JOB_TYPE_GPU_TFU,
V3DV_JOB_TYPE_GPU_CSD,
V3DV_JOB_TYPE_CPU_RESET_QUERIES,
V3DV_JOB_TYPE_CPU_END_QUERY,
V3DV_JOB_TYPE_CPU_COPY_QUERY_RESULTS,
V3DV_JOB_TYPE_CPU_CSD_INDIRECT,
V3DV_JOB_TYPE_CPU_TIMESTAMP_QUERY,
};
struct v3dv_reset_query_cpu_job_info {
struct v3dv_query_pool *pool;
uint32_t first;
uint32_t count;
};
struct v3dv_end_query_info {
struct v3dv_query_pool *pool;
uint32_t query;
/* This is one unless multiview is used */
uint32_t count;
};
struct v3dv_copy_query_results_cpu_job_info {
struct v3dv_query_pool *pool;
uint32_t first;
uint32_t count;
struct v3dv_buffer *dst;
uint32_t offset;
uint32_t stride;
VkQueryResultFlags flags;
};
struct v3dv_submit_sync_info {
/* List of syncs to wait before running a job */
uint32_t wait_count;
struct vk_sync_wait *waits;
/* List of syncs to signal when all jobs complete */
uint32_t signal_count;
struct vk_sync_signal *signals;
};
struct v3dv_csd_indirect_cpu_job_info {
struct v3dv_buffer *buffer;
uint32_t offset;
struct v3dv_job *csd_job;
uint32_t wg_size;
uint32_t *wg_uniform_offsets[3];
bool needs_wg_uniform_rewrite;
};
struct v3dv_timestamp_query_cpu_job_info {
struct v3dv_query_pool *pool;
uint32_t query;
/* This is one unless multiview is used */
uint32_t count;
};
struct v3dv_job {
struct list_head list_link;
/* We only create job clones when executing secondary command buffers into
* primaries. These clones don't make deep copies of the original object
* so we want to flag them to avoid freeing resources they don't own.
*/
bool is_clone;
/* If this is a cloned job, if it has its own BCL resource. This happens
* when we suspend jobs with in command buffers with the
* VK_COMMAND_BUFFER_USAGE_SIMULTANEOUS_USE_BIT flag.
*/
bool clone_owns_bcl;
/* VK_KHR_dynamic_rendering */
bool suspending;
bool resuming;
struct v3dv_cl_out *suspend_branch_inst_ptr;
uint32_t suspended_bcl_end;
/* If the job executes on the transfer stage of the pipeline */
bool is_transfer;
/* VK_KHR_buffer_device_address allows shaders to use pointers that can
* dereference memory in any buffer that has been flagged with
* VK_BUFFER_USAGE_SHADER_DEVICE_ADDRESS_BIT. These buffers may not
* be bound via descriptor sets, so we need to make sure that a job that
* uses this functionality includes all these buffers in its kernel
* submission.
*/
bool uses_buffer_device_address;
/* True if we have not identified anything that would be incompatible
* with double-buffer (like MSAA) or that would make double-buffer mode
* not efficient (like tile loads or not having any stores).
*/
bool can_use_double_buffer;
/* This structure keeps track of various scores to inform a heuristic
* for double-buffer mode.
*/
struct v3d_double_buffer_score double_buffer_score;
/* We only need to allocate tile state for all layers if the binner
* writes primitives to layers other than the first. This can only be
* done using layered rendering (writing gl_Layer from a geometry shader),
* so for other cases of multilayered framebuffers (typically with
* meta copy/clear operations) that won't use layered rendering, we only
* need one layer worth of of tile state for the binner.
*/
bool allocate_tile_state_for_all_layers;
/* A pointer to the location of the TILE_BINNING_MODE_CFG packet so we can
* rewrite it to enable double-buffer mode by the time we have enough info
* about the job to make that decision.
*/
struct v3dv_cl_out *bcl_tile_binning_mode_ptr;
enum v3dv_job_type type;
struct v3dv_device *device;
struct v3dv_cmd_buffer *cmd_buffer;
struct v3dv_cl bcl;
struct v3dv_cl rcl;
struct v3dv_cl indirect;
/* Set of all BOs referenced by the job. This will be used for making
* the list of BOs that the kernel will need to have paged in to
* execute our job.
*/
struct set *bos;
uint32_t bo_count;
uint64_t bo_handle_mask;
struct v3dv_bo *tile_alloc;
struct v3dv_bo *tile_state;
bool tmu_dirty_rcl;
uint32_t first_subpass;
/* When the current subpass is split into multiple jobs, this flag is set
* to true for any jobs after the first in the same subpass.
*/
bool is_subpass_continue;
/* If this job is the last job emitted for a subpass. */
bool is_subpass_finish;
struct v3dv_frame_tiling frame_tiling;
enum v3dv_ez_state ez_state;
enum v3dv_ez_state first_ez_state;
/* If we have already decided if we need to disable Early Z/S completely
* for this job.
*/
bool decided_global_ez_enable;
/* If the job emitted any draw calls with Early Z/S enabled */
bool has_ez_draws;
/* If this job has been configured to use early Z/S clear */
bool early_zs_clear;
/* Number of draw calls recorded into the job */
uint32_t draw_count;
/* A flag indicating whether we want to flush every draw separately. This
* can be used for debugging, or for cases where special circumstances
* require this behavior.
*/
bool always_flush;
/* A mask of V3DV_BARRIER_* indicating the source(s) of the barrier. We
* can use this to select the hw queues where we need to serialize the job.
*/
uint8_t serialize;
/* If this is a CL job, whether we should sync before binning */
bool needs_bcl_sync;
/* If we have emitted a (default) point size packet in this job */
bool emitted_default_point_size;
/* Job specs for CPU jobs */
union {
struct v3dv_reset_query_cpu_job_info query_reset;
struct v3dv_end_query_info query_end;
struct v3dv_copy_query_results_cpu_job_info query_copy_results;
struct v3dv_csd_indirect_cpu_job_info csd_indirect;
struct v3dv_timestamp_query_cpu_job_info query_timestamp;
} cpu;
/* Job specs for TFU jobs */
struct drm_v3d_submit_tfu tfu;
/* Job specs for CSD jobs */
struct {
struct v3dv_bo *shared_memory;
uint32_t wg_count[3];
uint32_t wg_base[3];
struct drm_v3d_submit_csd submit;
} csd;
/* Perfmons with last job sync for CSD and CL jobs */
struct v3dv_perf_query *perf;
};
void v3dv_job_init(struct v3dv_job *job,
enum v3dv_job_type type,
struct v3dv_device *device,
struct v3dv_cmd_buffer *cmd_buffer,
int32_t subpass_idx);
void v3dv_job_destroy(struct v3dv_job *job);
void v3dv_job_add_bo(struct v3dv_job *job, struct v3dv_bo *bo);
void v3dv_job_add_bo_unchecked(struct v3dv_job *job, struct v3dv_bo *bo);
void v3dv_job_start_frame(struct v3dv_job *job,
uint32_t width,
uint32_t height,
uint32_t layers,
bool allocate_tile_state_for_all_layers,
uint32_t render_target_count,
uint8_t max_internal_bpp,
uint8_t total_color_bpp,
bool msaa);
bool v3dv_job_type_is_gpu(struct v3dv_job *job);
struct v3dv_job *
v3dv_job_clone(struct v3dv_job *job, bool skip_bcl);
struct v3dv_job *
v3dv_job_clone_in_cmd_buffer(struct v3dv_job *job,
struct v3dv_cmd_buffer *cmd_buffer);
struct v3dv_job *v3dv_cmd_buffer_create_cpu_job(struct v3dv_device *device,
enum v3dv_job_type type,
struct v3dv_cmd_buffer *cmd_buffer,
uint32_t subpass_idx);
void
v3dv_cmd_buffer_ensure_array_state(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t slot_size,
uint32_t used_count,
uint32_t *alloc_count,
void **ptr);
void v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer,
bool indexed, bool indirect,
uint32_t vertex_count);
bool v3dv_job_allocate_tile_state(struct v3dv_job *job);
void
v3dv_setup_dynamic_framebuffer(struct v3dv_cmd_buffer *cmd_buffer,
const VkRenderingInfoKHR *pRenderingInfo);
void
v3dv_destroy_dynamic_framebuffer(struct v3dv_cmd_buffer *cmd_buffer);
void
v3dv_setup_dynamic_render_pass(struct v3dv_cmd_buffer *cmd_buffer,
const VkRenderingInfoKHR *pRenderingInfo);
void
v3dv_setup_dynamic_render_pass_inheritance(struct v3dv_cmd_buffer *cmd_buffer,
const VkCommandBufferInheritanceRenderingInfo *info);
struct v3dv_draw_info {
uint32_t vertex_count;
uint32_t instance_count;
uint32_t first_vertex;
uint32_t first_instance;
};
struct v3dv_vertex_binding {
struct v3dv_buffer *buffer;
VkDeviceSize offset;
VkDeviceSize size;
};
struct v3dv_descriptor_state {
struct v3dv_descriptor_set *descriptor_sets[MAX_SETS];
uint32_t valid;
uint32_t dynamic_offsets[MAX_DYNAMIC_BUFFERS];
};
struct v3dv_cmd_pipeline_state {
struct v3dv_pipeline *pipeline;
struct v3dv_descriptor_state descriptor_state;
};
enum {
V3DV_BARRIER_GRAPHICS_BIT = (1 << 0),
V3DV_BARRIER_COMPUTE_BIT = (1 << 1),
V3DV_BARRIER_TRANSFER_BIT = (1 << 2),
V3DV_BARRIER_CPU_BIT = (1 << 3),
};
#define V3DV_BARRIER_ALL (V3DV_BARRIER_GRAPHICS_BIT | \
V3DV_BARRIER_TRANSFER_BIT | \
V3DV_BARRIER_COMPUTE_BIT | \
V3DV_BARRIER_CPU_BIT);
struct v3dv_barrier_state {
/* Mask of V3DV_BARRIER_* indicating where we consume a barrier. */
uint8_t dst_mask;
/* For each possible consumer of a barrier, a mask of V3DV_BARRIER_*
* indicating the sources of the dependency.
*/
uint8_t src_mask_graphics;
uint8_t src_mask_transfer;
uint8_t src_mask_compute;
/* For graphics barriers, access masks involved. Used to decide if we need
* to execute a binning or render barrier.
*/
VkAccessFlags2 bcl_buffer_access;
VkAccessFlags2 bcl_image_access;
};
struct v3dv_cmd_buffer_state {
struct v3dv_render_pass *pass;
struct v3dv_framebuffer *framebuffer;
/* VK_KHR_dynamic_rendering */
struct v3dv_render_pass dynamic_pass;
struct v3dv_subpass dynamic_subpass;
struct v3dv_render_pass_attachment dynamic_attachments[18 /* (8 color + D/S) x 2 (for resolves) */];
struct v3dv_subpass_attachment dynamic_subpass_attachments[18];
struct v3dv_framebuffer *dynamic_framebuffer;
VkRect2D render_area;
/* Current job being recorded */
struct v3dv_job *job;
uint32_t subpass_idx;
struct v3dv_cmd_pipeline_state gfx;
struct v3dv_cmd_pipeline_state compute;
/* For most state tracking we rely on vk_dynamic_graphics_state, but we
* maintain a custom structure for some state-related data that we want to
* cache.
*/
struct v3dv_dynamic_state dynamic;
/* This dirty is for v3dv_cmd_dirty_bits (FIXME: perhaps we should be more
* explicit about it). For dirty flags coming from Vulkan dynamic state,
* use the vk_dynamic_graphics_state handled by the vk_cmd_buffer
*/
uint32_t dirty;
VkShaderStageFlagBits dirty_descriptor_stages;
VkShaderStageFlagBits dirty_push_constants_stages;
/* Current clip window. We use this to check whether we have an active
* scissor, since in that case we can't use TLB clears and need to fallback
* to drawing rects.
*/
VkRect2D clip_window;
/* Whether our render area is aligned to tile boundaries. If this is false
* then we have tiles that are only partially covered by the render area,
* and therefore, we need to be careful with our loads and stores so we don't
* modify pixels for the tile area that is not covered by the render area.
* This means, for example, that we can't use the TLB to clear, since that
* always clears full tiles.
*/
bool tile_aligned_render_area;
/* FIXME: we have just one client-side BO for the push constants,
* independently of the stageFlags in vkCmdPushConstants, and the
* pipelineBindPoint in vkCmdBindPipeline. We could probably do more stage
* tuning in the future if it makes sense.
*/
uint32_t push_constants_size;
uint32_t push_constants_data[MAX_PUSH_CONSTANTS_SIZE / 4];
uint32_t attachment_alloc_count;
struct v3dv_cmd_buffer_attachment_state *attachments;
struct v3dv_vertex_binding vertex_bindings[MAX_VBS];
struct {
VkBuffer buffer;
VkDeviceSize offset;
VkDeviceSize size;
uint8_t index_size;
} index_buffer;
/* Current uniforms */
struct {
struct v3dv_cl_reloc vs_bin;
struct v3dv_cl_reloc vs;
struct v3dv_cl_reloc gs_bin;
struct v3dv_cl_reloc gs;
struct v3dv_cl_reloc fs;
} uniforms;
/* Current view index for multiview rendering */
uint32_t view_index;
/* Current draw ID for multidraw */
uint32_t draw_id;
/* Used to flag OOM conditions during command buffer recording */
bool oom;
/* If we are currently recording job(s) for a transfer operation */
bool is_transfer;
/* VK_KHR_dynamic_rendering */
bool suspending;
bool resuming;
/* Barrier state tracking */
struct v3dv_barrier_state barrier;
/* Secondary command buffer state */
struct {
bool occlusion_query_enable;
} inheritance;
/* Command buffer state saved during a meta operation */
struct {
uint32_t subpass_idx;
VkRenderPass pass;
VkFramebuffer framebuffer;
uint32_t attachment_alloc_count;
uint32_t attachment_count;
struct v3dv_cmd_buffer_attachment_state *attachments;
bool tile_aligned_render_area;
VkRect2D render_area;
struct vk_dynamic_graphics_state dynamic_graphics_state;
struct v3dv_dynamic_state dynamic;
struct v3dv_cmd_pipeline_state gfx;
bool has_descriptor_state;
uint32_t push_constants[MAX_PUSH_CONSTANTS_SIZE / 4];
uint32_t push_constants_size;
} meta;
/* Command buffer state for queries */
struct {
/* A list of vkCmdQueryEnd commands recorded in the command buffer during
* a render pass. We queue these here and then schedule the corresponding
* CPU jobs for them at the time we finish the GPU job in which they have
* been recorded.
*/
struct {
uint32_t used_count;
uint32_t alloc_count;
struct v3dv_end_query_info *states;
} end;
struct {
/* This BO is not NULL if we have an active occlusion query, that is,
* we have called vkCmdBeginQuery but not vkCmdEndQuery.
*/
struct v3dv_bo *bo;
uint32_t offset;
/* When the driver emits draw calls to implement other operations in
* the middle of a render pass (such as an attachment clear), we need
* to pause occlusion query recording and resume it later so that
* these draw calls don't register in occlussion counters. We use
* this to store the BO reference in which we should resume occlusion
* query counters after the driver is done emitting its draw calls.
*/
struct v3dv_bo *paused_bo;
/* This pointer is not NULL if we have an active performance query */
struct v3dv_perf_query *perf;
} active_query;
} query;
/* This is dynamic state since VK_EXT_extended_dynamic_state. */
bool z_updates_enable;
/* ez_state can be dynamic since VK_EXT_extended_dynamic_state so we need
* to keep track of it in the cmd_buffer state
*/
enum v3dv_ez_state ez_state;
/* incompatible_ez_test can be dynamic since VK_EXT_extended_dynamic_state
* so we need to keep track of it in the cmd_buffer state
*/
bool incompatible_ez_test;
};
void
v3dv_cmd_buffer_state_get_viewport_z_xform(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t vp_idx,
float *translate_z,
float *scale_z);
VkResult
v3dv_query_allocate_resources(struct v3dv_device *decice);
void
v3dv_query_free_resources(struct v3dv_device *decice);
VkResult v3dv_get_query_pool_results_cpu(struct v3dv_device *device,
struct v3dv_query_pool *pool,
uint32_t first,
uint32_t count,
void *data,
VkDeviceSize stride,
VkQueryResultFlags flags);
void v3dv_reset_query_pool_cpu(struct v3dv_device *device,
struct v3dv_query_pool *query_pool,
uint32_t first,
uint32_t last);
void v3dv_cmd_buffer_emit_set_query_availability(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_query_pool *pool,
uint32_t query, uint32_t count,
uint8_t availability);
typedef void (*v3dv_cmd_buffer_private_obj_destroy_cb)(VkDevice device,
uint64_t pobj,
VkAllocationCallbacks *alloc);
struct v3dv_cmd_buffer_private_obj {
struct list_head list_link;
uint64_t obj;
v3dv_cmd_buffer_private_obj_destroy_cb destroy_cb;
};
extern const struct vk_command_buffer_ops v3dv_cmd_buffer_ops;
struct v3dv_cmd_buffer {
struct vk_command_buffer vk;
struct v3dv_device *device;
VkCommandBufferUsageFlags usage_flags;
enum v3dv_cmd_buffer_status status;
struct v3dv_cmd_buffer_state state;
/* Buffer where we upload push constant data to resolve indirect indexing */
struct v3dv_cl_reloc push_constants_resource;
/* Collection of Vulkan objects created internally by the driver (typically
* during recording of meta operations) that are part of the command buffer
* and should be destroyed with it.
*/
struct list_head private_objs; /* v3dv_cmd_buffer_private_obj */
/* Per-command buffer resources for meta operations. */
struct {
struct {
/* The current descriptor pool for blit sources */
VkDescriptorPool dspool;
} blit;
struct {
/* The current descriptor pool for texel buffer copy sources */
VkDescriptorPool dspool;
} texel_buffer_copy;
struct {
/* The current descriptor pool for the copy query results output buffer */
VkDescriptorPool dspool;
} query;
} meta;
/* List of jobs in the command buffer. For primary command buffers it
* represents the jobs we want to submit to the GPU. For secondary command
* buffers it represents jobs that will be merged into a primary command
* buffer via vkCmdExecuteCommands.
*/
struct list_head jobs;
};
struct v3dv_job *v3dv_cmd_buffer_start_job(struct v3dv_cmd_buffer *cmd_buffer,
int32_t subpass_idx,
enum v3dv_job_type type);
void v3dv_cmd_buffer_finish_job(struct v3dv_cmd_buffer *cmd_buffer);
struct v3dv_job *v3dv_cmd_buffer_subpass_start(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t subpass_idx);
struct v3dv_job *v3dv_cmd_buffer_subpass_resume(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t subpass_idx);
void v3dv_cmd_buffer_subpass_finish(struct v3dv_cmd_buffer *cmd_buffer);
void v3dv_cmd_buffer_meta_state_push(struct v3dv_cmd_buffer *cmd_buffer,
bool push_descriptor_state);
void v3dv_cmd_buffer_meta_state_pop(struct v3dv_cmd_buffer *cmd_buffer,
bool needs_subpass_resume);
void v3dv_cmd_buffer_begin_query(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_query_pool *pool,
uint32_t query,
VkQueryControlFlags flags);
void v3dv_cmd_buffer_pause_occlusion_query(struct v3dv_cmd_buffer *cmd_buffer);
void v3dv_cmd_buffer_resume_occlusion_query(struct v3dv_cmd_buffer *cmd_buffer);
void v3dv_cmd_buffer_end_query(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_query_pool *pool,
uint32_t query);
void v3dv_cmd_buffer_copy_query_results(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_query_pool *pool,
uint32_t first,
uint32_t count,
struct v3dv_buffer *dst,
uint32_t offset,
uint32_t stride,
VkQueryResultFlags flags);
void v3dv_cmd_buffer_add_tfu_job(struct v3dv_cmd_buffer *cmd_buffer,
struct drm_v3d_submit_tfu *tfu);
void v3dv_cmd_buffer_rewrite_indirect_csd_job(struct v3dv_device *device,
struct v3dv_csd_indirect_cpu_job_info *info,
const uint32_t *wg_counts);
void v3dv_cmd_buffer_add_private_obj(struct v3dv_cmd_buffer *cmd_buffer,
uint64_t obj,
v3dv_cmd_buffer_private_obj_destroy_cb destroy_cb);
void v3dv_merge_barrier_state(struct v3dv_barrier_state *dst,
struct v3dv_barrier_state *src);
void v3dv_cmd_buffer_consume_bcl_sync(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_job *job);
bool v3dv_cmd_buffer_check_needs_load(const struct v3dv_cmd_buffer_state *state,
VkImageAspectFlags aspect,
uint32_t first_subpass_idx,
VkAttachmentLoadOp load_op,
uint32_t last_subpass_idx,
VkAttachmentStoreOp store_op);
bool v3dv_cmd_buffer_check_needs_store(const struct v3dv_cmd_buffer_state *state,
VkImageAspectFlags aspect,
uint32_t last_subpass_idx,
VkAttachmentStoreOp store_op);
void v3dv_cmd_buffer_emit_pipeline_barrier(struct v3dv_cmd_buffer *cmd_buffer,
const VkDependencyInfo *info);
bool v3dv_cmd_buffer_copy_image_tfu(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_image *dst,
struct v3dv_image *src,
const VkImageCopy2 *region);
void v3dv_cmd_buffer_resolve_image(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_image *dst,
struct v3dv_image *src,
VkFormat resolve_format,
const VkImageResolve2 *region);
bool v3dv_job_apply_barrier_state(struct v3dv_job *job,
struct v3dv_barrier_state *barrier);
/* Flags OOM conditions in command buffer state.
*
* Note: notice that no-op jobs don't have a command buffer reference.
*/
static inline void
v3dv_flag_oom(struct v3dv_cmd_buffer *cmd_buffer, struct v3dv_job *job)
{
if (cmd_buffer) {
cmd_buffer->state.oom = true;
} else {
assert(job);
if (job->cmd_buffer)
job->cmd_buffer->state.oom = true;
}
}
static inline struct v3dv_descriptor_state *
v3dv_cmd_buffer_get_descriptor_state(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_pipeline *pipeline)
{
if (v3dv_pipeline_get_binding_point(pipeline) == VK_PIPELINE_BIND_POINT_COMPUTE)
return &cmd_buffer->state.compute.descriptor_state;
else
return &cmd_buffer->state.gfx.descriptor_state;
}
#define v3dv_return_if_oom(_cmd_buffer, _job) do { \
const struct v3dv_cmd_buffer *__cmd_buffer = _cmd_buffer; \
if (__cmd_buffer && __cmd_buffer->state.oom) \
return; \
const struct v3dv_job *__job = _job; \
if (__job && __job->cmd_buffer && __job->cmd_buffer->state.oom) \
return; \
} while(0) \
VK_DEFINE_HANDLE_CASTS(v3dv_cmd_buffer, vk.base, VkCommandBuffer,
VK_OBJECT_TYPE_COMMAND_BUFFER)
#endif /* V3DV_CMD_BUFFER_H */