freedreno/a3xx: shadow sampler support
[mesa.git] / src / gallium / drivers / svga / svga_state_fs.c
index 7119a19f0a8da6a98067e981f10c209ebd05dc7e..7931528c661421f97fdd48ec32f3edd36a6e0468 100644 (file)
@@ -235,15 +235,43 @@ make_fs_key(const struct svga_context *svga,
    if (svga->curr.blend->need_white_fragments) {
       key->white_fragments = 1;
    }
-   
+
+#ifdef DEBUG
+   /*
+    * We expect a consistent set of samplers and sampler views.
+    * Do some debug checks/warnings here.
+    */
+   {
+      static boolean warned = FALSE;
+      unsigned i, n = MAX2(svga->curr.num_sampler_views,
+                           svga->curr.num_samplers);
+      /* Only warn once to prevent too much debug output */
+      if (!warned) {
+         if (svga->curr.num_sampler_views != svga->curr.num_samplers) {
+            debug_printf("svga: mismatched number of sampler views (%u) "
+                         "vs. samplers (%u)\n",
+                         svga->curr.num_sampler_views,
+                         svga->curr.num_samplers);
+         }
+         for (i = 0; i < n; i++) {
+            if ((svga->curr.sampler_views[i] == NULL) !=
+                (svga->curr.sampler[i] == NULL))
+               debug_printf("sampler_view[%u] = %p but sampler[%u] = %p\n",
+                            i, svga->curr.sampler_views[i],
+                            i, svga->curr.sampler[i]);
+         }
+         warned = TRUE;
+      }
+   }
+#endif
+
    /* XXX: want to limit this to the textures that the shader actually
     * refers to.
     *
     * SVGA_NEW_TEXTURE_BINDING | SVGA_NEW_SAMPLER
     */
    for (i = 0; i < svga->curr.num_sampler_views; i++) {
-      if (svga->curr.sampler_views[i]) {
-         assert(svga->curr.sampler[i]);
+      if (svga->curr.sampler_views[i] && svga->curr.sampler[i]) {
          assert(svga->curr.sampler_views[i]->texture);
          key->tex[i].texture_target = svga->curr.sampler_views[i]->texture->target;
          if (!svga->curr.sampler[i]->normalized_coords) {
@@ -262,7 +290,7 @@ make_fs_key(const struct svga_context *svga,
 
    idx = 0;
    for (i = 0; i < svga->curr.num_samplers; ++i) {
-      if (svga->curr.sampler_views[i]) {
+      if (svga->curr.sampler_views[i] && svga->curr.sampler[i]) {
          struct pipe_resource *tex = svga->curr.sampler_views[i]->texture;
          struct svga_texture *stex = svga_texture(tex);
          SVGA3dSurfaceFormat format = stex->key.format;
@@ -321,13 +349,36 @@ make_fs_key(const struct svga_context *svga,
 }
 
 
+/**
+ * svga_reemit_fs_bindings - Reemit the fragment shader bindings
+ */
+enum pipe_error
+svga_reemit_fs_bindings(struct svga_context *svga)
+{
+   enum pipe_error ret;
+
+   assert(svga->rebind.fs);
+   assert(svga_have_gb_objects(svga));
+
+   if (!svga->state.hw_draw.fs)
+      return PIPE_OK;
+
+   ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_PS,
+                            svga->state.hw_draw.fs->gb_shader);
+   if (ret != PIPE_OK)
+      return ret;
+
+   svga->rebind.fs = FALSE;
+   return PIPE_OK;
+}
+
+
+
 static enum pipe_error
 emit_hw_fs(struct svga_context *svga, unsigned dirty)
 {
    struct svga_shader_variant *variant = NULL;
-   unsigned id = SVGA3D_INVALID_ID;
    enum pipe_error ret = PIPE_OK;
-
    struct svga_fragment_shader *fs = svga->curr.fs;
    struct svga_fs_compile_key key;
 
@@ -349,17 +400,30 @@ emit_hw_fs(struct svga_context *svga, unsigned dirty)
          return ret;
    }
 
-   assert (variant);
-   id = variant->id;
-
-   assert(id != SVGA3D_INVALID_ID);
+   assert(variant);
 
    if (variant != svga->state.hw_draw.fs) {
-      ret = SVGA3D_SetShader(svga->swc,
-                             SVGA3D_SHADERTYPE_PS,
-                             id );
-      if (ret != PIPE_OK)
-         return ret;
+      if (svga_have_gb_objects(svga)) {
+         /*
+          * Bind is necessary here only because pipebuffer_fenced may move
+          * the shader contents around....
+          */
+         ret = SVGA3D_BindGBShader(svga->swc, variant->gb_shader);
+         if (ret != PIPE_OK)
+            return ret;
+
+         ret = SVGA3D_SetGBShader(svga->swc, SVGA3D_SHADERTYPE_PS,
+                                  variant->gb_shader);
+         if (ret != PIPE_OK)
+            return ret;
+
+         svga->rebind.fs = FALSE;
+      }
+      else {
+         ret = SVGA3D_SetShader(svga->swc, SVGA3D_SHADERTYPE_PS, variant->id);
+         if (ret != PIPE_OK)
+            return ret;
+      }
 
       svga->dirty |= SVGA_NEW_FS_VARIANT;
       svga->state.hw_draw.fs = variant;