st/mesa: add support for ARB_texture_multisample (v3)
authorDave Airlie <airlied@redhat.com>
Sun, 3 Mar 2013 20:17:11 +0000 (06:17 +1000)
committerDave Airlie <airlied@redhat.com>
Thu, 11 Apr 2013 20:09:29 +0000 (21:09 +0100)
This adds support to the mesa state tracker for ARB_texture_multisample.

hardware doesn't seem to use a different texture instructions, so
I don't think we need to create one for TGSI at this time.

Thanks to Marek for fixes to sample number picking.

v2: idr pointed out a bug in how we picked the max sample counts,
use new internal format chooser interface to pick proper answers.
v3: use st_choose_format directly, it was okay, fix anding of masks.

Reviewed-by: Marek Olšák <maraeo@gmail.com>
Signed-off-by: Dave Airlie <airlied@redhat.com>
12 files changed:
src/mesa/state_tracker/st_atom_framebuffer.c
src/mesa/state_tracker/st_atom_msaa.c
src/mesa/state_tracker/st_cb_bitmap.c
src/mesa/state_tracker/st_cb_drawpixels.c
src/mesa/state_tracker/st_cb_fbo.c
src/mesa/state_tracker/st_cb_texture.c
src/mesa/state_tracker/st_extensions.c
src/mesa/state_tracker/st_gen_mipmap.c
src/mesa/state_tracker/st_glsl_to_tgsi.cpp
src/mesa/state_tracker/st_mesa_to_tgsi.c
src/mesa/state_tracker/st_texture.c
src/mesa/state_tracker/st_texture.h

index 3df8691f4b96fff304b916ee7ddefe7e2c7fce0b..c752640f49d9a5da1a6daeeea84c2882fd8c2001 100644 (file)
@@ -59,6 +59,7 @@ update_renderbuffer_surface(struct st_context *st,
    enum pipe_format format = st->ctx->Color.sRGBEnabled ? resource->format : util_format_linear(resource->format);
 
    if (!strb->surface ||
+       strb->surface->texture->nr_samples != strb->Base.NumSamples ||
        strb->surface->format != format ||
        strb->surface->texture != resource ||
        strb->surface->width != rtt_width ||
index 9baa4fcf2eb9fa2f06ee27223b49c11a18484b3b..fb760460c5738bfdca3f888fa638d57f9e5d8b05 100644 (file)
@@ -62,7 +62,8 @@ static void update_sample_mask( struct st_context *st )
          if (st->ctx->Multisample.SampleCoverageInvert)
             sample_mask = ~sample_mask;
       }
-      /* TODO merge with app-supplied sample mask */
+      if (st->ctx->Multisample.SampleMask)
+         sample_mask &= st->ctx->Multisample.SampleMaskValue;
    }
 
    /* mask off unused bits or don't care? */
index 68399643c53e14a30cd5ec42e785970bacecd7d6..456933621e233867504c313a6ab9bbbca506d611 100644 (file)
@@ -298,7 +298,7 @@ make_bitmap_texture(struct gl_context *ctx, GLsizei width, GLsizei height,
     * Create texture to hold bitmap pattern.
     */
    pt = st_texture_create(st, st->internal_target, st->bitmap.tex_format,
-                          0, width, height, 1, 1,
+                          0, width, height, 1, 1, 0,
                           PIPE_BIND_SAMPLER_VIEW);
    if (!pt) {
       _mesa_unmap_pbo_source(ctx, unpack);
@@ -566,7 +566,7 @@ reset_cache(struct st_context *st)
    cache->texture = st_texture_create(st, PIPE_TEXTURE_2D,
                                       st->bitmap.tex_format, 0,
                                       BITMAP_CACHE_WIDTH, BITMAP_CACHE_HEIGHT,
-                                      1, 1,
+                                      1, 1, 0,
                                      PIPE_BIND_SAMPLER_VIEW);
 }
 
index bfb8ee8e1d4364232d56e39015ba5051253ff2c2..de7b91f281b8dfaeadbf4b5131dd7d60e1936dc3 100644 (file)
@@ -465,7 +465,7 @@ alloc_texture(struct st_context *st, GLsizei width, GLsizei height,
    struct pipe_resource *pt;
 
    pt = st_texture_create(st, st->internal_target, texFormat, 0,
-                          width, height, 1, 1, PIPE_BIND_SAMPLER_VIEW);
+                          width, height, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
 
    return pt;
 }
index 4619aec0c77d6b36d39131af5923c38cd0092a82..7335bb4bac56b17749616b7c6666bf5b32fec912 100644 (file)
@@ -432,7 +432,7 @@ st_render_texture(struct gl_context *ctx,
    strb->rtt_level = att->TextureLevel;
    strb->rtt_face = att->CubeMapFace;
    strb->rtt_slice = att->Zoffset;
-
+   rb->NumSamples = texImage->NumSamples;
    rb->Width = texImage->Width2;
    rb->Height = texImage->Height2;
    rb->_BaseFormat = texImage->_BaseFormat;
index 9d0a6b7e0ad059f7ac400a3153d433610461fb26..123ed2be88dfbc943ce186c4cc79deec265fc47f 100644 (file)
@@ -77,6 +77,8 @@ gl_target_to_pipe(GLenum target)
    case GL_TEXTURE_2D:
    case GL_PROXY_TEXTURE_2D:
    case GL_TEXTURE_EXTERNAL_OES:
+   case GL_TEXTURE_2D_MULTISAMPLE:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
       return PIPE_TEXTURE_2D;
    case GL_TEXTURE_RECTANGLE_NV:
    case GL_PROXY_TEXTURE_RECTANGLE_NV:
@@ -98,6 +100,8 @@ gl_target_to_pipe(GLenum target)
       return PIPE_TEXTURE_1D_ARRAY;
    case GL_TEXTURE_2D_ARRAY_EXT:
    case GL_PROXY_TEXTURE_2D_ARRAY_EXT:
+   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
       return PIPE_TEXTURE_2D_ARRAY;
    case GL_TEXTURE_BUFFER:
       return PIPE_BUFFER;
@@ -407,7 +411,7 @@ guess_and_alloc_texture(struct st_context *st,
                                  ptWidth,
                                  ptHeight,
                                  ptDepth,
-                                 ptLayers,
+                                 ptLayers, 0,
                                  bindings);
 
    stObj->lastLevel = lastLevel;
@@ -495,7 +499,7 @@ st_AllocTextureImageBuffer(struct gl_context *ctx,
                                       ptWidth,
                                       ptHeight,
                                       ptDepth,
-                                      ptLayers,
+                                      ptLayers, 0,
                                       bindings);
       return stImage->pt != NULL;
    }
@@ -1491,7 +1495,7 @@ st_finalize_texture(struct gl_context *ctx,
    GLuint face;
    struct st_texture_image *firstImage;
    enum pipe_format firstImageFormat;
-   GLuint ptWidth, ptHeight, ptDepth, ptLayers;
+   GLuint ptWidth, ptHeight, ptDepth, ptLayers, ptNumSamples;
 
    if (_mesa_is_texture_complete(tObj, &tObj->Sampler)) {
       /* The texture is complete and we know exactly how many mipmap levels
@@ -1555,6 +1559,7 @@ st_finalize_texture(struct gl_context *ctx,
       /* convert GL dims to Gallium dims */
       st_gl_texture_dims_to_pipe_dims(stObj->base.Target, width, height, depth,
                                       &ptWidth, &ptHeight, &ptDepth, &ptLayers);
+      ptNumSamples = firstImage->base.NumSamples;
    }
 
    /* If we already have a gallium texture, check that it matches the texture
@@ -1567,6 +1572,7 @@ st_finalize_texture(struct gl_context *ctx,
           stObj->pt->width0 != ptWidth ||
           stObj->pt->height0 != ptHeight ||
           stObj->pt->depth0 != ptDepth ||
+          stObj->pt->nr_samples != ptNumSamples ||
           stObj->pt->array_size != ptLayers)
       {
          /* The gallium texture does not match the Mesa texture so delete the
@@ -1590,7 +1596,7 @@ st_finalize_texture(struct gl_context *ctx,
                                     ptWidth,
                                     ptHeight,
                                     ptDepth,
-                                    ptLayers,
+                                    ptLayers, ptNumSamples,
                                     bindings);
 
       if (!stObj->pt) {
@@ -1636,11 +1642,14 @@ st_AllocTextureStorage(struct gl_context *ctx,
                        GLsizei height, GLsizei depth)
 {
    const GLuint numFaces = _mesa_num_tex_faces(texObj->Target);
+   struct gl_texture_image *texImage = texObj->Image[0][0];
    struct st_context *st = st_context(ctx);
    struct st_texture_object *stObj = st_texture_object(texObj);
+   struct pipe_screen *screen = st->pipe->screen;
    GLuint ptWidth, ptHeight, ptDepth, ptLayers, bindings;
    enum pipe_format fmt;
    GLint level;
+   int num_samples = texImage->NumSamples;
 
    assert(levels > 0);
 
@@ -1650,10 +1659,30 @@ st_AllocTextureStorage(struct gl_context *ctx,
    stObj->depth0 = depth;
    stObj->lastLevel = levels - 1;
 
-   fmt = st_mesa_format_to_pipe_format(texObj->Image[0][0]->TexFormat);
+   fmt = st_mesa_format_to_pipe_format(texImage->TexFormat);
 
    bindings = default_bindings(st, fmt);
 
+   /* Raise the sample count if the requested one is unsupported. */
+   if (num_samples > 1) {
+      boolean found = FALSE;
+
+      for (; num_samples <= ctx->Const.MaxSamples; num_samples++) {
+         if (screen->is_format_supported(screen, fmt, PIPE_TEXTURE_2D,
+                                         num_samples,
+                                         PIPE_BIND_SAMPLER_VIEW)) {
+            /* Update the sample count in gl_texture_image as well. */
+            texImage->NumSamples = num_samples;
+            found = TRUE;
+            break;
+         }
+      }
+
+      if (!found) {
+         return GL_FALSE;
+      }
+   }
+
    st_gl_texture_dims_to_pipe_dims(texObj->Target,
                                    width, height, depth,
                                    &ptWidth, &ptHeight, &ptDepth, &ptLayers);
@@ -1665,7 +1694,7 @@ st_AllocTextureStorage(struct gl_context *ctx,
                                  ptWidth,
                                  ptHeight,
                                  ptDepth,
-                                 ptLayers,
+                                 ptLayers, num_samples,
                                  bindings);
    if (!stObj->pt)
       return GL_FALSE;
index b3f229ad07b1d53fa403897ca7ef87aa9f7d9370..f9864803ddd60a7e46db7b484ce00a26faf884d1 100644 (file)
@@ -37,7 +37,7 @@
 
 #include "st_context.h"
 #include "st_extensions.h"
-
+#include "st_format.h"
 
 static int _min(int a, int b)
 {
@@ -397,7 +397,8 @@ void st_init_extensions(struct st_context *st)
       { o(MESA_texture_array),               PIPE_CAP_MAX_TEXTURE_ARRAY_LAYERS         },
 
       { o(OES_standard_derivatives),         PIPE_CAP_SM3                              },
-      { o(ARB_texture_cube_map_array),       PIPE_CAP_CUBE_MAP_ARRAY                   }
+      { o(ARB_texture_cube_map_array),       PIPE_CAP_CUBE_MAP_ARRAY                   },
+      { o(ARB_texture_multisample),          PIPE_CAP_TEXTURE_MULTISAMPLE              }
    };
 
    /* Required: render target and sampler support */
@@ -657,10 +658,33 @@ void st_init_extensions(struct st_context *st)
 
    /* Maximum sample count. */
    for (i = 16; i > 0; --i) {
-      if (screen->is_format_supported(screen, PIPE_FORMAT_B8G8R8A8_UNORM,
-                                      PIPE_TEXTURE_2D, i,
-                                      PIPE_BIND_RENDER_TARGET)) {
+      enum pipe_format pformat = st_choose_format(st, GL_RGBA,
+                                                  GL_NONE, GL_NONE,
+                                                  PIPE_TEXTURE_2D, i,
+                                                  PIPE_BIND_RENDER_TARGET, FALSE);
+      if (pformat != PIPE_FORMAT_NONE) {
          ctx->Const.MaxSamples = i;
+         ctx->Const.MaxColorTextureSamples = i;
+         break;
+      }
+   }
+   for (i = ctx->Const.MaxSamples; i > 0; --i) {
+      enum pipe_format pformat = st_choose_format(st, GL_DEPTH_STENCIL,
+                                                  GL_NONE, GL_NONE,
+                                                  PIPE_TEXTURE_2D, i,
+                                                  PIPE_BIND_DEPTH_STENCIL, FALSE);
+      if (pformat != PIPE_FORMAT_NONE) {
+         ctx->Const.MaxDepthTextureSamples = i;
+         break;
+      }
+   }
+   for (i = ctx->Const.MaxSamples; i > 0; --i) {
+      enum pipe_format pformat = st_choose_format(st, GL_RGBA_INTEGER,
+                                                  GL_NONE, GL_NONE,
+                                                  PIPE_TEXTURE_2D, i,
+                                                  PIPE_BIND_RENDER_TARGET, FALSE);
+      if (pformat != PIPE_FORMAT_NONE) {
+         ctx->Const.MaxIntegerSamples = i;
          break;
       }
    }
index 8ce2e06a241a4f6775f0c33c7260fec6d47fd037..e5512af2a0d91a7625ed7f5138c3ca4497795d46 100644 (file)
@@ -172,6 +172,7 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target,
                                     oldTex->height0,
                                     oldTex->depth0,
                                     oldTex->array_size,
+                                    0,
                                     oldTex->bind);
 
       /* This will copy the old texture's base image into the new texture
index 338c652cb6a95b09c331c62b6431bd6b866d8adc..589c91287128f9291cbdd774a0b7c19f901ba5fd 100644 (file)
@@ -2683,7 +2683,7 @@ glsl_to_tgsi_visitor::visit(ir_call *ir)
 void
 glsl_to_tgsi_visitor::visit(ir_texture *ir)
 {
-   st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset;
+   st_src_reg result_src, coord, cube_sc, lod_info, projector, dx, dy, offset, sample_index;
    st_dst_reg result_dst, coord_dst, cube_sc_dst;
    glsl_to_tgsi_instruction *inst = NULL;
    unsigned opcode = TGSI_OPCODE_NOP;
@@ -2706,6 +2706,7 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
        */
       coord = get_temp(glsl_type::vec4_type);
       coord_dst = st_dst_reg(coord);
+      coord_dst.writemask = (1 << ir->coordinate->type->vector_elements) - 1;
       emit(ir, TGSI_OPCODE_MOV, coord_dst, this->result);
    }
 
@@ -2772,7 +2773,9 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
       }
       break;
    case ir_txf_ms:
-      assert(!"Unexpected ir_txf_ms opcode");
+      opcode = TGSI_OPCODE_TXF;
+      ir->lod_info.sample_index->accept(this);
+      sample_index = this->result;
       break;
    case ir_lod:
       assert(!"Unexpected ir_lod opcode");
@@ -2859,7 +2862,11 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
       }
    }
 
-   if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
+   if (ir->op == ir_txf_ms) {
+      coord_dst.writemask = WRITEMASK_W;
+      emit(ir, TGSI_OPCODE_MOV, coord_dst, sample_index);
+      coord_dst.writemask = WRITEMASK_XYZW;
+   } else if (opcode == TGSI_OPCODE_TXL || opcode == TGSI_OPCODE_TXB ||
        opcode == TGSI_OPCODE_TXF) {
       /* TGSI stores LOD or LOD bias in the last channel of the coords. */
       coord_dst.writemask = WRITEMASK_W;
@@ -2921,6 +2928,10 @@ glsl_to_tgsi_visitor::visit(ir_texture *ir)
    case GLSL_SAMPLER_DIM_EXTERNAL:
       inst->tex_target = TEXTURE_EXTERNAL_INDEX;
       break;
+   case GLSL_SAMPLER_DIM_MS:
+      inst->tex_target = (sampler_type->sampler_array)
+         ? TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX : TEXTURE_2D_MULTISAMPLE_INDEX;
+      break;
    default:
       assert(!"Should not get here.");
    }
index 3831a0a793b4d8aa187c56081ed0ee983c5d432c..5471a9a86f2206cf722e640261071ee3f9416704 100644 (file)
@@ -269,6 +269,8 @@ st_translate_texture_target( GLuint textarget,
    }
 
    switch( textarget ) {
+   case TEXTURE_2D_MULTISAMPLE_INDEX: return TGSI_TEXTURE_2D_MSAA;
+   case TEXTURE_2D_MULTISAMPLE_ARRAY_INDEX: return TGSI_TEXTURE_2D_ARRAY_MSAA;
    case TEXTURE_BUFFER_INDEX: return TGSI_TEXTURE_BUFFER;
    case TEXTURE_1D_INDEX:   return TGSI_TEXTURE_1D;
    case TEXTURE_2D_INDEX:   return TGSI_TEXTURE_2D;
index ed37098483e91ec298f67a24714e33e9c9f540f9..9a271826eaa0634388315fe9930dfa3c99d5d5b8 100644 (file)
@@ -60,6 +60,7 @@ st_texture_create(struct st_context *st,
                  GLuint height0,
                  GLuint depth0,
                   GLuint layers,
+                  GLuint nr_samples,
                   GLuint bind )
 {
    struct pipe_resource pt, *newtex;
@@ -90,6 +91,7 @@ st_texture_create(struct st_context *st,
    pt.usage = PIPE_USAGE_DEFAULT;
    pt.bind = bind;
    pt.flags = 0;
+   pt.nr_samples = nr_samples;
 
    newtex = screen->resource_create(screen, &pt);
 
@@ -138,6 +140,8 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture,
    case GL_TEXTURE_RECTANGLE:
    case GL_PROXY_TEXTURE_RECTANGLE:
    case GL_TEXTURE_EXTERNAL_OES:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE:
+   case GL_TEXTURE_2D_MULTISAMPLE:
       assert(depthIn == 1);
       *widthOut = widthIn;
       *heightOut = heightIn;
@@ -159,7 +163,9 @@ st_gl_texture_dims_to_pipe_dims(GLenum texture,
       *layersOut = 6;
       break;
    case GL_TEXTURE_2D_ARRAY:
+   case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:
    case GL_PROXY_TEXTURE_2D_ARRAY:
+   case GL_PROXY_TEXTURE_2D_MULTISAMPLE_ARRAY:
       *widthOut = widthIn;
       *heightOut = heightIn;
       *depthOut = 1;
@@ -402,7 +408,7 @@ st_create_color_map_texture(struct gl_context *ctx)
 
    /* create texture for color map/table */
    pt = st_texture_create(st, PIPE_TEXTURE_2D, format, 0,
-                          texSize, texSize, 1, 1, PIPE_BIND_SAMPLER_VIEW);
+                          texSize, texSize, 1, 1, 0, PIPE_BIND_SAMPLER_VIEW);
    return pt;
 }
 
index 8a701009a51d63f88a29112f355131fcedb60927..da899c90d4167b045a3b2698ca9cfed0bf01b1fc 100644 (file)
@@ -153,6 +153,7 @@ st_texture_create(struct st_context *st,
                   GLuint height0,
                   GLuint depth0,
                   GLuint layers,
+                  GLuint nr_samples,
                   GLuint tex_usage );