ac/nir: Add shader support for multiviews.
It uses an user SGPR to pass the view index to the shaders, except for the fragment shader where we use layer=view (which comes in handy when we want to do the NV ext that allows us to execute pre-FS stages once instead of per view). Reviewed-by: Dave Airlie <airlied@redhat.com>
This commit is contained in:
parent
2e86f6b259
commit
180c1b924e
|
@ -90,6 +90,7 @@ struct nir_to_llvm_context {
|
||||||
LLVMValueRef descriptor_sets[AC_UD_MAX_SETS];
|
LLVMValueRef descriptor_sets[AC_UD_MAX_SETS];
|
||||||
LLVMValueRef ring_offsets;
|
LLVMValueRef ring_offsets;
|
||||||
LLVMValueRef push_constants;
|
LLVMValueRef push_constants;
|
||||||
|
LLVMValueRef view_index;
|
||||||
LLVMValueRef num_work_groups;
|
LLVMValueRef num_work_groups;
|
||||||
LLVMValueRef workgroup_ids;
|
LLVMValueRef workgroup_ids;
|
||||||
LLVMValueRef local_invocation_ids;
|
LLVMValueRef local_invocation_ids;
|
||||||
|
@ -744,6 +745,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
|
||||||
if (ctx->shader_info->info.vs.needs_draw_id)
|
if (ctx->shader_info->info.vs.needs_draw_id)
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->abi.draw_id); // draw id
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->abi.draw_id); // draw id
|
||||||
}
|
}
|
||||||
|
if (ctx->shader_info->info.needs_multiview_view_index || (!ctx->options->key.vs.as_es && !ctx->options->key.vs.as_ls && ctx->options->key.has_multiview_view_index))
|
||||||
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->view_index);
|
||||||
if (ctx->options->key.vs.as_es)
|
if (ctx->options->key.vs.as_es)
|
||||||
add_sgpr_argument(&args, ctx->i32, &ctx->es2gs_offset); // es2gs offset
|
add_sgpr_argument(&args, ctx->i32, &ctx->es2gs_offset); // es2gs offset
|
||||||
else if (ctx->options->key.vs.as_ls)
|
else if (ctx->options->key.vs.as_ls)
|
||||||
|
@ -760,6 +763,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_out_offsets); // tcs out offsets
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_out_offsets); // tcs out offsets
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_out_layout); // tcs out layout
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_out_layout); // tcs out layout
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_in_layout); // tcs in layout
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_in_layout); // tcs in layout
|
||||||
|
if (ctx->shader_info->info.needs_multiview_view_index)
|
||||||
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->view_index);
|
||||||
add_sgpr_argument(&args, ctx->i32, &ctx->oc_lds); // param oc lds
|
add_sgpr_argument(&args, ctx->i32, &ctx->oc_lds); // param oc lds
|
||||||
add_sgpr_argument(&args, ctx->i32, &ctx->tess_factor_offset); // tess factor offset
|
add_sgpr_argument(&args, ctx->i32, &ctx->tess_factor_offset); // tess factor offset
|
||||||
add_vgpr_argument(&args, ctx->i32, &ctx->tcs_patch_id); // patch id
|
add_vgpr_argument(&args, ctx->i32, &ctx->tcs_patch_id); // patch id
|
||||||
|
@ -767,6 +772,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
|
||||||
break;
|
break;
|
||||||
case MESA_SHADER_TESS_EVAL:
|
case MESA_SHADER_TESS_EVAL:
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_offchip_layout); // tcs offchip layout
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->tcs_offchip_layout); // tcs offchip layout
|
||||||
|
if (ctx->shader_info->info.needs_multiview_view_index || (!ctx->options->key.tes.as_es && ctx->options->key.has_multiview_view_index))
|
||||||
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->view_index);
|
||||||
if (ctx->options->key.tes.as_es) {
|
if (ctx->options->key.tes.as_es) {
|
||||||
add_sgpr_argument(&args, ctx->i32, &ctx->oc_lds); // OC LDS
|
add_sgpr_argument(&args, ctx->i32, &ctx->oc_lds); // OC LDS
|
||||||
add_sgpr_argument(&args, ctx->i32, NULL); //
|
add_sgpr_argument(&args, ctx->i32, NULL); //
|
||||||
|
@ -783,6 +790,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
|
||||||
case MESA_SHADER_GEOMETRY:
|
case MESA_SHADER_GEOMETRY:
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->gsvs_ring_stride); // gsvs stride
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->gsvs_ring_stride); // gsvs stride
|
||||||
add_user_sgpr_argument(&args, ctx->i32, &ctx->gsvs_num_entries); // gsvs num entires
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->gsvs_num_entries); // gsvs num entires
|
||||||
|
if (ctx->shader_info->info.needs_multiview_view_index)
|
||||||
|
add_user_sgpr_argument(&args, ctx->i32, &ctx->view_index);
|
||||||
add_sgpr_argument(&args, ctx->i32, &ctx->gs2vs_offset); // gs2vs offset
|
add_sgpr_argument(&args, ctx->i32, &ctx->gs2vs_offset); // gs2vs offset
|
||||||
add_sgpr_argument(&args, ctx->i32, &ctx->gs_wave_id); // wave id
|
add_sgpr_argument(&args, ctx->i32, &ctx->gs_wave_id); // wave id
|
||||||
add_vgpr_argument(&args, ctx->i32, &ctx->gs_vtx_offset[0]); // vtx0
|
add_vgpr_argument(&args, ctx->i32, &ctx->gs_vtx_offset[0]); // vtx0
|
||||||
|
@ -894,6 +903,8 @@ static void create_function(struct nir_to_llvm_context *ctx)
|
||||||
|
|
||||||
set_userdata_location_shader(ctx, AC_UD_VS_BASE_VERTEX_START_INSTANCE, &user_sgpr_idx, vs_num);
|
set_userdata_location_shader(ctx, AC_UD_VS_BASE_VERTEX_START_INSTANCE, &user_sgpr_idx, vs_num);
|
||||||
}
|
}
|
||||||
|
if (ctx->view_index)
|
||||||
|
set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
|
||||||
if (ctx->options->key.vs.as_ls) {
|
if (ctx->options->key.vs.as_ls) {
|
||||||
set_userdata_location_shader(ctx, AC_UD_VS_LS_TCS_IN_LAYOUT, &user_sgpr_idx, 1);
|
set_userdata_location_shader(ctx, AC_UD_VS_LS_TCS_IN_LAYOUT, &user_sgpr_idx, 1);
|
||||||
}
|
}
|
||||||
|
@ -902,13 +913,19 @@ static void create_function(struct nir_to_llvm_context *ctx)
|
||||||
break;
|
break;
|
||||||
case MESA_SHADER_TESS_CTRL:
|
case MESA_SHADER_TESS_CTRL:
|
||||||
set_userdata_location_shader(ctx, AC_UD_TCS_OFFCHIP_LAYOUT, &user_sgpr_idx, 4);
|
set_userdata_location_shader(ctx, AC_UD_TCS_OFFCHIP_LAYOUT, &user_sgpr_idx, 4);
|
||||||
|
if (ctx->view_index)
|
||||||
|
set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
|
||||||
declare_tess_lds(ctx);
|
declare_tess_lds(ctx);
|
||||||
break;
|
break;
|
||||||
case MESA_SHADER_TESS_EVAL:
|
case MESA_SHADER_TESS_EVAL:
|
||||||
set_userdata_location_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT, &user_sgpr_idx, 1);
|
set_userdata_location_shader(ctx, AC_UD_TES_OFFCHIP_LAYOUT, &user_sgpr_idx, 1);
|
||||||
|
if (ctx->view_index)
|
||||||
|
set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
|
||||||
break;
|
break;
|
||||||
case MESA_SHADER_GEOMETRY:
|
case MESA_SHADER_GEOMETRY:
|
||||||
set_userdata_location_shader(ctx, AC_UD_GS_VS_RING_STRIDE_ENTRIES, &user_sgpr_idx, 2);
|
set_userdata_location_shader(ctx, AC_UD_GS_VS_RING_STRIDE_ENTRIES, &user_sgpr_idx, 2);
|
||||||
|
if (ctx->view_index)
|
||||||
|
set_userdata_location_shader(ctx, AC_UD_VIEW_INDEX, &user_sgpr_idx, 1);
|
||||||
break;
|
break;
|
||||||
case MESA_SHADER_FRAGMENT:
|
case MESA_SHADER_FRAGMENT:
|
||||||
if (ctx->shader_info->info.ps.needs_sample_positions) {
|
if (ctx->shader_info->info.ps.needs_sample_positions) {
|
||||||
|
@ -4022,6 +4039,9 @@ static void visit_intrinsic(struct ac_nir_context *ctx,
|
||||||
case nir_intrinsic_load_draw_id:
|
case nir_intrinsic_load_draw_id:
|
||||||
result = ctx->abi->draw_id;
|
result = ctx->abi->draw_id;
|
||||||
break;
|
break;
|
||||||
|
case nir_intrinsic_load_view_index:
|
||||||
|
result = ctx->nctx->view_index ? ctx->nctx->view_index : ctx->ac.i32_0;
|
||||||
|
break;
|
||||||
case nir_intrinsic_load_invocation_id:
|
case nir_intrinsic_load_invocation_id:
|
||||||
if (ctx->stage == MESA_SHADER_TESS_CTRL)
|
if (ctx->stage == MESA_SHADER_TESS_CTRL)
|
||||||
result = unpack_param(&ctx->ac, ctx->nctx->tcs_rel_ids, 8, 5);
|
result = unpack_param(&ctx->ac, ctx->nctx->tcs_rel_ids, 8, 5);
|
||||||
|
@ -5068,7 +5088,8 @@ handle_fs_inputs(struct nir_to_llvm_context *ctx,
|
||||||
|
|
||||||
unsigned index = 0;
|
unsigned index = 0;
|
||||||
|
|
||||||
if (ctx->shader_info->info.ps.uses_input_attachments)
|
if (ctx->shader_info->info.ps.uses_input_attachments ||
|
||||||
|
ctx->shader_info->info.needs_multiview_view_index)
|
||||||
ctx->input_mask |= 1ull << VARYING_SLOT_LAYER;
|
ctx->input_mask |= 1ull << VARYING_SLOT_LAYER;
|
||||||
|
|
||||||
for (unsigned i = 0; i < RADEON_LLVM_MAX_INPUTS; ++i) {
|
for (unsigned i = 0; i < RADEON_LLVM_MAX_INPUTS; ++i) {
|
||||||
|
@ -5103,6 +5124,9 @@ handle_fs_inputs(struct nir_to_llvm_context *ctx,
|
||||||
if (ctx->input_mask & (1 << VARYING_SLOT_LAYER))
|
if (ctx->input_mask & (1 << VARYING_SLOT_LAYER))
|
||||||
ctx->shader_info->fs.layer_input = true;
|
ctx->shader_info->fs.layer_input = true;
|
||||||
ctx->shader_info->fs.input_mask = ctx->input_mask >> VARYING_SLOT_VAR0;
|
ctx->shader_info->fs.input_mask = ctx->input_mask >> VARYING_SLOT_VAR0;
|
||||||
|
|
||||||
|
if (ctx->shader_info->info.needs_multiview_view_index)
|
||||||
|
ctx->view_index = ctx->inputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)];
|
||||||
}
|
}
|
||||||
|
|
||||||
static LLVMValueRef
|
static LLVMValueRef
|
||||||
|
@ -5507,6 +5531,18 @@ handle_vs_outputs_post(struct nir_to_llvm_context *ctx,
|
||||||
LLVMValueRef psize_value = NULL, layer_value = NULL, viewport_index_value = NULL;
|
LLVMValueRef psize_value = NULL, layer_value = NULL, viewport_index_value = NULL;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
|
if (ctx->options->key.has_multiview_view_index) {
|
||||||
|
LLVMValueRef* tmp_out = &ctx->nir->outputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)];
|
||||||
|
if(!*tmp_out) {
|
||||||
|
for(unsigned i = 0; i < 4; ++i)
|
||||||
|
ctx->nir->outputs[radeon_llvm_reg_index_soa(VARYING_SLOT_LAYER, i)] =
|
||||||
|
si_build_alloca_undef(&ctx->ac, ctx->ac.f32, "");
|
||||||
|
}
|
||||||
|
|
||||||
|
LLVMBuildStore(ctx->builder, to_float(&ctx->ac, ctx->view_index), *tmp_out);
|
||||||
|
ctx->output_mask |= 1ull << VARYING_SLOT_LAYER;
|
||||||
|
}
|
||||||
|
|
||||||
memset(outinfo->vs_output_param_offset, AC_EXP_PARAM_UNDEFINED,
|
memset(outinfo->vs_output_param_offset, AC_EXP_PARAM_UNDEFINED,
|
||||||
sizeof(outinfo->vs_output_param_offset));
|
sizeof(outinfo->vs_output_param_offset));
|
||||||
|
|
||||||
|
|
|
@ -70,6 +70,7 @@ struct ac_shader_variant_key {
|
||||||
struct ac_tes_variant_key tes;
|
struct ac_tes_variant_key tes;
|
||||||
struct ac_tcs_variant_key tcs;
|
struct ac_tcs_variant_key tcs;
|
||||||
};
|
};
|
||||||
|
bool has_multiview_view_index;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ac_nir_compiler_options {
|
struct ac_nir_compiler_options {
|
||||||
|
@ -92,7 +93,8 @@ enum ac_ud_index {
|
||||||
AC_UD_SCRATCH_RING_OFFSETS = 0,
|
AC_UD_SCRATCH_RING_OFFSETS = 0,
|
||||||
AC_UD_PUSH_CONSTANTS = 1,
|
AC_UD_PUSH_CONSTANTS = 1,
|
||||||
AC_UD_INDIRECT_DESCRIPTOR_SETS = 2,
|
AC_UD_INDIRECT_DESCRIPTOR_SETS = 2,
|
||||||
AC_UD_SHADER_START = 3,
|
AC_UD_VIEW_INDEX = 3,
|
||||||
|
AC_UD_SHADER_START = 4,
|
||||||
AC_UD_VS_VERTEX_BUFFERS = AC_UD_SHADER_START,
|
AC_UD_VS_VERTEX_BUFFERS = AC_UD_SHADER_START,
|
||||||
AC_UD_VS_BASE_VERTEX_START_INSTANCE,
|
AC_UD_VS_BASE_VERTEX_START_INSTANCE,
|
||||||
AC_UD_VS_LS_TCS_IN_LAYOUT,
|
AC_UD_VS_LS_TCS_IN_LAYOUT,
|
||||||
|
|
|
@ -51,6 +51,9 @@ gather_intrinsic_info(nir_intrinsic_instr *instr, struct ac_shader_info *info)
|
||||||
case nir_intrinsic_load_sample_pos:
|
case nir_intrinsic_load_sample_pos:
|
||||||
info->ps.force_persample = true;
|
info->ps.force_persample = true;
|
||||||
break;
|
break;
|
||||||
|
case nir_intrinsic_load_view_index:
|
||||||
|
info->needs_multiview_view_index = true;
|
||||||
|
break;
|
||||||
case nir_intrinsic_vulkan_resource_index:
|
case nir_intrinsic_vulkan_resource_index:
|
||||||
info->desc_set_used_mask |= (1 << nir_intrinsic_desc_set(instr));
|
info->desc_set_used_mask |= (1 << nir_intrinsic_desc_set(instr));
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -30,6 +30,7 @@ struct ac_nir_compiler_options;
|
||||||
struct ac_shader_info {
|
struct ac_shader_info {
|
||||||
bool needs_push_constants;
|
bool needs_push_constants;
|
||||||
uint32_t desc_set_used_mask;
|
uint32_t desc_set_used_mask;
|
||||||
|
bool needs_multiview_view_index;
|
||||||
struct {
|
struct {
|
||||||
bool has_vertex_buffers; /* needs vertex buffers and base/start */
|
bool has_vertex_buffers; /* needs vertex buffers and base/start */
|
||||||
bool needs_draw_id;
|
bool needs_draw_id;
|
||||||
|
|
Loading…
Reference in New Issue