[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