Signed-off-by: Topi Pohjolainen <topi.pohjolai...@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 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev