zink: handle direct xfb output from output variables

if an entire variable is being dumped into an xfb buffer, there's no need
to create an explicit xfb variable to copy the value into, and instead
the xfb attributes can just be set normally on the variable

this doesn't work for geometry shaders because outputs are per-vertex

fixes all KHR-GL46.enhanced_layouts xfb tests

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/9271>
This commit is contained in:
Mike Blumenkrantz
2021-02-24 15:00:22 -05:00
committed by Marge Bot
parent 7cef91dd43
commit 6d40db84c9
3 changed files with 42 additions and 1 deletions

View File

@@ -621,6 +621,14 @@ emit_output(struct ntv_context *ctx, struct nir_variable *var)
if (var->data.patch)
spirv_builder_emit_decoration(&ctx->builder, var_id, SpvDecorationPatch);
if (var->data.explicit_xfb_buffer) {
spirv_builder_emit_offset(&ctx->builder, var_id, var->data.offset);
spirv_builder_emit_xfb_buffer(&ctx->builder, var_id, var->data.xfb.buffer);
spirv_builder_emit_xfb_stride(&ctx->builder, var_id, var->data.xfb.stride);
if (var->data.stream)
spirv_builder_emit_stream(&ctx->builder, var_id, var->data.stream);
}
_mesa_hash_table_insert(ctx->vars, var, (void *)(intptr_t)var_id);
assert(ctx->num_entry_ifaces < ARRAY_SIZE(ctx->entry_ifaces));
@@ -1252,6 +1260,8 @@ emit_so_info(struct ntv_context *ctx, const struct zink_so_info *so_info)
{
unsigned output = 0;
for (unsigned i = 0; i < so_info->so_info.num_outputs; i++) {
if (so_info->skip[i])
continue;
struct pipe_stream_output so_output = so_info->so_info.output[i];
unsigned slot = so_info->so_info_slots[i] << 2 | so_output.start_component;
SpvId out_type = get_output_type(ctx, slot, so_output.num_components);
@@ -1299,6 +1309,8 @@ emit_so_outputs(struct ntv_context *ctx,
const struct zink_so_info *so_info)
{
for (unsigned i = 0; i < so_info->so_info.num_outputs; i++) {
if (so_info->skip[i])
continue;
uint32_t components[NIR_MAX_VEC_COMPONENTS];
unsigned slot = so_info->so_info_slots[i];
struct pipe_stream_output so_output = so_info->so_info.output[i];

View File

@@ -402,13 +402,13 @@ check_psiz(struct nir_shader *s)
return false;
}
/* semi-copied from iris */
static void
update_so_info(struct zink_shader *sh,
uint64_t outputs_written, bool have_psiz)
{
uint8_t reverse_map[64] = {};
unsigned slot = 0;
/* semi-copied from iris */
while (outputs_written) {
int bit = u_bit_scan64(&outputs_written);
/* PSIZ from nir_lower_point_size_mov breaks stream output, so always skip it */
@@ -417,8 +417,36 @@ update_so_info(struct zink_shader *sh,
reverse_map[slot++] = bit;
}
nir_foreach_shader_out_variable(var, sh->nir)
var->data.explicit_xfb_buffer = 0;
bool inlined[64] = {0};
for (unsigned i = 0; i < sh->streamout.so_info.num_outputs; i++) {
struct pipe_stream_output *output = &sh->streamout.so_info.output[i];
unsigned slot = reverse_map[output->register_index];
if ((sh->nir->info.stage != MESA_SHADER_GEOMETRY || util_bitcount(sh->nir->info.gs.active_stream_mask) == 1) &&
!output->start_component) {
nir_variable *var = NULL;
while (!var)
var = nir_find_variable_with_location(sh->nir, nir_var_shader_out, slot--);
slot++;
if (inlined[slot]) {
sh->streamout.skip[i] = true;
continue;
}
assert(var && var->data.location == slot);
/* if this is the entire variable, try to blast it out during the initial declaration */
if (glsl_get_components(var->type) == output->num_components) {
var->data.explicit_xfb_buffer = 1;
var->data.xfb.buffer = output->output_buffer;
var->data.xfb.stride = sh->streamout.so_info.stride[output->output_buffer] * 4;
var->data.offset = output->dst_offset * 4;
var->data.stream = output->stream;
sh->streamout.skip[i] = true;
inlined[slot] = true;
continue;
}
}
/* Map Gallium's condensed "slots" back to real VARYING_SLOT_* enums */
sh->streamout.so_info_slots[i] = reverse_map[output->register_index];
}

View File

@@ -51,6 +51,7 @@ struct tgsi_token;
struct zink_so_info {
struct pipe_stream_output_info so_info;
unsigned so_info_slots[PIPE_MAX_SO_OUTPUTS];
bool skip[PIPE_MAX_SO_OUTPUTS];
bool have_xfb;
};