summaryrefslogtreecommitdiff
path: root/src/gallium
diff options
context:
space:
mode:
authorKeith Whitwell <keith@tungstengraphics.com>2008-12-12 16:46:34 +0000
committerKeith Whitwell <keith@tungstengraphics.com>2008-12-12 16:57:39 +0000
commitd2c2e9316d043ab584794a3524f22776deb4c777 (patch)
tree1d6045093cd7c935ceb26a3afb6c57b177c0ac62 /src/gallium
parenteb20e2984e51e632ef1a51620db7aca3eb89dafa (diff)
gallium: avoid mapping same vertex buffer in subsequent frames
Quite a few util modules were maintaining a single vertex buffer over multiple frames, and potentially reusing it in subsequent frames. Unfortunately that would force us into syncrhonous rendering as the buffer manager would be forced to wait for the previous rendering to complete prior to allowing the map. This resolves that issue, but requires the state tracker to issue a few new flush() calls at the end of each frame.
Diffstat (limited to 'src/gallium')
-rw-r--r--src/gallium/auxiliary/util/u_blit.c88
-rw-r--r--src/gallium/auxiliary/util/u_blit.h4
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.c5
-rw-r--r--src/gallium/auxiliary/util/u_draw_quad.h2
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.c51
-rw-r--r--src/gallium/auxiliary/util/u_gen_mipmap.h5
6 files changed, 120 insertions, 35 deletions
diff --git a/src/gallium/auxiliary/util/u_blit.c b/src/gallium/auxiliary/util/u_blit.c
index d28201ac8d..2cef3338b5 100644
--- a/src/gallium/auxiliary/util/u_blit.c
+++ b/src/gallium/auxiliary/util/u_blit.c
@@ -66,6 +66,8 @@ struct blit_state
void *fs;
struct pipe_buffer *vbuf; /**< quad vertices */
+ unsigned vbuf_slot;
+
float vertices[4][2][4]; /**< vertex/texcoords for quad */
};
@@ -138,17 +140,7 @@ util_create_blit(struct pipe_context *pipe, struct cso_context *cso)
/* fragment shader */
ctx->fs = util_make_fragment_tex_shader(pipe, &ctx->frag_shader);
-
- ctx->vbuf = pipe_buffer_create(pipe->screen,
- 32,
- PIPE_BUFFER_USAGE_VERTEX,
- sizeof(ctx->vertices));
- if (!ctx->vbuf) {
- FREE(ctx);
- ctx->pipe->delete_fs_state(ctx->pipe, ctx->fs);
- ctx->pipe->delete_vs_state(ctx->pipe, ctx->vs);
- return NULL;
- }
+ ctx->vbuf = NULL;
/* init vertex data that doesn't change */
for (i = 0; i < 4; i++) {
@@ -181,15 +173,35 @@ util_destroy_blit(struct blit_state *ctx)
}
+static unsigned get_next_slot( struct blit_state *ctx )
+{
+ const unsigned max_slots = 4096 / sizeof ctx->vertices;
+
+ if (ctx->vbuf_slot >= max_slots)
+ util_blit_flush( ctx );
+
+ if (!ctx->vbuf) {
+ ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof ctx->vertices);
+ }
+
+ return ctx->vbuf_slot++ * sizeof ctx->vertices;
+}
+
+
+
/**
* Setup vertex data for the textured quad we'll draw.
* Note: y=0=top
*/
-static void
+static unsigned
setup_vertex_data(struct blit_state *ctx,
float x0, float y0, float x1, float y1, float z)
{
void *buf;
+ unsigned offset;
ctx->vertices[0][0][0] = x0;
ctx->vertices[0][0][1] = y0;
@@ -215,12 +227,16 @@ setup_vertex_data(struct blit_state *ctx,
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
+ offset = get_next_slot( ctx );
+
buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
- memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+ memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
+
+ return offset;
}
@@ -228,13 +244,14 @@ setup_vertex_data(struct blit_state *ctx,
* Setup vertex data for the textured quad we'll draw.
* Note: y=0=top
*/
-static void
+static unsigned
setup_vertex_data_tex(struct blit_state *ctx,
float x0, float y0, float x1, float y1,
float s0, float t0, float s1, float t1,
float z)
{
void *buf;
+ unsigned offset;
ctx->vertices[0][0][0] = x0;
ctx->vertices[0][0][1] = y0;
@@ -260,12 +277,16 @@ setup_vertex_data_tex(struct blit_state *ctx,
ctx->vertices[3][1][0] = s0;
ctx->vertices[3][1][1] = t1;
+ offset = get_next_slot( ctx );
+
buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
- memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+ memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
+
+ return offset;
}
/**
* Copy pixel block from src surface to dst surface.
@@ -291,6 +312,7 @@ util_blit_pixels(struct blit_state *ctx,
const int srcH = abs(srcY1 - srcY0);
const int srcLeft = MIN2(srcX0, srcX1);
const int srcTop = MIN2(srcY0, srcY1);
+ unsigned offset;
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -398,11 +420,11 @@ util_blit_pixels(struct blit_state *ctx,
cso_set_framebuffer(ctx->cso, &fb);
/* draw quad */
- setup_vertex_data(ctx,
- (float) dstX0, (float) dstY0,
- (float) dstX1, (float) dstY1, z);
+ offset = setup_vertex_data(ctx,
+ (float) dstX0, (float) dstY0,
+ (float) dstX1, (float) dstY1, z);
- util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+ util_draw_vertex_buffer(ctx->pipe, ctx->vbuf, offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
@@ -421,6 +443,18 @@ util_blit_pixels(struct blit_state *ctx,
screen->texture_release(screen, &tex);
}
+
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+void util_blit_flush( struct blit_state *ctx )
+{
+ pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
+ ctx->vbuf_slot = 0;
+}
+
+
+
/**
* Copy pixel block from src texture to dst surface.
* Overlapping regions are acceptable.
@@ -442,6 +476,7 @@ util_blit_pixels_tex(struct blit_state *ctx,
struct pipe_screen *screen = pipe->screen;
struct pipe_framebuffer_state fb;
float s0, t0, s1, t1;
+ unsigned offset;
assert(filter == PIPE_TEX_MIPFILTER_NEAREST ||
filter == PIPE_TEX_MIPFILTER_LINEAR);
@@ -496,13 +531,14 @@ util_blit_pixels_tex(struct blit_state *ctx,
cso_set_framebuffer(ctx->cso, &fb);
/* draw quad */
- setup_vertex_data_tex(ctx,
- (float) dstX0, (float) dstY0,
- (float) dstX1, (float) dstY1,
- s0, t0, s1, t1,
- z);
-
- util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+ offset = setup_vertex_data_tex(ctx,
+ (float) dstX0, (float) dstY0,
+ (float) dstX1, (float) dstY1,
+ s0, t0, s1, t1,
+ z);
+
+ util_draw_vertex_buffer(ctx->pipe,
+ ctx->vbuf, offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
diff --git a/src/gallium/auxiliary/util/u_blit.h b/src/gallium/auxiliary/util/u_blit.h
index 308075698f..c35beceda8 100644
--- a/src/gallium/auxiliary/util/u_blit.h
+++ b/src/gallium/auxiliary/util/u_blit.h
@@ -70,6 +70,10 @@ util_blit_pixels_tex(struct blit_state *ctx,
int dstX1, int dstY1,
float z, uint filter);
+/* Call at end of frame to avoid synchronous rendering.
+ */
+extern void
+util_blit_flush( struct blit_state *ctx );
#ifdef __cplusplus
}
diff --git a/src/gallium/auxiliary/util/u_draw_quad.c b/src/gallium/auxiliary/util/u_draw_quad.c
index 8ecae71b64..d7bb74b87b 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.c
+++ b/src/gallium/auxiliary/util/u_draw_quad.c
@@ -40,6 +40,7 @@
void
util_draw_vertex_buffer(struct pipe_context *pipe,
struct pipe_buffer *vbuf,
+ uint offset,
uint prim_type,
uint num_verts,
uint num_attribs)
@@ -53,7 +54,7 @@ util_draw_vertex_buffer(struct pipe_context *pipe,
/* tell pipe about the vertex buffer */
vbuffer.buffer = vbuf;
vbuffer.pitch = num_attribs * 4 * sizeof(float); /* vertex size */
- vbuffer.buffer_offset = 0;
+ vbuffer.buffer_offset = offset;
pipe->set_vertex_buffers(pipe, 1, &vbuffer);
/* tell pipe about the vertex attributes */
@@ -124,7 +125,7 @@ util_draw_texquad(struct pipe_context *pipe,
v[29] = 1.0;
pipe_buffer_unmap(pipe->screen, vbuf);
- util_draw_vertex_buffer(pipe, vbuf, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
+ util_draw_vertex_buffer(pipe, vbuf, 0, PIPE_PRIM_TRIANGLE_FAN, 4, 2);
}
pipe_buffer_reference(pipe->screen, &vbuf, NULL);
diff --git a/src/gallium/auxiliary/util/u_draw_quad.h b/src/gallium/auxiliary/util/u_draw_quad.h
index ec4862ead3..00d3f5b715 100644
--- a/src/gallium/auxiliary/util/u_draw_quad.h
+++ b/src/gallium/auxiliary/util/u_draw_quad.h
@@ -37,7 +37,7 @@ struct pipe_buffer;
extern void
util_draw_vertex_buffer(struct pipe_context *pipe,
- struct pipe_buffer *vbuf,
+ struct pipe_buffer *vbuf, uint offset,
uint num_attribs, uint num_verts, uint prim_type);
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.c b/src/gallium/auxiliary/util/u_gen_mipmap.c
index 9d305ad763..5f395ec6e9 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.c
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.c
@@ -69,6 +69,8 @@ struct gen_mipmap_state
void *fs;
struct pipe_buffer *vbuf; /**< quad vertices */
+ unsigned vbuf_slot;
+
float vertices[4][2][4]; /**< vertex/texcoords for quad */
};
@@ -779,10 +781,28 @@ util_create_gen_mipmap(struct pipe_context *pipe,
}
-static void
+static unsigned get_next_slot( struct gen_mipmap_state *ctx )
+{
+ const unsigned max_slots = 4096 / sizeof ctx->vertices;
+
+ if (ctx->vbuf_slot >= max_slots)
+ util_gen_mipmap_flush( ctx );
+
+ if (!ctx->vbuf) {
+ ctx->vbuf = pipe_buffer_create(ctx->pipe->screen,
+ 32,
+ PIPE_BUFFER_USAGE_VERTEX,
+ max_slots * sizeof ctx->vertices);
+ }
+
+ return ctx->vbuf_slot++ * sizeof ctx->vertices;
+}
+
+static unsigned
set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
{
void *buf;
+ unsigned offset;
ctx->vertices[0][0][0] = 0.0f; /*x*/
ctx->vertices[0][0][1] = 0.0f; /*y*/
@@ -804,12 +824,16 @@ set_vertex_data(struct gen_mipmap_state *ctx, float width, float height)
ctx->vertices[3][1][0] = 0.0f;
ctx->vertices[3][1][1] = 1.0f;
+ offset = get_next_slot( ctx );
+
buf = pipe_buffer_map(ctx->pipe->screen, ctx->vbuf,
PIPE_BUFFER_USAGE_CPU_WRITE);
- memcpy(buf, ctx->vertices, sizeof(ctx->vertices));
+ memcpy((char *)buf + offset, ctx->vertices, sizeof(ctx->vertices));
pipe_buffer_unmap(ctx->pipe->screen, ctx->vbuf);
+
+ return offset;
}
@@ -834,6 +858,17 @@ util_destroy_gen_mipmap(struct gen_mipmap_state *ctx)
}
+
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+void util_gen_mipmap_flush( struct gen_mipmap_state *ctx )
+{
+ pipe_buffer_reference(ctx->pipe->screen, &ctx->vbuf, NULL);
+ ctx->vbuf_slot = 0;
+}
+
+
/**
* Generate mipmap images. It's assumed all needed texture memory is
* already allocated.
@@ -855,6 +890,7 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
struct pipe_framebuffer_state fb;
uint dstLevel;
uint zslice = 0;
+ uint offset;
/* check if we can render in the texture's format */
if (!screen->is_format_supported(screen, pt->format, PIPE_TEXTURE_2D,
@@ -925,10 +961,13 @@ util_gen_mipmap(struct gen_mipmap_state *ctx,
cso_set_sampler_textures(ctx->cso, 1, &pt);
/* quad coords in window coords (bypassing clipping, viewport mapping) */
- set_vertex_data(ctx,
- (float) pt->width[dstLevel],
- (float) pt->height[dstLevel]);
- util_draw_vertex_buffer(ctx->pipe, ctx->vbuf,
+ offset = set_vertex_data(ctx,
+ (float) pt->width[dstLevel],
+ (float) pt->height[dstLevel]);
+
+ util_draw_vertex_buffer(ctx->pipe,
+ ctx->vbuf,
+ offset,
PIPE_PRIM_TRIANGLE_FAN,
4, /* verts */
2); /* attribs/vert */
diff --git a/src/gallium/auxiliary/util/u_gen_mipmap.h b/src/gallium/auxiliary/util/u_gen_mipmap.h
index 3277024f07..54608f9466 100644
--- a/src/gallium/auxiliary/util/u_gen_mipmap.h
+++ b/src/gallium/auxiliary/util/u_gen_mipmap.h
@@ -50,6 +50,11 @@ util_create_gen_mipmap(struct pipe_context *pipe, struct cso_context *cso);
extern void
util_destroy_gen_mipmap(struct gen_mipmap_state *ctx);
+/* Release vertex buffer at end of frame to avoid synchronous
+ * rendering.
+ */
+extern void
+util_gen_mipmap_flush( struct gen_mipmap_state *ctx );
extern void