From 3038e8984df2be35a7164043ec6d385e32e26238 Mon Sep 17 00:00:00 2001 From: Charmaine Lee Date: Thu, 14 Jan 2016 10:22:17 -0700 Subject: [PATCH] gallium/st: add pipe_context::generate_mipmap() This patch adds a new interface to support hardware mipmap generation. PIPE_CAP_GENERATE_MIPMAP is added to allow a driver to specify if this new interface is supported; if not supported, the state tracker will fallback to mipmap generation by rendering/texturing. v2: add PIPE_CAP_GENERATE_MIPMAP to the disabled section for all drivers v3: add format to the generate_mipmap interface to allow mipmap generation using a format other than the resource format v4: fix return type of trace_context_generate_mipmap() Reviewed-by: Brian Paul Reviewed-by: Roland Scheidegger Reviewed-by: Jose Fonseca --- src/gallium/docs/source/context.rst | 11 ++++++ src/gallium/docs/source/screen.rst | 2 + .../drivers/freedreno/freedreno_screen.c | 1 + src/gallium/drivers/i915/i915_screen.c | 1 + src/gallium/drivers/ilo/ilo_screen.c | 1 + src/gallium/drivers/llvmpipe/lp_screen.c | 1 + .../drivers/nouveau/nv30/nv30_screen.c | 1 + .../drivers/nouveau/nv50/nv50_screen.c | 1 + .../drivers/nouveau/nvc0/nvc0_screen.c | 1 + src/gallium/drivers/r300/r300_screen.c | 1 + src/gallium/drivers/r600/r600_pipe.c | 1 + src/gallium/drivers/radeonsi/si_pipe.c | 1 + src/gallium/drivers/softpipe/sp_screen.c | 1 + src/gallium/drivers/svga/svga_screen.c | 1 + src/gallium/drivers/trace/tr_context.c | 37 +++++++++++++++++++ src/gallium/drivers/vc4/vc4_screen.c | 1 + src/gallium/drivers/virgl/virgl_screen.c | 1 + src/gallium/include/pipe/p_context.h | 12 ++++++ src/gallium/include/pipe/p_defines.h | 1 + src/mesa/state_tracker/st_gen_mipmap.c | 17 ++++++--- 20 files changed, 89 insertions(+), 5 deletions(-) diff --git a/src/gallium/docs/source/context.rst b/src/gallium/docs/source/context.rst index 9a32716f921..4c03e00008c 100644 --- a/src/gallium/docs/source/context.rst +++ b/src/gallium/docs/source/context.rst @@ -648,3 +648,14 @@ In addition, normal texture sampling is allowed from the compute program: ``bind_sampler_states`` may be used to set up texture samplers for the compute stage and ``set_sampler_views`` may be used to bind a number of sampler views to it. + +Mipmap generation +^^^^^^^^^^^^^^^^^ + +If PIPE_CAP_GENERATE_MIPMAP is true, ``generate_mipmap`` can be used +to generate mipmaps for the specified texture resource. +It replaces texel image levels base_level+1 through +last_level for layers range from first_layer through last_layer. +It returns TRUE if mipmap generation succeeds, otherwise it +returns FALSE. Mipmap generation may fail when it is not supported +for particular texture types or formats. diff --git a/src/gallium/docs/source/screen.rst b/src/gallium/docs/source/screen.rst index 81de7f85708..d7ea123b0e9 100644 --- a/src/gallium/docs/source/screen.rst +++ b/src/gallium/docs/source/screen.rst @@ -303,6 +303,8 @@ The integer capabilities: shader buffers are not supported. * ``PIPE_CAP_INVALIDATE_BUFFER``: Whether the use of ``invalidate_resource`` for buffers is supported. +* ``PIPE_CAP_GENERATE_MIPMAP``: Indicates whether pipe_context::generate_mipmap + is supported. .. _pipe_capf: diff --git a/src/gallium/drivers/freedreno/freedreno_screen.c b/src/gallium/drivers/freedreno/freedreno_screen.c index 70af0385111..a75b04b327a 100644 --- a/src/gallium/drivers/freedreno/freedreno_screen.c +++ b/src/gallium/drivers/freedreno/freedreno_screen.c @@ -246,6 +246,7 @@ fd_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_MAX_VIEWPORTS: diff --git a/src/gallium/drivers/i915/i915_screen.c b/src/gallium/drivers/i915/i915_screen.c index fa3e8163273..ede5558a11e 100644 --- a/src/gallium/drivers/i915/i915_screen.c +++ b/src/gallium/drivers/i915/i915_screen.c @@ -260,6 +260,7 @@ i915_get_param(struct pipe_screen *screen, enum pipe_cap cap) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_MAX_DUAL_SOURCE_RENDER_TARGETS: diff --git a/src/gallium/drivers/ilo/ilo_screen.c b/src/gallium/drivers/ilo/ilo_screen.c index 0306542fac0..fa327571b9b 100644 --- a/src/gallium/drivers/ilo/ilo_screen.c +++ b/src/gallium/drivers/ilo/ilo_screen.c @@ -484,6 +484,7 @@ ilo_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/llvmpipe/lp_screen.c b/src/gallium/drivers/llvmpipe/lp_screen.c index eadbbb31d19..fb52f5dc063 100644 --- a/src/gallium/drivers/llvmpipe/lp_screen.c +++ b/src/gallium/drivers/llvmpipe/lp_screen.c @@ -309,6 +309,7 @@ llvmpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; } /* should only get here on unhandled cases */ diff --git a/src/gallium/drivers/nouveau/nv30/nv30_screen.c b/src/gallium/drivers/nouveau/nv30/nv30_screen.c index 421bf655590..933330f107a 100644 --- a/src/gallium/drivers/nouveau/nv30/nv30_screen.c +++ b/src/gallium/drivers/nouveau/nv30/nv30_screen.c @@ -182,6 +182,7 @@ nv30_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/nouveau/nv50/nv50_screen.c b/src/gallium/drivers/nouveau/nv50/nv50_screen.c index 2b7f928b15a..712835c1ce1 100644 --- a/src/gallium/drivers/nouveau/nv50/nv50_screen.c +++ b/src/gallium/drivers/nouveau/nv50/nv50_screen.c @@ -225,6 +225,7 @@ nv50_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c index cd8e950e2ba..ccf96fb2815 100644 --- a/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c +++ b/src/gallium/drivers/nouveau/nvc0/nvc0_screen.c @@ -214,6 +214,7 @@ nvc0_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_VENDOR_ID: diff --git a/src/gallium/drivers/r300/r300_screen.c b/src/gallium/drivers/r300/r300_screen.c index a0afef7d80f..8823b8d3197 100644 --- a/src/gallium/drivers/r300/r300_screen.c +++ b/src/gallium/drivers/r300/r300_screen.c @@ -208,6 +208,7 @@ static int r300_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; /* SWTCL-only features. */ diff --git a/src/gallium/drivers/r600/r600_pipe.c b/src/gallium/drivers/r600/r600_pipe.c index 569f77c2b85..08fdd361049 100644 --- a/src/gallium/drivers/r600/r600_pipe.c +++ b/src/gallium/drivers/r600/r600_pipe.c @@ -356,6 +356,7 @@ static int r600_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: diff --git a/src/gallium/drivers/radeonsi/si_pipe.c b/src/gallium/drivers/radeonsi/si_pipe.c index cb80a72f94b..f6ff4a81bd4 100644 --- a/src/gallium/drivers/radeonsi/si_pipe.c +++ b/src/gallium/drivers/radeonsi/si_pipe.c @@ -348,6 +348,7 @@ static int si_get_param(struct pipe_screen* pscreen, enum pipe_cap param) case PIPE_CAP_MULTI_DRAW_INDIRECT: case PIPE_CAP_MULTI_DRAW_INDIRECT_PARAMS: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_MAX_SHADER_PATCH_VARYINGS: diff --git a/src/gallium/drivers/softpipe/sp_screen.c b/src/gallium/drivers/softpipe/sp_screen.c index f2d1dee58d9..143702a5650 100644 --- a/src/gallium/drivers/softpipe/sp_screen.c +++ b/src/gallium/drivers/softpipe/sp_screen.c @@ -259,6 +259,7 @@ softpipe_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; } /* should only get here on unhandled cases */ diff --git a/src/gallium/drivers/svga/svga_screen.c b/src/gallium/drivers/svga/svga_screen.c index b506019cb5e..0528d8df833 100644 --- a/src/gallium/drivers/svga/svga_screen.c +++ b/src/gallium/drivers/svga/svga_screen.c @@ -392,6 +392,7 @@ svga_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_DRAW_PARAMETERS: case PIPE_CAP_TGSI_FS_POSITION_IS_SYSVAL: case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: + case PIPE_CAP_GENERATE_MIPMAP: return 0; } diff --git a/src/gallium/drivers/trace/tr_context.c b/src/gallium/drivers/trace/tr_context.c index d4c88c9be6d..b5ab9249835 100644 --- a/src/gallium/drivers/trace/tr_context.c +++ b/src/gallium/drivers/trace/tr_context.c @@ -1291,6 +1291,42 @@ trace_context_flush(struct pipe_context *_pipe, } +static inline boolean +trace_context_generate_mipmap(struct pipe_context *_pipe, + struct pipe_resource *res, + enum pipe_format format, + unsigned base_level, + unsigned last_level, + unsigned first_layer, + unsigned last_layer) +{ + struct trace_context *tr_ctx = trace_context(_pipe); + struct pipe_context *pipe = tr_ctx->pipe; + boolean ret; + + res = trace_resource_unwrap(tr_ctx, res); + + trace_dump_call_begin("pipe_context", "generate_mipmap"); + + trace_dump_arg(ptr, pipe); + trace_dump_arg(ptr, res); + + trace_dump_arg(format, format); + trace_dump_arg(uint, base_level); + trace_dump_arg(uint, last_level); + trace_dump_arg(uint, first_layer); + trace_dump_arg(uint, last_layer); + + ret = pipe->generate_mipmap(pipe, res, format, base_level, last_level, + first_layer, last_layer); + + trace_dump_ret(bool, ret); + trace_dump_call_end(); + + return ret; +} + + static inline void trace_context_destroy(struct pipe_context *_pipe) { @@ -1620,6 +1656,7 @@ trace_context_create(struct trace_screen *tr_scr, TR_CTX_INIT(clear_render_target); TR_CTX_INIT(clear_depth_stencil); TR_CTX_INIT(flush); + TR_CTX_INIT(generate_mipmap); TR_CTX_INIT(texture_barrier); TR_CTX_INIT(memory_barrier); TR_CTX_INIT(set_tess_state); diff --git a/src/gallium/drivers/vc4/vc4_screen.c b/src/gallium/drivers/vc4/vc4_screen.c index 5a9483797a9..fb41877017d 100644 --- a/src/gallium/drivers/vc4/vc4_screen.c +++ b/src/gallium/drivers/vc4/vc4_screen.c @@ -197,6 +197,7 @@ vc4_screen_get_param(struct pipe_screen *pscreen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; /* Stream output. */ diff --git a/src/gallium/drivers/virgl/virgl_screen.c b/src/gallium/drivers/virgl/virgl_screen.c index 63af8dd6419..fb2e5670ef0 100644 --- a/src/gallium/drivers/virgl/virgl_screen.c +++ b/src/gallium/drivers/virgl/virgl_screen.c @@ -227,6 +227,7 @@ virgl_get_param(struct pipe_screen *screen, enum pipe_cap param) case PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL: case PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT: case PIPE_CAP_INVALIDATE_BUFFER: + case PIPE_CAP_GENERATE_MIPMAP: return 0; case PIPE_CAP_VENDOR_ID: return 0x1af4; diff --git a/src/gallium/include/pipe/p_context.h b/src/gallium/include/pipe/p_context.h index 78155c05348..4b551ed0b41 100644 --- a/src/gallium/include/pipe/p_context.h +++ b/src/gallium/include/pipe/p_context.h @@ -677,6 +677,18 @@ struct pipe_context { */ void (*dump_debug_state)(struct pipe_context *ctx, FILE *stream, unsigned flags); + + /** + * Generate mipmap. + * \return TRUE if mipmap generation succeeds, FALSE otherwise + */ + boolean (*generate_mipmap)(struct pipe_context *ctx, + struct pipe_resource *resource, + enum pipe_format format, + unsigned base_level, + unsigned last_level, + unsigned first_layer, + unsigned last_layer); }; diff --git a/src/gallium/include/pipe/p_defines.h b/src/gallium/include/pipe/p_defines.h index 0655f080e42..cb837cd2597 100644 --- a/src/gallium/include/pipe/p_defines.h +++ b/src/gallium/include/pipe/p_defines.h @@ -643,6 +643,7 @@ enum pipe_cap PIPE_CAP_TGSI_FS_FACE_IS_INTEGER_SYSVAL, PIPE_CAP_SHADER_BUFFER_OFFSET_ALIGNMENT, PIPE_CAP_INVALIDATE_BUFFER, + PIPE_CAP_GENERATE_MIPMAP, }; #define PIPE_QUIRK_TEXTURE_BORDER_COLOR_SWIZZLE_NV50 (1 << 0) diff --git a/src/mesa/state_tracker/st_gen_mipmap.c b/src/mesa/state_tracker/st_gen_mipmap.c index b3700406df0..3e6c0a73bc7 100644 --- a/src/mesa/state_tracker/st_gen_mipmap.c +++ b/src/mesa/state_tracker/st_gen_mipmap.c @@ -149,12 +149,19 @@ st_generate_mipmap(struct gl_context *ctx, GLenum target, last_layer = util_max_layer(pt, baseLevel); } - /* Try to generate the mipmap by rendering/texturing. If that fails, - * use the software fallback. + /* First see if the driver supports hardware mipmap generation, + * if not then generate the mipmap by rendering/texturing. + * If that fails, use the software fallback. */ - if (!util_gen_mipmap(st->pipe, pt, pt->format, baseLevel, lastLevel, - first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) { - _mesa_generate_mipmap(ctx, target, texObj); + if (!st->pipe->screen->get_param(st->pipe->screen, + PIPE_CAP_GENERATE_MIPMAP) || + !st->pipe->generate_mipmap(st->pipe, pt, pt->format, baseLevel, + lastLevel, first_layer, last_layer)) { + + if (!util_gen_mipmap(st->pipe, pt, pt->format, baseLevel, lastLevel, + first_layer, last_layer, PIPE_TEX_FILTER_LINEAR)) { + _mesa_generate_mipmap(ctx, target, texObj); + } } /* Fill in the Mesa gl_texture_image fields */ -- 2.30.2