summaryrefslogtreecommitdiff
path: root/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
diff options
context:
space:
mode:
authorEric Anholt <eric@anholt.net>2007-12-14 11:02:48 -0800
committerEric Anholt <eric@anholt.net>2007-12-14 11:04:26 -0800
commit38bad7677e57d629eeffd4ef39a7fc254db12735 (patch)
tree977b9f821b6c8a9ef166e0533c7a2664a72cffcb /src/mesa/drivers/dri/i965/brw_wm_surface_state.c
parent0037ad4186c11267d85fcde378be79eb6acf74f3 (diff)
[965] Replace the state cache suballocator with direct dri_bufmgr use.
The user-space suballocator that was used avoided relocation computations by using the general and surface state base registers and allocating those types of buffers out of pools built on top of single buffer objects. It also avoided calls into the buffer manager for these small state allocations, since only one buffer object was being used. However, the buffer allocation cost appears to be low, and with relocation caching, computing relocations for buffers is essentially free. Additionally, implementing the suballocator required a don't-fence-subdata flag to disable waiting on buffer maps so that writing new data didn't block on rendering using old data, and careful handling when mapping to update old data (which we need to do for unavoidable relocations with FBOs). More importantly, when the suballocator filled, it had no replacement algorithm and just threw out all of the contents and forced them to be recomputed, which is a significant cost. This is the first step, which just changes the buffer type, but doesn't yet improve the hash table to not result in full recompute on overflow. Because the buffers are all allocated out of the general buffer allocator, we can no longer use the general/surface state bases to avoid relocations, and they are set to 0 instead.
Diffstat (limited to 'src/mesa/drivers/dri/i965/brw_wm_surface_state.c')
-rw-r--r--src/mesa/drivers/dri/i965/brw_wm_surface_state.c157
1 files changed, 121 insertions, 36 deletions
diff --git a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
index 2ade4eeae8..affbca8902 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_surface_state.c
@@ -139,40 +139,46 @@ static GLuint translate_tex_format( GLuint mesa_format )
}
}
-static
-void brw_update_texture_surface( GLcontext *ctx, GLuint unit )
+struct brw_wm_surface_key {
+ GLenum target;
+ dri_bo *bo;
+ GLint format;
+ GLint first_level, last_level;
+ GLint width, height, depth;
+ GLint pitch, cpp;
+ GLboolean tiled;
+};
+
+static dri_bo *
+brw_create_texture_surface( struct brw_context *brw,
+ struct brw_wm_surface_key *key )
{
- struct brw_context *brw = brw_context(ctx);
- struct gl_texture_object *tObj = brw->attribs.Texture->Unit[unit]._Current;
- struct intel_texture_object *intelObj = intel_texture_object(tObj);
- struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel];
struct brw_surface_state surf;
memset(&surf, 0, sizeof(surf));
surf.ss0.mipmap_layout_mode = BRW_SURFACE_MIPMAPLAYOUT_BELOW;
- surf.ss0.surface_type = translate_tex_target(tObj->Target);
- surf.ss0.surface_format = translate_tex_format(firstImage->TexFormat->MesaFormat);
+ surf.ss0.surface_type = translate_tex_target(key->target);
+ surf.ss0.surface_format = translate_tex_format(key->format);
/* This is ok for all textures with channel width 8bit or less:
*/
/* surf.ss0.data_return_format = BRW_SURFACERETURNFORMAT_S1; */
- /* Updated in emit_reloc */
- surf.ss1.base_addr = intelObj->mt->region->buffer->offset;
+ surf.ss1.base_addr = key->bo->offset; /* reloc */
- surf.ss2.mip_count = intelObj->lastLevel - intelObj->firstLevel;
- surf.ss2.width = firstImage->Width - 1;
- surf.ss2.height = firstImage->Height - 1;
+ surf.ss2.mip_count = key->last_level - key->first_level;
+ surf.ss2.width = key->width - 1;
+ surf.ss2.height = key->height - 1;
surf.ss3.tile_walk = BRW_TILEWALK_XMAJOR;
- surf.ss3.tiled_surface = intelObj->mt->region->tiled; /* always zero */
- surf.ss3.pitch = (intelObj->mt->pitch * intelObj->mt->cpp) - 1;
- surf.ss3.depth = firstImage->Depth - 1;
+ surf.ss3.tiled_surface = key->tiled; /* always zero */
+ surf.ss3.pitch = (key->pitch * key->cpp) - 1;
+ surf.ss3.depth = key->depth - 1;
surf.ss4.min_lod = 0;
- if (tObj->Target == GL_TEXTURE_CUBE_MAP) {
+ if (key->target == GL_TEXTURE_CUBE_MAP) {
surf.ss0.cube_pos_x = 1;
surf.ss0.cube_pos_y = 1;
surf.ss0.cube_pos_z = 1;
@@ -181,14 +187,78 @@ void brw_update_texture_surface( GLcontext *ctx, GLuint unit )
surf.ss0.cube_neg_z = 1;
}
- brw->wm.bind.surf_ss_offset[unit + 1] =
- brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf );
+ return brw_upload_cache( &brw->cache, BRW_SS_SURFACE,
+ key, sizeof(*key),
+ &key->bo, 1,
+ &surf, sizeof(surf),
+ NULL, NULL );
}
-
+static void
+brw_update_texture_surface( GLcontext *ctx, GLuint unit )
+{
+ struct brw_context *brw = brw_context(ctx);
+ struct gl_texture_object *tObj = brw->attribs.Texture->Unit[unit]._Current;
+ struct intel_texture_object *intelObj = intel_texture_object(tObj);
+ struct gl_texture_image *firstImage = tObj->Image[0][intelObj->firstLevel];
+ struct brw_wm_surface_key key;
+
+ key.target = tObj->Target;
+ key.format = firstImage->TexFormat->MesaFormat;
+ key.bo = intelObj->mt->region->buffer;
+ key.first_level = intelObj->firstLevel;
+ key.last_level = intelObj->lastLevel;
+ key.width = firstImage->Width;
+ key.height = firstImage->Height;
+ key.pitch = intelObj->mt->pitch;
+ key.cpp = intelObj->mt->cpp;
+ key.depth = firstImage->Depth;
+ key.tiled = intelObj->mt->region->tiled;
+
+ dri_bo_unreference(brw->wm.surf_bo[unit + 1]);
+ brw->wm.surf_bo[unit + 1] = brw_search_cache(&brw->cache, BRW_SS_SURFACE,
+ &key, sizeof(key),
+ &key.bo, 1,
+ NULL);
+ if (brw->wm.surf_bo[unit + 1] == NULL)
+ brw->wm.surf_bo[unit + 1] = brw_create_texture_surface(brw, &key);
+}
#define OFFSET(TYPE, FIELD) ( (GLuint)&(((TYPE *)0)->FIELD) )
+/**
+ * Constructs the binding table for the WM surface state, which maps unit
+ * numbers to surface state objects.
+ */
+static dri_bo *
+brw_wm_get_binding_table(struct brw_context *brw)
+{
+ dri_bo *bind_bo;
+
+ bind_bo = brw_search_cache(&brw->cache, BRW_SS_SURF_BIND,
+ NULL, 0,
+ brw->wm.surf_bo, brw->wm.nr_surfaces,
+ NULL);
+
+ if (bind_bo == NULL) {
+ GLuint data_size = brw->wm.nr_surfaces * 4;
+ uint32_t *data = malloc(data_size);
+ int i;
+
+ for (i = 0; i < brw->wm.nr_surfaces; i++)
+ data[i] = brw->wm.surf_bo[i]->offset;
+
+ bind_bo = brw_upload_cache( &brw->cache, BRW_SS_SURF_BIND,
+ NULL, 0,
+ brw->wm.surf_bo, brw->wm.nr_surfaces,
+ data, data_size,
+ NULL, NULL);
+
+ free(data);
+ }
+
+ return bind_bo;
+}
static void upload_wm_surfaces(struct brw_context *brw )
{
@@ -219,8 +289,7 @@ static void upload_wm_surfaces(struct brw_context *brw )
surf.ss0.writedisable_blue = !brw->attribs.Color->ColorMask[2];
surf.ss0.writedisable_alpha = !brw->attribs.Color->ColorMask[3];
- /* Updated in emit_reloc */
- surf.ss1.base_addr = region->buffer->offset;
+ surf.ss1.base_addr = region->buffer->offset; /* reloc */
surf.ss2.width = region->pitch - 1; /* XXX: not really! */
surf.ss2.height = region->height - 1;
@@ -228,7 +297,10 @@ static void upload_wm_surfaces(struct brw_context *brw )
surf.ss3.tiled_surface = region->tiled;
surf.ss3.pitch = (region->pitch * region->cpp) - 1;
- brw->wm.bind.surf_ss_offset[0] = brw_cache_data( &brw->cache[BRW_SS_SURFACE], &surf );
+ /* Key size will never match key size for textures, so we're safe. */
+ dri_bo_unreference(brw->wm.surf_bo[0]);
+ brw->wm.surf_bo[0] = brw_cache_data( &brw->cache, BRW_SS_SURFACE, &surf,
+ &region->buffer, 1 );
brw->wm.nr_surfaces = 1;
}
@@ -248,45 +320,58 @@ static void upload_wm_surfaces(struct brw_context *brw )
else if( texUnit->_ReallyEnabled &&
texUnit->_Current == intel->frame_buffer_texobj )
{
- brw->wm.bind.surf_ss_offset[i+1] = brw->wm.bind.surf_ss_offset[0];
+ dri_bo_unreference(brw->wm.surf_bo[i+1]);
+ brw->wm.surf_bo[i+1] = brw->wm.surf_bo[0];
+ dri_bo_reference(brw->wm.surf_bo[i+1]);
brw->wm.nr_surfaces = i+2;
- }
- else {
- brw->wm.bind.surf_ss_offset[i+1] = 0;
+ } else {
+ dri_bo_unreference(brw->wm.surf_bo[i+1]);
+ brw->wm.surf_bo[i+1] = NULL;
}
}
- brw->wm.bind_ss_offset = brw_cache_data( &brw->cache[BRW_SS_SURF_BIND],
- &brw->wm.bind );
+ dri_bo_unreference(brw->wm.bind_bo);
+ brw->wm.bind_bo = brw_wm_get_binding_table(brw);
}
static void emit_reloc_wm_surfaces(struct brw_context *brw)
{
- int unit;
+ int unit, i;
- /* Emit framebuffer relocation */
- dri_emit_reloc(brw_cache_buffer(brw, BRW_SS_SURFACE),
+ /* Emit SS framebuffer relocation */
+ dri_emit_reloc(brw->wm.surf_bo[0],
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ | DRM_BO_FLAG_WRITE,
0,
- brw->wm.bind.surf_ss_offset[0] +
offsetof(struct brw_surface_state, ss1),
brw->state.draw_region->buffer);
- /* Emit relocations for texture buffers */
+ /* Emit SS relocations for texture buffers */
for (unit = 0; unit < BRW_MAX_TEX_UNIT; unit++) {
struct gl_texture_unit *texUnit = &brw->attribs.Texture->Unit[unit];
struct gl_texture_object *tObj = texUnit->_Current;
struct intel_texture_object *intelObj = intel_texture_object(tObj);
if (texUnit->_ReallyEnabled && intelObj->mt != NULL) {
- dri_emit_reloc(brw_cache_buffer(brw, BRW_SS_SURFACE),
+ dri_emit_reloc(brw->wm.surf_bo[unit + 1],
DRM_BO_FLAG_MEM_TT | DRM_BO_FLAG_READ,
0,
- brw->wm.bind.surf_ss_offset[unit + 1] +
offsetof(struct brw_surface_state, ss1),
intelObj->mt->region->buffer);
}
}
+
+ /* Emit binding table relocations to surface state */
+ for (i = 0; i < BRW_WM_MAX_SURF; i++) {
+ if (brw->wm.surf_bo[i] != NULL) {
+ dri_emit_reloc(brw->wm.bind_bo,
+ DRM_BO_FLAG_MEM_TT |
+ DRM_BO_FLAG_READ |
+ DRM_BO_FLAG_WRITE,
+ 0,
+ i * 4,
+ brw->wm.surf_bo[i]);
+ }
+ }
}
const struct brw_tracked_state brw_wm_surfaces = {