zink: handle swizzled offset/count values for shader bitfield ops
glsl/nir automatically swizzle the value if a vecN is being used, but spirv requires a single scalar, so this has to be detected and unswizzled to avoid violating spec and crashing shader compilers that are less permissive than mesa's fixes (nvidia): dEQP-GLES31.functional.shaders.builtin_functions.integer.bitfieldextract* KHR-GL46.shader_bitfield_operation.bitfieldExtract* Reviewed-by: Dave Airlie <airlied@redhat.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14690>
This commit is contained in:

committed by
Marge Bot

parent
11e2c4b502
commit
8e97f51c67
@@ -1614,6 +1614,19 @@ needs_derivative_control(nir_alu_instr *alu)
|
||||
}
|
||||
}
|
||||
|
||||
static SpvId
|
||||
unswizzle_src(struct ntv_context *ctx, nir_ssa_def *ssa, SpvId src, unsigned num_components)
|
||||
{
|
||||
/* value may have already been cast to ivec, so cast back */
|
||||
SpvId cast_type = get_uvec_type(ctx, ssa->bit_size, num_components);
|
||||
src = emit_bitcast(ctx, cast_type, src);
|
||||
|
||||
/* extract from swizzled vec */
|
||||
SpvId type = spirv_builder_type_uint(&ctx->builder, ssa->bit_size);
|
||||
uint32_t idx = 0;
|
||||
return spirv_builder_emit_composite_extract(&ctx->builder, type, src, &idx, 1);
|
||||
}
|
||||
|
||||
static void
|
||||
emit_alu(struct ntv_context *ctx, nir_alu_instr *alu)
|
||||
{
|
||||
@@ -1630,6 +1643,34 @@ emit_alu(struct ntv_context *ctx, nir_alu_instr *alu)
|
||||
if (needs_derivative_control(alu))
|
||||
spirv_builder_emit_cap(&ctx->builder, SpvCapabilityDerivativeControl);
|
||||
|
||||
/* modify params here */
|
||||
switch (alu->op) {
|
||||
/* Offset must be an integer type scalar.
|
||||
* Offset is the lowest-order bit of the bit field.
|
||||
* It is consumed as an unsigned value.
|
||||
*
|
||||
* Count must be an integer type scalar.
|
||||
*
|
||||
* if these ops have more than one component in the dest, then their offset and count
|
||||
* are swizzled like ssa_1.xxx, but only a single scalar can be provided
|
||||
*/
|
||||
case nir_op_ubitfield_extract:
|
||||
case nir_op_ibitfield_extract:
|
||||
if (num_components > 1) {
|
||||
src[1] = unswizzle_src(ctx, alu->src[1].src.ssa, src[1], num_components);
|
||||
src[2] = unswizzle_src(ctx, alu->src[2].src.ssa, src[2], num_components);
|
||||
}
|
||||
break;
|
||||
case nir_op_bitfield_insert:
|
||||
if (num_components > 1) {
|
||||
src[2] = unswizzle_src(ctx, alu->src[2].src.ssa, src[2], num_components);
|
||||
src[3] = unswizzle_src(ctx, alu->src[3].src.ssa, src[3], num_components);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
SpvId result = 0;
|
||||
switch (alu->op) {
|
||||
case nir_op_mov:
|
||||
|
Reference in New Issue
Block a user