lavapipe: Suspend conditional rendering around ray tracing dispatches

cc: mesa-stable

Reviewed-by: Mike Blumenkrantz <michael.blumenkrantz@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/35754>
(cherry picked from commit 131b917246)
This commit is contained in:
Konstantin Seurer 2025-06-25 22:06:00 +02:00 committed by Eric Engestrom
parent 27df7b4a8c
commit b474d8e858
2 changed files with 58 additions and 32 deletions

View file

@ -2414,7 +2414,7 @@
"description": "lavapipe: Suspend conditional rendering around ray tracing dispatches",
"nominated": true,
"nomination_type": 1,
"resolution": 0,
"resolution": 1,
"main_sha": null,
"because_sha": null,
"notes": null

View file

@ -80,6 +80,13 @@ struct lvp_render_attachment {
bool read_only;
};
struct lvp_conditional_rendering_state {
struct pipe_resource *buffer;
uint32_t offset;
bool condition;
bool enabled;
};
struct rendering_state {
struct pipe_context *pctx;
struct lvp_device *device;
@ -171,7 +178,6 @@ struct rendering_state {
VkRect2D render_area;
bool suspending;
bool render_cond;
uint32_t color_att_count;
struct lvp_render_attachment color_att[PIPE_MAX_COLOR_BUFS];
struct lvp_render_attachment depth_att;
@ -205,6 +211,8 @@ struct rendering_state {
struct lvp_pipeline *exec_graph;
struct lvp_conditional_rendering_state conditional_rendering;
struct {
struct lvp_shader *compute_shader;
uint8_t push_constants[128 * 4];
@ -1392,7 +1400,7 @@ static void render_clear_fast(struct rendering_state *state)
if (state->framebuffer.viewmask)
goto slow_clear;
if (state->render_cond)
if (state->conditional_rendering.enabled)
goto slow_clear;
uint32_t buffers = 0;
@ -3401,21 +3409,35 @@ static void handle_draw_indirect_byte_count(struct vk_cmd_queue_entry *cmd,
state->pctx->draw_vbo(state->pctx, &state->info, 0, NULL, &draw, 1);
}
static void
lvp_emit_conditional_rendering(struct rendering_state *state)
{
if (state->conditional_rendering.enabled) {
state->pctx->render_condition_mem(
state->pctx,
state->conditional_rendering.buffer,
state->conditional_rendering.offset,
state->conditional_rendering.condition);
} else {
state->pctx->render_condition_mem(state->pctx, NULL, 0, false);
}
}
static void handle_begin_conditional_rendering(struct vk_cmd_queue_entry *cmd,
struct rendering_state *state)
{
struct VkConditionalRenderingBeginInfoEXT *bcr = cmd->u.begin_conditional_rendering_ext.conditional_rendering_begin;
state->render_cond = true;
state->pctx->render_condition_mem(state->pctx,
lvp_buffer_from_handle(bcr->buffer)->bo,
bcr->offset,
bcr->flags & VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT);
state->conditional_rendering.buffer = lvp_buffer_from_handle(bcr->buffer)->bo;
state->conditional_rendering.offset = bcr->offset;
state->conditional_rendering.condition = bcr->flags & VK_CONDITIONAL_RENDERING_INVERTED_BIT_EXT;
state->conditional_rendering.enabled = true;
lvp_emit_conditional_rendering(state);
}
static void handle_end_conditional_rendering(struct rendering_state *state)
{
state->render_cond = false;
state->pctx->render_condition_mem(state->pctx, NULL, 0, false);
state->conditional_rendering.enabled = false;
lvp_emit_conditional_rendering(state);
}
static void handle_set_vertex_input(struct vk_cmd_queue_entry *cmd,
@ -4532,8 +4554,10 @@ handle_write_acceleration_structures_properties(struct vk_cmd_queue_entry *cmd,
}
}
static void emit_ray_tracing_state(struct rendering_state *state)
static void
lvp_trace_rays(struct rendering_state *state, VkTraceRaysIndirectCommand2KHR *command)
{
/* Emit ray tracing state. */
bool pcbuf_dirty = state->pcbuf_dirty[MESA_SHADER_RAYGEN];
if (pcbuf_dirty)
update_pcbuf(state, MESA_SHADER_COMPUTE, MESA_SHADER_RAYGEN);
@ -4550,6 +4574,26 @@ static void emit_ray_tracing_state(struct rendering_state *state)
state->pcbuf_dirty[MESA_SHADER_COMPUTE] = true;
state->constbuf_dirty[MESA_SHADER_COMPUTE] = true;
state->compute_shader_dirty = true;
/* Dispatch. The spec states that conditional rendering only affects compute dispatches
* so ray tracing dispatches have to suspend it.
*/
state->trace_rays_info.grid[0] = DIV_ROUND_UP(command->width, state->trace_rays_info.block[0]);
state->trace_rays_info.grid[1] = DIV_ROUND_UP(command->height, state->trace_rays_info.block[1]);
state->trace_rays_info.grid[2] = DIV_ROUND_UP(command->depth, state->trace_rays_info.block[2]);
bool conditional_rendering_enabled = state->conditional_rendering.enabled;
if (conditional_rendering_enabled) {
state->conditional_rendering.enabled = false;
lvp_emit_conditional_rendering(state);
}
state->pctx->launch_grid(state->pctx, &state->trace_rays_info);
if (conditional_rendering_enabled) {
state->conditional_rendering.enabled = true;
lvp_emit_conditional_rendering(state);
}
}
static void
@ -4557,8 +4601,6 @@ handle_trace_rays(struct vk_cmd_queue_entry *cmd, struct rendering_state *state)
{
struct vk_cmd_trace_rays_khr *trace = &cmd->u.trace_rays_khr;
emit_ray_tracing_state(state);
VkTraceRaysIndirectCommand2KHR *command = lvp_push_internal_buffer(
state, MESA_SHADER_COMPUTE, sizeof(VkTraceRaysIndirectCommand2KHR));
@ -4579,11 +4621,7 @@ handle_trace_rays(struct vk_cmd_queue_entry *cmd, struct rendering_state *state)
.depth = trace->depth,
};
state->trace_rays_info.grid[0] = DIV_ROUND_UP(trace->width, state->trace_rays_info.block[0]);
state->trace_rays_info.grid[1] = DIV_ROUND_UP(trace->height, state->trace_rays_info.block[1]);
state->trace_rays_info.grid[2] = DIV_ROUND_UP(trace->depth, state->trace_rays_info.block[2]);
state->pctx->launch_grid(state->pctx, &state->trace_rays_info);
lvp_trace_rays(state, command);
}
static void
@ -4591,8 +4629,6 @@ handle_trace_rays_indirect(struct vk_cmd_queue_entry *cmd, struct rendering_stat
{
struct vk_cmd_trace_rays_indirect_khr *trace = &cmd->u.trace_rays_indirect_khr;
emit_ray_tracing_state(state);
size_t indirect_offset;
VkBuffer _indirect = get_buffer(state, (void *)(uintptr_t)trace->indirect_device_address, &indirect_offset);
VK_FROM_HANDLE(lvp_buffer, indirect, _indirect);
@ -4622,13 +4658,9 @@ handle_trace_rays_indirect(struct vk_cmd_queue_entry *cmd, struct rendering_stat
.depth = src->depth,
};
state->trace_rays_info.grid[0] = DIV_ROUND_UP(src->width, state->trace_rays_info.block[0]);
state->trace_rays_info.grid[1] = DIV_ROUND_UP(src->height, state->trace_rays_info.block[1]);
state->trace_rays_info.grid[2] = DIV_ROUND_UP(src->depth, state->trace_rays_info.block[2]);
state->pctx->buffer_unmap(state->pctx, transfer);
state->pctx->launch_grid(state->pctx, &state->trace_rays_info);
lvp_trace_rays(state, command);
}
static void
@ -4636,8 +4668,6 @@ handle_trace_rays_indirect2(struct vk_cmd_queue_entry *cmd, struct rendering_sta
{
struct vk_cmd_trace_rays_indirect2_khr *trace = &cmd->u.trace_rays_indirect2_khr;
emit_ray_tracing_state(state);
size_t indirect_offset;
VkBuffer _indirect = get_buffer(state, (void *)(uintptr_t)trace->indirect_device_address, &indirect_offset);
VK_FROM_HANDLE(lvp_buffer, indirect, _indirect);
@ -4651,13 +4681,9 @@ handle_trace_rays_indirect2(struct vk_cmd_queue_entry *cmd, struct rendering_sta
state, MESA_SHADER_COMPUTE, sizeof(VkTraceRaysIndirectCommand2KHR));
*command = *src;
state->trace_rays_info.grid[0] = DIV_ROUND_UP(src->width, state->trace_rays_info.block[0]);
state->trace_rays_info.grid[1] = DIV_ROUND_UP(src->height, state->trace_rays_info.block[1]);
state->trace_rays_info.grid[2] = DIV_ROUND_UP(src->depth, state->trace_rays_info.block[2]);
state->pctx->buffer_unmap(state->pctx, transfer);
state->pctx->launch_grid(state->pctx, &state->trace_rays_info);
lvp_trace_rays(state, command);
}
static void