microsoft/nir_to_dxil: Avoid emitting SampleCmpLevel prior to SM 6.7 if possible
authorPedro J. Estébanez <pedrojrulez@gmail.com>
Mon, 21 Nov 2022 11:56:37 +0000 (12:56 +0100)
committerMarge Bot <emma+marge@anholt.net>
Tue, 22 Nov 2022 16:49:36 +0000 (16:49 +0000)
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19896>

src/microsoft/compiler/nir_to_dxil.c

index 70fe678..55c14a1 100644 (file)
@@ -4858,17 +4858,9 @@ emit_sample_cmp(struct ntd_context *ctx, struct texop_parameters *params)
 {
    const struct dxil_func *func;
    enum dxil_intr opcode;
-   int numparam;
 
-   if (ctx->mod.shader_kind == DXIL_PIXEL_SHADER) {
-      func = dxil_get_function(&ctx->mod, "dx.op.sampleCmp", DXIL_F32);
-      opcode = DXIL_INTR_SAMPLE_CMP;
-      numparam = 12;
-   } else {
-      func = dxil_get_function(&ctx->mod, "dx.op.sampleCmpLevelZero", DXIL_F32);
-      opcode = DXIL_INTR_SAMPLE_CMP_LVL_ZERO;
-      numparam = 11;
-   }
+   func = dxil_get_function(&ctx->mod, "dx.op.sampleCmp", DXIL_F32);
+   opcode = DXIL_INTR_SAMPLE_CMP;
 
    if (!func)
       return NULL;
@@ -4881,7 +4873,30 @@ emit_sample_cmp(struct ntd_context *ctx, struct texop_parameters *params)
       params->cmp, params->min_lod
    };
 
-   return dxil_emit_call(&ctx->mod, func, args, numparam);
+   return dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args));
+}
+
+static const struct dxil_value *
+emit_sample_cmp_level_zero(struct ntd_context *ctx, struct texop_parameters *params)
+{
+   const struct dxil_func *func;
+   enum dxil_intr opcode;
+
+   func = dxil_get_function(&ctx->mod, "dx.op.sampleCmpLevelZero", DXIL_F32);
+   opcode = DXIL_INTR_SAMPLE_CMP_LVL_ZERO;
+
+   if (!func)
+      return NULL;
+
+   const struct dxil_value *args[11] = {
+      dxil_module_get_int32_const(&ctx->mod, opcode),
+      params->tex, params->sampler,
+      params->coord[0], params->coord[1], params->coord[2], params->coord[3],
+      params->offset[0], params->offset[1], params->offset[2],
+      params->cmp
+   };
+
+   return dxil_emit_call(&ctx->mod, func, args, ARRAY_SIZE(args));
 }
 
 static const struct dxil_value *
@@ -5008,6 +5023,7 @@ emit_tex(struct ntd_context *ctx, nir_tex_instr *instr)
    unsigned coord_components = 0, offset_components = 0, dx_components = 0, dy_components = 0;
    params.overload = get_overload(instr->dest_type, 32);
 
+   bool lod_is_zero = false;
    for (unsigned i = 0; i < instr->num_srcs; i++) {
       nir_alu_type type = nir_tex_instr_src_type(instr, i);
 
@@ -5048,6 +5064,9 @@ emit_tex(struct ntd_context *ctx, nir_tex_instr *instr)
             params.lod_or_sample = int_undef;
          if (!params.lod_or_sample)
             return false;
+
+         if (nir_src_is_const(instr->src[i].src) && nir_src_as_float(instr->src[i].src) == 0.0f)
+            lod_is_zero = true;
          break;
 
       case nir_tex_src_min_lod:
@@ -5148,12 +5167,21 @@ emit_tex(struct ntd_context *ctx, nir_tex_instr *instr)
          break;
       }
       params.lod_or_sample = dxil_module_get_float_const(&ctx->mod, 0);
+      lod_is_zero = true;
       FALLTHROUGH;
    case nir_texop_txl:
-      if (params.cmp != NULL)
-         sample = emit_sample_cmp_level(ctx, &params);
-      else
-         sample = emit_sample_level(ctx, &params);
+      if (lod_is_zero && params.cmp != NULL && ctx->opts->shader_model_max < SHADER_MODEL_6_7) {
+         /* Prior to SM 6.7, if the level is constant 0.0, ignore the LOD argument,
+          * so level-less DXIL instructions are used. This is needed to avoid emitting
+          * dx.op.sampleCmpLevel, which would not be available.
+          */
+         sample = emit_sample_cmp_level_zero(ctx, &params);
+      } else {
+         if (params.cmp != NULL)
+            sample = emit_sample_cmp_level(ctx, &params);
+         else
+            sample = emit_sample_level(ctx, &params);
+      }
       break;
 
    case nir_texop_txd: