diff --git a/src/imagination/vulkan/pvr_blit.c b/src/imagination/vulkan/pvr_blit.c index 3d236852ef9..4828f1d5379 100644 --- a/src/imagination/vulkan/pvr_blit.c +++ b/src/imagination/vulkan/pvr_blit.c @@ -30,6 +30,7 @@ #include "pvr_blit.h" #include "pvr_buffer.h" #include "pvr_clear.h" +#include "pvr_cmd_buffer.h" #include "pvr_csb.h" #include "pvr_device.h" #include "pvr_formats.h" diff --git a/src/imagination/vulkan/pvr_clear.c b/src/imagination/vulkan/pvr_clear.c index d398bc90c92..3a503e0570e 100644 --- a/src/imagination/vulkan/pvr_clear.c +++ b/src/imagination/vulkan/pvr_clear.c @@ -28,6 +28,7 @@ #include "pco/pco_data.h" #include "pco_uscgen_programs.h" #include "pvr_clear.h" +#include "pvr_cmd_buffer.h" #include "pvr_device.h" #include "pvr_pds.h" #include "pvr_private.h" diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 56f11475487..7692620ccc6 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -21,6 +21,8 @@ * SOFTWARE. */ +#include "pvr_cmd_buffer.h" + #include #include #include diff --git a/src/imagination/vulkan/pvr_cmd_buffer.h b/src/imagination/vulkan/pvr_cmd_buffer.h new file mode 100644 index 00000000000..af13ac436d0 --- /dev/null +++ b/src/imagination/vulkan/pvr_cmd_buffer.h @@ -0,0 +1,632 @@ +/* + * Copyright © 2022 Imagination Technologies Ltd. + * + * based in part on anv driver which is: + * Copyright © 2015 Intel Corporation + * + * based in part on radv driver which is: + * Copyright © 2016 Red Hat. + * Copyright © 2016 Bas Nieuwenhuizen + * + * SPDX-License-Identifier: MIT + */ + +#ifndef PVR_CMD_BUFFER_H +#define PVR_CMD_BUFFER_H + +#include "vk_command_buffer.h" + +#include "pvr_common.h" +#include "pvr_framebuffer.h" +#include "pvr_job_render.h" +#include "pvr_types.h" + +struct pvr_pds_upload; +struct pvr_private_compute_pipeline; +struct pvr_query_info; + +struct pvr_vertex_binding { + struct pvr_buffer *buffer; + VkDeviceSize offset; + VkDeviceSize size; +}; + +#define PVR_TRANSFER_MAX_SOURCES 10U +#define PVR_TRANSFER_MAX_CUSTOM_MAPPINGS 6U + +/** A surface describes a source or destination for a transfer operation. */ +struct pvr_transfer_cmd_surface { + pvr_dev_addr_t dev_addr; + + /* Memory address for extra U/V planes. */ + pvr_dev_addr_t uv_address[2]; + + /* Surface width in texels. */ + uint32_t width; + + /* Surface height in texels. */ + uint32_t height; + + uint32_t depth; + + /* Z position in a 3D tecture. 0.0f <= z_position <= depth. */ + float z_position; + + /* Stride in texels. */ + uint32_t stride; + + VkFormat vk_format; + + enum pvr_memlayout mem_layout; + + uint32_t sample_count; +}; + +struct pvr_rect_mapping { + VkRect2D src_rect; + VkRect2D dst_rect; + bool flip_x; + bool flip_y; +}; + +struct pvr_transfer_cmd_source { + struct pvr_transfer_cmd_surface surface; + + uint32_t mapping_count; + struct pvr_rect_mapping mappings[PVR_TRANSFER_MAX_CUSTOM_MAPPINGS]; + + /* In the case of a simple 1:1 copy, this setting does not affect the output + * but will affect performance. Use clamp to edge when possible. + */ + /* This is of type enum ROGUE_TEXSTATE_ADDRMODE. */ + int addr_mode; + + /* Source filtering method. */ + enum pvr_filter filter; + + /* MSAA resolve operation. */ + enum pvr_resolve_op resolve_op; +}; + +struct pvr_transfer_cmd { + /* Node to link this cmd into the transfer_cmds list in + * pvr_sub_cmd::transfer structure. + */ + struct list_head link; + + uint32_t flags; + + uint32_t source_count; + + struct pvr_transfer_cmd_source sources[PVR_TRANSFER_MAX_SOURCES]; + + union fi clear_color[4]; + + struct pvr_transfer_cmd_surface dst; + + VkRect2D scissor; + + /* Pointer to cmd buffer this transfer cmd belongs to. This is mainly used + * to link buffer objects allocated during job submission into + * cmd_buffer::bo_list head. + */ + struct pvr_cmd_buffer *cmd_buffer; + + /* Deferred RTA clears are allocated from pvr_cmd_buffer->deferred_clears and + * cannot be freed directly. + */ + bool is_deferred_clear; +}; + +struct pvr_sub_cmd_gfx { + const struct pvr_framebuffer *framebuffer; + + struct pvr_render_job job; + + struct pvr_suballoc_bo *depth_bias_bo; + struct pvr_suballoc_bo *scissor_bo; + + /* Tracking how the loaded depth/stencil values are being used. */ + enum pvr_depth_stencil_usage depth_usage; + enum pvr_depth_stencil_usage stencil_usage; + + /* Tracking whether the subcommand modifies depth/stencil. */ + bool modifies_depth; + bool modifies_stencil; + + /* Store the render to a scratch buffer. */ + bool barrier_store; + /* Load the render (stored with a `barrier_store`) as a background to the + * current render. + */ + bool barrier_load; + + const struct pvr_query_pool *query_pool; + struct util_dynarray sec_query_indices; + + /* Control stream builder object */ + struct pvr_csb control_stream; + + struct pvr_bo *multiview_ctrl_stream; + uint32_t multiview_ctrl_stream_stride; + + /* Required iff pvr_sub_cmd_gfx_requires_split_submit() returns true. */ + struct pvr_bo *terminate_ctrl_stream; + + uint32_t hw_render_idx; + + uint32_t max_tiles_in_flight; + + bool empty_cmd; + + /* True if any fragment shader used in this sub command uses atomic + * operations. + */ + bool frag_uses_atomic_ops; + + bool disable_compute_overlap; + + /* True if any fragment shader used in this sub command has side + * effects. + */ + bool frag_has_side_effects; + + /* True if any vertex shader used in this sub command contains both + * texture reads and texture writes. + */ + bool vertex_uses_texture_rw; + + /* True if any fragment shader used in this sub command contains + * both texture reads and texture writes. + */ + bool frag_uses_texture_rw; + + bool has_query; + + bool wait_on_previous_transfer; + + bool has_depth_feedback; + + uint32_t view_mask; + bool multiview_enabled; +}; + +struct pvr_sub_cmd_compute { + /* Control stream builder object. */ + struct pvr_csb control_stream; + + uint32_t num_shared_regs; + + /* True if any shader used in this sub command uses atomic + * operations. + */ + bool uses_atomic_ops; + + bool uses_barrier; + + bool pds_sw_barrier_requires_clearing; +}; + +struct pvr_sub_cmd_transfer { + bool serialize_with_frag; + + /* Pointer to the actual transfer command list, allowing primary and + * secondary sub-commands to share the same list. + */ + struct list_head *transfer_cmds; + + /* List of pvr_transfer_cmd type structures. Do not access the list + * directly, but always use the transfer_cmds pointer above. + */ + struct list_head transfer_cmds_priv; +}; + +struct pvr_sub_cmd_event { + enum pvr_event_type type; + + union { + struct pvr_sub_cmd_event_set_reset { + struct pvr_event *event; + /* Stages to wait for until the event is set or reset. */ + uint32_t wait_for_stage_mask; + } set_reset; + + struct pvr_sub_cmd_event_wait { + uint32_t count; + /* Events to wait for before resuming. */ + struct pvr_event **events; + /* Stages to wait at. */ + uint32_t *wait_at_stage_masks; + } wait; + + struct pvr_sub_cmd_event_barrier { + /* Stages to wait for. */ + uint32_t wait_for_stage_mask; + /* Stages to wait at. */ + uint32_t wait_at_stage_mask; + } barrier; + }; +}; + +struct pvr_sub_cmd { + /* This links the subcommand in pvr_cmd_buffer:sub_cmds list. */ + struct list_head link; + + enum pvr_sub_cmd_type type; + + /* True if the sub_cmd is owned by this command buffer. False if taken from + * a secondary command buffer, in that case we are not supposed to free any + * resources associated with the sub_cmd. + */ + bool owned; + + union { + struct pvr_sub_cmd_gfx gfx; + struct pvr_sub_cmd_compute compute; + struct pvr_sub_cmd_transfer transfer; + struct pvr_sub_cmd_event event; + }; +}; + +struct pvr_render_pass_info { + const struct pvr_render_pass *pass; + struct pvr_framebuffer *framebuffer; + + struct pvr_image_view **attachments; + + uint32_t subpass_idx; + uint32_t current_hw_subpass; + + VkRect2D render_area; + + uint32_t clear_value_count; + VkClearValue *clear_values; + + VkPipelineBindPoint pipeline_bind_point; + + bool process_empty_tiles; + bool enable_bg_tag; + uint32_t isp_userpass; +}; + +struct pvr_ppp_state { + uint32_t header; + + struct { + /* TODO: Can we get rid of the "control" field? */ + struct ROGUE_TA_STATE_ISPCTL control_struct; + uint32_t control; + + uint32_t front_a; + uint32_t front_b; + uint32_t back_a; + uint32_t back_b; + } isp; + + struct pvr_ppp_dbsc { + uint16_t scissor_index; + uint16_t depthbias_index; + } depthbias_scissor_indices; + + struct { + uint32_t pixel_shader_base; + uint32_t texture_uniform_code_base; + uint32_t size_info1; + uint32_t size_info2; + uint32_t varying_base; + uint32_t texture_state_data_base; + uint32_t uniform_state_data_base; + } pds; + + struct { + uint32_t word0; + uint32_t word1; + } region_clipping; + + struct { + uint32_t a0; + uint32_t m0; + uint32_t a1; + uint32_t m1; + uint32_t a2; + uint32_t m2; + } viewports[PVR_MAX_VIEWPORTS]; + + uint32_t viewport_count; + + uint32_t output_selects; + + uint32_t varying_word[2]; + + uint32_t ppp_control; +}; + +/* Represents a control stream related command that is deferred for execution in + * a secondary command buffer. + */ +struct pvr_deferred_cs_command { + enum pvr_deferred_cs_command_type type; + union { + struct { + struct pvr_ppp_dbsc state; + + uint32_t *vdm_state; + } dbsc; + + struct { + struct pvr_ppp_dbsc state; + + struct pvr_suballoc_bo *ppp_cs_bo; + uint32_t patch_offset; + } dbsc2; + }; +}; + +struct pvr_cmd_buffer_draw_state { + uint32_t base_instance; + uint32_t base_vertex; + bool draw_indirect; + bool draw_indexed; +}; + +struct pvr_push_constants { + uint8_t data[PVR_MAX_PUSH_CONSTANTS_SIZE]; + unsigned bytes_updated; + pvr_dev_addr_t dev_addr; + bool dirty; +}; + +struct pvr_cmd_buffer_state { + /* Pipeline binding. */ + const struct pvr_graphics_pipeline *gfx_pipeline; + + const struct pvr_compute_pipeline *compute_pipeline; + + struct pvr_render_pass_info render_pass_info; + + struct pvr_sub_cmd *current_sub_cmd; + + struct pvr_ppp_state ppp_state; + + struct ROGUE_TA_STATE_HEADER emit_header; + + struct pvr_vertex_binding vertex_bindings[PVR_MAX_VERTEX_INPUT_BINDINGS]; + + struct { + struct pvr_buffer *buffer; + VkDeviceSize offset; + VkIndexType type; + } index_buffer_binding; + + /* Array size of barriers_needed is based on number of sync pipeline + * stages. + */ + uint32_t barriers_needed[PVR_NUM_SYNC_PIPELINE_STAGES]; + + struct pvr_descriptor_state gfx_desc_state; + struct pvr_descriptor_state compute_desc_state; + + struct pvr_push_constants push_consts[PVR_STAGE_ALLOCATION_COUNT]; + + VkFormat depth_format; + + struct { + bool compute_pipeline_binding : 1; + bool compute_desc_dirty : 1; + + bool gfx_pipeline_binding : 1; + bool gfx_desc_dirty : 1; + + bool vertex_bindings : 1; + bool index_buffer_binding : 1; + bool vertex_descriptors : 1; + bool fragment_descriptors : 1; + + bool isp_userpass : 1; + + /* Some draw state needs to be tracked for changes between draw calls + * i.e. if we get a draw with baseInstance=0, followed by a call with + * baseInstance=1 that needs to cause us to select a different PDS + * attrib program and update the BASE_INSTANCE PDS const. If only + * baseInstance changes then we just have to update the data section. + */ + bool draw_base_instance : 1; + bool draw_variant : 1; + + bool vis_test; + } dirty; + + struct pvr_cmd_buffer_draw_state draw_state; + + struct { + uint32_t code_offset; + const struct pvr_pds_info *info; + } pds_shader; + + const struct pvr_query_pool *query_pool; + bool vis_test_enabled; + uint32_t vis_reg; + + struct util_dynarray query_indices; + + uint32_t max_shared_regs; + + /* Address of data segment for vertex attrib upload program. */ + uint32_t pds_vertex_attrib_offset; + + uint32_t pds_fragment_descriptor_data_offset; + uint32_t pds_compute_descriptor_data_offset; +}; + +/* Do not change this. This is the format used for the depth_bias_array + * elements uploaded to the device. + */ +struct pvr_depth_bias_state { + /* Saved information from pCreateInfo. */ + float constant_factor; + float slope_factor; + float clamp; +}; + +/* Do not change this. This is the format used for the scissor_array + * elements uploaded to the device. + */ +struct pvr_scissor_words { + /* Contains a packed IPF_SCISSOR_WORD_0. */ + uint32_t w0; + /* Contains a packed IPF_SCISSOR_WORD_1. */ + uint32_t w1; +}; + +struct pvr_cmd_buffer { + struct vk_command_buffer vk; + + struct pvr_device *device; + + /* Buffer usage flags */ + VkCommandBufferUsageFlags usage_flags; + + /* Array of struct pvr_depth_bias_state. */ + struct util_dynarray depth_bias_array; + + /* Array of struct pvr_scissor_words. */ + struct util_dynarray scissor_array; + struct pvr_scissor_words scissor_words; + + struct pvr_cmd_buffer_state state; + + /* List of struct pvr_deferred_cs_command control stream related commands to + * execute in secondary command buffer. + */ + struct util_dynarray deferred_csb_commands; + /* List of struct pvr_transfer_cmd used to emulate RTA clears on non RTA + * capable cores. + */ + struct util_dynarray deferred_clears; + + /* List of pvr_bo structs associated with this cmd buffer. */ + struct list_head bo_list; + + struct list_head sub_cmds; +}; + +VK_DEFINE_HANDLE_CASTS(pvr_cmd_buffer, + vk.base, + VkCommandBuffer, + VK_OBJECT_TYPE_COMMAND_BUFFER) + +/* This function is intended to be used when the error being set has been + * returned from a function call, i.e. the error happened further down the + * stack. `vk_command_buffer_set_error()` should be used at the point an error + * occurs, i.e. VK_ERROR_* is being passed in. + * This ensures we only ever get the error printed once. + */ +static inline VkResult +pvr_cmd_buffer_set_error_unwarned(struct pvr_cmd_buffer *cmd_buffer, + VkResult error) +{ + assert(error != VK_SUCCESS); + + if (cmd_buffer->vk.record_result == VK_SUCCESS) + cmd_buffer->vk.record_result = error; + + return error; +} + +static inline bool pvr_sub_cmd_gfx_requires_split_submit( + const struct pvr_sub_cmd_gfx *const sub_cmd) +{ + return sub_cmd->job.run_frag && sub_cmd->framebuffer->layers > 1; +} + +#define PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer) \ + do { \ + struct pvr_cmd_buffer *const _cmd_buffer = (cmd_buffer); \ + const VkResult _record_result = \ + vk_command_buffer_get_record_result(&_cmd_buffer->vk); \ + \ + if (_cmd_buffer->vk.state != MESA_VK_COMMAND_BUFFER_STATE_RECORDING) { \ + vk_errorf(_cmd_buffer, \ + VK_ERROR_OUT_OF_DEVICE_MEMORY, \ + "Command buffer is not in recording state"); \ + return; \ + } else if (_record_result < VK_SUCCESS) { \ + vk_errorf(_cmd_buffer, \ + _record_result, \ + "Skipping function as command buffer has " \ + "previous build error"); \ + return; \ + } \ + } while (0) + +VkResult pvr_cmd_buffer_add_transfer_cmd(struct pvr_cmd_buffer *cmd_buffer, + struct pvr_transfer_cmd *transfer_cmd); + +VkResult pvr_cmd_buffer_alloc_mem(struct pvr_cmd_buffer *cmd_buffer, + struct pvr_winsys_heap *heap, + uint64_t size, + struct pvr_suballoc_bo **const pvr_bo_out); + +VkResult +pvr_cmd_buffer_upload_general(struct pvr_cmd_buffer *const cmd_buffer, + const void *const data, + const size_t size, + struct pvr_suballoc_bo **const pvr_bo_out); +VkResult pvr_cmd_buffer_upload_pds(struct pvr_cmd_buffer *const cmd_buffer, + const uint32_t *data, + uint32_t data_size_dwords, + uint32_t data_alignment, + const uint32_t *code, + uint32_t code_size_dwords, + uint32_t code_alignment, + uint64_t min_alignment, + struct pvr_pds_upload *const pds_upload_out); + +VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, + enum pvr_sub_cmd_type type); +VkResult pvr_cmd_buffer_end_sub_cmd(struct pvr_cmd_buffer *cmd_buffer); + +void pvr_compute_generate_fence(struct pvr_cmd_buffer *cmd_buffer, + struct pvr_sub_cmd_compute *const sub_cmd, + bool deallocate_shareds); +void pvr_compute_update_shared_private( + struct pvr_cmd_buffer *cmd_buffer, + struct pvr_sub_cmd_compute *const sub_cmd, + struct pvr_private_compute_pipeline *pipeline); + +void pvr_compute_update_kernel_private( + struct pvr_cmd_buffer *cmd_buffer, + struct pvr_sub_cmd_compute *const sub_cmd, + struct pvr_private_compute_pipeline *pipeline, + const uint32_t global_workgroup_size[static const PVR_WORKGROUP_DIMENSIONS]); + +VkResult pvr_add_query_program(struct pvr_cmd_buffer *cmd_buffer, + const struct pvr_query_info *query_info); + +static inline void +pvr_render_targets_datasets_destroy(struct pvr_render_target *render_target) +{ + u_foreach_bit (valid_idx, render_target->valid_mask) { + struct pvr_rt_dataset *rt_dataset = render_target->rt_dataset[valid_idx]; + + if (rt_dataset && render_target->valid_mask & BITFIELD_BIT(valid_idx)) + pvr_render_target_dataset_destroy(rt_dataset); + + render_target->rt_dataset[valid_idx] = NULL; + render_target->valid_mask &= ~BITFIELD_BIT(valid_idx); + } +} + +void pvr_reset_graphics_dirty_state(struct pvr_cmd_buffer *const cmd_buffer, + bool start_geom); + +void pvr_calculate_vertex_cam_size(const struct pvr_device_info *dev_info, + const uint32_t vs_output_size, + const bool raster_enable, + uint32_t *const cam_size_out, + uint32_t *const vs_max_instances_out); + +const struct pvr_renderpass_hwsetup_subpass * +pvr_get_hw_subpass(const struct pvr_render_pass *pass, const uint32_t subpass); + +#endif /* PVR_CMD_BUFFER_H */ diff --git a/src/imagination/vulkan/pvr_device.c b/src/imagination/vulkan/pvr_device.c index 31564fee65c..8a5df37463f 100644 --- a/src/imagination/vulkan/pvr_device.c +++ b/src/imagination/vulkan/pvr_device.c @@ -51,6 +51,7 @@ #include "pvr_border.h" #include "pvr_buffer.h" #include "pvr_clear.h" +#include "pvr_cmd_buffer.h" #include "pvr_csb.h" #include "pvr_csb_enum_helpers.h" #include "pvr_debug.h" diff --git a/src/imagination/vulkan/pvr_job_compute.c b/src/imagination/vulkan/pvr_job_compute.c index 00d62ed9bcc..56f0dac5a97 100644 --- a/src/imagination/vulkan/pvr_job_compute.c +++ b/src/imagination/vulkan/pvr_job_compute.c @@ -26,6 +26,7 @@ #include #include +#include "pvr_cmd_buffer.h" #include "pvr_csb.h" #include "pvr_debug.h" #include "pvr_device.h" diff --git a/src/imagination/vulkan/pvr_job_render.c b/src/imagination/vulkan/pvr_job_render.c index bac5d3a1361..6f69c69a450 100644 --- a/src/imagination/vulkan/pvr_job_render.c +++ b/src/imagination/vulkan/pvr_job_render.c @@ -29,6 +29,7 @@ #include "hwdef/rogue_hw_defs.h" #include "hwdef/rogue_hw_utils.h" #include "pvr_bo.h" +#include "pvr_cmd_buffer.h" #include "pvr_csb.h" #include "pvr_debug.h" #include "pvr_device.h" diff --git a/src/imagination/vulkan/pvr_job_transfer.c b/src/imagination/vulkan/pvr_job_transfer.c index add5a41419d..a0b7eda66d1 100644 --- a/src/imagination/vulkan/pvr_job_transfer.c +++ b/src/imagination/vulkan/pvr_job_transfer.c @@ -28,6 +28,7 @@ #include #include +#include "pvr_cmd_buffer.h" #include "pvr_csb.h" #include "pvr_csb_enum_helpers.h" #include "pvr_device.h" diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index dfe0f4d2657..c3ebda0e208 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -62,7 +62,6 @@ #include "util/simple_mtx.h" #include "util/u_dynarray.h" #include "util/u_math.h" -#include "vk_command_buffer.h" #include "vk_enum_to_str.h" #include "vk_graphics_state.h" #include "vk_log.h" @@ -77,498 +76,11 @@ # define VG(x) ((void)0) #endif -struct pvr_bo; -struct pvr_buffer; struct pvr_compute_pipeline; struct pvr_device; struct pvr_graphics_pipeline; struct pvr_physical_device; -struct pvr_vertex_binding { - struct pvr_buffer *buffer; - VkDeviceSize offset; - VkDeviceSize size; -}; - -#define PVR_TRANSFER_MAX_SOURCES 10U -#define PVR_TRANSFER_MAX_CUSTOM_MAPPINGS 6U - -/** A surface describes a source or destination for a transfer operation. */ -struct pvr_transfer_cmd_surface { - pvr_dev_addr_t dev_addr; - - /* Memory address for extra U/V planes. */ - pvr_dev_addr_t uv_address[2]; - - /* Surface width in texels. */ - uint32_t width; - - /* Surface height in texels. */ - uint32_t height; - - uint32_t depth; - - /* Z position in a 3D tecture. 0.0f <= z_position <= depth. */ - float z_position; - - /* Stride in texels. */ - uint32_t stride; - - VkFormat vk_format; - - enum pvr_memlayout mem_layout; - - uint32_t sample_count; -}; - -struct pvr_rect_mapping { - VkRect2D src_rect; - VkRect2D dst_rect; - bool flip_x; - bool flip_y; -}; - -struct pvr_transfer_cmd_source { - struct pvr_transfer_cmd_surface surface; - - uint32_t mapping_count; - struct pvr_rect_mapping mappings[PVR_TRANSFER_MAX_CUSTOM_MAPPINGS]; - - /* In the case of a simple 1:1 copy, this setting does not affect the output - * but will affect performance. Use clamp to edge when possible. - */ - /* This is of type enum ROGUE_TEXSTATE_ADDRMODE. */ - int addr_mode; - - /* Source filtering method. */ - enum pvr_filter filter; - - /* MSAA resolve operation. */ - enum pvr_resolve_op resolve_op; -}; - -struct pvr_transfer_cmd { - /* Node to link this cmd into the transfer_cmds list in - * pvr_sub_cmd::transfer structure. - */ - struct list_head link; - - uint32_t flags; - - uint32_t source_count; - - struct pvr_transfer_cmd_source sources[PVR_TRANSFER_MAX_SOURCES]; - - union fi clear_color[4]; - - struct pvr_transfer_cmd_surface dst; - - VkRect2D scissor; - - /* Pointer to cmd buffer this transfer cmd belongs to. This is mainly used - * to link buffer objects allocated during job submission into - * cmd_buffer::bo_list head. - */ - struct pvr_cmd_buffer *cmd_buffer; - - /* Deferred RTA clears are allocated from pvr_cmd_buffer->deferred_clears and - * cannot be freed directly. - */ - bool is_deferred_clear; -}; - -struct pvr_sub_cmd_gfx { - const struct pvr_framebuffer *framebuffer; - - struct pvr_render_job job; - - struct pvr_suballoc_bo *depth_bias_bo; - struct pvr_suballoc_bo *scissor_bo; - - /* Tracking how the loaded depth/stencil values are being used. */ - enum pvr_depth_stencil_usage depth_usage; - enum pvr_depth_stencil_usage stencil_usage; - - /* Tracking whether the subcommand modifies depth/stencil. */ - bool modifies_depth; - bool modifies_stencil; - - /* Store the render to a scratch buffer. */ - bool barrier_store; - /* Load the render (stored with a `barrier_store`) as a background to the - * current render. - */ - bool barrier_load; - - const struct pvr_query_pool *query_pool; - struct util_dynarray sec_query_indices; - - /* Control stream builder object */ - struct pvr_csb control_stream; - - struct pvr_bo *multiview_ctrl_stream; - uint32_t multiview_ctrl_stream_stride; - - /* Required iff pvr_sub_cmd_gfx_requires_split_submit() returns true. */ - struct pvr_bo *terminate_ctrl_stream; - - uint32_t hw_render_idx; - - uint32_t max_tiles_in_flight; - - bool empty_cmd; - - /* True if any fragment shader used in this sub command uses atomic - * operations. - */ - bool frag_uses_atomic_ops; - - bool disable_compute_overlap; - - /* True if any fragment shader used in this sub command has side - * effects. - */ - bool frag_has_side_effects; - - /* True if any vertex shader used in this sub command contains both - * texture reads and texture writes. - */ - bool vertex_uses_texture_rw; - - /* True if any fragment shader used in this sub command contains - * both texture reads and texture writes. - */ - bool frag_uses_texture_rw; - - bool has_query; - - bool wait_on_previous_transfer; - - bool has_depth_feedback; - - uint32_t view_mask; - bool multiview_enabled; -}; - -struct pvr_sub_cmd_compute { - /* Control stream builder object. */ - struct pvr_csb control_stream; - - uint32_t num_shared_regs; - - /* True if any shader used in this sub command uses atomic - * operations. - */ - bool uses_atomic_ops; - - bool uses_barrier; - - bool pds_sw_barrier_requires_clearing; -}; - -struct pvr_sub_cmd_transfer { - bool serialize_with_frag; - - /* Pointer to the actual transfer command list, allowing primary and - * secondary sub-commands to share the same list. - */ - struct list_head *transfer_cmds; - - /* List of pvr_transfer_cmd type structures. Do not access the list - * directly, but always use the transfer_cmds pointer above. - */ - struct list_head transfer_cmds_priv; -}; - -struct pvr_sub_cmd_event { - enum pvr_event_type type; - - union { - struct pvr_sub_cmd_event_set_reset { - struct pvr_event *event; - /* Stages to wait for until the event is set or reset. */ - uint32_t wait_for_stage_mask; - } set_reset; - - struct pvr_sub_cmd_event_wait { - uint32_t count; - /* Events to wait for before resuming. */ - struct pvr_event **events; - /* Stages to wait at. */ - uint32_t *wait_at_stage_masks; - } wait; - - struct pvr_sub_cmd_event_barrier { - /* Stages to wait for. */ - uint32_t wait_for_stage_mask; - /* Stages to wait at. */ - uint32_t wait_at_stage_mask; - } barrier; - }; -}; - -struct pvr_sub_cmd { - /* This links the subcommand in pvr_cmd_buffer:sub_cmds list. */ - struct list_head link; - - enum pvr_sub_cmd_type type; - - /* True if the sub_cmd is owned by this command buffer. False if taken from - * a secondary command buffer, in that case we are not supposed to free any - * resources associated with the sub_cmd. - */ - bool owned; - - union { - struct pvr_sub_cmd_gfx gfx; - struct pvr_sub_cmd_compute compute; - struct pvr_sub_cmd_transfer transfer; - struct pvr_sub_cmd_event event; - }; -}; - -struct pvr_render_pass_info { - const struct pvr_render_pass *pass; - struct pvr_framebuffer *framebuffer; - - struct pvr_image_view **attachments; - - uint32_t subpass_idx; - uint32_t current_hw_subpass; - - VkRect2D render_area; - - uint32_t clear_value_count; - VkClearValue *clear_values; - - VkPipelineBindPoint pipeline_bind_point; - - bool process_empty_tiles; - bool enable_bg_tag; - uint32_t isp_userpass; -}; - -struct pvr_ppp_state { - uint32_t header; - - struct { - /* TODO: Can we get rid of the "control" field? */ - struct ROGUE_TA_STATE_ISPCTL control_struct; - uint32_t control; - - uint32_t front_a; - uint32_t front_b; - uint32_t back_a; - uint32_t back_b; - } isp; - - struct pvr_ppp_dbsc { - uint16_t scissor_index; - uint16_t depthbias_index; - } depthbias_scissor_indices; - - struct { - uint32_t pixel_shader_base; - uint32_t texture_uniform_code_base; - uint32_t size_info1; - uint32_t size_info2; - uint32_t varying_base; - uint32_t texture_state_data_base; - uint32_t uniform_state_data_base; - } pds; - - struct { - uint32_t word0; - uint32_t word1; - } region_clipping; - - struct { - uint32_t a0; - uint32_t m0; - uint32_t a1; - uint32_t m1; - uint32_t a2; - uint32_t m2; - } viewports[PVR_MAX_VIEWPORTS]; - - uint32_t viewport_count; - - uint32_t output_selects; - - uint32_t varying_word[2]; - - uint32_t ppp_control; -}; - -/* Represents a control stream related command that is deferred for execution in - * a secondary command buffer. - */ -struct pvr_deferred_cs_command { - enum pvr_deferred_cs_command_type type; - union { - struct { - struct pvr_ppp_dbsc state; - - uint32_t *vdm_state; - } dbsc; - - struct { - struct pvr_ppp_dbsc state; - - struct pvr_suballoc_bo *ppp_cs_bo; - uint32_t patch_offset; - } dbsc2; - }; -}; - -struct pvr_cmd_buffer_draw_state { - uint32_t base_instance; - uint32_t base_vertex; - bool draw_indirect; - bool draw_indexed; -}; - -struct pvr_push_constants { - uint8_t data[PVR_MAX_PUSH_CONSTANTS_SIZE]; - unsigned bytes_updated; - pvr_dev_addr_t dev_addr; - bool dirty; -}; - -struct pvr_cmd_buffer_state { - /* Pipeline binding. */ - const struct pvr_graphics_pipeline *gfx_pipeline; - - const struct pvr_compute_pipeline *compute_pipeline; - - struct pvr_render_pass_info render_pass_info; - - struct pvr_sub_cmd *current_sub_cmd; - - struct pvr_ppp_state ppp_state; - - struct ROGUE_TA_STATE_HEADER emit_header; - - struct pvr_vertex_binding vertex_bindings[PVR_MAX_VERTEX_INPUT_BINDINGS]; - - struct { - struct pvr_buffer *buffer; - VkDeviceSize offset; - VkIndexType type; - } index_buffer_binding; - - /* Array size of barriers_needed is based on number of sync pipeline - * stages. - */ - uint32_t barriers_needed[PVR_NUM_SYNC_PIPELINE_STAGES]; - - struct pvr_descriptor_state gfx_desc_state; - struct pvr_descriptor_state compute_desc_state; - - struct pvr_push_constants push_consts[PVR_STAGE_ALLOCATION_COUNT]; - - VkFormat depth_format; - - struct { - bool compute_pipeline_binding : 1; - bool compute_desc_dirty : 1; - - bool gfx_pipeline_binding : 1; - bool gfx_desc_dirty : 1; - - bool vertex_bindings : 1; - bool index_buffer_binding : 1; - bool vertex_descriptors : 1; - bool fragment_descriptors : 1; - - bool isp_userpass : 1; - - /* Some draw state needs to be tracked for changes between draw calls - * i.e. if we get a draw with baseInstance=0, followed by a call with - * baseInstance=1 that needs to cause us to select a different PDS - * attrib program and update the BASE_INSTANCE PDS const. If only - * baseInstance changes then we just have to update the data section. - */ - bool draw_base_instance : 1; - bool draw_variant : 1; - - bool vis_test; - } dirty; - - struct pvr_cmd_buffer_draw_state draw_state; - - struct { - uint32_t code_offset; - const struct pvr_pds_info *info; - } pds_shader; - - const struct pvr_query_pool *query_pool; - bool vis_test_enabled; - uint32_t vis_reg; - - struct util_dynarray query_indices; - - uint32_t max_shared_regs; - - /* Address of data segment for vertex attrib upload program. */ - uint32_t pds_vertex_attrib_offset; - - uint32_t pds_fragment_descriptor_data_offset; - uint32_t pds_compute_descriptor_data_offset; -}; - -/* Do not change this. This is the format used for the depth_bias_array - * elements uploaded to the device. - */ -struct pvr_depth_bias_state { - /* Saved information from pCreateInfo. */ - float constant_factor; - float slope_factor; - float clamp; -}; - -/* Do not change this. This is the format used for the scissor_array - * elements uploaded to the device. - */ -struct pvr_scissor_words { - /* Contains a packed IPF_SCISSOR_WORD_0. */ - uint32_t w0; - /* Contains a packed IPF_SCISSOR_WORD_1. */ - uint32_t w1; -}; - -struct pvr_cmd_buffer { - struct vk_command_buffer vk; - - struct pvr_device *device; - - /* Buffer usage flags */ - VkCommandBufferUsageFlags usage_flags; - - /* Array of struct pvr_depth_bias_state. */ - struct util_dynarray depth_bias_array; - - /* Array of struct pvr_scissor_words. */ - struct util_dynarray scissor_array; - struct pvr_scissor_words scissor_words; - - struct pvr_cmd_buffer_state state; - - /* List of struct pvr_deferred_cs_command control stream related commands to - * execute in secondary command buffer. - */ - struct util_dynarray deferred_csb_commands; - /* List of struct pvr_transfer_cmd used to emulate RTA clears on non RTA - * capable cores. - */ - struct util_dynarray deferred_clears; - - /* List of pvr_bo structs associated with this cmd buffer. */ - struct list_head bo_list; - - struct list_head sub_cmds; -}; - struct pvr_stage_allocation_descriptor_state { struct pvr_pds_upload pds_code; /* Since we upload the code segment separately from the data segment @@ -741,20 +253,6 @@ struct pvr_query_info { VkResult pvr_wsi_init(struct pvr_physical_device *pdevice); void pvr_wsi_finish(struct pvr_physical_device *pdevice); -VkResult pvr_cmd_buffer_add_transfer_cmd(struct pvr_cmd_buffer *cmd_buffer, - struct pvr_transfer_cmd *transfer_cmd); - -VkResult pvr_cmd_buffer_alloc_mem(struct pvr_cmd_buffer *cmd_buffer, - struct pvr_winsys_heap *heap, - uint64_t size, - struct pvr_suballoc_bo **const pvr_bo_out); - -void pvr_calculate_vertex_cam_size(const struct pvr_device_info *dev_info, - const uint32_t vs_output_size, - const bool raster_enable, - uint32_t *const cam_size_out, - uint32_t *const vs_max_instances_out); - static inline struct pvr_compute_pipeline * to_pvr_compute_pipeline(struct pvr_pipeline *pipeline) { @@ -835,95 +333,11 @@ pvr_stage_mask_dst(VkPipelineStageFlags2 stage_mask) return pvr_stage_mask(stage_mask); } -static inline bool pvr_sub_cmd_gfx_requires_split_submit( - const struct pvr_sub_cmd_gfx *const sub_cmd) -{ - return sub_cmd->job.run_frag && sub_cmd->framebuffer->layers > 1; -} - -/* This function is intended to be used when the error being set has been - * returned from a function call, i.e. the error happened further down the - * stack. `vk_command_buffer_set_error()` should be used at the point an error - * occurs, i.e. VK_ERROR_* is being passed in. - * This ensures we only ever get the error printed once. - */ -static inline VkResult -pvr_cmd_buffer_set_error_unwarned(struct pvr_cmd_buffer *cmd_buffer, - VkResult error) -{ - assert(error != VK_SUCCESS); - - if (cmd_buffer->vk.record_result == VK_SUCCESS) - cmd_buffer->vk.record_result = error; - - return error; -} - -VkResult -pvr_cmd_buffer_upload_general(struct pvr_cmd_buffer *const cmd_buffer, - const void *const data, - const size_t size, - struct pvr_suballoc_bo **const pvr_bo_out); -VkResult pvr_cmd_buffer_upload_pds(struct pvr_cmd_buffer *const cmd_buffer, - const uint32_t *data, - uint32_t data_size_dwords, - uint32_t data_alignment, - const uint32_t *code, - uint32_t code_size_dwords, - uint32_t code_alignment, - uint64_t min_alignment, - struct pvr_pds_upload *const pds_upload_out); - -VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, - enum pvr_sub_cmd_type type); -VkResult pvr_cmd_buffer_end_sub_cmd(struct pvr_cmd_buffer *cmd_buffer); - -void pvr_compute_generate_fence(struct pvr_cmd_buffer *cmd_buffer, - struct pvr_sub_cmd_compute *const sub_cmd, - bool deallocate_shareds); -void pvr_compute_update_shared_private( - struct pvr_cmd_buffer *cmd_buffer, - struct pvr_sub_cmd_compute *const sub_cmd, - struct pvr_private_compute_pipeline *pipeline); -void pvr_compute_update_kernel_private( - struct pvr_cmd_buffer *cmd_buffer, - struct pvr_sub_cmd_compute *const sub_cmd, - struct pvr_private_compute_pipeline *pipeline, - const uint32_t global_workgroup_size[static const PVR_WORKGROUP_DIMENSIONS]); - size_t pvr_pds_get_max_descriptor_upload_const_map_size_in_bytes(void); VkResult pvr_device_create_compute_query_programs(struct pvr_device *device); void pvr_device_destroy_compute_query_programs(struct pvr_device *device); -VkResult pvr_add_query_program(struct pvr_cmd_buffer *cmd_buffer, - const struct pvr_query_info *query_info); - -void pvr_reset_graphics_dirty_state(struct pvr_cmd_buffer *const cmd_buffer, - bool start_geom); - -const struct pvr_renderpass_hwsetup_subpass * -pvr_get_hw_subpass(const struct pvr_render_pass *pass, const uint32_t subpass); - -static inline void -pvr_render_targets_datasets_destroy(struct pvr_render_target *render_target) -{ - u_foreach_bit (valid_idx, render_target->valid_mask) { - struct pvr_rt_dataset *rt_dataset = render_target->rt_dataset[valid_idx]; - - if (rt_dataset && render_target->valid_mask & BITFIELD_BIT(valid_idx)) - pvr_render_target_dataset_destroy(rt_dataset); - - render_target->rt_dataset[valid_idx] = NULL; - render_target->valid_mask &= ~BITFIELD_BIT(valid_idx); - } -} - -VK_DEFINE_HANDLE_CASTS(pvr_cmd_buffer, - vk.base, - VkCommandBuffer, - VK_OBJECT_TYPE_COMMAND_BUFFER) - VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_descriptor_set_layout, vk.base, VkDescriptorSetLayout, @@ -945,26 +359,6 @@ VK_DEFINE_NONDISP_HANDLE_CASTS(pvr_query_pool, VkQueryPool, VK_OBJECT_TYPE_QUERY_POOL) -#define PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer) \ - do { \ - struct pvr_cmd_buffer *const _cmd_buffer = (cmd_buffer); \ - const VkResult _record_result = \ - vk_command_buffer_get_record_result(&_cmd_buffer->vk); \ - \ - if (_cmd_buffer->vk.state != MESA_VK_COMMAND_BUFFER_STATE_RECORDING) { \ - vk_errorf(_cmd_buffer, \ - VK_ERROR_OUT_OF_DEVICE_MEMORY, \ - "Command buffer is not in recording state"); \ - return; \ - } else if (_record_result < VK_SUCCESS) { \ - vk_errorf(_cmd_buffer, \ - _record_result, \ - "Skipping function as command buffer has " \ - "previous build error"); \ - return; \ - } \ - } while (0) - /** * Print a FINISHME message, including its source location. */ diff --git a/src/imagination/vulkan/pvr_query.c b/src/imagination/vulkan/pvr_query.c index 6e97ecc1cc3..690226c47a2 100644 --- a/src/imagination/vulkan/pvr_query.c +++ b/src/imagination/vulkan/pvr_query.c @@ -31,6 +31,7 @@ #include #include "pvr_bo.h" +#include "pvr_cmd_buffer.h" #include "pvr_csb.h" #include "pvr_device.h" #include "pvr_device_info.h" diff --git a/src/imagination/vulkan/pvr_query_compute.c b/src/imagination/vulkan/pvr_query_compute.c index 98209716155..b61c0d7a5ff 100644 --- a/src/imagination/vulkan/pvr_query_compute.c +++ b/src/imagination/vulkan/pvr_query_compute.c @@ -33,6 +33,7 @@ #include "pco_uscgen_programs.h" #include "pvr_bo.h" #include "pvr_buffer.h" +#include "pvr_cmd_buffer.h" #include "pvr_device.h" #include "pvr_formats.h" #include "pvr_pds.h" diff --git a/src/imagination/vulkan/pvr_queue.c b/src/imagination/vulkan/pvr_queue.c index 6a8d248d04e..9fffdfaf35c 100644 --- a/src/imagination/vulkan/pvr_queue.c +++ b/src/imagination/vulkan/pvr_queue.c @@ -38,6 +38,7 @@ #include #include +#include "pvr_cmd_buffer.h" #include "pvr_device.h" #include "pvr_job_compute.h" #include "pvr_job_context.h"