svga: Performance fixes
[mesa.git] / src / gallium / drivers / svga / svga_state_sampler.c
index 482449ecc663ce0195a4a10e22eebbecd25eb11b..bbfd889e9f407d6b65acdb9d3c98b7abc288e5eb 100644 (file)
@@ -30,7 +30,7 @@
 
 #include "pipe/p_defines.h"
 #include "util/u_bitmask.h"
-#include "util/u_format.h"
+#include "util/format/u_format.h"
 #include "util/u_inlines.h"
 #include "util/u_math.h"
 #include "util/u_memory.h"
@@ -44,7 +44,7 @@
 #include "svga_shader.h"
 #include "svga_state.h"
 #include "svga_surface.h"
-
+#include "svga3d_surfacedefs.h"
 
 /** Get resource handle for a texture or buffer */
 static inline struct svga_winsys_surface *
@@ -131,7 +131,7 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
    if (sv->id == SVGA3D_INVALID_ID) {
       struct svga_screen *ss = svga_screen(svga->pipe.screen);
       struct pipe_resource *texture = sv->base.texture;
-      struct svga_winsys_surface *surface = svga_resource_handle(texture);
+      struct svga_winsys_surface *surface;
       SVGA3dSurfaceFormat format;
       SVGA3dResourceType resourceDim;
       SVGA3dShaderResourceViewDesc viewDesc;
@@ -141,20 +141,32 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
        * create a BGRA view (and vice versa).
        */
       if (viewFormat == PIPE_FORMAT_B8G8R8X8_UNORM &&
-          texture->format == PIPE_FORMAT_B8G8R8A8_UNORM) {
+          svga_texture_device_format_has_alpha(texture)) {
          viewFormat = PIPE_FORMAT_B8G8R8A8_UNORM;
       }
       else if (viewFormat == PIPE_FORMAT_B8G8R8A8_UNORM &&
-          texture->format == PIPE_FORMAT_B8G8R8X8_UNORM) {
+               !svga_texture_device_format_has_alpha(texture)) {
          viewFormat = PIPE_FORMAT_B8G8R8X8_UNORM;
       }
 
-      format = svga_translate_format(ss, viewFormat,
-                                     PIPE_BIND_SAMPLER_VIEW);
-      assert(format != SVGA3D_FORMAT_INVALID);
+      if (texture->target == PIPE_BUFFER) {
+         unsigned pf_flags;
+         svga_translate_texture_buffer_view_format(viewFormat,
+                                                   &format,
+                                                   &pf_flags);
+         surface = svga_buffer_handle(svga, texture, PIPE_BIND_SAMPLER_VIEW);
+      }
+      else {
+         format = svga_translate_format(ss, viewFormat,
+                                        PIPE_BIND_SAMPLER_VIEW);
+
+         /* Convert the format to a sampler-friendly format, if needed */
+         format = svga_sampler_format(format);
 
-      /* Convert the format to a sampler-friendly format, if needed */
-      format = svga_sampler_format(format);
+         surface = svga_texture(texture)->handle;
+      }
+
+      assert(format != SVGA3D_FORMAT_INVALID);
 
       if (texture->target == PIPE_BUFFER) {
          unsigned elem_size = util_format_get_blocksize(sv->base.format);
@@ -225,15 +237,14 @@ svga_validate_pipe_sampler_view(struct svga_context *svga,
 
 
 static enum pipe_error
-update_sampler_resources(struct svga_context *svga, unsigned dirty)
+update_sampler_resources(struct svga_context *svga, uint64_t dirty)
 {
    enum pipe_error ret = PIPE_OK;
    enum pipe_shader_type shader;
 
-   if (!svga_have_vgpu10(svga))
-      return PIPE_OK;
+   assert(svga_have_vgpu10(svga));
 
-   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
+   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) {
       SVGA3dShaderResourceViewId ids[PIPE_MAX_SAMPLERS];
       struct svga_winsys_surface *surfaces[PIPE_MAX_SAMPLERS];
       struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
@@ -278,14 +289,54 @@ update_sampler_resources(struct svga_context *svga, unsigned dirty)
          if (count != svga->state.hw_draw.num_sampler_views[shader] ||
              memcmp(sampler_views, svga->state.hw_draw.sampler_views[shader],
                     count * sizeof(sampler_views[0])) != 0) {
-            ret = SVGA3D_vgpu10_SetShaderResources(svga->swc,
-                                                svga_shader_type(shader),
-                                                0, /* startView */
-                                                nviews,
-                                                ids,
-                                                surfaces);
-            if (ret != PIPE_OK)
-               return ret;
+            SVGA3dShaderResourceViewId *pIds = ids;
+            struct svga_winsys_surface **pSurf = surfaces;
+            unsigned numSR = 0;
+
+            /* Loop through the sampler view list to only emit
+             * the sampler views that are not already in the
+             * corresponding entries in the device's
+             * shader resource list.
+             */
+            for (i = 0; i < nviews; i++) {
+                boolean emit;
+
+                emit = sampler_views[i] ==
+                       svga->state.hw_draw.sampler_views[shader][i];
+
+                if (!emit && i == nviews-1) {
+                   /* Include the last sampler view in the next emit
+                    * if it is different.
+                    */
+                   emit = TRUE;
+                   numSR++;
+                   i++;
+                }
+                if (emit) {
+                   /* numSR can only be 0 if the first entry of the list
+                    * is the same as the one in the device list.
+                    * In this case, * there is nothing to send yet.
+                    */
+                   if (numSR) {
+                      ret = SVGA3D_vgpu10_SetShaderResources(
+                               svga->swc,
+                               svga_shader_type(shader),
+                               i - numSR, /* startView */
+                               numSR,
+                               pIds,
+                               pSurf);
+
+                      if (ret != PIPE_OK)
+                         return ret;
+                   }
+                   pIds += (numSR + 1);
+                   pSurf += (numSR + 1);
+                   numSR = 0;
+                }
+                else
+                   numSR++;
+            }
 
             /* Save referenced sampler views in the hw draw state.  */
             svga->state.hw_draw.num_sampler_views[shader] = count;
@@ -300,7 +351,8 @@ update_sampler_resources(struct svga_context *svga, unsigned dirty)
 
    /* Handle polygon stipple sampler view */
    if (svga->curr.rast->templ.poly_stipple_enable) {
-      const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
+      const unsigned unit =
+         svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
       struct svga_pipe_sampler_view *sv = svga->polygon_stipple.sampler_view;
       struct svga_winsys_surface *surface;
 
@@ -336,23 +388,37 @@ struct svga_tracked_state svga_hw_sampler_bindings = {
 
 
 static enum pipe_error
-update_samplers(struct svga_context *svga, unsigned dirty )
+update_samplers(struct svga_context *svga, uint64_t dirty )
 {
    enum pipe_error ret = PIPE_OK;
    enum pipe_shader_type shader;
 
-   if (!svga_have_vgpu10(svga))
-      return PIPE_OK;
+   assert(svga_have_vgpu10(svga));
 
-   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_GEOMETRY; shader++) {
+   for (shader = PIPE_SHADER_VERTEX; shader <= PIPE_SHADER_TESS_EVAL; shader++) {
       const unsigned count = svga->curr.num_samplers[shader];
       SVGA3dSamplerId ids[PIPE_MAX_SAMPLERS];
       unsigned i;
       unsigned nsamplers;
 
       for (i = 0; i < count; i++) {
+         bool fs_shadow = false;
+
+         /* _NEW_FS */
+         if (shader == PIPE_SHADER_FRAGMENT) {
+            struct svga_fs_variant *fs =
+               svga_fs_variant(svga->state.hw_draw.fs);
+            /* If the fragment shader is doing the shadow comparison
+             * for this texture unit, don't enable shadow compare in
+             * the texture sampler state.
+             */
+            if (fs && (fs->fs_shadow_compare_units & (1 << i))) {
+               fs_shadow = true;
+            }
+         }
+
          if (svga->curr.sampler[shader][i]) {
-            ids[i] = svga->curr.sampler[shader][i]->id;
+            ids[i] = svga->curr.sampler[shader][i]->id[fs_shadow];
             assert(ids[i] != SVGA3D_INVALID_ID);
          }
          else {
@@ -386,7 +452,8 @@ update_samplers(struct svga_context *svga, unsigned dirty )
 
    /* Handle polygon stipple sampler texture */
    if (svga->curr.rast->templ.poly_stipple_enable) {
-      const unsigned unit = svga->state.hw_draw.fs->pstipple_sampler_unit;
+      const unsigned unit =
+         svga_fs_variant(svga->state.hw_draw.fs)->pstipple_sampler_unit;
       struct svga_sampler_state *sampler = svga->polygon_stipple.sampler;
 
       assert(sampler);
@@ -395,18 +462,18 @@ update_samplers(struct svga_context *svga, unsigned dirty )
       }
 
       if (svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit]
-          != sampler->id) {
+          != sampler->id[0]) {
          ret = SVGA3D_vgpu10_SetSamplers(svga->swc,
                                          1, /* count */
                                          unit, /* start */
                                          SVGA3D_SHADERTYPE_PS,
-                                         &sampler->id);
+                                         &sampler->id[0]);
          if (ret != PIPE_OK)
             return ret;
 
          /* save the polygon stipple sampler in the hw draw state */
          svga->state.hw_draw.samplers[PIPE_SHADER_FRAGMENT][unit] =
-            sampler->id;
+            sampler->id[0];
       }
    }
 
@@ -416,8 +483,8 @@ update_samplers(struct svga_context *svga, unsigned dirty )
 
 struct svga_tracked_state svga_hw_sampler = {
    "texture sampler emit",
-   (SVGA_NEW_SAMPLER |
-    SVGA_NEW_STIPPLE |
-    SVGA_NEW_TEXTURE_FLAGS),
+   (SVGA_NEW_FS |
+    SVGA_NEW_SAMPLER |
+    SVGA_NEW_STIPPLE),
    update_samplers
 };