r300_texture_desc.c revision d0408cf55d9e8d1d376bd844386ef5c9789a3597
1/* 2 * Copyright 2008 Corbin Simpson <MostAwesomeDude@gmail.com> 3 * Copyright 2010 Marek Olšák <maraeo@gmail.com> 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * on the rights to use, copy, modify, merge, publish, distribute, sub 9 * license, and/or sell copies of the Software, and to permit persons to whom 10 * the Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice (including the next 13 * paragraph) shall be included in all copies or substantial portions of the 14 * Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 18 * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL 19 * THE AUTHOR(S) AND/OR THEIR SUPPLIERS BE LIABLE FOR ANY CLAIM, 20 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 21 * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 22 * USE OR OTHER DEALINGS IN THE SOFTWARE. */ 23 24#include "r300_texture_desc.h" 25 26#include "r300_context.h" 27#include "r300_winsys.h" 28 29#include "util/u_format.h" 30 31/* Returns the number of pixels that the texture should be aligned to 32 * in the given dimension. */ 33unsigned r300_get_pixel_alignment(enum pipe_format format, 34 unsigned num_samples, 35 enum r300_buffer_tiling microtile, 36 enum r300_buffer_tiling macrotile, 37 enum r300_dim dim) 38{ 39 static const unsigned table[2][5][3][2] = 40 { 41 { 42 /* Macro: linear linear linear 43 Micro: linear tiled square-tiled */ 44 {{ 32, 1}, { 8, 4}, { 0, 0}}, /* 8 bits per pixel */ 45 {{ 16, 1}, { 8, 2}, { 4, 4}}, /* 16 bits per pixel */ 46 {{ 8, 1}, { 4, 2}, { 0, 0}}, /* 32 bits per pixel */ 47 {{ 4, 1}, { 2, 2}, { 0, 0}}, /* 64 bits per pixel */ 48 {{ 2, 1}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ 49 }, 50 { 51 /* Macro: tiled tiled tiled 52 Micro: linear tiled square-tiled */ 53 {{256, 8}, {64, 32}, { 0, 0}}, /* 8 bits per pixel */ 54 {{128, 8}, {64, 16}, {32, 32}}, /* 16 bits per pixel */ 55 {{ 64, 8}, {32, 16}, { 0, 0}}, /* 32 bits per pixel */ 56 {{ 32, 8}, {16, 16}, { 0, 0}}, /* 64 bits per pixel */ 57 {{ 16, 8}, { 0, 0}, { 0, 0}} /* 128 bits per pixel */ 58 } 59 }; 60 static const unsigned aa_block[2] = {4, 8}; 61 unsigned tile = 0; 62 unsigned pixsize = util_format_get_blocksize(format); 63 64 assert(macrotile <= R300_BUFFER_TILED); 65 assert(microtile <= R300_BUFFER_SQUARETILED); 66 assert(pixsize <= 16); 67 assert(dim <= DIM_HEIGHT); 68 69 if (num_samples > 1) { 70 /* Multisampled textures have their own alignment scheme. */ 71 if (pixsize == 4) 72 tile = aa_block[dim]; 73 /* XXX FP16 AA. */ 74 } else { 75 /* Standard alignment. */ 76 tile = table[macrotile][util_logbase2(pixsize)][microtile][dim]; 77 } 78 79 assert(tile); 80 return tile; 81} 82 83/* Return true if macrotiling should be enabled on the miplevel. */ 84static boolean r300_texture_macro_switch(struct r300_texture_desc *desc, 85 unsigned level, 86 boolean rv350_mode, 87 enum r300_dim dim) 88{ 89 unsigned tile, texdim; 90 91 tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, 92 desc->microtile, R300_BUFFER_TILED, dim); 93 if (dim == DIM_WIDTH) { 94 texdim = u_minify(desc->width0, level); 95 } else { 96 texdim = u_minify(desc->height0, level); 97 } 98 99 /* See TX_FILTER1_n.MACRO_SWITCH. */ 100 if (rv350_mode) { 101 return texdim >= tile; 102 } else { 103 return texdim > tile; 104 } 105} 106 107/** 108 * Return the stride, in bytes, of the texture image of the given texture 109 * at the given level. 110 */ 111static unsigned r300_texture_get_stride(struct r300_screen *screen, 112 struct r300_texture_desc *desc, 113 unsigned level) 114{ 115 unsigned tile_width, width, stride; 116 117 if (desc->stride_in_bytes_override) 118 return desc->stride_in_bytes_override; 119 120 /* Check the level. */ 121 if (level > desc->b.b.last_level) { 122 SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", 123 __FUNCTION__, level, desc->b.b.last_level); 124 return 0; 125 } 126 127 width = u_minify(desc->width0, level); 128 129 if (util_format_is_plain(desc->b.b.format)) { 130 tile_width = r300_get_pixel_alignment(desc->b.b.format, 131 desc->b.b.nr_samples, 132 desc->microtile, 133 desc->macrotile[level], 134 DIM_WIDTH); 135 width = align(width, tile_width); 136 137 stride = util_format_get_stride(desc->b.b.format, width); 138 139 /* Some IGPs need a minimum stride of 64 bytes, hmm... */ 140 if (!desc->macrotile[level] && 141 (screen->caps.family == CHIP_FAMILY_RS600 || 142 screen->caps.family == CHIP_FAMILY_RS690 || 143 screen->caps.family == CHIP_FAMILY_RS740)) { 144 unsigned min_stride; 145 146 if (desc->microtile) { 147 unsigned tile_height = 148 r300_get_pixel_alignment(desc->b.b.format, 149 desc->b.b.nr_samples, 150 desc->microtile, 151 desc->macrotile[level], 152 DIM_HEIGHT); 153 154 min_stride = 64 / tile_height; 155 } else { 156 min_stride = 64; 157 } 158 159 return stride < min_stride ? min_stride : stride; 160 } 161 162 /* The alignment to 32 bytes is sort of implied by the layout... */ 163 return stride; 164 } else { 165 return align(util_format_get_stride(desc->b.b.format, width), 32); 166 } 167} 168 169static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, 170 unsigned level, 171 boolean *out_aligned_for_cbzb) 172{ 173 unsigned height, tile_height; 174 175 height = u_minify(desc->height0, level); 176 177 if (util_format_is_plain(desc->b.b.format)) { 178 tile_height = r300_get_pixel_alignment(desc->b.b.format, 179 desc->b.b.nr_samples, 180 desc->microtile, 181 desc->macrotile[level], 182 DIM_HEIGHT); 183 height = align(height, tile_height); 184 185 /* This is needed for the kernel checker, unfortunately. */ 186 if ((desc->b.b.target != PIPE_TEXTURE_1D && 187 desc->b.b.target != PIPE_TEXTURE_2D && 188 desc->b.b.target != PIPE_TEXTURE_RECT) || 189 desc->b.b.last_level != 0) { 190 height = util_next_power_of_two(height); 191 } 192 193 /* See if the CBZB clear can be used on the buffer, 194 * taking the texture size into account. */ 195 if (out_aligned_for_cbzb) { 196 if (desc->macrotile[level]) { 197 /* When clearing, the layer (width*height) is horizontally split 198 * into two, and the upper and lower halves are cleared by the CB 199 * and ZB units, respectively. Therefore, the number of macrotiles 200 * in the Y direction must be even. */ 201 202 /* Align the height so that there is an even number of macrotiles. 203 * Do so for 3 or more macrotiles in the Y direction. */ 204 if (level == 0 && desc->b.b.last_level == 0 && 205 (desc->b.b.target == PIPE_TEXTURE_1D || 206 desc->b.b.target == PIPE_TEXTURE_2D || 207 desc->b.b.target == PIPE_TEXTURE_RECT) && 208 height >= tile_height * 3) { 209 height = align(height, tile_height * 2); 210 } 211 212 *out_aligned_for_cbzb = height % (tile_height * 2) == 0; 213 } else { 214 *out_aligned_for_cbzb = FALSE; 215 } 216 } 217 } 218 219 return util_format_get_nblocksy(desc->b.b.format, height); 220} 221 222static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, 223 struct r300_texture_desc *desc) 224{ 225 /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures 226 * incorrectly. This is a workaround to prevent CS from being rejected. */ 227 228 unsigned i, size; 229 230 if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) && 231 desc->b.b.target == PIPE_TEXTURE_3D && 232 desc->b.b.last_level > 0) { 233 size = 0; 234 235 for (i = 0; i <= desc->b.b.last_level; i++) { 236 size += desc->stride_in_bytes[i] * 237 r300_texture_get_nblocksy(desc, i, FALSE); 238 } 239 240 size *= desc->depth0; 241 desc->size_in_bytes = size; 242 } 243} 244 245/* Get a width in pixels from a stride in bytes. */ 246static unsigned stride_to_width(enum pipe_format format, 247 unsigned stride_in_bytes) 248{ 249 return (stride_in_bytes / util_format_get_blocksize(format)) * 250 util_format_get_blockwidth(format); 251} 252 253static void r300_setup_miptree(struct r300_screen *screen, 254 struct r300_texture_desc *desc, 255 boolean align_for_cbzb) 256{ 257 struct pipe_resource *base = &desc->b.b; 258 unsigned stride, size, layer_size, nblocksy, i; 259 boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; 260 boolean aligned_for_cbzb; 261 262 desc->size_in_bytes = 0; 263 264 SCREEN_DBG(screen, DBG_TEXALLOC, 265 "r300: Making miptree for texture, format %s\n", 266 util_format_short_name(base->format)); 267 268 for (i = 0; i <= base->last_level; i++) { 269 /* Let's see if this miplevel can be macrotiled. */ 270 desc->macrotile[i] = 271 (desc->macrotile[0] == R300_BUFFER_TILED && 272 r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) && 273 r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ? 274 R300_BUFFER_TILED : R300_BUFFER_LINEAR; 275 276 stride = r300_texture_get_stride(screen, desc, i); 277 278 /* Compute the number of blocks in Y, see if the CBZB clear can be 279 * used on the texture. */ 280 aligned_for_cbzb = FALSE; 281 if (align_for_cbzb && desc->cbzb_allowed[i]) 282 nblocksy = r300_texture_get_nblocksy(desc, i, &aligned_for_cbzb); 283 else 284 nblocksy = r300_texture_get_nblocksy(desc, i, NULL); 285 286 layer_size = stride * nblocksy; 287 288 if (base->nr_samples) { 289 layer_size *= base->nr_samples; 290 } 291 292 if (base->target == PIPE_TEXTURE_CUBE) 293 size = layer_size * 6; 294 else 295 size = layer_size * u_minify(desc->depth0, i); 296 297 desc->offset_in_bytes[i] = desc->size_in_bytes; 298 desc->size_in_bytes = desc->offset_in_bytes[i] + size; 299 desc->layer_size_in_bytes[i] = layer_size; 300 desc->stride_in_bytes[i] = stride; 301 desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride); 302 desc->cbzb_allowed[i] = desc->cbzb_allowed[i] && aligned_for_cbzb; 303 304 SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " 305 "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", 306 i, u_minify(desc->width0, i), u_minify(desc->height0, i), 307 u_minify(desc->depth0, i), stride, desc->size_in_bytes, 308 desc->macrotile[i] ? "TRUE" : "FALSE"); 309 } 310} 311 312static void r300_setup_flags(struct r300_texture_desc *desc) 313{ 314 desc->uses_stride_addressing = 315 !util_is_power_of_two(desc->b.b.width0) || 316 (desc->stride_in_bytes_override && 317 stride_to_width(desc->b.b.format, 318 desc->stride_in_bytes_override) != desc->b.b.width0); 319 320 desc->is_npot = 321 desc->uses_stride_addressing || 322 !util_is_power_of_two(desc->b.b.height0) || 323 !util_is_power_of_two(desc->b.b.depth0); 324} 325 326static void r300_setup_cbzb_flags(struct r300_screen *rscreen, 327 struct r300_texture_desc *desc) 328{ 329 unsigned i, bpp; 330 boolean first_level_valid; 331 332 bpp = util_format_get_blocksizebits(desc->b.b.format); 333 334 /* 1) The texture must be point-sampled, 335 * 2) The depth must be 16 or 32 bits. 336 * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage 337 * with certain texture sizes. Macrotiling ensures the alignment. */ 338 first_level_valid = desc->b.b.nr_samples <= 1 && 339 (bpp == 16 || bpp == 32) && 340 desc->macrotile[0]; 341 342 if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) 343 first_level_valid = FALSE; 344 345 for (i = 0; i <= desc->b.b.last_level; i++) 346 desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i]; 347} 348 349static void r300_setup_tiling(struct r300_screen *screen, 350 struct r300_texture_desc *desc) 351{ 352 struct r300_winsys_screen *rws = screen->rws; 353 enum pipe_format format = desc->b.b.format; 354 boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; 355 boolean is_zb = util_format_is_depth_or_stencil(format); 356 boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); 357 358 if (!util_format_is_plain(format)) { 359 return; 360 } 361 362 /* If height == 1, disable microtiling except for zbuffer. */ 363 if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) { 364 return; 365 } 366 367 /* Set microtiling. */ 368 switch (util_format_get_blocksize(format)) { 369 case 1: 370 case 4: 371 case 8: 372 desc->microtile = R300_BUFFER_TILED; 373 break; 374 375 case 2: 376 if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { 377 desc->microtile = R300_BUFFER_SQUARETILED; 378 } 379 break; 380 } 381 382 if (dbg_no_tiling) { 383 return; 384 } 385 386 /* Set macrotiling. */ 387 if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) && 388 r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) { 389 desc->macrotile[0] = R300_BUFFER_TILED; 390 } 391} 392 393static void r300_tex_print_info(struct r300_screen *rscreen, 394 struct r300_texture_desc *desc, 395 const char *func) 396{ 397 fprintf(stderr, 398 "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, " 399 "LastLevel: %i, Size: %i, Format: %s\n", 400 func, 401 desc->macrotile[0] ? "YES" : " NO", 402 desc->microtile ? "YES" : " NO", 403 desc->stride_in_pixels[0], 404 desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0, 405 desc->b.b.last_level, desc->size_in_bytes, 406 util_format_short_name(desc->b.b.format)); 407} 408 409boolean r300_texture_desc_init(struct r300_screen *rscreen, 410 struct r300_texture_desc *desc, 411 const struct pipe_resource *base, 412 enum r300_buffer_tiling microtile, 413 enum r300_buffer_tiling macrotile, 414 unsigned stride_in_bytes_override, 415 unsigned max_buffer_size) 416{ 417 desc->b.b = *base; 418 desc->b.b.screen = &rscreen->screen; 419 desc->stride_in_bytes_override = stride_in_bytes_override; 420 desc->width0 = base->width0; 421 desc->height0 = base->height0; 422 desc->depth0 = base->depth0; 423 424 r300_setup_flags(desc); 425 426 /* Align a 3D NPOT texture to POT. */ 427 if (base->target == PIPE_TEXTURE_3D && desc->is_npot) { 428 desc->width0 = util_next_power_of_two(desc->width0); 429 desc->height0 = util_next_power_of_two(desc->height0); 430 desc->depth0 = util_next_power_of_two(desc->depth0); 431 } 432 433 /* Setup tiling. */ 434 if (microtile == R300_BUFFER_SELECT_LAYOUT || 435 macrotile == R300_BUFFER_SELECT_LAYOUT) { 436 r300_setup_tiling(rscreen, desc); 437 } else { 438 desc->microtile = microtile; 439 desc->macrotile[0] = macrotile; 440 assert(desc->b.b.last_level == 0); 441 } 442 443 r300_setup_cbzb_flags(rscreen, desc); 444 445 /* Setup the miptree description. */ 446 r300_setup_miptree(rscreen, desc, TRUE); 447 /* If the required buffer size is larger the given max size, 448 * try again without the alignment for the CBZB clear. */ 449 if (max_buffer_size && desc->size_in_bytes > max_buffer_size) { 450 r300_setup_miptree(rscreen, desc, FALSE); 451 } 452 453 r300_texture_3d_fix_mipmapping(rscreen, desc); 454 455 if (max_buffer_size) { 456 /* Make sure the buffer we got is large enough. */ 457 if (desc->size_in_bytes > max_buffer_size) { 458 fprintf(stderr, "r300: texture_desc_init: The buffer is not " 459 "large enough. Got: %i, Need: %i, Info:\n", 460 max_buffer_size, desc->size_in_bytes); 461 r300_tex_print_info(rscreen, desc, "texture_desc_init"); 462 return FALSE; 463 } 464 465 desc->buffer_size_in_bytes = max_buffer_size; 466 } else { 467 desc->buffer_size_in_bytes = desc->size_in_bytes; 468 } 469 470 if (SCREEN_DBG_ON(rscreen, DBG_TEX)) 471 r300_tex_print_info(rscreen, desc, "texture_desc_init"); 472 473 return TRUE; 474} 475 476unsigned r300_texture_get_offset(struct r300_texture_desc *desc, 477 unsigned level, unsigned zslice, 478 unsigned face) 479{ 480 unsigned offset = desc->offset_in_bytes[level]; 481 482 switch (desc->b.b.target) { 483 case PIPE_TEXTURE_3D: 484 assert(face == 0); 485 return offset + zslice * desc->layer_size_in_bytes[level]; 486 487 case PIPE_TEXTURE_CUBE: 488 assert(zslice == 0); 489 return offset + face * desc->layer_size_in_bytes[level]; 490 491 default: 492 assert(zslice == 0 && face == 0); 493 return offset; 494 } 495} 496