v3dv: broadcast multiview draw commands

We implement multiview by replicating draw commands for all enabled
views and setting a command buffer state for the currently active
view we are broadcasting to.

Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/12034>
This commit is contained in:
Iago Toral Quiroga 2021-07-23 09:41:14 +02:00 committed by Marge Bot
parent d5acae3206
commit 5fd55ab16d
4 changed files with 87 additions and 17 deletions

View File

@ -2096,6 +2096,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
const bool has_new_viewport = dirty_uniform_state & V3DV_CMD_DIRTY_VIEWPORT;
const bool has_new_push_constants = dirty_uniform_state & V3DV_CMD_DIRTY_PUSH_CONSTANTS;
const bool has_new_descriptors = dirty_uniform_state & V3DV_CMD_DIRTY_DESCRIPTOR_SETS;
const bool has_new_view_index = dirty_uniform_state & V3DV_CMD_DIRTY_VIEW_INDEX;
/* VK_SHADER_STAGE_FRAGMENT_BIT */
const bool has_new_descriptors_fs =
@ -2107,8 +2108,10 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
(cmd_buffer->state.dirty_push_constants_stages & VK_SHADER_STAGE_FRAGMENT_BIT);
const bool needs_fs_update = has_new_pipeline ||
has_new_view_index ||
has_new_push_constants_fs ||
has_new_descriptors_fs;
has_new_descriptors_fs ||
has_new_view_index;
if (needs_fs_update) {
struct v3dv_shader_variant *fs_variant =
@ -2131,6 +2134,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
VK_SHADER_STAGE_GEOMETRY_BIT);
const bool needs_gs_update = has_new_viewport ||
has_new_view_index ||
has_new_pipeline ||
has_new_push_constants_gs ||
has_new_descriptors_gs;
@ -2160,6 +2164,7 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
(cmd_buffer->state.dirty_push_constants_stages & VK_SHADER_STAGE_VERTEX_BIT);
const bool needs_vs_update = has_new_viewport ||
has_new_view_index ||
has_new_pipeline ||
has_new_push_constants_vs ||
has_new_descriptors_vs;
@ -2177,6 +2182,8 @@ update_gfx_uniform_state(struct v3dv_cmd_buffer *cmd_buffer,
cmd_buffer->state.uniforms.vs_bin =
v3dv_write_uniforms(cmd_buffer, pipeline, vs_bin_variant);
}
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_VIEW_INDEX;
}
/* This stores command buffer state that we might be about to stomp for
@ -2462,7 +2469,8 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer)
*dirty & (V3DV_CMD_DIRTY_PIPELINE |
V3DV_CMD_DIRTY_PUSH_CONSTANTS |
V3DV_CMD_DIRTY_DESCRIPTOR_SETS |
V3DV_CMD_DIRTY_VIEWPORT);
V3DV_CMD_DIRTY_VIEWPORT |
V3DV_CMD_DIRTY_VIEW_INDEX);
if (dirty_uniform_state)
update_gfx_uniform_state(cmd_buffer, dirty_uniform_state);
@ -2513,12 +2521,32 @@ v3dv_cmd_buffer_emit_pre_draw(struct v3dv_cmd_buffer *cmd_buffer)
cmd_buffer->state.dirty &= ~V3DV_CMD_DIRTY_PIPELINE;
}
static inline void
cmd_buffer_set_view_index(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t view_index)
{
cmd_buffer->state.view_index = view_index;
cmd_buffer->state.dirty |= V3DV_CMD_DIRTY_VIEW_INDEX;
}
static void
cmd_buffer_draw(struct v3dv_cmd_buffer *cmd_buffer,
struct v3dv_draw_info *info)
{
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw)(cmd_buffer, info);
struct v3dv_render_pass *pass = cmd_buffer->state.pass;
if (likely(!pass->multiview_enabled)) {
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw)(cmd_buffer, info);
return;
}
uint32_t view_mask = pass->subpasses[cmd_buffer->state.subpass_idx].view_mask;
while (view_mask) {
cmd_buffer_set_view_index(cmd_buffer, u_bit_scan(&view_mask));
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw)(cmd_buffer, info);
}
}
VKAPI_ATTR void VKAPI_CALL
@ -2554,9 +2582,23 @@ v3dv_CmdDrawIndexed(VkCommandBuffer commandBuffer,
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indexed)
(cmd_buffer, indexCount, instanceCount,
firstIndex, vertexOffset, firstInstance);
struct v3dv_render_pass *pass = cmd_buffer->state.pass;
if (likely(!pass->multiview_enabled)) {
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indexed)
(cmd_buffer, indexCount, instanceCount,
firstIndex, vertexOffset, firstInstance);
return;
}
uint32_t view_mask = pass->subpasses[cmd_buffer->state.subpass_idx].view_mask;
while (view_mask) {
cmd_buffer_set_view_index(cmd_buffer, u_bit_scan(&view_mask));
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indexed)
(cmd_buffer, indexCount, instanceCount,
firstIndex, vertexOffset, firstInstance);
}
}
VKAPI_ATTR void VKAPI_CALL
@ -2573,8 +2615,21 @@ v3dv_CmdDrawIndirect(VkCommandBuffer commandBuffer,
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indirect)
(cmd_buffer, buffer, offset, drawCount, stride);
struct v3dv_render_pass *pass = cmd_buffer->state.pass;
if (likely(!pass->multiview_enabled)) {
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indirect)
(cmd_buffer, buffer, offset, drawCount, stride);
return;
}
uint32_t view_mask = pass->subpasses[cmd_buffer->state.subpass_idx].view_mask;
while (view_mask) {
cmd_buffer_set_view_index(cmd_buffer, u_bit_scan(&view_mask));
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_draw_indirect)
(cmd_buffer, buffer, offset, drawCount, stride);
}
}
VKAPI_ATTR void VKAPI_CALL
@ -2591,8 +2646,21 @@ v3dv_CmdDrawIndexedIndirect(VkCommandBuffer commandBuffer,
V3DV_FROM_HANDLE(v3dv_cmd_buffer, cmd_buffer, commandBuffer);
V3DV_FROM_HANDLE(v3dv_buffer, buffer, _buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_indexed_indirect)
(cmd_buffer, buffer, offset, drawCount, stride);
struct v3dv_render_pass *pass = cmd_buffer->state.pass;
if (likely(!pass->multiview_enabled)) {
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_indexed_indirect)
(cmd_buffer, buffer, offset, drawCount, stride);
return;
}
uint32_t view_mask = pass->subpasses[cmd_buffer->state.subpass_idx].view_mask;
while (view_mask) {
cmd_buffer_set_view_index(cmd_buffer, u_bit_scan(&view_mask));
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
v3dv_X(cmd_buffer->device, cmd_buffer_emit_indexed_indirect)
(cmd_buffer, buffer, offset, drawCount, stride);
}
}
VKAPI_ATTR void VKAPI_CALL

View File

@ -807,6 +807,7 @@ enum v3dv_cmd_dirty_bits {
V3DV_CMD_DIRTY_OCCLUSION_QUERY = 1 << 13,
V3DV_CMD_DIRTY_DEPTH_BIAS = 1 << 14,
V3DV_CMD_DIRTY_LINE_WIDTH = 1 << 15,
V3DV_CMD_DIRTY_VIEW_INDEX = 1 << 16,
};
struct v3dv_dynamic_state {
@ -1148,6 +1149,9 @@ struct v3dv_cmd_buffer_state {
struct v3dv_cl_reloc fs;
} uniforms;
/* Current view index for multiview rendering */
uint32_t view_index;
/* Used to flag OOM conditions during command buffer recording */
bool oom;

View File

@ -525,6 +525,10 @@ v3dv_write_uniforms_wg_offsets(struct v3dv_cmd_buffer *cmd_buffer,
break;
}
case QUNIFORM_VIEW_INDEX:
cl_aligned_u32(&uniforms, job->cmd_buffer->state.view_index);
break;
case QUNIFORM_NUM_WORK_GROUPS:
assert(job->type == V3DV_JOB_TYPE_GPU_CSD);
assert(job->csd.wg_count[data] > 0);

View File

@ -2096,8 +2096,6 @@ v3dX(cmd_buffer_emit_draw_indexed)(struct v3dv_cmd_buffer *cmd_buffer,
int32_t vertexOffset,
uint32_t firstInstance)
{
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
struct v3dv_job *job = cmd_buffer->state.job;
assert(job);
@ -2152,8 +2150,6 @@ v3dX(cmd_buffer_emit_draw_indirect)(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t drawCount,
uint32_t stride)
{
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
struct v3dv_job *job = cmd_buffer->state.job;
assert(job);
@ -2180,8 +2176,6 @@ v3dX(cmd_buffer_emit_indexed_indirect)(struct v3dv_cmd_buffer *cmd_buffer,
uint32_t drawCount,
uint32_t stride)
{
v3dv_cmd_buffer_emit_pre_draw(cmd_buffer);
struct v3dv_job *job = cmd_buffer->state.job;
assert(job);