radv: lower has_multiview_view_index in NIR
This lowering is done in a new NIR pass where the layer is written before emit_vertex_with_counter for geometry shaders and after the position for other vertex stages. Signed-off-by: Samuel Pitoiset <samuel.pitoiset@gmail.com> Reviewed-by: Rhys Perry <pendingchaos02@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/15456>
This commit is contained in:

committed by
Marge Bot

parent
2b18234e61
commit
d32656bc65
@@ -10476,13 +10476,6 @@ create_vs_exports(isel_context* ctx)
|
|||||||
get_arg(ctx, ctx->args->ac.vs_prim_id);
|
get_arg(ctx, ctx->args->ac.vs_prim_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ctx->options->key.has_multiview_view_index &&
|
|
||||||
!outinfo->writes_layer_per_primitive) {
|
|
||||||
ctx->outputs.mask[VARYING_SLOT_LAYER] |= 0x1;
|
|
||||||
ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] =
|
|
||||||
as_vgpr(ctx, get_arg(ctx, ctx->args->ac.view_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Hardware requires position data to always be exported, even if the
|
/* Hardware requires position data to always be exported, even if the
|
||||||
* application did not write gl_Position.
|
* application did not write gl_Position.
|
||||||
*/
|
*/
|
||||||
@@ -10531,13 +10524,6 @@ create_primitive_exports(isel_context *ctx, Temp prim_ch1)
|
|||||||
|
|
||||||
Builder bld(ctx->program, ctx->block);
|
Builder bld(ctx->program, ctx->block);
|
||||||
|
|
||||||
if (ctx->options->key.has_multiview_view_index &&
|
|
||||||
outinfo->writes_layer_per_primitive) {
|
|
||||||
ctx->outputs.mask[VARYING_SLOT_LAYER] |= 0x1;
|
|
||||||
ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] =
|
|
||||||
as_vgpr(ctx, get_arg(ctx, ctx->args->ac.view_index));
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Use zeroes if the shader doesn't write these but they are needed by eg. PS. */
|
/* Use zeroes if the shader doesn't write these but they are needed by eg. PS. */
|
||||||
if (outinfo->writes_layer_per_primitive && !ctx->outputs.mask[VARYING_SLOT_LAYER])
|
if (outinfo->writes_layer_per_primitive && !ctx->outputs.mask[VARYING_SLOT_LAYER])
|
||||||
ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] = bld.copy(bld.def(v1), Operand::c32(0));
|
ctx->outputs.temps[VARYING_SLOT_LAYER * 4u] = bld.copy(bld.def(v1), Operand::c32(0));
|
||||||
|
@@ -1070,19 +1070,6 @@ handle_vs_outputs_post(struct radv_shader_context *ctx, bool export_prim_id, boo
|
|||||||
struct radv_shader_output_values *outputs;
|
struct radv_shader_output_values *outputs;
|
||||||
unsigned noutput = 0;
|
unsigned noutput = 0;
|
||||||
|
|
||||||
if (ctx->options->key.has_multiview_view_index) {
|
|
||||||
LLVMValueRef *tmp_out = &ctx->abi.outputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, 0)];
|
|
||||||
if (!*tmp_out) {
|
|
||||||
for (unsigned i = 0; i < 4; ++i)
|
|
||||||
ctx->abi.outputs[ac_llvm_reg_index_soa(VARYING_SLOT_LAYER, i)] =
|
|
||||||
ac_build_alloca_undef(&ctx->ac, ctx->ac.f32, "");
|
|
||||||
}
|
|
||||||
|
|
||||||
LLVMValueRef view_index = ac_get_arg(&ctx->ac, ctx->args->ac.view_index);
|
|
||||||
LLVMBuildStore(ctx->ac.builder, ac_to_float(&ctx->ac, view_index), *tmp_out);
|
|
||||||
ctx->output_mask |= 1ull << VARYING_SLOT_LAYER;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ctx->shader_info->so.num_outputs && !ctx->args->is_gs_copy_shader) {
|
if (ctx->shader_info->so.num_outputs && !ctx->args->is_gs_copy_shader) {
|
||||||
/* The GS copy shader emission already emits streamout. */
|
/* The GS copy shader emission already emits streamout. */
|
||||||
radv_emit_streamout(ctx, 0);
|
radv_emit_streamout(ctx, 0);
|
||||||
@@ -1177,9 +1164,6 @@ ngg_gs_get_vertex_storage(struct radv_shader_context *ctx)
|
|||||||
{
|
{
|
||||||
unsigned num_outputs = util_bitcount64(ctx->output_mask);
|
unsigned num_outputs = util_bitcount64(ctx->output_mask);
|
||||||
|
|
||||||
if (ctx->options->key.has_multiview_view_index)
|
|
||||||
num_outputs++;
|
|
||||||
|
|
||||||
LLVMTypeRef elements[2] = {
|
LLVMTypeRef elements[2] = {
|
||||||
LLVMArrayType(ctx->ac.i32, 4 * num_outputs),
|
LLVMArrayType(ctx->ac.i32, 4 * num_outputs),
|
||||||
LLVMArrayType(ctx->ac.i8, 4),
|
LLVMArrayType(ctx->ac.i8, 4),
|
||||||
@@ -1650,12 +1634,11 @@ gfx10_ngg_gs_emit_epilogue_2(struct radv_shader_context *ctx)
|
|||||||
ac_build_ifcc(&ctx->ac, tmp, 5145);
|
ac_build_ifcc(&ctx->ac, tmp, 5145);
|
||||||
{
|
{
|
||||||
const struct radv_vs_output_info *outinfo = &ctx->shader_info->vs.outinfo;
|
const struct radv_vs_output_info *outinfo = &ctx->shader_info->vs.outinfo;
|
||||||
bool export_view_index = ctx->options->key.has_multiview_view_index;
|
|
||||||
struct radv_shader_output_values *outputs;
|
struct radv_shader_output_values *outputs;
|
||||||
unsigned noutput = 0;
|
unsigned noutput = 0;
|
||||||
|
|
||||||
/* Allocate a temporary array for the output values. */
|
/* Allocate a temporary array for the output values. */
|
||||||
unsigned num_outputs = util_bitcount64(ctx->output_mask) + export_view_index;
|
unsigned num_outputs = util_bitcount64(ctx->output_mask);
|
||||||
outputs = calloc(num_outputs, sizeof(outputs[0]));
|
outputs = calloc(num_outputs, sizeof(outputs[0]));
|
||||||
|
|
||||||
tmp = ngg_gs_vertex_ptr(ctx, tid);
|
tmp = ngg_gs_vertex_ptr(ctx, tid);
|
||||||
@@ -1697,18 +1680,6 @@ gfx10_ngg_gs_emit_epilogue_2(struct radv_shader_context *ctx)
|
|||||||
noutput++;
|
noutput++;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Export ViewIndex. */
|
|
||||||
if (export_view_index) {
|
|
||||||
outputs[noutput].slot_name = VARYING_SLOT_LAYER;
|
|
||||||
outputs[noutput].slot_index = 0;
|
|
||||||
outputs[noutput].usage_mask = 0x1;
|
|
||||||
outputs[noutput].values[0] =
|
|
||||||
ac_to_float(&ctx->ac, ac_get_arg(&ctx->ac, ctx->args->ac.view_index));
|
|
||||||
for (unsigned j = 1; j < 4; j++)
|
|
||||||
outputs[noutput].values[j] = ctx->ac.f32_0;
|
|
||||||
noutput++;
|
|
||||||
}
|
|
||||||
|
|
||||||
radv_llvm_export_vs(ctx, outputs, noutput, outinfo, outinfo->export_clip_dists);
|
radv_llvm_export_vs(ctx, outputs, noutput, outinfo, outinfo->export_clip_dists);
|
||||||
FREE(outputs);
|
FREE(outputs);
|
||||||
}
|
}
|
||||||
|
@@ -2511,6 +2511,77 @@ radv_lower_viewport_to_zero(nir_shader *nir)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static nir_variable *
|
||||||
|
find_layer_out_var(nir_shader *nir)
|
||||||
|
{
|
||||||
|
nir_variable *var = nir_find_variable_with_location(nir, nir_var_shader_out, VARYING_SLOT_LAYER);
|
||||||
|
if (var != NULL)
|
||||||
|
return var;
|
||||||
|
|
||||||
|
var = nir_variable_create(nir, nir_var_shader_out, glsl_int_type(), "layer id");
|
||||||
|
var->data.per_primitive = nir->info.stage == MESA_SHADER_MESH;
|
||||||
|
var->data.location = VARYING_SLOT_LAYER;
|
||||||
|
var->data.interpolation = INTERP_MODE_NONE;
|
||||||
|
|
||||||
|
return var;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool
|
||||||
|
radv_lower_multiview(nir_shader *nir)
|
||||||
|
{
|
||||||
|
nir_function_impl *impl = nir_shader_get_entrypoint(nir);
|
||||||
|
bool progress = false;
|
||||||
|
|
||||||
|
nir_builder b;
|
||||||
|
nir_builder_init(&b, impl);
|
||||||
|
|
||||||
|
/* Iterate in reverse order since there should be only one deref store to POS after
|
||||||
|
* lower_io_to_temporaries for vertex shaders and inject the layer there. For geometry shaders,
|
||||||
|
* the layer is injected right before every emit_vertex_with_counter.
|
||||||
|
*/
|
||||||
|
nir_variable *layer = NULL;
|
||||||
|
nir_foreach_block_reverse(block, impl) {
|
||||||
|
nir_foreach_instr_reverse(instr, block) {
|
||||||
|
if (instr->type != nir_instr_type_intrinsic)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (nir->info.stage == MESA_SHADER_GEOMETRY) {
|
||||||
|
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||||
|
if (intr->intrinsic != nir_intrinsic_emit_vertex_with_counter)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
b.cursor = nir_before_instr(instr);
|
||||||
|
} else {
|
||||||
|
nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
|
||||||
|
if (intr->intrinsic != nir_intrinsic_store_deref)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
nir_variable *var = nir_intrinsic_get_var(intr, 0);
|
||||||
|
if (var->data.mode != nir_var_shader_out || var->data.location != VARYING_SLOT_POS)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
b.cursor = nir_after_instr(instr);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!layer)
|
||||||
|
layer = find_layer_out_var(nir);
|
||||||
|
|
||||||
|
nir_store_var(&b, layer, nir_load_view_index(&b), 1);
|
||||||
|
|
||||||
|
/* Update outputs_written to reflect that the pass added a new output. */
|
||||||
|
nir->info.outputs_written |= BITFIELD64_BIT(VARYING_SLOT_LAYER);
|
||||||
|
if (nir->info.stage == MESA_SHADER_MESH)
|
||||||
|
nir->info.per_primitive_outputs |= BITFIELD64_BIT(VARYING_SLOT_LAYER);
|
||||||
|
|
||||||
|
progress = true;
|
||||||
|
if (nir->info.stage == MESA_SHADER_VERTEX)
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return progress;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
radv_link_shaders(struct radv_pipeline *pipeline,
|
radv_link_shaders(struct radv_pipeline *pipeline,
|
||||||
const struct radv_pipeline_key *pipeline_key,
|
const struct radv_pipeline_key *pipeline_key,
|
||||||
@@ -2688,6 +2759,14 @@ radv_link_shaders(struct radv_pipeline *pipeline,
|
|||||||
radv_lower_viewport_to_zero(shaders[MESA_SHADER_FRAGMENT]);
|
radv_lower_viewport_to_zero(shaders[MESA_SHADER_FRAGMENT]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Export the layer in the last VGT stage if multiview is used. */
|
||||||
|
if (pipeline_key->has_multiview_view_index && pipeline->graphics.last_vgt_api_stage != -1 &&
|
||||||
|
!(shaders[pipeline->graphics.last_vgt_api_stage]->info.outputs_written &
|
||||||
|
VARYING_BIT_LAYER)) {
|
||||||
|
nir_shader *last_vgt_shader = shaders[pipeline->graphics.last_vgt_api_stage];
|
||||||
|
radv_lower_multiview(last_vgt_shader);
|
||||||
|
}
|
||||||
|
|
||||||
for (int i = 1; !optimize_conservatively && (i < shader_count); ++i) {
|
for (int i = 1; !optimize_conservatively && (i < shader_count); ++i) {
|
||||||
if (nir_link_opt_varyings(ordered_shaders[i], ordered_shaders[i - 1])) {
|
if (nir_link_opt_varyings(ordered_shaders[i], ordered_shaders[i - 1])) {
|
||||||
nir_opt_constant_folding(ordered_shaders[i - 1]);
|
nir_opt_constant_folding(ordered_shaders[i - 1]);
|
||||||
@@ -4377,8 +4456,7 @@ radv_create_shaders(struct radv_pipeline *pipeline, struct radv_pipeline_layout
|
|||||||
|
|
||||||
pipeline->gs_copy_shader = radv_create_gs_copy_shader(
|
pipeline->gs_copy_shader = radv_create_gs_copy_shader(
|
||||||
device, nir[MESA_SHADER_GEOMETRY], &info, &gs_copy_args, &gs_copy_binary,
|
device, nir[MESA_SHADER_GEOMETRY], &info, &gs_copy_args, &gs_copy_binary,
|
||||||
keep_executable_info, keep_statistic_info, pipeline_key->has_multiview_view_index,
|
keep_executable_info, keep_statistic_info, pipeline_key->optimisations_disabled);
|
||||||
pipeline_key->optimisations_disabled);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (nir[MESA_SHADER_FRAGMENT]) {
|
if (nir[MESA_SHADER_FRAGMENT]) {
|
||||||
|
@@ -2051,12 +2051,11 @@ struct radv_shader *
|
|||||||
radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *shader,
|
radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *shader,
|
||||||
struct radv_shader_info *info, const struct radv_shader_args *args,
|
struct radv_shader_info *info, const struct radv_shader_args *args,
|
||||||
struct radv_shader_binary **binary_out, bool keep_shader_info,
|
struct radv_shader_binary **binary_out, bool keep_shader_info,
|
||||||
bool keep_statistic_info, bool multiview, bool disable_optimizations)
|
bool keep_statistic_info, bool disable_optimizations)
|
||||||
{
|
{
|
||||||
struct radv_nir_compiler_options options = {0};
|
struct radv_nir_compiler_options options = {0};
|
||||||
gl_shader_stage stage = MESA_SHADER_VERTEX;
|
gl_shader_stage stage = MESA_SHADER_VERTEX;
|
||||||
|
|
||||||
options.key.has_multiview_view_index = multiview;
|
|
||||||
options.key.optimisations_disabled = disable_optimizations;
|
options.key.optimisations_disabled = disable_optimizations;
|
||||||
|
|
||||||
return shader_compile(device, NULL, &shader, 1, stage, info, args, &options, true, false,
|
return shader_compile(device, NULL, &shader, 1, stage, info, args, &options, true, false,
|
||||||
|
@@ -553,7 +553,7 @@ void radv_free_shader_memory(struct radv_device *device, union radv_shader_arena
|
|||||||
struct radv_shader *
|
struct radv_shader *
|
||||||
radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *nir,
|
radv_create_gs_copy_shader(struct radv_device *device, struct nir_shader *nir,
|
||||||
struct radv_shader_info *info, const struct radv_shader_args *args,
|
struct radv_shader_info *info, const struct radv_shader_args *args,
|
||||||
struct radv_shader_binary **binary_out, bool multiview,
|
struct radv_shader_binary **binary_out,
|
||||||
bool keep_shader_info, bool keep_statistic_info,
|
bool keep_shader_info, bool keep_statistic_info,
|
||||||
bool disable_optimizations);
|
bool disable_optimizations);
|
||||||
|
|
||||||
|
@@ -74,38 +74,6 @@ struct user_sgpr_info {
|
|||||||
bool inlined_all_push_consts;
|
bool inlined_all_push_consts;
|
||||||
};
|
};
|
||||||
|
|
||||||
static bool
|
|
||||||
needs_view_index_sgpr(const struct radv_pipeline_key *key, const struct radv_shader_info *info,
|
|
||||||
gl_shader_stage stage)
|
|
||||||
{
|
|
||||||
switch (stage) {
|
|
||||||
case MESA_SHADER_VERTEX:
|
|
||||||
if (info->uses_view_index ||
|
|
||||||
(!info->vs.as_es && !info->vs.as_ls && key->has_multiview_view_index))
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case MESA_SHADER_TESS_EVAL:
|
|
||||||
if (info->uses_view_index || (!info->tes.as_es && key->has_multiview_view_index))
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case MESA_SHADER_TESS_CTRL:
|
|
||||||
if (info->uses_view_index)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case MESA_SHADER_GEOMETRY:
|
|
||||||
if (info->uses_view_index || (info->is_ngg && key->has_multiview_view_index))
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
case MESA_SHADER_MESH:
|
|
||||||
if (info->uses_view_index || key->has_multiview_view_index)
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
static uint8_t
|
static uint8_t
|
||||||
count_vs_user_sgprs(const struct radv_shader_info *info)
|
count_vs_user_sgprs(const struct radv_shader_info *info)
|
||||||
{
|
{
|
||||||
@@ -554,7 +522,7 @@ radv_declare_shader_args(enum chip_class chip_class, const struct radv_pipeline_
|
|||||||
struct radv_shader_args *args)
|
struct radv_shader_args *args)
|
||||||
{
|
{
|
||||||
struct user_sgpr_info user_sgpr_info;
|
struct user_sgpr_info user_sgpr_info;
|
||||||
bool needs_view_index = needs_view_index_sgpr(key, info, stage);
|
bool needs_view_index = info->uses_view_index;
|
||||||
bool has_api_gs = stage == MESA_SHADER_GEOMETRY;
|
bool has_api_gs = stage == MESA_SHADER_GEOMETRY;
|
||||||
|
|
||||||
if (chip_class >= GFX10 && info->is_ngg && stage != MESA_SHADER_GEOMETRY) {
|
if (chip_class >= GFX10 && info->is_ngg && stage != MESA_SHADER_GEOMETRY) {
|
||||||
|
@@ -673,14 +673,6 @@ radv_nir_shader_info_pass(struct radv_device *device, const struct nir_shader *n
|
|||||||
|
|
||||||
struct radv_vs_output_info *outinfo = get_vs_output_info(nir, info);
|
struct radv_vs_output_info *outinfo = get_vs_output_info(nir, info);
|
||||||
if (outinfo) {
|
if (outinfo) {
|
||||||
/* Make sure to export the LayerID if the subpass has multiviews. */
|
|
||||||
if (pipeline_key->has_multiview_view_index) {
|
|
||||||
if (nir->info.stage == MESA_SHADER_MESH)
|
|
||||||
outinfo->writes_layer_per_primitive = true;
|
|
||||||
else
|
|
||||||
outinfo->writes_layer = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
int pos_written = 0x1;
|
int pos_written = 0x1;
|
||||||
|
|
||||||
if (outinfo->writes_pointsize || outinfo->writes_viewport_index || outinfo->writes_layer ||
|
if (outinfo->writes_pointsize || outinfo->writes_viewport_index || outinfo->writes_layer ||
|
||||||
|
Reference in New Issue
Block a user