zink: implement nir_texop_txd
authorErik Faye-Lund <erik.faye-lund@collabora.com>
Tue, 17 Dec 2019 20:17:09 +0000 (21:17 +0100)
committerErik Faye-Lund <erik.faye-lund@collabora.com>
Thu, 19 Dec 2019 12:14:29 +0000 (13:14 +0100)
This lets us enable PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD, which in turns
gives us ARB_shader_texture_lod.

Still fails one piglit test on ANV, namely
spec@arb_shader_texture_lod@execution@arb_shader_texture_lod-texgradcube,
but with 33 new passing tests, I think this is worth it.

Reviewed-by: Dave Airlie <airlied@redhat.com>
Tested-by: Marge Bot <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3140>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/merge_requests/3140>

src/gallium/drivers/zink/nir_to_spirv/nir_to_spirv.c
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.c
src/gallium/drivers/zink/nir_to_spirv/spirv_builder.h
src/gallium/drivers/zink/zink_screen.c

index 36e6fa0f1fee353cec700032a7ecf67785746f44..e11882348cbc1c28862c799899889f54eb1bdb2f 100644 (file)
@@ -1324,11 +1324,12 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
 {
    assert(tex->op == nir_texop_tex ||
           tex->op == nir_texop_txb ||
-          tex->op == nir_texop_txl);
+          tex->op == nir_texop_txl ||
+          tex->op == nir_texop_txd);
    assert(nir_alu_type_get_base_type(tex->dest_type) == nir_type_float);
    assert(tex->texture_index == tex->sampler_index);
 
-   SpvId coord = 0, proj = 0, bias = 0, lod = 0, dref = 0;
+   SpvId coord = 0, proj = 0, bias = 0, lod = 0, dref = 0, dx = 0, dy = 0;
    unsigned coord_components = 0;
    for (unsigned i = 0; i < tex->num_srcs; i++) {
       switch (tex->src[i].src_type) {
@@ -1361,6 +1362,16 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
          assert(dref != 0);
          break;
 
+      case nir_tex_src_ddx:
+         dx = get_src_float(ctx, &tex->src[i].src);
+         assert(dx != 0);
+         break;
+
+      case nir_tex_src_ddy:
+         dy = get_src_float(ctx, &tex->src[i].src);
+         assert(dy != 0);
+         break;
+
       default:
          fprintf(stderr, "texture source: %d\n", tex->src[i].src_type);
          unreachable("unknown texture source");
@@ -1418,7 +1429,7 @@ emit_tex(struct ntv_context *ctx, nir_tex_instr *tex)
                                                   actual_dest_type, load,
                                                   coord,
                                                   proj != 0,
-                                                  lod, bias, dref);
+                                                  lod, bias, dref, dx, dy);
    spirv_builder_emit_decoration(&ctx->builder, result,
                                  SpvDecorationRelaxedPrecision);
 
index 32d5283c2172c94e96f6ad8282fbffb29ac54e33..275f81eb4fb99e60dbe0fd00b0532e6102282e71 100644 (file)
@@ -513,7 +513,9 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
                                 bool proj,
                                 SpvId lod,
                                 SpvId bias,
-                                SpvId dref)
+                                SpvId dref,
+                                SpvId dx,
+                                SpvId dy)
 {
    SpvId result = spirv_builder_new_id(b);
 
@@ -521,7 +523,7 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
    int operands = 5;
    if (proj)
       opcode += SpvOpImageSampleProjImplicitLod - SpvOpImageSampleImplicitLod;
-   if (lod)
+   if (lod || (dx && dy))
       opcode += SpvOpImageSampleExplicitLod - SpvOpImageSampleImplicitLod;
    if (dref) {
       opcode += SpvOpImageSampleDrefImplicitLod - SpvOpImageSampleImplicitLod;
@@ -529,7 +531,7 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
    }
 
    SpvImageOperandsMask operand_mask = 0;
-   SpvId extra_operands[3];
+   SpvId extra_operands[4];
    int num_extra_operands = SpvImageOperandsMaskNone;
    if (bias) {
       extra_operands[++num_extra_operands] = bias;
@@ -538,6 +540,10 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
    if (lod) {
       extra_operands[++num_extra_operands] = lod;
       operand_mask |= SpvImageOperandsLodMask;
+   } else if (dx && dy) {
+      extra_operands[++num_extra_operands] = dx;
+      extra_operands[++num_extra_operands] = dy;
+      operand_mask |= SpvImageOperandsGradMask;
    }
 
    /* finalize num_extra_operands / extra_operands */
index 612e6ec03736de7c2e08376b83aa70314af68d3b..736eb211fc78cb7ef89c8a6cf076c4a7b36b995b 100644 (file)
@@ -213,7 +213,9 @@ spirv_builder_emit_image_sample(struct spirv_builder *b,
                                 bool proj,
                                 SpvId lod,
                                 SpvId bias,
-                                SpvId dref);
+                                SpvId dref,
+                                SpvId dx,
+                                SpvId dy);
 
 SpvId
 spirv_builder_emit_ext_inst(struct spirv_builder *b, SpvId result_type,
index 81dd65672c91ffe5a17d8b1529cfe30282484e46..5441445e1b8813e094adfb2e3001ffcc0469164c 100644 (file)
@@ -122,11 +122,7 @@ zink_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
       return 1 + util_logbase2(screen->props.limits.maxImageDimensionCube);
 
    case PIPE_CAP_BLEND_EQUATION_SEPARATE:
-      return 1;
-
    case PIPE_CAP_FRAGMENT_SHADER_TEXTURE_LOD:
-      return 0; /* TODO: re-enable after implementing nir_texop_txd */
-
    case PIPE_CAP_FRAGMENT_SHADER_DERIVATIVES:
    case PIPE_CAP_VERTEX_SHADER_SATURATE:
       return 1;