nv50: add support for PIPE_CAP_SAMPLE_SHADING
authorIlia Mirkin <imirkin@alum.mit.edu>
Sun, 30 Mar 2014 22:25:40 +0000 (18:25 -0400)
committerIlia Mirkin <imirkin@alum.mit.edu>
Sat, 26 Apr 2014 15:53:24 +0000 (11:53 -0400)
Signed-off-by: Ilia Mirkin <imirkin@alum.mit.edu>
14 files changed:
src/gallium/drivers/nouveau/codegen/nv50_ir.h
src/gallium/drivers/nouveau/codegen/nv50_ir_driver.h
src/gallium/drivers/nouveau/codegen/nv50_ir_from_tgsi.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_lowering_nv50.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_print.cpp
src/gallium/drivers/nouveau/codegen/nv50_ir_target_nv50.cpp
src/gallium/drivers/nouveau/nv50/nv50_context.h
src/gallium/drivers/nouveau/nv50/nv50_program.c
src/gallium/drivers/nouveau/nv50/nv50_program.h
src/gallium/drivers/nouveau/nv50/nv50_screen.c
src/gallium/drivers/nouveau/nv50/nv50_shader_state.c
src/gallium/drivers/nouveau/nv50/nv50_state.c
src/gallium/drivers/nouveau/nv50/nv50_state_validate.c
src/gallium/drivers/nouveau/nv50/nv50_surface.c

index 286ac834e75a6015742f87b856d6babbc16d2a31..96071be0e89c1bc2bd574f526793337223743dc6 100644 (file)
@@ -354,6 +354,7 @@ enum SVSemantic
    SV_POINT_COORD,
    SV_CLIP_DISTANCE,
    SV_SAMPLE_INDEX,
+   SV_SAMPLE_POS,
    SV_TESS_FACTOR,
    SV_TESS_COORD,
    SV_TID,
index f2f4ead1f0a9d806c6625cefd21b0ccc64967cdd..2fe559124901024f5f7ff9f81bf821252a1c831d 100644 (file)
@@ -74,7 +74,6 @@ struct nv50_ir_varying
 #define NV50_SEMANTIC_INVOCATIONID  (TGSI_SEMANTIC_COUNT + 6)
 #define NV50_SEMANTIC_TESSFACTOR    (TGSI_SEMANTIC_COUNT + 7)
 #define NV50_SEMANTIC_TESSCOORD     (TGSI_SEMANTIC_COUNT + 8)
-#define NV50_SEMANTIC_SAMPLEMASK    (TGSI_SEMANTIC_COUNT + 9)
 #define NV50_SEMANTIC_COUNT         (TGSI_SEMANTIC_COUNT + 10)
 
 #define NV50_TESS_PART_FRACT_ODD  0
@@ -181,12 +180,14 @@ struct nv50_ir_prog_info
       uint8_t edgeFlagOut;
       uint8_t fragDepth;         /* output index of FragDepth */
       uint8_t sampleMask;        /* output index of SampleMask */
+      boolean sampleInterp;      /* perform sample interp on all fp inputs */
       uint8_t backFaceColor[2];  /* input/output indices of back face colour */
       uint8_t globalAccess;      /* 1 for read, 2 for wr, 3 for rw */
       boolean nv50styleSurfaces; /* generate gX[] access for raw buffers */
       uint8_t resInfoCBSlot;     /* cX[] used for tex handles, surface info */
       uint16_t texBindBase;      /* base address for tex handles (nve4) */
       uint16_t suInfoBase;       /* base address for surface info (nve4) */
+      uint16_t sampleInfoBase;   /* base address for sample positions */
       uint8_t msInfoCBSlot;      /* cX[] used for multisample info */
       uint16_t msInfoBase;       /* base address for multisample info */
    } io;
index 90820eace7efab0fb5e9b85288089107e402242d..0ec0b9a179dc6e6f914e066371d72273709b21a6 100644 (file)
@@ -346,6 +346,8 @@ static nv50_ir::SVSemantic translateSysVal(uint sysval)
    case TGSI_SEMANTIC_BLOCK_ID:   return nv50_ir::SV_CTAID;
    case TGSI_SEMANTIC_BLOCK_SIZE: return nv50_ir::SV_NTID;
    case TGSI_SEMANTIC_THREAD_ID:  return nv50_ir::SV_TID;
+   case TGSI_SEMANTIC_SAMPLEID:   return nv50_ir::SV_SAMPLE_INDEX;
+   case TGSI_SEMANTIC_SAMPLEPOS:  return nv50_ir::SV_SAMPLE_POS;
    default:
       assert(0);
       return nv50_ir::SV_CLOCK;
@@ -925,7 +927,7 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
                default:
                   break;
                }
-               if (decl->Interp.Centroid)
+               if (decl->Interp.Centroid || info->io.sampleInterp)
                   info->in[i].centroid = 1;
             }
          }
@@ -956,6 +958,9 @@ bool Source::scanDeclaration(const struct tgsi_full_declaration *decl)
                decl->Declaration.UsageMask << (si * 4);
             info->io.genUserClip = -1;
             break;
+         case TGSI_SEMANTIC_SAMPLEMASK:
+            info->io.sampleMask = i;
+            break;
          default:
             break;
          }
index 29f85cf70da927d1dd08d71a90fb6f9c42dd3954..69e88e6902dcea0dc9e766e2fbbda513911f8f82 100644 (file)
@@ -1032,6 +1032,18 @@ NV50LoweringPreSSA::handleRDSV(Instruction *i)
          bld.mkMov(def, bld.mkImm(0));
       }
       break;
+   case SV_SAMPLE_POS: {
+      Value *off = new_LValue(func, FILE_ADDRESS);
+      bld.mkOp1(OP_RDSV, TYPE_U32, def, bld.mkSysVal(SV_SAMPLE_INDEX, 0));
+      bld.mkOp2(OP_SHL, TYPE_U32, off, def, bld.mkImm(3));
+      bld.mkLoad(TYPE_F32,
+                 def,
+                 bld.mkSymbol(
+                       FILE_MEMORY_CONST, prog->driver->io.resInfoCBSlot,
+                       TYPE_U32, prog->driver->io.sampleInfoBase + 4 * idx),
+                 off);
+      break;
+   }
    default:
       bld.mkFetch(i->getDef(0), i->dType,
                   FILE_SHADER_INPUT, addr, i->getIndirect(0, 0), NULL);
index 4093bc0389372baf5a5077d056e9ab0160ea244f..1415eb5d209bbbab54e969e4ace88898e2e5ff88 100644 (file)
@@ -253,6 +253,7 @@ static const char *SemanticStr[SV_LAST + 1] =
    "POINT_COORD",
    "CLIP_DISTANCE",
    "SAMPLE_INDEX",
+   "SAMPLE_POS",
    "TESS_FACTOR",
    "TESS_COORD",
    "TID",
index de076463f66aad09c8197057c5c07e92842c3ebe..0b2f27ad49796f8efce3776b3c27444977ed5380 100644 (file)
@@ -249,6 +249,8 @@ TargetNV50::getSVAddress(DataFile shaderFile, const Symbol *sym) const
       return 0x2 + 2 * sym->reg.data.sv.index;
    case SV_TID:
       return 0;
+   case SV_SAMPLE_POS:
+      return 0; /* sample position is handled differently */
    default:
       return sysvalLocation[sym->reg.data.sv.sv];
    }
index 32ca5918f95eb56d3a4a6f3fabfc850c5a337810..b776deed0ea3cb3ce1f75bfb2502cd9d93ab2133 100644 (file)
@@ -49,6 +49,7 @@
 #define NV50_NEW_TEXTURES     (1 << 19)
 #define NV50_NEW_SAMPLERS     (1 << 20)
 #define NV50_NEW_STRMOUT      (1 << 21)
+#define NV50_NEW_MIN_SAMPLES  (1 << 22)
 #define NV50_NEW_CONTEXT      (1 << 31)
 
 #define NV50_BIND_FB          0
 /* For each MS level (4), 8 sets of 32-bit integer pairs sample offsets */
 #define NV50_CB_AUX_MS_OFFSET     0x880
 #define NV50_CB_AUX_MS_SIZE       (4 * 8 * 4 * 2)
-/* next spot: 0x980 */
+/* Sample position pairs for the current output MS level */
+#define NV50_CB_AUX_SAMPLE_OFFSET 0x980
+#define NV50_CB_AUX_SAMPLE_OFFSET_SIZE (4 * 8 * 2)
+/* next spot: 0x9c0 */
 /* 4 32-bit floats for the vertex runout, put at the end */
 #define NV50_CB_AUX_RUNOUT_OFFSET (NV50_CB_AUX_SIZE - 0x10)
 
@@ -170,6 +174,7 @@ struct nv50_context {
    struct pipe_clip_state clip;
 
    unsigned sample_mask;
+   unsigned min_samples;
 
    boolean vbo_push_hint;
 
index 0e06125df01133f3a8adcbacb8b74115da581ad4..4744a3cc6508bfd0c0ef185a4609e5052c05655b 100644 (file)
@@ -234,8 +234,10 @@ nv50_fragprog_assign_slots(struct nv50_ir_prog_info *info)
       prog->max_out = MAX2(prog->max_out, prog->out[i].hw + 4);
    }
 
-   if (info->io.sampleMask < PIPE_MAX_SHADER_OUTPUTS)
+   if (info->io.sampleMask < PIPE_MAX_SHADER_OUTPUTS) {
       info->out[info->io.sampleMask].slot[0] = prog->max_out++;
+      prog->fp.has_samplemask = 1;
+   }
 
    if (info->io.fragDepth < PIPE_MAX_SHADER_OUTPUTS)
       info->out[info->io.fragDepth].slot[2] = prog->max_out++;
@@ -333,9 +335,11 @@ nv50_program_translate(struct nv50_program *prog, uint16_t chipset)
    info->io.ucpCBSlot = 15;
    info->io.ucpBase = NV50_CB_AUX_UCP_OFFSET;
    info->io.genUserClip = prog->vp.clpd_nr;
+   info->io.sampleInterp = prog->fp.sample_interp;
 
    info->io.resInfoCBSlot = 15;
    info->io.suInfoBase = NV50_CB_AUX_TEX_MS_OFFSET;
+   info->io.sampleInfoBase = NV50_CB_AUX_SAMPLE_OFFSET;
    info->io.msInfoCBSlot = 15;
    info->io.msInfoBase = NV50_CB_AUX_MS_OFFSET;
 
index 87b06790d4fb8b785e4382133e2ac8388f65e53f..fe6bd6025be3d475ee4b78966a6b2994fb0e5934 100644 (file)
@@ -84,6 +84,8 @@ struct nv50_program {
       uint32_t flags[2]; /* 0x19a8, 196c */
       uint32_t interp; /* 0x1988 */
       uint32_t colors; /* 0x1904 */
+      uint8_t has_samplemask;
+      uint8_t sample_interp;
    } fp;
 
    struct {
index 243c7c4c39c9b1e0a34b66bb78fa742ee932f230..7ffffa67a03658470866797a1ff3ea5a9c8d3c35 100644 (file)
@@ -198,13 +198,13 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param)
    case PIPE_CAP_TEXTURE_GATHER_SM5:
    case PIPE_CAP_BUFFER_MAP_PERSISTENT_COHERENT:
    case PIPE_CAP_FAKE_SW_MSAA:
-   case PIPE_CAP_SAMPLE_SHADING:
       return 0;
    case PIPE_CAP_MAX_VIEWPORTS:
       return NV50_MAX_VIEWPORTS;
    case PIPE_CAP_MAX_TEXTURE_GATHER_COMPONENTS:
       return (class_3d >= NVA3_3D_CLASS) ? 4 : 0;
    case PIPE_CAP_TEXTURE_QUERY_LOD:
+   case PIPE_CAP_SAMPLE_SHADING:
       return class_3d >= NVA3_3D_CLASS;
    default:
       NOUVEAU_ERR("unknown PIPE_CAP %d\n", param);
index 28cff8ba913358e0d10e16c6cdc09029ffe0c0a2..c698782d8bd65fd2276c9c726b197787767ad314 100644 (file)
@@ -172,6 +172,8 @@ nv50_fragprog_validate(struct nv50_context *nv50)
    struct nouveau_pushbuf *push = nv50->base.pushbuf;
    struct nv50_program *fp = nv50->fragprog;
 
+   fp->fp.sample_interp = nv50->min_samples > 1;
+
    if (!nv50_program_validate(nv50, fp))
          return;
    nv50_program_update_context_state(nv50, fp, 1);
@@ -186,6 +188,17 @@ nv50_fragprog_validate(struct nv50_context *nv50)
    PUSH_DATA (push, fp->fp.flags[1]);
    BEGIN_NV04(push, NV50_3D(FP_START_ID), 1);
    PUSH_DATA (push, fp->code_base);
+
+   if (nv50->screen->tesla->oclass >= NVA3_3D_CLASS) {
+      BEGIN_NV04(push, SUBC_3D(NVA3_3D_FP_MULTISAMPLE), 1);
+      if (nv50->min_samples > 1 || fp->fp.has_samplemask)
+         PUSH_DATA(push,
+                   NVA3_3D_FP_MULTISAMPLE_FORCE_PER_SAMPLE |
+                   (NVA3_3D_FP_MULTISAMPLE_EXPORT_SAMPLE_MASK *
+                    fp->fp.has_samplemask));
+      else
+         PUSH_DATA(push, 0);
+   }
 }
 
 void
index 647c01f19739a24725d632ffdca2571cbf29290b..d0bc7ff1a2a8b62209e9459f6f9c4f4b80685b87 100644 (file)
@@ -864,6 +864,16 @@ nv50_set_sample_mask(struct pipe_context *pipe, unsigned sample_mask)
    nv50->dirty |= NV50_NEW_SAMPLE_MASK;
 }
 
+static void
+nv50_set_min_samples(struct pipe_context *pipe, unsigned min_samples)
+{
+   struct nv50_context *nv50 = nv50_context(pipe);
+
+   if (nv50->min_samples != min_samples) {
+      nv50->min_samples = min_samples;
+      nv50->dirty |= NV50_NEW_MIN_SAMPLES;
+   }
+}
 
 static void
 nv50_set_framebuffer_state(struct pipe_context *pipe,
@@ -1135,6 +1145,7 @@ nv50_init_state_functions(struct nv50_context *nv50)
    pipe->set_stencil_ref = nv50_set_stencil_ref;
    pipe->set_clip_state = nv50_set_clip_state;
    pipe->set_sample_mask = nv50_set_sample_mask;
+   pipe->set_min_samples = nv50_set_min_samples;
    pipe->set_constant_buffer = nv50_set_constant_buffer;
    pipe->set_framebuffer_state = nv50_set_framebuffer_state;
    pipe->set_polygon_stipple = nv50_set_polygon_stipple;
@@ -1153,4 +1164,5 @@ nv50_init_state_functions(struct nv50_context *nv50)
    pipe->set_stream_output_targets = nv50_set_stream_output_targets;
 
    nv50->sample_mask = ~0;
+   nv50->min_samples = 1;
 }
index 100d02d56030afc0b9229485ab0d88bd7feac295..18451c74f8da93a62231a78f68045911534283ec 100644 (file)
@@ -129,6 +129,19 @@ nv50_validate_fb(struct nv50_context *nv50)
    BEGIN_NV04(push, NV50_3D(VIEWPORT_HORIZ(0)), 2);
    PUSH_DATA (push, fb->width << 16);
    PUSH_DATA (push, fb->height << 16);
+
+   if (nv50->screen->tesla->oclass >= NVA3_3D_CLASS) {
+      unsigned ms = 1 << ms_mode;
+      BEGIN_NV04(push, NV50_3D(CB_ADDR), 1);
+      PUSH_DATA (push, (NV50_CB_AUX_SAMPLE_OFFSET << (8 - 2)) | NV50_CB_AUX);
+      BEGIN_NI04(push, NV50_3D(CB_DATA(0)), 2 * ms);
+      for (i = 0; i < ms; i++) {
+         float xy[2];
+         nv50->base.pipe.get_sample_position(&nv50->base.pipe, ms, i, xy);
+         PUSH_DATAf(push, xy[0]);
+         PUSH_DATAf(push, xy[1]);
+      }
+   }
 }
 
 static void
@@ -358,6 +371,23 @@ nv50_validate_sample_mask(struct nv50_context *nv50)
    PUSH_DATA (push, mask[3]);
 }
 
+static void
+nv50_validate_min_samples(struct nv50_context *nv50)
+{
+   struct nouveau_pushbuf *push = nv50->base.pushbuf;
+   int samples;
+
+   if (nv50->screen->tesla->oclass < NVA3_3D_CLASS)
+      return;
+
+   samples = util_next_power_of_two(nv50->min_samples);
+   if (samples > 1)
+      samples |= NVA3_3D_SAMPLE_SHADING_ENABLE;
+
+   BEGIN_NV04(push, SUBC_3D(NVA3_3D_SAMPLE_SHADING), 1);
+   PUSH_DATA (push, samples);
+}
+
 static void
 nv50_switch_pipe_context(struct nv50_context *ctx_to)
 {
@@ -414,7 +444,8 @@ static struct state_validate {
     { nv50_validate_viewport,      NV50_NEW_VIEWPORT },
     { nv50_vertprog_validate,      NV50_NEW_VERTPROG },
     { nv50_gmtyprog_validate,      NV50_NEW_GMTYPROG },
-    { nv50_fragprog_validate,      NV50_NEW_FRAGPROG },
+    { nv50_fragprog_validate,      NV50_NEW_FRAGPROG |
+                                   NV50_NEW_MIN_SAMPLES },
     { nv50_fp_linkage_validate,    NV50_NEW_FRAGPROG | NV50_NEW_VERTPROG |
                                    NV50_NEW_GMTYPROG | NV50_NEW_RASTERIZER },
     { nv50_gp_linkage_validate,    NV50_NEW_GMTYPROG | NV50_NEW_VERTPROG },
@@ -427,7 +458,8 @@ static struct state_validate {
     { nv50_validate_samplers,      NV50_NEW_SAMPLERS },
     { nv50_stream_output_validate, NV50_NEW_STRMOUT |
                                    NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG },
-    { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS }
+    { nv50_vertex_arrays_validate, NV50_NEW_VERTEX | NV50_NEW_ARRAYS },
+    { nv50_validate_min_samples,   NV50_NEW_MIN_SAMPLES },
 };
 #define validate_list_len (sizeof(validate_list) / sizeof(validate_list[0]))
 
index e60aec52e10d82b897a6c6c9a3e12feef780b763..6b4dc4d49495b7bd8c10da11d481dd3e5be2b34b 100644 (file)
@@ -622,6 +622,7 @@ struct nv50_blitctx
       unsigned num_samplers[3];
       struct pipe_sampler_view *texture[2];
       struct nv50_tsc_entry *sampler[2];
+      unsigned min_samples;
       uint32_t dirty;
    } saved;
    struct nv50_rasterizer_stateobj rast;
@@ -1000,6 +1001,8 @@ nv50_blitctx_pre_blit(struct nv50_blitctx *ctx)
    ctx->saved.gp = nv50->gmtyprog;
    ctx->saved.fp = nv50->fragprog;
 
+   ctx->saved.min_samples = nv50->min_samples;
+
    nv50->rast = &ctx->rast;
 
    nv50->vertprog = &blitter->vp;
@@ -1021,13 +1024,15 @@ nv50_blitctx_pre_blit(struct nv50_blitctx *ctx)
    nv50->num_samplers[0] = nv50->num_samplers[1] = 0;
    nv50->num_samplers[2] = 2;
 
+   nv50->min_samples = 1;
+
    ctx->saved.dirty = nv50->dirty;
 
    nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_FB);
    nouveau_bufctx_reset(nv50->bufctx_3d, NV50_BIND_TEXTURES);
 
    nv50->dirty =
-      NV50_NEW_FRAMEBUFFER |
+      NV50_NEW_FRAMEBUFFER | NV50_NEW_MIN_SAMPLES |
       NV50_NEW_VERTPROG | NV50_NEW_FRAGPROG | NV50_NEW_GMTYPROG |
       NV50_NEW_TEXTURES | NV50_NEW_SAMPLERS;
 }
@@ -1052,6 +1057,8 @@ nv50_blitctx_post_blit(struct nv50_blitctx *blit)
    nv50->gmtyprog = blit->saved.gp;
    nv50->fragprog = blit->saved.fp;
 
+   nv50->min_samples = blit->saved.min_samples;
+
    pipe_sampler_view_reference(&nv50->textures[2][0], NULL);
    pipe_sampler_view_reference(&nv50->textures[2][1], NULL);
 
@@ -1076,6 +1083,8 @@ nv50_blitctx_post_blit(struct nv50_blitctx *blit)
        NV50_NEW_RASTERIZER | NV50_NEW_ZSA | NV50_NEW_BLEND |
        NV50_NEW_TEXTURES | NV50_NEW_SAMPLERS |
        NV50_NEW_VERTPROG | NV50_NEW_GMTYPROG | NV50_NEW_FRAGPROG);
+
+   nv50->base.pipe.set_min_samples(&nv50->base.pipe, blit->saved.min_samples);
 }