intel: Add support for tiled textures.

This is about a 30% performance win in OA with high settings on my GM45,
and experiments with 915GM indicate that it'll be around a 20% win there.
Currently, 915-class hardware is seriously hurt by the fact that we use
fence regs to control the tiling even for 3D instructions that could live
without them, so we spend a bunch of time waiting on previous rendering in
order to pull fences off.  Thus, the texture_tiling driconf option defaults
off there for now.
This commit is contained in:
Eric Anholt
2009-06-03 16:40:20 +00:00
parent 165ae5e2fb
commit 1ba96651e1
13 changed files with 120 additions and 44 deletions

View File

@@ -112,7 +112,8 @@ static GLint bottom_offsets[6] = {
*/
static void
i915_miptree_layout_cube(struct intel_context *intel,
struct intel_mipmap_tree * mt)
struct intel_mipmap_tree * mt,
uint32_t tiling)
{
const GLuint dim = mt->width0;
GLuint face;
@@ -122,7 +123,7 @@ i915_miptree_layout_cube(struct intel_context *intel,
assert(lvlWidth == lvlHeight); /* cubemap images are square */
/* double pitch for cube layouts */
mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2);
mt->total_height = dim * 4;
for (level = mt->first_level; level <= mt->last_level; level++) {
@@ -156,7 +157,8 @@ i915_miptree_layout_cube(struct intel_context *intel,
static void
i915_miptree_layout_3d(struct intel_context *intel,
struct intel_mipmap_tree * mt)
struct intel_mipmap_tree * mt,
uint32_t tiling)
{
GLuint width = mt->width0;
GLuint height = mt->height0;
@@ -165,7 +167,7 @@ i915_miptree_layout_3d(struct intel_context *intel,
GLint level;
/* Calculate the size of a single slice. */
mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
/* XXX: hardware expects/requires 9 levels at minimum. */
for (level = mt->first_level; level <= MAX2(8, mt->last_level); level++) {
@@ -200,14 +202,15 @@ i915_miptree_layout_3d(struct intel_context *intel,
static void
i915_miptree_layout_2d(struct intel_context *intel,
struct intel_mipmap_tree * mt)
struct intel_mipmap_tree * mt,
uint32_t tiling)
{
GLuint width = mt->width0;
GLuint height = mt->height0;
GLuint img_height;
GLint level;
mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
mt->total_height = 0;
for (level = mt->first_level; level <= mt->last_level; level++) {
@@ -228,19 +231,20 @@ i915_miptree_layout_2d(struct intel_context *intel,
}
GLboolean
i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt,
uint32_t tiling)
{
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP:
i915_miptree_layout_cube(intel, mt);
i915_miptree_layout_cube(intel, mt, tiling);
break;
case GL_TEXTURE_3D:
i915_miptree_layout_3d(intel, mt);
i915_miptree_layout_3d(intel, mt, tiling);
break;
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
i915_miptree_layout_2d(intel, mt);
i915_miptree_layout_2d(intel, mt, tiling);
break;
default:
_mesa_problem(NULL, "Unexpected tex target in i915_miptree_layout()");
@@ -317,7 +321,8 @@ i915_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
static void
i945_miptree_layout_cube(struct intel_context *intel,
struct intel_mipmap_tree * mt)
struct intel_mipmap_tree * mt,
uint32_t tiling)
{
const GLuint dim = mt->width0;
GLuint face;
@@ -331,9 +336,9 @@ i945_miptree_layout_cube(struct intel_context *intel,
* or the final row of 4x4, 2x2 and 1x1 faces below this.
*/
if (dim > 32)
mt->pitch = intel_miptree_pitch_align (intel, mt, dim * 2);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, dim * 2);
else
mt->pitch = intel_miptree_pitch_align (intel, mt, 14 * 8);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, 14 * 8);
if (dim >= 4)
mt->total_height = dim * 4 + 4;
@@ -408,7 +413,8 @@ i945_miptree_layout_cube(struct intel_context *intel,
static void
i945_miptree_layout_3d(struct intel_context *intel,
struct intel_mipmap_tree * mt)
struct intel_mipmap_tree * mt,
uint32_t tiling)
{
GLuint width = mt->width0;
GLuint height = mt->height0;
@@ -417,7 +423,7 @@ i945_miptree_layout_3d(struct intel_context *intel,
GLuint pack_y_pitch;
GLuint level;
mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
mt->total_height = 0;
pack_y_pitch = MAX2(mt->height0, 2);
@@ -462,22 +468,23 @@ i945_miptree_layout_3d(struct intel_context *intel,
}
GLboolean
i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt)
i945_miptree_layout(struct intel_context *intel, struct intel_mipmap_tree * mt,
uint32_t tiling)
{
switch (mt->target) {
case GL_TEXTURE_CUBE_MAP:
if (mt->compressed)
i945_miptree_layout_cube(intel, mt);
i945_miptree_layout_cube(intel, mt, tiling);
else
i915_miptree_layout_cube(intel, mt);
i915_miptree_layout_cube(intel, mt, tiling);
break;
case GL_TEXTURE_3D:
i945_miptree_layout_3d(intel, mt);
i945_miptree_layout_3d(intel, mt, tiling);
break;
case GL_TEXTURE_1D:
case GL_TEXTURE_2D:
case GL_TEXTURE_RECTANGLE_ARB:
i945_miptree_layout_2d(intel, mt);
i945_miptree_layout_2d(intel, mt, tiling);
break;
default:
_mesa_problem(NULL, "Unexpected tex target in i945_miptree_layout()");

View File

@@ -40,7 +40,8 @@
#define FILE_DEBUG_FLAG DEBUG_MIPTREE
GLboolean brw_miptree_layout(struct intel_context *intel,
struct intel_mipmap_tree *mt)
struct intel_mipmap_tree *mt,
uint32_t tiling)
{
/* XXX: these vary depending on image format: */
/* GLint align_w = 4; */
@@ -64,8 +65,8 @@ GLboolean brw_miptree_layout(struct intel_context *intel,
mt->pitch = ALIGN(width, align_w);
pack_y_pitch = (height + 3) / 4;
} else {
mt->pitch = intel_miptree_pitch_align (intel, mt, mt->width0);
pack_y_pitch = ALIGN(mt->height0, align_h);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->width0);
pack_y_pitch = ALIGN(mt->height0, align_h);
}
pack_x_pitch = mt->pitch;
@@ -122,7 +123,7 @@ GLboolean brw_miptree_layout(struct intel_context *intel,
}
default:
i945_miptree_layout_2d(intel, mt);
i945_miptree_layout_2d(intel, mt, tiling);
break;
}
DBG("%s: %dx%dx%d - sz 0x%x\n", __FUNCTION__,

View File

@@ -724,6 +724,8 @@ intelInitContext(struct intel_context *intel,
else if (driQueryOptionb(&intel->optionCache, "force_s3tc_enable")) {
_mesa_enable_extension(ctx, "GL_EXT_texture_compression_s3tc");
}
intel->use_texture_tiling = driQueryOptionb(&intel->optionCache,
"texture_tiling");
intel->prim.primitive = ~0;

View File

@@ -305,6 +305,8 @@ struct intel_context
*/
GLboolean is_front_buffer_rendering;
GLboolean use_texture_tiling;
drm_clip_rect_t fboRect; /**< cliprect for FBO rendering */
int perf_boxes;

View File

@@ -217,7 +217,8 @@ intel_alloc_renderbuffer_storage(GLcontext * ctx, struct gl_renderbuffer *rb,
DBG("Allocating %d x %d Intel RBO (pitch %d)\n", width,
height, pitch);
irb->region = intel_region_alloc(intel, cpp, width, height, pitch,
irb->region = intel_region_alloc(intel, I915_TILING_NONE,
cpp, width, height, pitch,
GL_TRUE);
if (!irb->region)
return GL_FALSE; /* out of memory? */

View File

@@ -57,7 +57,8 @@ intel_miptree_create_internal(struct intel_context *intel,
GLuint last_level,
GLuint width0,
GLuint height0,
GLuint depth0, GLuint cpp, GLuint compress_byte)
GLuint depth0, GLuint cpp, GLuint compress_byte,
uint32_t tiling)
{
GLboolean ok;
struct intel_mipmap_tree *mt = calloc(sizeof(*mt), 1);
@@ -81,11 +82,11 @@ intel_miptree_create_internal(struct intel_context *intel,
#ifdef I915
if (IS_945(intel->intelScreen->deviceID))
ok = i945_miptree_layout(intel, mt);
ok = i945_miptree_layout(intel, mt, tiling);
else
ok = i915_miptree_layout(intel, mt);
ok = i915_miptree_layout(intel, mt, tiling);
#else
ok = brw_miptree_layout(intel, mt);
ok = brw_miptree_layout(intel, mt, tiling);
#endif
if (!ok) {
@@ -109,10 +110,18 @@ intel_miptree_create(struct intel_context *intel,
GLboolean expect_accelerated_upload)
{
struct intel_mipmap_tree *mt;
uint32_t tiling;
if (intel->use_texture_tiling && compress_byte == 0 &&
intel->intelScreen->kernel_exec_fencing)
tiling = I915_TILING_X;
else
tiling = I915_TILING_NONE;
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level, width0,
height0, depth0, cpp, compress_byte);
height0, depth0, cpp, compress_byte,
tiling);
/*
* pitch == 0 || height == 0 indicates the null texture
*/
@@ -120,6 +129,7 @@ intel_miptree_create(struct intel_context *intel,
return NULL;
mt->region = intel_region_alloc(intel,
tiling,
mt->cpp,
mt->pitch,
mt->total_height,
@@ -149,7 +159,8 @@ intel_miptree_create_for_region(struct intel_context *intel,
mt = intel_miptree_create_internal(intel, target, internal_format,
first_level, last_level,
region->width, region->height, 1,
region->cpp, compress_byte);
region->cpp, compress_byte,
I915_TILING_NONE);
if (!mt)
return mt;
#if 0
@@ -187,6 +198,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling,
int pitch)
{
#ifdef I915
@@ -207,6 +219,11 @@ int intel_miptree_pitch_align (struct intel_context *intel,
pitch_align = 4;
}
if (tiling == I915_TILING_X)
pitch_align = 512;
else if (tiling == I915_TILING_Y)
pitch_align = 128;
pitch = ALIGN(pitch * mt->cpp, pitch_align);
#ifdef I915

View File

@@ -148,6 +148,7 @@ intel_miptree_create_for_region(struct intel_context *intel,
int intel_miptree_pitch_align (struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling,
int pitch);
void intel_miptree_reference(struct intel_mipmap_tree **dst,
@@ -218,10 +219,13 @@ void intel_miptree_image_copy(struct intel_context *intel,
/* i915_mipmap_tree.c:
*/
GLboolean i915_miptree_layout(struct intel_context *intel,
struct intel_mipmap_tree *mt);
struct intel_mipmap_tree *mt,
uint32_t tiling);
GLboolean i945_miptree_layout(struct intel_context *intel,
struct intel_mipmap_tree *mt);
struct intel_mipmap_tree *mt,
uint32_t tiling);
GLboolean brw_miptree_layout(struct intel_context *intel,
struct intel_mipmap_tree *mt);
struct intel_mipmap_tree *mt,
uint32_t tiling);
#endif

View File

@@ -116,7 +116,10 @@ intel_region_map(struct intel_context *intel, struct intel_region *region)
if (region->pbo)
intel_region_cow(intel, region);
dri_bo_map(region->buffer, GL_TRUE);
if (intel->intelScreen->kernel_exec_fencing)
drm_intel_gem_bo_map_gtt(region->buffer);
else
dri_bo_map(region->buffer, GL_TRUE);
region->map = region->buffer->virtual;
}
@@ -128,7 +131,10 @@ intel_region_unmap(struct intel_context *intel, struct intel_region *region)
{
_DBG("%s %p\n", __FUNCTION__, region);
if (!--region->map_refcount) {
dri_bo_unmap(region->buffer);
if (intel->intelScreen->kernel_exec_fencing)
drm_intel_gem_bo_map_gtt(region->buffer);
else
dri_bo_unmap(region->buffer);
region->map = NULL;
}
}
@@ -164,10 +170,12 @@ intel_region_alloc_internal(struct intel_context *intel,
struct intel_region *
intel_region_alloc(struct intel_context *intel,
uint32_t tiling,
GLuint cpp, GLuint width, GLuint height, GLuint pitch,
GLboolean expect_accelerated_upload)
{
dri_bo *buffer;
struct intel_region *region;
if (expect_accelerated_upload) {
buffer = drm_intel_bo_alloc_for_render(intel->bufmgr, "region",
@@ -177,7 +185,16 @@ intel_region_alloc(struct intel_context *intel,
pitch * cpp * height, 64);
}
return intel_region_alloc_internal(intel, cpp, width, height, pitch, buffer);
region = intel_region_alloc_internal(intel, cpp, width, height,
pitch, buffer);
if (tiling != I915_TILING_NONE) {
assert(((pitch * cpp) & 511) == 0);
drm_intel_bo_set_tiling(buffer, &tiling, pitch * cpp);
drm_intel_bo_get_tiling(buffer, &region->tiling, &region->bit_6_swizzle);
}
return region;
}
struct intel_region *

View File

@@ -73,7 +73,8 @@ struct intel_region
* copied by calling intel_reference_region().
*/
struct intel_region *intel_region_alloc(struct intel_context *intel,
GLuint cpp, GLuint width,
uint32_t tiling,
GLuint cpp, GLuint width,
GLuint height, GLuint pitch,
GLboolean expect_accelerated_upload);

View File

@@ -49,6 +49,10 @@
#include "i915_drm.h"
#include "i830_dri.h"
#define DRI_CONF_TEXTURE_TILING(def) \
DRI_CONF_OPT_BEGIN(texture_tiling, bool, def) \
DRI_CONF_DESC(en, "Enable texture tiling") \
DRI_CONF_OPT_END \
PUBLIC const char __driConfigOptions[] =
DRI_CONF_BEGIN
@@ -64,6 +68,13 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_ENUM(1, "Enable reuse of all sizes of buffer objects")
DRI_CONF_DESC_END
DRI_CONF_OPT_END
#ifdef I915
DRI_CONF_TEXTURE_TILING(false)
#else
DRI_CONF_TEXTURE_TILING(true)
#endif
DRI_CONF_SECTION_END
DRI_CONF_SECTION_QUALITY
DRI_CONF_FORCE_S3TC_ENABLE(false)
@@ -76,7 +87,7 @@ PUBLIC const char __driConfigOptions[] =
DRI_CONF_SECTION_END
DRI_CONF_END;
const GLuint __driNConfigOptions = 8;
const GLuint __driNConfigOptions = 9;
#ifdef USE_NEW_INTERFACE
static PFNGLXCREATECONTEXTMODES create_context_modes = NULL;

View File

@@ -118,8 +118,12 @@ do_copy_texsubimage(struct intel_context *intel,
dstx += x - orig_x;
dsty += y - orig_y;
/* image_offset may be non-page-aligned, but that's illegal for tiling. */
assert(intelImage->mt->region->tiling == I915_TILING_NONE);
/* Can't blit to tiled buffers with non-tile-aligned offset. */
if (intelImage->mt->region->tiling != I915_TILING_NONE &&
(image_offset & 4095) != 0) {
UNLOCK_HARDWARE(intel);
return GL_FALSE;
}
if (ctx->ReadBuffer->Name == 0) {
/* reading from a window, adjust x, y */

View File

@@ -52,7 +52,9 @@ GLuint intel_compressed_alignment(GLenum internalFormat)
return alignment;
}
void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt )
void i945_miptree_layout_2d( struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling )
{
GLint align_h = 2, align_w = 4;
GLuint level;
@@ -86,13 +88,18 @@ void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tr
if (mip1_width > mt->pitch) {
mt->pitch = mip1_width;
if (tiling == I915_TILING_X)
mt->pitch = ALIGN(mt->pitch * mt->cpp, 512) / mt->cpp;
if (tiling == I915_TILING_Y)
mt->pitch = ALIGN(mt->pitch * mt->cpp, 128) / mt->cpp;
}
}
/* Pitch must be a whole number of dwords, even though we
* express it in texels.
*/
mt->pitch = intel_miptree_pitch_align (intel, mt, mt->pitch);
mt->pitch = intel_miptree_pitch_align (intel, mt, tiling, mt->pitch);
mt->total_height = 0;
for ( level = mt->first_level ; level <= mt->last_level ; level++ ) {

View File

@@ -38,5 +38,7 @@ static GLuint minify( GLuint d )
return MAX2(1, d>>1);
}
extern void i945_miptree_layout_2d( struct intel_context *intel, struct intel_mipmap_tree *mt );
extern void i945_miptree_layout_2d(struct intel_context *intel,
struct intel_mipmap_tree *mt,
uint32_t tiling);
extern GLuint intel_compressed_alignment(GLenum);