svga: Performance fixes
[mesa.git] / src / gallium / drivers / svga / svga_surface.c
index d7c9850e68e46a1f0d09bf5858868a9242da15f7..68edf1c21db55af445f50dc2964f02da2b65fd25 100644 (file)
@@ -30,7 +30,7 @@
 #include "util/u_inlines.h"
 #include "os/os_thread.h"
 #include "util/u_bitmask.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
 
 
 static void svga_mark_surface_dirty(struct pipe_surface *surf);
 
+void
+svga_texture_copy_region(struct svga_context *svga,
+                         struct svga_winsys_surface *src_handle,
+                         unsigned srcSubResource,
+                         unsigned src_x, unsigned src_y, unsigned src_z,
+                         struct svga_winsys_surface *dst_handle,
+                         unsigned dstSubResource,
+                         unsigned dst_x, unsigned dst_y, unsigned dst_z,
+                         unsigned width, unsigned height, unsigned depth)
+{
+   SVGA3dCopyBox box;
+
+   assert(svga_have_vgpu10(svga));
+
+   box.x = dst_x;
+   box.y = dst_y;
+   box.z = dst_z;
+   box.w = width;
+   box.h = height;
+   box.d = depth;
+   box.srcx = src_x;
+   box.srcy = src_y;
+   box.srcz = src_z;
+
+   SVGA_RETRY(svga, SVGA3D_vgpu10_PredCopyRegion
+              (svga->swc, dst_handle, dstSubResource,
+               src_handle, srcSubResource, &box));
+}
+
+
 void
 svga_texture_copy_handle(struct svga_context *svga,
                          struct svga_winsys_surface *src_handle,
@@ -55,7 +85,6 @@ svga_texture_copy_handle(struct svga_context *svga,
                          unsigned width, unsigned height, unsigned depth)
 {
    struct svga_surface dst, src;
-   enum pipe_error ret;
    SVGA3dCopyBox box, *boxes;
 
    assert(svga);
@@ -86,18 +115,11 @@ svga_texture_copy_handle(struct svga_context *svga,
             dst_handle, dst_level, dst_x, dst_y, dst_z);
 */
 
-   ret = SVGA3D_BeginSurfaceCopy(svga->swc,
-                                 &src.base,
-                                 &dst.base,
-                                 &boxes, 1);
-   if (ret != PIPE_OK) {
-      svga_context_flush(svga, NULL);
-      ret = SVGA3D_BeginSurfaceCopy(svga->swc,
-                                    &src.base,
-                                    &dst.base,
-                                    &boxes, 1);
-      assert(ret == PIPE_OK);
-   }
+   SVGA_RETRY(svga, SVGA3D_BeginSurfaceCopy(svga->swc,
+                                            &src.base,
+                                            &dst.base,
+                                            &boxes, 1));
+
    *boxes = box;
    SVGA_FIFOCommitAll(svga->swc);
 }
@@ -132,15 +154,24 @@ svga_texture_copy_handle_resource(struct svga_context *svga,
             unsigned depth = (zslice_pick < 0 ?
                               u_minify(src_tex->b.b.depth0, miplevel) : 1);
 
-            svga_texture_copy_handle(svga,
-                                     src_tex->handle,
-                                     0, 0, zoffset,
-                                     miplevel,
-                                     j + layeroffset,
-                                     dst, 0, 0, 0, i, j,
-                                     u_minify(src_tex->b.b.width0, miplevel),
-                                     u_minify(src_tex->b.b.height0, miplevel),
-                                     depth);
+            if (src_tex->b.b.nr_samples > 1) {
+               unsigned subResource = j * numMipLevels + i;
+               svga_texture_copy_region(svga, src_tex->handle,
+                                        subResource, 0, 0, zoffset,
+                                        dst, subResource, 0, 0, 0,
+                                        src_tex->b.b.width0, src_tex->b.b.height0, depth);
+            }
+            else {
+               svga_texture_copy_handle(svga,
+                                        src_tex->handle,
+                                        0, 0, zoffset,
+                                        miplevel,
+                                        j + layeroffset,
+                                        dst, 0, 0, 0, i, j,
+                                        u_minify(src_tex->b.b.width0, miplevel),
+                                        u_minify(src_tex->b.b.height0, miplevel),
+                                        depth);
+            }
          }
       }
    }
@@ -151,7 +182,7 @@ struct svga_winsys_surface *
 svga_texture_view_surface(struct svga_context *svga,
                           struct svga_texture *tex,
                           unsigned bind_flags,
-                          SVGA3dSurfaceFlags flags,
+                          SVGA3dSurfaceAllFlags flags,
                           SVGA3dSurfaceFormat format,
                           unsigned start_mip,
                           unsigned num_mip,
@@ -186,7 +217,8 @@ svga_texture_view_surface(struct svga_context *svga,
    key->sampleCount = tex->b.b.nr_samples > 1 ? tex->b.b.nr_samples : 0;
 
    if (key->sampleCount > 1) {
-      key->flags |= SVGA3D_SURFACE_MASKABLE_ANTIALIAS;
+      assert(ss->sws->have_sm4_1);
+      key->flags |= SVGA3D_SURFACE_MULTISAMPLE;
    }
 
    if (tex->b.b.target == PIPE_TEXTURE_CUBE && layer_pick < 0) {
@@ -261,7 +293,7 @@ svga_create_surface_view(struct pipe_context *pipe,
    struct svga_surface *s;
    unsigned layer, zslice, bind;
    unsigned nlayers = 1;
-   SVGA3dSurfaceFlags flags = 0;
+   SVGA3dSurfaceAllFlags flags = 0;
    SVGA3dSurfaceFormat format;
    struct pipe_surface *retVal = NULL;
 
@@ -276,7 +308,8 @@ svga_create_surface_view(struct pipe_context *pipe,
       zslice = 0;
    }
    else if (pt->target == PIPE_TEXTURE_1D_ARRAY ||
-            pt->target == PIPE_TEXTURE_2D_ARRAY) {
+            pt->target == PIPE_TEXTURE_2D_ARRAY ||
+            pt->target == PIPE_TEXTURE_CUBE_ARRAY) {
       layer = surf_tmpl->u.tex.first_layer;
       zslice = 0;
       nlayers = surf_tmpl->u.tex.last_layer - surf_tmpl->u.tex.first_layer + 1;
@@ -347,6 +380,10 @@ svga_create_surface_view(struct pipe_context *pipe,
             if (nlayers == 6)
                flags |= SVGA3D_SURFACE_CUBEMAP;
             break;
+         case PIPE_TEXTURE_CUBE_ARRAY:
+            if (nlayers % 6 == 0)
+               flags |= SVGA3D_SURFACE_CUBEMAP | SVGA3D_SURFACE_ARRAY;
+            break;   
          default:
             break;
          }
@@ -462,6 +499,7 @@ create_backed_surface_view(struct svga_context *svga, struct svga_surface *s)
 
       switch (tex->b.b.target) {
       case PIPE_TEXTURE_CUBE:
+      case PIPE_TEXTURE_CUBE_ARRAY:
       case PIPE_TEXTURE_1D_ARRAY:
       case PIPE_TEXTURE_2D_ARRAY:
          layer = s->base.u.tex.first_layer;
@@ -509,7 +547,7 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
     * associated resource. We will then use the cloned surface view for
     * render target.
     */
-   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
+   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) {
       if (svga_check_sampler_view_resource_collision(svga, s->handle, shader)) {
          SVGA_DBG(DEBUG_VIEWS,
                   "same resource used in shaderResource and renderTarget 0x%x\n",
@@ -524,6 +562,16 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
       }
    }
 
+   /**
+    * Create an alternate surface view for the specified context if the
+    * view was created for another context.
+    */
+   if (s && s->base.context != &svga->pipe) {
+      struct pipe_surface *surf;
+      surf = svga_create_surface_view(&svga->pipe, s->base.texture, &s->base, FALSE);
+      s = svga_surface(surf);
+   }
+
    if (s && s->view_id == SVGA3D_INVALID_ID) {
       SVGA3dResourceType resType;
       SVGA3dRenderTargetViewDesc desc;
@@ -537,11 +585,7 @@ svga_validate_surface_view(struct svga_context *svga, struct svga_surface *s)
           * need to update the host-side copy with the invalid
           * content when the associated mob is first bound to the surface.
           */
-         if (svga->swc->surface_invalidate(svga->swc, stex->handle) != PIPE_OK) {
-            svga_context_flush(svga, NULL);
-            ret = svga->swc->surface_invalidate(svga->swc, stex->handle);
-            assert(ret == PIPE_OK);
-         }
+         SVGA_RETRY(svga, SVGA3D_InvalidateGBSurface(svga->swc, stex->handle));
          stex->validated = TRUE;
       }
 
@@ -606,7 +650,6 @@ svga_surface_destroy(struct pipe_context *pipe,
    struct svga_surface *s = svga_surface(surf);
    struct svga_texture *t = svga_texture(surf->texture);
    struct svga_screen *ss = svga_screen(surf->texture->screen);
-   enum pipe_error ret = PIPE_OK;
 
    SVGA_STATS_TIME_PUSH(ss->sws, SVGA_STATS_TIME_DESTROYSURFACE);
 
@@ -625,8 +668,6 @@ svga_surface_destroy(struct pipe_context *pipe,
    }
 
    if (s->view_id != SVGA3D_INVALID_ID) {
-      unsigned try;
-
       /* The SVGA3D device will generate a device error if the
        * render target view or depth stencil view is destroyed from
        * a context other than the one it was created with.
@@ -638,18 +679,14 @@ svga_surface_destroy(struct pipe_context *pipe,
       }
       else {
          assert(svga_have_vgpu10(svga));
-         for (try = 0; try < 2; try++) {
-            if (util_format_is_depth_or_stencil(s->base.format)) {
-               ret = SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc, s->view_id);
-            }
-            else {
-               ret = SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc, s->view_id);
-            }
-            if (ret == PIPE_OK)
-               break;
-            svga_context_flush(svga, NULL);
+         if (util_format_is_depth_or_stencil(s->base.format)) {
+            SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyDepthStencilView(svga->swc,
+                                                                   s->view_id));
+         }
+         else {
+            SVGA_RETRY(svga, SVGA3D_vgpu10_DestroyRenderTargetView(svga->swc,
+                                                                   s->view_id));
          }
-         assert(ret == PIPE_OK);
          util_bitmask_clear(svga->surface_view_id_bm, s->view_id);
       }
    }
@@ -751,13 +788,19 @@ svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
       unsigned zslice, layer;
       unsigned nlayers = 1;
       unsigned i;
+      unsigned numMipLevels = tex->b.b.last_level + 1;
+      unsigned srcLevel = s->real_level;
+      unsigned dstLevel = surf->u.tex.level;
+      unsigned width = u_minify(tex->b.b.width0, dstLevel);
+      unsigned height = u_minify(tex->b.b.height0, dstLevel);
 
       if (surf->texture->target == PIPE_TEXTURE_CUBE) {
          zslice = 0;
          layer = surf->u.tex.first_layer;
       }
       else if (surf->texture->target == PIPE_TEXTURE_1D_ARRAY ||
-               surf->texture->target == PIPE_TEXTURE_2D_ARRAY) {
+               surf->texture->target == PIPE_TEXTURE_2D_ARRAY ||
+               surf->texture->target == PIPE_TEXTURE_CUBE_ARRAY) {
          zslice = 0;
          layer = surf->u.tex.first_layer;
          nlayers = surf->u.tex.last_layer - surf->u.tex.first_layer + 1;
@@ -770,16 +813,32 @@ svga_propagate_surface(struct svga_context *svga, struct pipe_surface *surf,
       SVGA_DBG(DEBUG_VIEWS,
                "Propagate surface %p to resource %p, level %u\n",
                surf, tex, surf->u.tex.level);
-      for (i = 0; i < nlayers; i++) {
-         svga_texture_copy_handle(svga,
-                                  s->handle, 0, 0, 0, s->real_level,
-                                  s->real_layer + i,
-                                  tex->handle, 0, 0, zslice, surf->u.tex.level,
-                                  layer + i,
-                                  u_minify(tex->b.b.width0, surf->u.tex.level),
-                                  u_minify(tex->b.b.height0, surf->u.tex.level),
-                                  1);
-         svga_define_texture_level(tex, layer + i, surf->u.tex.level);
+
+      if (svga_have_vgpu10(svga)) {
+         unsigned srcSubResource, dstSubResource;
+
+         for (i = 0; i < nlayers; i++) {
+            srcSubResource = (s->real_layer + i) * numMipLevels + srcLevel;
+            dstSubResource = (layer + i) * numMipLevels + dstLevel;
+
+            svga_texture_copy_region(svga,
+                                     s->handle, srcSubResource, 0, 0, 0,
+                                     tex->handle, dstSubResource, 0, 0, zslice,
+                                     width, height, 1);
+            svga_define_texture_level(tex, layer + i, dstLevel);
+         }
+      }
+      else {
+         for (i = 0; i < nlayers; i++) {
+            svga_texture_copy_handle(svga,
+                                     s->handle, 0, 0, 0, srcLevel,
+                                     s->real_layer + i,
+                                     tex->handle, 0, 0, zslice, dstLevel,
+                                     layer + i,
+                                     width, height, 1);
+        
+            svga_define_texture_level(tex, layer + i, dstLevel);
+         }
       }
 
       /* Sync the surface view age with the texture age */
@@ -851,6 +910,10 @@ svga_get_sample_position(struct pipe_context *context,
    static const float pos1[1][2] = {
       { 0.5, 0.5 }
    };
+   static const float pos2[2][2] = {
+      { 0.75, 0.75 },
+      { 0.25, 0.25 }
+   };
    static const float pos4[4][2] = {
       { 0.375000, 0.125000 },
       { 0.875000, 0.375000 },
@@ -888,6 +951,9 @@ svga_get_sample_position(struct pipe_context *context,
    const float (*positions)[2];
 
    switch (sample_count) {
+   case 2:
+      positions = pos2;
+      break;
    case 4:
       positions = pos4;
       break;