[Mesa-dev] [PATCH 04/14] i965/meta: Add helper for looking up blit programs

Topi Pohjolainen topi.pohjolainen at intel.com
Thu Apr 23 11:18:18 PDT 2015


Signed-off-by: Topi Pohjolainen <topi.pohjolainen at intel.com>
---
 src/mesa/drivers/dri/i965/brw_meta_util.c | 148 ++++++++++++++++++++++++++++++
 src/mesa/drivers/dri/i965/brw_meta_util.h |   9 ++
 2 files changed, 157 insertions(+)

diff --git a/src/mesa/drivers/dri/i965/brw_meta_util.c b/src/mesa/drivers/dri/i965/brw_meta_util.c
index a3b0604..0ff9445 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_util.c
+++ b/src/mesa/drivers/dri/i965/brw_meta_util.c
@@ -21,8 +21,13 @@
  * IN THE SOFTWARE.
  */
 
+#include "brw_context.h"
+#include "brw_wm.h"
+#include "brw_state.h"
 #include "brw_meta_util.h"
 #include "main/fbobject.h"
+#include "main/shaderobj.h"
+#include "drivers/common/meta.h"
 
 /**
  * Helper function for handling mirror image blits.
@@ -157,3 +162,146 @@ brw_meta_mirror_clip_and_scissor(const struct gl_context *ctx,
 
    return false;
 }
+
+/**
+ * Meta shaders used for 2D blits and clears use pass-thru vertex shaders
+ * which just pass the vertices unmodified to clipping. This is exploit in
+ * the pipeline setup by disabling the vertex shader stage and passing the
+ * vertices directly to clip unit. Hence we only need to store the details
+ * for the fragment program.
+ */
+static bool
+meta_recompile(struct  brw_context *brw,
+               struct brw_wm_prog_key *key,
+               struct gl_shader_program *sh_prog,
+               uint32_t *wm_prog_offset,
+               const struct brw_wm_prog_data **wm_prog_data)
+{
+   if (brw_search_cache(&brw->cache, BRW_CACHE_FS_PROG, key, sizeof(*key),
+                        wm_prog_offset, wm_prog_data))
+      return true;
+
+   struct gl_shader *sh = sh_prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+   struct gl_fragment_program *fp = (struct gl_fragment_program *)sh->Program;
+
+   /* In case a program is already compiled but not available in the cache it
+    * means there isn't yet a version that writes the same number of
+    * renderbuffers as will be needed next. Hence compile another flavour.
+    */
+   uint32_t old_prog_offset = brw->wm.base.prog_offset;
+   struct brw_wm_prog_data *old_prog_data = brw->wm.prog_data;
+   bool status = brw_compile_wm_prog(brw, sh_prog, brw_fragment_program(fp),
+                                     key);
+   *wm_prog_offset = brw->wm.base.prog_offset;
+   *wm_prog_data = brw->wm.prog_data;
+   brw->wm.base.prog_offset = old_prog_offset;
+   brw->wm.prog_data = old_prog_data;
+
+   return status;
+}
+
+static struct gl_shader_program *
+get_blit_shader(struct brw_context *brw, GLenum target, bool do_depth)
+{
+   struct gl_context *ctx = &brw->ctx;
+   struct blit_state *blit = &ctx->Meta->Blit;
+   struct blit_shader_table *tbl = do_depth ? &blit->shaders_with_depth :
+                                              &blit->shaders_without_depth;
+   const struct blit_shader *sh = _mesa_meta_choose_blit_shader(target, tbl);
+
+   /* Reset the core context state to the default except the current fbo
+    * settings and compile the blit program of the desired type. After the
+    * compilation restore the core context to the state it was before.
+    */
+   if (!sh->shader_prog) {
+      _mesa_meta_begin(ctx, MESA_META_ALL & ~MESA_META_DRAW_BUFFERS);
+      sh = _mesa_meta_setup_blit_shader(ctx, target, do_depth, tbl);
+      _mesa_meta_end(ctx);
+   }
+
+   return _mesa_lookup_shader_program_err(ctx, sh->shader_prog, __FUNCTION__);
+}
+
+/* Mimick the algorithm used in core meta to deduce the texture target. */
+static GLenum
+resolve_target(const struct gl_context *ctx, bool do_depth)
+{
+   const struct gl_framebuffer *read_fb = ctx->ReadBuffer;
+   int att_index = do_depth ? BUFFER_DEPTH : read_fb->_ColorReadBufferIndex;
+   const struct gl_renderbuffer_attachment *read_att =
+      &read_fb->Attachment[att_index];
+
+   if (read_att->Texture) {
+      /* The six faces of a cube are laid out in the memory identically
+       * to a 2D texture array of the same size (having depth six). Hence
+       * the blit can be performed using the simpler 2D array program.
+       */
+      if (read_att->Texture->Target == GL_TEXTURE_CUBE_MAP ||
+          read_att->Texture->Target == GL_TEXTURE_CUBE_MAP_ARRAY)
+         return GL_TEXTURE_2D_ARRAY;
+
+      return read_att->Texture->Target;
+   }
+
+   if (read_att->Renderbuffer->NumSamples > 1)
+      return GL_TEXTURE_2D_MULTISAMPLE;
+
+   return GL_TEXTURE_2D;
+}
+
+static void
+get_current_blit_wm_prog_key(const struct gl_context *ctx,
+                             const struct brw_fragment_program *fp,
+                             struct brw_wm_prog_key *key)
+{
+   memset(key, 0, sizeof(*key));
+
+   key->nr_color_regions = ctx->DrawBuffer->_NumColorDrawBuffers;
+   key->program_string_id = fp->id;
+
+   /* Every blit program has one and only one texture tobe sampled. And
+    * none of the blit runs use settings that would require special flavour
+    * of the program. All the texture key settings are fixed to default.
+    */
+   key->tex.swizzles[0] = SWIZZLE_NOOP;
+}
+
+bool
+brw_meta_choose_blit_shader(struct brw_context *brw,
+                            GLbitfield mask, GLenum filter,
+                            GLenum *target,
+                            const struct gl_fragment_program **fp,
+                            uint32_t *wm_prog_offset,
+                            const struct brw_wm_prog_data **wm_prog_data)
+{
+   /* Stencil blits have special i965-meta-path. */
+   if (mask & GL_STENCIL_BUFFER_BIT)
+      return false;
+
+   const bool do_depth = mask & GL_DEPTH_BUFFER_BIT;
+   *target = resolve_target(&brw->ctx, do_depth);
+
+   const bool is_target_msaa = *target == GL_TEXTURE_2D_MULTISAMPLE ||
+                               *target == GL_TEXTURE_2D_MULTISAMPLE_ARRAY;
+
+   /* TODO: Support for depth blits. */
+   if (do_depth)
+      return false;
+
+   /* TODO: Support for multisampled blits. */
+   if (is_target_msaa)
+      return false;
+
+   struct gl_shader_program *prog = get_blit_shader(brw, *target, do_depth);
+   if (!prog)
+      return false;
+
+   struct gl_shader *sh = prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+   *fp = (const struct gl_fragment_program *)sh->Program;
+
+   struct brw_wm_prog_key key;
+   get_current_blit_wm_prog_key(&brw->ctx,
+                                brw_fragment_program_const(*fp), &key);
+
+   return meta_recompile(brw, &key, prog, wm_prog_offset, wm_prog_data);
+}
diff --git a/src/mesa/drivers/dri/i965/brw_meta_util.h b/src/mesa/drivers/dri/i965/brw_meta_util.h
index dc9dff2..976957b 100644
--- a/src/mesa/drivers/dri/i965/brw_meta_util.h
+++ b/src/mesa/drivers/dri/i965/brw_meta_util.h
@@ -26,6 +26,7 @@
 
 #include <stdbool.h>
 #include "main/mtypes.h"
+#include "brw_context.h"
 
 #ifdef __cplusplus
 extern "C" {
@@ -41,6 +42,14 @@ brw_meta_mirror_clip_and_scissor(const struct gl_context *ctx,
                                  GLfloat *dstX1, GLfloat *dstY1,
                                  bool *mirror_x, bool *mirror_y);
 
+bool
+brw_meta_choose_blit_shader(struct brw_context *brw,
+                            GLbitfield mask, GLenum filter,
+                            GLenum *target,
+                            const struct gl_fragment_program **fp,
+                            uint32_t *wm_prog_offset,
+                            const struct brw_wm_prog_data **wm_prog_data);
+
 #ifdef __cplusplus
 }
 #endif
-- 
1.9.3



More information about the mesa-dev mailing list