mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-01-03 09:20:13 +01:00
zink: handle partial writes to shader outputs
this is super gross. spirv doesn't provide any facility for doing per-component writes, which means all components of a value must be written every time to this end, we need to manually split both the src and dst composites and do per-component access for each store in order to accurately handle both non-sequential wrmasks (which could be handled by nir_lower_wrmasks, yes, but we aren't using it) as well as partial wrmasks see also mesa/mesa#4006 Reviewed-by: Erik Faye-Lund <kusmabite@gmail.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/8152>
This commit is contained in:
parent
334759d850
commit
6324699e67
1 changed files with 31 additions and 1 deletions
|
|
@ -1766,8 +1766,38 @@ emit_store_deref(struct ntv_context *ctx, nir_intrinsic_instr *intr)
|
|||
SpvId ptr = get_src(ctx, &intr->src[0]);
|
||||
SpvId src = get_src(ctx, &intr->src[1]);
|
||||
|
||||
SpvId type = get_glsl_type(ctx, nir_src_as_deref(intr->src[0])->type);
|
||||
const struct glsl_type *gtype = nir_src_as_deref(intr->src[0])->type;
|
||||
SpvId type = get_glsl_type(ctx, gtype);
|
||||
nir_variable *var = nir_deref_instr_get_variable(nir_src_as_deref(intr->src[0]));
|
||||
unsigned num_writes = util_bitcount(nir_intrinsic_write_mask(intr));
|
||||
unsigned wrmask = nir_intrinsic_write_mask(intr);
|
||||
if (num_writes && num_writes != intr->num_components) {
|
||||
/* no idea what we do if this fails */
|
||||
assert(glsl_type_is_array(gtype) || glsl_type_is_vector(gtype));
|
||||
|
||||
/* this is a partial write, so we have to loop and do a per-component write */
|
||||
SpvId result_type;
|
||||
SpvId member_type;
|
||||
if (glsl_type_is_vector(gtype)) {
|
||||
result_type = get_glsl_basetype(ctx, glsl_get_base_type(gtype));
|
||||
member_type = get_uvec_type(ctx, 32, 1);
|
||||
} else
|
||||
member_type = result_type = get_glsl_type(ctx, glsl_get_array_element(gtype));
|
||||
SpvId ptr_type = spirv_builder_type_pointer(&ctx->builder,
|
||||
SpvStorageClassOutput,
|
||||
result_type);
|
||||
for (unsigned i = 0; i < 4; i++)
|
||||
if ((wrmask >> i) & 1) {
|
||||
SpvId idx = emit_uint_const(ctx, 32, i);
|
||||
SpvId val = spirv_builder_emit_composite_extract(&ctx->builder, member_type, src, &i, 1);
|
||||
val = emit_bitcast(ctx, result_type, val);
|
||||
SpvId member = spirv_builder_emit_access_chain(&ctx->builder, ptr_type,
|
||||
ptr, &idx, 1);
|
||||
spirv_builder_emit_store(&ctx->builder, member, val);
|
||||
}
|
||||
return;
|
||||
|
||||
}
|
||||
SpvId result;
|
||||
if (ctx->stage == MESA_SHADER_FRAGMENT && var->data.location == FRAG_RESULT_SAMPLE_MASK) {
|
||||
src = emit_bitcast(ctx, type, src);
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue