Keith, I've taken your comment into consideration and started laying out a new simple driver module which I call Blitter. The idea is to provide acceleration for operations like clear, surface_copy, and surface_fill. The module doesn't depend on a CSO context, instead, a driver must call appropriate util_blitter_save* functions to save CSOs and a blit operation takes care of their restoration once it's done.
I attached a patch illustrating the idea with the clear implemented and a working example of usage, but it's not ready to get pushed yet. Please tell me what you think about it. Marek On Tue, Dec 8, 2009 at 1:42 PM, Keith Whitwell <[email protected]> wrote: > On Mon, 2009-12-07 at 05:01 -0800, Marek Olšák wrote: >> Hi, >> >> Because some hardware under some circumstances (e.g. disabled tiling) >> may not be able to use a hardware-specific clear path, it would be >> nice to let a state tracker do the clearing by drawing a >> screen-aligned quad. I am proposing to change the pipe_context->clear >> function to return TRUE if buffers were cleared by the driver, and >> FALSE if the state tracker should do the clearing by taking a generic >> path. >> >> As an example, r300g can use the fast clearing only if colorbuffers >> and zbuffers are micro-tiled, otherwise it must draw a screen-aligned >> quad and doing it in the driver is really messy. >> >> The attached patch implements this interface change and adapts all >> state trackers and drivers. >> >> I noticed that a lot of drivers still use slow util_clear, so they >> will greatly benefit from this patch. It's up to their maintainers >> whether they enable it, I suspect some unstable drivers may not be >> able to draw a quad without visual errors. >> >> Please review. > > Marek, > > I think I'd prefer a scheme where we make it easier for the drivers to > do whatever they need internally to get clears done. This is mainly for > consistency with the rest of Gallium, where once we ask a driver to do > something, the contract is that it will get done, and that the > state-tracker can have a good idea about what a driver's capabilities > are ahead of time. > > In terms of this, it seems what we're really missing to allow drivers to > call equivalents of util_draw_quad() and friends is a way to > save/restore the current bound state which will get clobbered running > the quad blitter. > > Providing a general facility to support this in the driver gives the > equivalent functionality of this fallback patch on every path which > could potentially do this type of fallback, as opposed to adding return > values and dealing with fallbacks in every state tracker. > > So, I think I'll be naking this patch, but I recognise the issue and > would be interested to see ways that we can enable the driver to call > some driver-side equivalent of util_draw_quad() or similar to achieve > the clear. > > Keith > >
From 518c29f9c1860a7e58f4e2c793af1b41350922e5 Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Marek=20Ol=C5=A1=C3=A1k?= <[email protected]> Date: Thu, 10 Dec 2009 10:25:33 +0100 Subject: [PATCH 1/2] util: add blitter --- src/gallium/auxiliary/util/Makefile | 1 + src/gallium/auxiliary/util/SConscript | 1 + src/gallium/auxiliary/util/u_blitter.c | 271 ++++++++++++++++++++++++++++++++ src/gallium/auxiliary/util/u_blitter.h | 153 ++++++++++++++++++ 4 files changed, 426 insertions(+), 0 deletions(-) create mode 100644 src/gallium/auxiliary/util/u_blitter.c create mode 100644 src/gallium/auxiliary/util/u_blitter.h diff --git a/src/gallium/auxiliary/util/Makefile b/src/gallium/auxiliary/util/Makefile index 1d8bb55..8df7445 100644 --- a/src/gallium/auxiliary/util/Makefile +++ b/src/gallium/auxiliary/util/Makefile @@ -9,6 +9,7 @@ C_SOURCES = \ u_debug_symbol.c \ u_debug_stack.c \ u_blit.c \ + u_blitter.c \ u_cache.c \ u_cpu_detect.c \ u_draw_quad.c \ diff --git a/src/gallium/auxiliary/util/SConscript b/src/gallium/auxiliary/util/SConscript index 8d99106..45d89c0 100644 --- a/src/gallium/auxiliary/util/SConscript +++ b/src/gallium/auxiliary/util/SConscript @@ -23,6 +23,7 @@ util = env.ConvenienceLibrary( source = [ 'u_bitmask.c', 'u_blit.c', + 'u_blitter.c', 'u_cache.c', 'u_cpu_detect.c', 'u_debug.c', diff --git a/src/gallium/auxiliary/util/u_blitter.c b/src/gallium/auxiliary/util/u_blitter.c new file mode 100644 index 0000000..9433c1a --- /dev/null +++ b/src/gallium/auxiliary/util/u_blitter.c @@ -0,0 +1,271 @@ +/************************************************************************** + * + * Copyright 2009 Marek Olšák <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * Blitter + * + * @author Marek Olšák + */ + + +#include "pipe/p_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_inlines.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_state.h" + +#include "util/u_memory.h" +#include "util/u_blitter.h" +#include "util/u_draw_quad.h" +#include "util/u_simple_shaders.h" + + +struct blitter_context_priv +{ + struct blitter_context blitter; + + struct pipe_context *pipe; /**< pipe context */ + struct pipe_buffer *vbuf; /**< quad */ + + float vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */ + + /* Constant state objects. */ + void *vs_passthrough_col; /**< vertex shader {pos, color} */ + void *fs_passthrough_col; /**< fragment shader */ + void *vs_passthrough_tex; /**< vertex shader {pos, texcoord} */ + void *fs_texfetch; /**< fragment shader for fetching a texture */ + + void *blend_clear_color; /**< blend state with writemask of RGBA */ + void *blend_keep_color; /**< blend state with writemask of 0 */ + + void *dsa_clear_ds[0xff]; /**< the indices mean stencil clear values */ + void *dsa_keep_ds; /**< dsa state with writemasks of 0 */ + + void *rs_state; /**< rasterizer state */ +}; + + +struct blitter_context *util_blitter_create(struct pipe_context *pipe) +{ + struct blitter_context_priv *ctx; + struct pipe_blend_state blend_clear_color, blend_keep_color; + struct pipe_depth_stencil_alpha_state dsa_clear_ds, dsa_keep_ds; + struct pipe_rasterizer_state rs_state; + unsigned i; + + ctx = CALLOC_STRUCT(blitter_context_priv); + if (!ctx) + return NULL; + + ctx->pipe = pipe; + + /* blend state objects */ + memset(&blend_clear_color, 0, sizeof(blend_clear_color)); + memset(&blend_keep_color, 0, sizeof(blend_keep_color)); + blend_clear_color.colormask = PIPE_MASK_RGBA; + + ctx->blend_clear_color = + pipe->create_blend_state(pipe, &blend_clear_color); + ctx->blend_keep_color = + pipe->create_blend_state(pipe, &blend_keep_color); + + /* depth stencil alpha state objects */ + memset(&dsa_clear_ds, 0, sizeof(dsa_clear_ds)); + memset(&dsa_keep_ds, 0, sizeof(dsa_keep_ds)); + + dsa_clear_ds.depth.enabled = 1; + dsa_clear_ds.depth.writemask = 1; + dsa_clear_ds.depth.func = PIPE_FUNC_ALWAYS; + dsa_clear_ds.stencil[0].enabled = 1; + dsa_clear_ds.stencil[0].func = PIPE_FUNC_ALWAYS; + dsa_clear_ds.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE; + dsa_clear_ds.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE; + dsa_clear_ds.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE; + dsa_clear_ds.stencil[0].valuemask = 0xff; + dsa_clear_ds.stencil[0].writemask = 0xff; + + /* create a depth stencil alpha state for each possible stencil clear + * value */ + for (i = 0; i < 0xff; i++) + { + dsa_clear_ds.stencil[0].ref_value = i; + + ctx->dsa_clear_ds[i] = + pipe->create_depth_stencil_alpha_state(pipe, &dsa_clear_ds); + } + + ctx->dsa_keep_ds = + pipe->create_depth_stencil_alpha_state(pipe, &dsa_keep_ds); + + /* rasterizer state */ + memset(&rs_state, 0, sizeof(rs_state)); + rs_state.front_winding = PIPE_WINDING_CW; + rs_state.cull_mode = PIPE_WINDING_NONE; + rs_state.bypass_vs_clip_and_viewport = 1; + + ctx->rs_state = pipe->create_rasterizer_state(pipe, &rs_state); + + /* vertex shaders */ + { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_COLOR }; + const uint semantic_indexes[] = { 0, 0 }; + ctx->vs_passthrough_col = + util_make_vertex_passthrough_shader(pipe, 2, semantic_names, + semantic_indexes); + } + { + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC }; + const uint semantic_indexes[] = { 0, 0 }; + ctx->vs_passthrough_tex = + util_make_vertex_passthrough_shader(pipe, 2, semantic_names, + semantic_indexes); + } + + /* fragment shaders */ + ctx->fs_passthrough_col = util_make_fragment_passthrough_shader(pipe); + ctx->fs_texfetch = util_make_fragment_tex_shader(pipe); + + /* set invariant vertex coordinates */ + for (i = 0; i < 4; i++) + ctx->vertices[i][0][3] = 1; /*w*/ + + /* create the vertex buffer */ + ctx->vbuf = pipe_buffer_create(ctx->pipe->screen, + 32, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(ctx->vertices)); + + return &ctx->blitter; +} + +/** + * Destroy a blitter context + */ +void util_blitter_destroy(struct blitter_context *blitter) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->pipe; + int i; + + pipe->delete_blend_state(pipe, ctx->blend_clear_color); + pipe->delete_blend_state(pipe, ctx->blend_keep_color); + pipe->delete_depth_stencil_alpha_state(pipe, ctx->dsa_keep_ds); + + for (i = 0; i < 0xff; i++) + pipe->delete_depth_stencil_alpha_state(pipe, + ctx->dsa_clear_ds[i]); + + pipe->delete_rasterizer_state(pipe, ctx->rs_state); + pipe->delete_vs_state(pipe, ctx->vs_passthrough_col); + pipe->delete_vs_state(pipe, ctx->vs_passthrough_tex); + pipe->delete_fs_state(pipe, ctx->fs_passthrough_col); + pipe->delete_fs_state(pipe, ctx->fs_texfetch); + pipe_buffer_reference(&ctx->vbuf, NULL); + FREE(ctx); +} + +void util_blitter_clear(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned buffers, + const float *rgba, + double depth, unsigned stencil) +{ + struct blitter_context_priv *ctx = (struct blitter_context_priv*)blitter; + struct pipe_context *pipe = ctx->pipe; + int i; + + /* make sure these CSOs have been saved */ + assert(ctx->blitter.saved_blend_state && + ctx->blitter.saved_dsa_state && + ctx->blitter.saved_rs_state && + ctx->blitter.saved_fs && + ctx->blitter.saved_vs); + + /* bind CSOs */ + if (buffers & PIPE_CLEAR_COLOR) + pipe->bind_blend_state(pipe, ctx->blend_clear_color); + else + pipe->bind_blend_state(pipe, ctx->blend_keep_color); + + if (buffers & PIPE_CLEAR_DEPTHSTENCIL) + pipe->bind_depth_stencil_alpha_state(pipe, + ctx->dsa_clear_ds[stencil&0xff]); + else + pipe->bind_depth_stencil_alpha_state(pipe, ctx->dsa_keep_ds); + + pipe->bind_rasterizer_state(pipe, ctx->rs_state); + pipe->bind_fs_state(pipe, ctx->fs_passthrough_col); + pipe->bind_vs_state(pipe, ctx->vs_passthrough_col); + + /* set vertex positions */ + ctx->vertices[0][0][0] = 0; /*v0.x*/ + ctx->vertices[0][0][1] = 0; /*v0.y*/ + + ctx->vertices[1][0][0] = width; /*v1.x*/ + ctx->vertices[1][0][1] = 0; /*v1.y*/ + + ctx->vertices[2][0][0] = width; /*v2.x*/ + ctx->vertices[2][0][1] = height; /*v2.y*/ + + ctx->vertices[3][0][0] = 0; /*v3.x*/ + ctx->vertices[3][0][1] = height; /*v3.y*/ + + /* set clear color and depth values */ + for (i = 0; i < 4; i++) + { + ctx->vertices[i][0][2] = depth; /*z*/ + + ctx->vertices[i][1][0] = rgba[0]; + ctx->vertices[i][1][1] = rgba[1]; + ctx->vertices[i][1][2] = rgba[2]; + ctx->vertices[i][1][3] = rgba[3]; + } + + /* write vertices and draw them */ + /* XXX avoid calling pipe_buffer_write every frame. */ + pipe_buffer_write(ctx->pipe->screen, ctx->vbuf, + 0, sizeof(ctx->vertices), ctx->vertices); + + util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, + 4, /* verts */ + 2); /* attribs/vert */ + + /* restore CSOs */ + pipe->bind_blend_state(pipe, ctx->blitter.saved_blend_state); + pipe->bind_depth_stencil_alpha_state(pipe, ctx->blitter.saved_dsa_state); + pipe->bind_rasterizer_state(pipe, ctx->blitter.saved_rs_state); + pipe->bind_fs_state(pipe, ctx->blitter.saved_fs); + pipe->bind_vs_state(pipe, ctx->blitter.saved_vs); + + ctx->blitter.saved_blend_state = 0; + ctx->blitter.saved_dsa_state = 0; + ctx->blitter.saved_rs_state = 0; + ctx->blitter.saved_fs = 0; + ctx->blitter.saved_vs = 0; +} diff --git a/src/gallium/auxiliary/util/u_blitter.h b/src/gallium/auxiliary/util/u_blitter.h new file mode 100644 index 0000000..e778490 --- /dev/null +++ b/src/gallium/auxiliary/util/u_blitter.h @@ -0,0 +1,153 @@ +/************************************************************************** + * + * Copyright 2009 Marek Olšák <[email protected]> + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef U_BLITTER_H +#define U_BLITTER_H + +#include "pipe/p_state.h" + + +#ifdef __cplusplus +extern "C" { +#endif + +struct pipe_context; + +struct blitter_context +{ + /* Private members, really. */ + void *saved_blend_state; /**< blend state */ + void *saved_dsa_state; /**< depth stencil alpha state */ + void *saved_rs_state; /**< rasterizer state */ + void *saved_fs, *saved_vs; /**< fragment shader, vertex shader */ + int saved_num_textures; + struct pipe_texture *saved_textures[32]; /* is 32 enough? */ +}; + +/** + * Create a blitter context. + */ +struct blitter_context *util_blitter_create(struct pipe_context *pipe); + +/** + * Destroy a blitter context. + */ +void util_blitter_destroy(struct blitter_context *blitter); + +/** + * Clear a specified set of currently bound buffers to specified values. + * + * These state objects should be saved in the blitter before this function is + * called: + * - blend state + * - depth stencil alpha state + * - rasterizer state + * - vertex shader + * - fragment shader + */ +void util_blitter_clear(struct blitter_context *blitter, + unsigned width, unsigned height, + unsigned buffers, + const float *rgba, + double depth, unsigned stencil); + +/** + * Copy a block of pixels from one surface to another. + * The surfaces must be of the same format. + */ +void util_blitter_copy(struct blitter_context *blitter, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + struct pipe_surface *src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height); + +/** + * Fill a region of a surface with a constant value. + */ +void util_blitter_fill(struct blitter_context *blitter, + struct pipe_surface *dst, + unsigned dstx, unsigned dsty, + unsigned width, unsigned height, + unsigned value); + +/* The functions below should be used to save currently bound constant state + * objects inside a driver. The objects are automatically restored at the end + * of the util_blitter_{clear, fill, copy} functions and then forgotten. + * + * CSOs not listed here are not affected by util_blitter. */ + +static INLINE +void util_blitter_save_blend(struct blitter_context *blitter, + void *state) +{ + blitter->saved_blend_state = state; +} + +static INLINE +void util_blitter_save_depth_stencil_alpha(struct blitter_context *blitter, + void *state) +{ + blitter->saved_dsa_state = state; +} + +static INLINE +void util_blitter_save_rasterizer(struct blitter_context *blitter, + void *state) +{ + blitter->saved_rs_state = state; +} + +static INLINE +void util_blitter_save_fragment_textures(struct blitter_context *blitter, + int num_textures, + struct pipe_texture **textures) +{ + assert(num_textures <= 32); + blitter->saved_num_textures = num_textures; + memcpy(blitter->saved_textures, textures, + num_textures * sizeof(struct pipe_texture *)); +} + +static INLINE +void util_blitter_save_fragment_shader(struct blitter_context *blitter, + void *fs) +{ + blitter->saved_fs = fs; +} + +static INLINE +void util_blitter_save_vertex_shader(struct blitter_context *blitter, + void *vs) +{ + blitter->saved_vs = vs; +} + +#ifdef __cplusplus +} +#endif + +#endif -- 1.6.3.3
From 2b1cf1e3e45e72eb8876356ac0d19633346223bf Mon Sep 17 00:00:00 2001 From: =?utf-8?q?Marek=20Ol=C5=A1=C3=A1k?= <[email protected]> Date: Thu, 10 Dec 2009 10:20:36 +0100 Subject: [PATCH 2/2] r300g: add accelerated clear --- src/gallium/drivers/r300/r300_clear.c | 15 ++++++++++++--- src/gallium/drivers/r300/r300_context.c | 5 +++++ src/gallium/drivers/r300/r300_context.h | 4 ++++ 3 files changed, 21 insertions(+), 3 deletions(-) diff --git a/src/gallium/drivers/r300/r300_clear.c b/src/gallium/drivers/r300/r300_clear.c index 02d6d50..8bc76d9 100644 --- a/src/gallium/drivers/r300/r300_clear.c +++ b/src/gallium/drivers/r300/r300_clear.c @@ -32,7 +32,16 @@ void r300_clear(struct pipe_context* pipe, double depth, unsigned stencil) { - /* XXX we can and should do one clear if both color and zs are set */ - util_clear(pipe, &r300_context(pipe)->framebuffer_state, - buffers, rgba, depth, stencil); + struct r300_context* r300 = r300_context(pipe); + + util_blitter_save_blend(r300->blitter, r300->blend_state); + util_blitter_save_depth_stencil_alpha(r300->blitter, r300->dsa_state); + util_blitter_save_rasterizer(r300->blitter, r300->rs_state); + util_blitter_save_fragment_shader(r300->blitter, r300->fs); + util_blitter_save_vertex_shader(r300->blitter, r300->vs); + + util_blitter_clear(r300->blitter, + r300->framebuffer_state.width, + r300->framebuffer_state.height, + buffers, rgba, depth, stencil); } diff --git a/src/gallium/drivers/r300/r300_context.c b/src/gallium/drivers/r300/r300_context.c index 5b337f0..d89bd01 100644 --- a/src/gallium/drivers/r300/r300_context.c +++ b/src/gallium/drivers/r300/r300_context.c @@ -52,6 +52,8 @@ static void r300_destroy_context(struct pipe_context* context) struct r300_context* r300 = r300_context(context); struct r300_query* query, * temp; + util_blitter_destroy(r300->blitter); + util_hash_table_foreach(r300->shader_hash_table, r300_clear_hash_table, NULL); util_hash_table_destroy(r300->shader_hash_table); @@ -175,5 +177,8 @@ struct pipe_context* r300_create_context(struct pipe_screen* screen, r300->winsys->set_flush_cb(r300->winsys, r300_flush_cb, r300); r300->dirty_state = R300_NEW_KITCHEN_SINK; r300->dirty_hw++; + + r300->blitter = util_blitter_create(&r300->context); + return &r300->context; } diff --git a/src/gallium/drivers/r300/r300_context.h b/src/gallium/drivers/r300/r300_context.h index 0be1903..6bd2766 100644 --- a/src/gallium/drivers/r300/r300_context.h +++ b/src/gallium/drivers/r300/r300_context.h @@ -25,6 +25,8 @@ #include "draw/draw_vertex.h" +#include "util/u_blitter.h" + #include "pipe/p_context.h" #include "pipe/p_inlines.h" @@ -248,6 +250,8 @@ struct r300_context { struct radeon_winsys* winsys; /* Draw module. Used mostly for SW TCL. */ struct draw_context* draw; + /* Accelerated blit support. */ + struct blitter_context* blitter; /* Vertex buffer for rendering. */ struct pipe_buffer* vbo; -- 1.6.3.3
------------------------------------------------------------------------------ Return on Information: Google Enterprise Search pays you back Get the facts. http://p.sf.net/sfu/google-dev2dev
_______________________________________________ Mesa3d-dev mailing list [email protected] https://lists.sourceforge.net/lists/listinfo/mesa3d-dev
