aco: improve code for f2{i,u}{8,16}
[mesa.git] / src / amd / compiler / aco_instruction_selection.cpp
index 8e5942c1971872e8319758173900ecc8c50d6743..0b59a7e2e91883fd74babd64f2e347a7c105eb3b 100644 (file)
@@ -2294,7 +2294,6 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr)
       assert(dst.size() == 1);
       Temp src = get_alu_src(ctx, instr->src[0]);
       if (instr->src[0].src.ssa->bit_size == 8) {
-         //TODO: we should use v_cvt_f32_ubyte1/v_cvt_f32_ubyte2/etc depending on the register assignment
          bld.vop1(aco_opcode::v_cvt_f32_ubyte0, Definition(dst), src);
       } else {
          if (instr->src[0].src.ssa->bit_size == 16)
@@ -2328,33 +2327,31 @@ void visit_alu_instr(isel_context *ctx, nir_alu_instr *instr)
    case nir_op_f2i8:
    case nir_op_f2i16: {
       Temp src = get_alu_src(ctx, instr->src[0]);
+      Temp tmp = dst.type() == RegType::vgpr ? dst : bld.tmp(v1);
       if (instr->src[0].src.ssa->bit_size == 16)
-         src = bld.vop1(aco_opcode::v_cvt_i16_f16, bld.def(v1), src);
+         src = bld.vop1(aco_opcode::v_cvt_i16_f16, Definition(tmp), src);
       else if (instr->src[0].src.ssa->bit_size == 32)
-         src = bld.vop1(aco_opcode::v_cvt_i32_f32, bld.def(v1), src);
+         src = bld.vop1(aco_opcode::v_cvt_i32_f32, Definition(tmp), src);
       else
-         src = bld.vop1(aco_opcode::v_cvt_i32_f64, bld.def(v1), src);
+         src = bld.vop1(aco_opcode::v_cvt_i32_f64, Definition(tmp), src);
 
-      if (dst.type() == RegType::vgpr)
-         bld.pseudo(aco_opcode::p_extract_vector, Definition(dst), src, Operand(0u));
-      else
+      if (dst.type() != RegType::vgpr)
          bld.pseudo(aco_opcode::p_as_uniform, Definition(dst), src);
       break;
    }
    case nir_op_f2u8:
    case nir_op_f2u16: {
       Temp src = get_alu_src(ctx, instr->src[0]);
+      Temp tmp = dst.type() == RegType::vgpr ? dst : bld.tmp(v1);
       if (instr->src[0].src.ssa->bit_size == 16)
-         src = bld.vop1(aco_opcode::v_cvt_u16_f16, bld.def(v1), src);
+         bld.vop1(aco_opcode::v_cvt_u16_f16, Definition(tmp), src);
       else if (instr->src[0].src.ssa->bit_size == 32)
-         src = bld.vop1(aco_opcode::v_cvt_u32_f32, bld.def(v1), src);
+         bld.vop1(aco_opcode::v_cvt_u32_f32, Definition(tmp), src);
       else
-         src = bld.vop1(aco_opcode::v_cvt_u32_f64, bld.def(v1), src);
+         bld.vop1(aco_opcode::v_cvt_u32_f64, Definition(tmp), src);
 
-      if (dst.type() == RegType::vgpr)
-         bld.pseudo(aco_opcode::p_extract_vector, Definition(dst), src, Operand(0u));
-      else
-         bld.pseudo(aco_opcode::p_as_uniform, Definition(dst), src);
+      if (dst.type() != RegType::vgpr)
+         bld.pseudo(aco_opcode::p_as_uniform, Definition(dst), tmp);
       break;
    }
    case nir_op_f2i32: {
@@ -3193,7 +3190,7 @@ void emit_load(isel_context *ctx, Builder& bld, const LoadEmitInfo *info)
       }
 
       /* shift result right if needed */
-      if (info->component_size < 4) {
+      if (info->component_size < 4 && byte_align_loads) {
          Operand align((uint32_t)byte_align);
          if (byte_align == -1) {
             if (offset.isConstant())
@@ -10100,6 +10097,26 @@ static bool export_fs_mrt_color(isel_context *ctx, int slot)
    if (target == V_008DFC_SQ_EXP_NULL)
       return false;
 
+   /* Replace NaN by zero (only 32-bit) to fix game bugs if requested. */
+   if (ctx->options->enable_mrt_output_nan_fixup &&
+       !is_16bit &&
+       (col_format == V_028714_SPI_SHADER_32_R ||
+        col_format == V_028714_SPI_SHADER_32_GR ||
+        col_format == V_028714_SPI_SHADER_32_AR ||
+        col_format == V_028714_SPI_SHADER_32_ABGR ||
+        col_format == V_028714_SPI_SHADER_FP16_ABGR)) {
+      for (int i = 0; i < 4; i++) {
+         if (!(write_mask & (1 << i)))
+            continue;
+
+         Temp isnan = bld.vopc(aco_opcode::v_cmp_class_f32,
+                               bld.hint_vcc(bld.def(bld.lm)), values[i],
+                               bld.copy(bld.def(v1), Operand(3u)));
+         values[i] = bld.vop2(aco_opcode::v_cndmask_b32, bld.def(v1), values[i],
+                              bld.copy(bld.def(v1), Operand(0u)), isnan);
+      }
+   }
+
    if ((bool) compr_op) {
       for (int i = 0; i < 2; i++) {
          /* check if at least one of the values to be compressed is enabled */