[Mesa-dev] [PATCH] st/glsl_to_tgsi: fix mismatch between TGSI BFI/BFE and GLSL

Ilia Mirkin imirkin at alum.mit.edu
Mon Oct 24 13:34:28 UTC 2016


These work properly on nvc0. I'd rather you work around it in your backend.

On Mon, Oct 24, 2016 at 9:31 AM, Nicolai Hähnle <nhaehnle at gmail.com> wrote:
> From: Nicolai Hähnle <nicolai.haehnle at amd.com>
>
> TGSI's BFI/BFE specifies that the bits and offset are masked by 0x1f. GLSL
> has no such masking and simply says that the result is undefined when
> bits or offset are negative or bits + offset > 32.
>
> The GLSL definition is annoying from a driver perspective, because mapping
> the GLSL intrinsics directly to TGSI means the case bits == 32, offset == 0
> is handled incorrectly. The TGSI definition is the one from DirectX and
> matches AMD GCN.
>
> This patch adds the necessary workaround instructions in st_glsl_to_tgsi,
> which should be correct for all drivers. If there is hardware that
> implements GLSL-style bitfield operations natively, we could add extra
> opcodes and a pipe cap so that the corresponding drivers don't lose
> performance.
> ---
>  src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 18 ++++++++++++++----
>  1 file changed, 14 insertions(+), 4 deletions(-)
>
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index f376462..5f49612 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -2154,26 +2154,36 @@ glsl_to_tgsi_visitor::visit_expression(ir_expression* ir, st_src_reg *op)
>        emit_asm(ir, TGSI_OPCODE_LRP, result_dst, op[2], op[1], op[0]);
>        break;
>     case ir_triop_csel:
>        if (this->ctx->Const.NativeIntegers)
>           emit_asm(ir, TGSI_OPCODE_UCMP, result_dst, op[0], op[1], op[2]);
>        else {
>           op[0].negate = ~op[0].negate;
>           emit_asm(ir, TGSI_OPCODE_CMP, result_dst, op[0], op[1], op[2]);
>        }
>        break;
> -   case ir_triop_bitfield_extract:
> -      emit_asm(ir, TGSI_OPCODE_IBFE, result_dst, op[0], op[1], op[2]);
> +   case ir_triop_bitfield_extract: {
> +      st_src_reg is_ge32 = get_temp(glsl_type::uint_type);
> +      st_src_reg bfe = get_temp(ir->type);
> +      emit_asm(ir, TGSI_OPCODE_ISGE, st_dst_reg(is_ge32), op[2], st_src_reg_for_int(32));
> +      emit_asm(ir, TGSI_OPCODE_IBFE, st_dst_reg(bfe), op[0], op[1], op[2]);
> +      emit_asm(ir, TGSI_OPCODE_UCMP, result_dst, is_ge32, op[0], bfe);
>        break;
> -   case ir_quadop_bitfield_insert:
> -      emit_asm(ir, TGSI_OPCODE_BFI, result_dst, op[0], op[1], op[2], op[3]);
> +   }
> +   case ir_quadop_bitfield_insert: {
> +      st_src_reg is_ge32 = get_temp(glsl_type::uint_type);
> +      st_src_reg bfi = get_temp(ir->type);
> +      emit_asm(ir, TGSI_OPCODE_ISGE, st_dst_reg(is_ge32), op[3], st_src_reg_for_int(32));
> +      emit_asm(ir, TGSI_OPCODE_BFI, st_dst_reg(bfi), op[0], op[1], op[2], op[3]);
> +      emit_asm(ir, TGSI_OPCODE_UCMP, result_dst, is_ge32, op[1], bfi);
>        break;
> +   }
>     case ir_unop_bitfield_reverse:
>        emit_asm(ir, TGSI_OPCODE_BREV, result_dst, op[0]);
>        break;
>     case ir_unop_bit_count:
>        emit_asm(ir, TGSI_OPCODE_POPC, result_dst, op[0]);
>        break;
>     case ir_unop_find_msb:
>        emit_asm(ir, TGSI_OPCODE_IMSB, result_dst, op[0]);
>        break;
>     case ir_unop_find_lsb:
> --
> 2.7.4
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list