diff --git a/src/imagination/vulkan/pvr_cmd_buffer.c b/src/imagination/vulkan/pvr_cmd_buffer.c index 763a535ccc0..30e863d171e 100644 --- a/src/imagination/vulkan/pvr_cmd_buffer.c +++ b/src/imagination/vulkan/pvr_cmd_buffer.c @@ -139,6 +139,8 @@ static void pvr_cmd_buffer_free_resources(struct pvr_cmd_buffer *cmd_buffer) vk_free(&cmd_buffer->vk.pool->alloc, cmd_buffer->state.render_pass_info.clear_values); + util_dynarray_fini(&cmd_buffer->state.query_indices); + pvr_cmd_buffer_free_sub_cmds(cmd_buffer); list_for_each_entry_safe (struct pvr_bo, bo, &cmd_buffer->bo_list, link) { @@ -1421,7 +1423,7 @@ pvr_compute_generate_fence(struct pvr_cmd_buffer *cmd_buffer, pvr_compute_generate_control_stream(csb, sub_cmd, &info); } -static VkResult pvr_cmd_buffer_end_sub_cmd(struct pvr_cmd_buffer *cmd_buffer) +VkResult pvr_cmd_buffer_end_sub_cmd(struct pvr_cmd_buffer *cmd_buffer) { struct pvr_cmd_buffer_state *state = &cmd_buffer->state; struct pvr_sub_cmd *sub_cmd = state->current_sub_cmd; @@ -1595,8 +1597,8 @@ pvr_cmd_uses_deferred_cs_cmds(const struct pvr_cmd_buffer *const cmd_buffer) deferred_control_stream_flags; } -static VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, - enum pvr_sub_cmd_type type) +VkResult pvr_cmd_buffer_start_sub_cmd(struct pvr_cmd_buffer *cmd_buffer, + enum pvr_sub_cmd_type type) { struct pvr_cmd_buffer_state *state = &cmd_buffer->state; struct pvr_device *device = cmd_buffer->device; @@ -2472,8 +2474,12 @@ VkResult pvr_BeginCommandBuffer(VkCommandBuffer commandBuffer, pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_GRAPHICS); if (result != VK_SUCCESS) return result; + + state->vis_test_enabled = inheritance_info->occlusionQueryEnable; } + util_dynarray_init(&state->query_indices, NULL); + memset(state->barriers_needed, 0xFF, sizeof(*state->barriers_needed) * ARRAY_SIZE(state->barriers_needed)); @@ -3604,6 +3610,11 @@ pvr_setup_isp_faces_and_control(struct pvr_cmd_buffer *const cmd_buffer, ispctl.dbenable = !rasterizer_discard && dynamic_state->rs.depth_bias.enable && obj_type == PVRX(TA_OBJTYPE_TRIANGLE); + if (!rasterizer_discard && cmd_buffer->state.vis_test_enabled) { + ispctl.vistest = true; + ispctl.visreg = cmd_buffer->state.vis_reg; + } + ispctl.scenable = !rasterizer_discard; ppp_state->isp.control_struct = ispctl; @@ -4526,7 +4537,7 @@ pvr_emit_dirty_ppp_state(struct pvr_cmd_buffer *const cmd_buffer, MESA_VK_DYNAMIC_DS_STENCIL_WRITE_MASK) || BITSET_TEST(dynamic_state->dirty, MESA_VK_DYNAMIC_RS_LINE_WIDTH) || - state->dirty.isp_userpass) { + state->dirty.isp_userpass || state->dirty.vis_test) { pvr_setup_isp_faces_and_control(cmd_buffer, NULL); } @@ -4829,6 +4840,8 @@ static VkResult pvr_validate_draw_state(struct pvr_cmd_buffer *cmd_buffer) sub_cmd->frag_uses_texture_rw |= fragment_state->uses_texture_rw; sub_cmd->vertex_uses_texture_rw |= vertex_state->uses_texture_rw; + sub_cmd->job.get_vis_results = state->vis_test_enabled; + fstencil_keep = (dynamic_state->ds.stencil.front.op.fail == VK_STENCIL_OP_KEEP) && (dynamic_state->ds.stencil.front.op.pass == VK_STENCIL_OP_KEEP); @@ -4937,6 +4950,7 @@ static VkResult pvr_validate_draw_state(struct pvr_cmd_buffer *cmd_buffer) state->dirty.gfx_pipeline_binding = false; state->dirty.isp_userpass = false; state->dirty.vertex_bindings = false; + state->dirty.vis_test = false; return VK_SUCCESS; } @@ -5701,6 +5715,9 @@ pvr_execute_graphics_cmd_buffer(struct pvr_cmd_buffer *cmd_buffer, struct pvr_sub_cmd *primary_sub_cmd = state->current_sub_cmd; VkResult result; + /* Inherited queries are not supported. */ + assert(!state->vis_test_enabled); + if (list_is_empty(&sec_cmd_buffer->sub_cmds)) return; @@ -6431,6 +6448,11 @@ VkResult pvr_EndCommandBuffer(VkCommandBuffer commandBuffer) if (state->status != VK_SUCCESS) return state->status; + /* TODO: We should be freeing all the resources, allocated for recording, + * here. + */ + util_dynarray_fini(&state->query_indices); + result = pvr_cmd_buffer_end_sub_cmd(cmd_buffer); if (result != VK_SUCCESS) return result; diff --git a/src/imagination/vulkan/pvr_job_render.c b/src/imagination/vulkan/pvr_job_render.c index 19f768e4ff9..7db4e7b8678 100644 --- a/src/imagination/vulkan/pvr_job_render.c +++ b/src/imagination/vulkan/pvr_job_render.c @@ -1623,6 +1623,9 @@ pvr_render_job_ws_fragment_state_init(struct pvr_render_ctx *ctx, if (job->frag_uses_atomic_ops) state->flags |= PVR_WINSYS_FRAG_FLAG_SINGLE_CORE; + + if (job->get_vis_results) + state->flags |= PVR_WINSYS_FRAG_FLAG_GET_VIS_RESULTS; } static void pvr_render_job_ws_submit_info_init( diff --git a/src/imagination/vulkan/pvr_job_render.h b/src/imagination/vulkan/pvr_job_render.h index 825fd85735b..bb122931bdc 100644 --- a/src/imagination/vulkan/pvr_job_render.h +++ b/src/imagination/vulkan/pvr_job_render.h @@ -51,6 +51,7 @@ struct pvr_render_job { bool disable_compute_overlap; bool enable_bg_tag; bool process_empty_tiles; + bool get_vis_results; uint32_t pds_pixel_event_data_offset; diff --git a/src/imagination/vulkan/pvr_private.h b/src/imagination/vulkan/pvr_private.h index 02e2df423c9..f31a6937893 100644 --- a/src/imagination/vulkan/pvr_private.h +++ b/src/imagination/vulkan/pvr_private.h @@ -684,6 +684,11 @@ struct pvr_sub_cmd_gfx { bool modifies_depth; bool modifies_stencil; + bool barrier_store; + bool barrier_load; + + const struct pvr_query_pool *query_pool; + /* Control stream builder object */ struct pvr_csb control_stream; @@ -961,6 +966,8 @@ struct pvr_cmd_buffer_state { */ bool draw_base_instance : 1; bool draw_variant : 1; + + bool vis_test; } dirty; struct pvr_cmd_buffer_draw_state draw_state; @@ -970,6 +977,12 @@ struct pvr_cmd_buffer_state { 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. */ @@ -1554,6 +1567,10 @@ VkResult pvr_device_tile_buffer_ensure_cap(struct pvr_device *device, uint32_t capacity, uint32_t size_in_bytes); +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_update_shared_private( struct pvr_cmd_buffer *cmd_buffer, struct pvr_sub_cmd_compute *const sub_cmd, diff --git a/src/imagination/vulkan/pvr_query.c b/src/imagination/vulkan/pvr_query.c index 61c06a3db71..de73bff032d 100644 --- a/src/imagination/vulkan/pvr_query.c +++ b/src/imagination/vulkan/pvr_query.c @@ -230,7 +230,51 @@ void pvr_CmdBeginQuery(VkCommandBuffer commandBuffer, uint32_t query, VkQueryControlFlags flags) { - assert(!"Unimplemented"); + PVR_FROM_HANDLE(pvr_cmd_buffer, cmd_buffer, commandBuffer); + struct pvr_cmd_buffer_state *state = &cmd_buffer->state; + PVR_FROM_HANDLE(pvr_query_pool, pool, queryPool); + + PVR_CHECK_COMMAND_BUFFER_BUILDING_STATE(cmd_buffer); + + /* Occlusion queries can't be nested. */ + assert(!state->vis_test_enabled); + + if (state->current_sub_cmd) { + assert(state->current_sub_cmd->type == PVR_SUB_CMD_TYPE_GRAPHICS); + + if (!state->current_sub_cmd->gfx.query_pool) { + state->current_sub_cmd->gfx.query_pool = pool; + } else if (state->current_sub_cmd->gfx.query_pool != pool) { + VkResult result; + + /* Kick render. */ + state->current_sub_cmd->gfx.barrier_store = true; + + result = pvr_cmd_buffer_end_sub_cmd(cmd_buffer); + if (result != VK_SUCCESS) + return; + + result = + pvr_cmd_buffer_start_sub_cmd(cmd_buffer, PVR_SUB_CMD_TYPE_GRAPHICS); + if (result != VK_SUCCESS) + return; + + /* Use existing render setup, but load color attachments from HW + * BGOBJ. + */ + state->current_sub_cmd->gfx.barrier_load = true; + state->current_sub_cmd->gfx.barrier_store = false; + state->current_sub_cmd->gfx.query_pool = pool; + } + } + + state->query_pool = pool; + state->vis_test_enabled = true; + state->vis_reg = query; + state->dirty.vis_test = true; + + /* Add the index to the list for this render. */ + util_dynarray_append(&state->query_indices, __typeof__(query), query); } void pvr_CmdEndQuery(VkCommandBuffer commandBuffer, diff --git a/src/imagination/vulkan/winsys/pvr_winsys.h b/src/imagination/vulkan/winsys/pvr_winsys.h index e7851025f4b..cb03f3727a9 100644 --- a/src/imagination/vulkan/winsys/pvr_winsys.h +++ b/src/imagination/vulkan/winsys/pvr_winsys.h @@ -338,6 +338,7 @@ struct pvr_winsys_compute_submit_info { #define PVR_WINSYS_FRAG_FLAG_STENCIL_BUFFER_PRESENT BITFIELD_BIT(1U) #define PVR_WINSYS_FRAG_FLAG_PREVENT_CDM_OVERLAP BITFIELD_BIT(2U) #define PVR_WINSYS_FRAG_FLAG_SINGLE_CORE BITFIELD_BIT(3U) +#define PVR_WINSYS_FRAG_FLAG_GET_VIS_RESULTS BITFIELD_BIT(4U) struct pvr_winsys_render_submit_info { struct pvr_winsys_rt_dataset *rt_dataset; diff --git a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c index d6d1510f595..64e9f4348b3 100644 --- a/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c +++ b/src/imagination/vulkan/winsys/pvrsrvkm/pvr_srv_job_render.c @@ -659,6 +659,9 @@ static void pvr_srv_fragment_cmd_init( if (state->flags & PVR_WINSYS_FRAG_FLAG_SINGLE_CORE) cmd->flags |= ROGUE_FWIF_RENDERFLAGS_SINGLE_CORE; + + if (state->flags & PVR_WINSYS_FRAG_FLAG_GET_VIS_RESULTS) + cmd->flags |= ROGUE_FWIF_RENDERFLAGS_GETVISRESULTS; } VkResult pvr_srv_winsys_render_submit(