r300_texture_desc.c revision 56ba7e913fef0ea2b1bead582108f9ab3ab8263d
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, boolean is_rs690) 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 61 static const unsigned aa_block[2] = {4, 8}; 62 unsigned tile = 0; 63 unsigned pixsize = util_format_get_blocksize(format); 64 65 assert(macrotile <= R300_BUFFER_TILED); 66 assert(microtile <= R300_BUFFER_SQUARETILED); 67 assert(pixsize <= 16); 68 assert(dim <= DIM_HEIGHT); 69 70 if (num_samples > 1) { 71 /* Multisampled textures have their own alignment scheme. */ 72 if (pixsize == 4) 73 tile = aa_block[dim]; 74 /* XXX FP16 AA. */ 75 } else { 76 /* Standard alignment. */ 77 tile = table[macrotile][util_logbase2(pixsize)][microtile][dim]; 78 if (macrotile == 0 && is_rs690 && dim == DIM_WIDTH) { 79 int align; 80 int h_tile; 81 h_tile = table[macrotile][util_logbase2(pixsize)][microtile][DIM_HEIGHT]; 82 align = 64 / (pixsize * h_tile); 83 if (tile < align) 84 tile = align; 85 } 86 } 87 88 assert(tile); 89 return tile; 90} 91 92/* Return true if macrotiling should be enabled on the miplevel. */ 93static boolean r300_texture_macro_switch(struct r300_resource *tex, 94 unsigned level, 95 boolean rv350_mode, 96 enum r300_dim dim) 97{ 98 unsigned tile, texdim; 99 100 tile = r300_get_pixel_alignment(tex->b.b.b.format, tex->b.b.b.nr_samples, 101 tex->tex.microtile, R300_BUFFER_TILED, dim, 0); 102 if (dim == DIM_WIDTH) { 103 texdim = u_minify(tex->tex.width0, level); 104 } else { 105 texdim = u_minify(tex->tex.height0, level); 106 } 107 108 /* See TX_FILTER1_n.MACRO_SWITCH. */ 109 if (rv350_mode) { 110 return texdim >= tile; 111 } else { 112 return texdim > tile; 113 } 114} 115 116/** 117 * Return the stride, in bytes, of the texture image of the given texture 118 * at the given level. 119 */ 120static unsigned r300_texture_get_stride(struct r300_screen *screen, 121 struct r300_resource *tex, 122 unsigned level) 123{ 124 unsigned tile_width, width, stride; 125 boolean is_rs690 = (screen->caps.family == CHIP_FAMILY_RS600 || 126 screen->caps.family == CHIP_FAMILY_RS690 || 127 screen->caps.family == CHIP_FAMILY_RS740); 128 129 if (tex->tex.stride_in_bytes_override) 130 return tex->tex.stride_in_bytes_override; 131 132 /* Check the level. */ 133 if (level > tex->b.b.b.last_level) { 134 SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", 135 __FUNCTION__, level, tex->b.b.b.last_level); 136 return 0; 137 } 138 139 width = u_minify(tex->tex.width0, level); 140 141 if (util_format_is_plain(tex->b.b.b.format)) { 142 tile_width = r300_get_pixel_alignment(tex->b.b.b.format, 143 tex->b.b.b.nr_samples, 144 tex->tex.microtile, 145 tex->tex.macrotile[level], 146 DIM_WIDTH, is_rs690); 147 width = align(width, tile_width); 148 149 stride = util_format_get_stride(tex->b.b.b.format, width); 150 /* The alignment to 32 bytes is sort of implied by the layout... */ 151 return stride; 152 } else { 153 return align(util_format_get_stride(tex->b.b.b.format, width), is_rs690 ? 64 : 32); 154 } 155} 156 157static unsigned r300_texture_get_nblocksy(struct r300_resource *tex, 158 unsigned level, 159 boolean *out_aligned_for_cbzb) 160{ 161 unsigned height, tile_height; 162 163 height = u_minify(tex->tex.height0, level); 164 165 if (util_format_is_plain(tex->b.b.b.format)) { 166 tile_height = r300_get_pixel_alignment(tex->b.b.b.format, 167 tex->b.b.b.nr_samples, 168 tex->tex.microtile, 169 tex->tex.macrotile[level], 170 DIM_HEIGHT, 0); 171 height = align(height, tile_height); 172 173 /* This is needed for the kernel checker, unfortunately. */ 174 if ((tex->b.b.b.target != PIPE_TEXTURE_1D && 175 tex->b.b.b.target != PIPE_TEXTURE_2D && 176 tex->b.b.b.target != PIPE_TEXTURE_RECT) || 177 tex->b.b.b.last_level != 0) { 178 height = util_next_power_of_two(height); 179 } 180 181 /* See if the CBZB clear can be used on the buffer, 182 * taking the texture size into account. */ 183 if (out_aligned_for_cbzb) { 184 if (tex->tex.macrotile[level]) { 185 /* When clearing, the layer (width*height) is horizontally split 186 * into two, and the upper and lower halves are cleared by the CB 187 * and ZB units, respectively. Therefore, the number of macrotiles 188 * in the Y direction must be even. */ 189 190 /* Align the height so that there is an even number of macrotiles. 191 * Do so for 3 or more macrotiles in the Y direction. */ 192 if (level == 0 && tex->b.b.b.last_level == 0 && 193 (tex->b.b.b.target == PIPE_TEXTURE_1D || 194 tex->b.b.b.target == PIPE_TEXTURE_2D || 195 tex->b.b.b.target == PIPE_TEXTURE_RECT) && 196 height >= tile_height * 3) { 197 height = align(height, tile_height * 2); 198 } 199 200 *out_aligned_for_cbzb = height % (tile_height * 2) == 0; 201 } else { 202 *out_aligned_for_cbzb = FALSE; 203 } 204 } 205 } 206 207 return util_format_get_nblocksy(tex->b.b.b.format, height); 208} 209 210static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, 211 struct r300_resource *tex) 212{ 213 /* The kernels <= 2.6.34-rc4 compute the size of mipmapped 3D textures 214 * incorrectly. This is a workaround to prevent CS from being rejected. */ 215 216 unsigned i, size; 217 218 if (!screen->rws->get_value(screen->rws, R300_VID_DRM_2_3_0) && 219 tex->b.b.b.target == PIPE_TEXTURE_3D && 220 tex->b.b.b.last_level > 0) { 221 size = 0; 222 223 for (i = 0; i <= tex->b.b.b.last_level; i++) { 224 size += tex->tex.stride_in_bytes[i] * 225 r300_texture_get_nblocksy(tex, i, FALSE); 226 } 227 228 size *= tex->tex.depth0; 229 tex->tex.size_in_bytes = size; 230 } 231} 232 233/* Get a width in pixels from a stride in bytes. */ 234static unsigned stride_to_width(enum pipe_format format, 235 unsigned stride_in_bytes) 236{ 237 return (stride_in_bytes / util_format_get_blocksize(format)) * 238 util_format_get_blockwidth(format); 239} 240 241static void r300_setup_miptree(struct r300_screen *screen, 242 struct r300_resource *tex, 243 boolean align_for_cbzb) 244{ 245 struct pipe_resource *base = &tex->b.b.b; 246 unsigned stride, size, layer_size, nblocksy, i; 247 boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; 248 boolean aligned_for_cbzb; 249 250 tex->tex.size_in_bytes = 0; 251 252 SCREEN_DBG(screen, DBG_TEXALLOC, 253 "r300: Making miptree for texture, format %s\n", 254 util_format_short_name(base->format)); 255 256 for (i = 0; i <= base->last_level; i++) { 257 /* Let's see if this miplevel can be macrotiled. */ 258 tex->tex.macrotile[i] = 259 (tex->tex.macrotile[0] == R300_BUFFER_TILED && 260 r300_texture_macro_switch(tex, i, rv350_mode, DIM_WIDTH) && 261 r300_texture_macro_switch(tex, i, rv350_mode, DIM_HEIGHT)) ? 262 R300_BUFFER_TILED : R300_BUFFER_LINEAR; 263 264 stride = r300_texture_get_stride(screen, tex, i); 265 266 /* Compute the number of blocks in Y, see if the CBZB clear can be 267 * used on the texture. */ 268 aligned_for_cbzb = FALSE; 269 if (align_for_cbzb && tex->tex.cbzb_allowed[i]) 270 nblocksy = r300_texture_get_nblocksy(tex, i, &aligned_for_cbzb); 271 else 272 nblocksy = r300_texture_get_nblocksy(tex, i, NULL); 273 274 layer_size = stride * nblocksy; 275 276 if (base->nr_samples) { 277 layer_size *= base->nr_samples; 278 } 279 280 if (base->target == PIPE_TEXTURE_CUBE) 281 size = layer_size * 6; 282 else 283 size = layer_size * u_minify(tex->tex.depth0, i); 284 285 tex->tex.offset_in_bytes[i] = tex->tex.size_in_bytes; 286 tex->tex.size_in_bytes = tex->tex.offset_in_bytes[i] + size; 287 tex->tex.layer_size_in_bytes[i] = layer_size; 288 tex->tex.stride_in_bytes[i] = stride; 289 tex->tex.stride_in_pixels[i] = stride_to_width(tex->b.b.b.format, stride); 290 tex->tex.cbzb_allowed[i] = tex->tex.cbzb_allowed[i] && aligned_for_cbzb; 291 292 SCREEN_DBG(screen, DBG_TEXALLOC, "r300: Texture miptree: Level %d " 293 "(%dx%dx%d px, pitch %d bytes) %d bytes total, macrotiled %s\n", 294 i, u_minify(tex->tex.width0, i), u_minify(tex->tex.height0, i), 295 u_minify(tex->tex.depth0, i), stride, tex->tex.size_in_bytes, 296 tex->tex.macrotile[i] ? "TRUE" : "FALSE"); 297 } 298} 299 300static void r300_setup_flags(struct r300_resource *tex) 301{ 302 tex->tex.uses_stride_addressing = 303 !util_is_power_of_two(tex->b.b.b.width0) || 304 (tex->tex.stride_in_bytes_override && 305 stride_to_width(tex->b.b.b.format, 306 tex->tex.stride_in_bytes_override) != tex->b.b.b.width0); 307 308 tex->tex.is_npot = 309 tex->tex.uses_stride_addressing || 310 !util_is_power_of_two(tex->b.b.b.height0) || 311 !util_is_power_of_two(tex->b.b.b.depth0); 312} 313 314static void r300_setup_cbzb_flags(struct r300_screen *rscreen, 315 struct r300_resource *tex) 316{ 317 unsigned i, bpp; 318 boolean first_level_valid; 319 320 bpp = util_format_get_blocksizebits(tex->b.b.b.format); 321 322 /* 1) The texture must be point-sampled, 323 * 2) The depth must be 16 or 32 bits. 324 * 3) If the midpoint ZB offset is not aligned to 2048, it returns garbage 325 * with certain texture sizes. Macrotiling ensures the alignment. */ 326 first_level_valid = tex->b.b.b.nr_samples <= 1 && 327 (bpp == 16 || bpp == 32) && 328 tex->tex.macrotile[0]; 329 330 if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) 331 first_level_valid = FALSE; 332 333 for (i = 0; i <= tex->b.b.b.last_level; i++) 334 tex->tex.cbzb_allowed[i] = first_level_valid && tex->tex.macrotile[i]; 335} 336 337#define ALIGN_DIVUP(x, y) (((x) + (y) - 1) / (y)) 338 339static void r300_setup_zmask_flags(struct r300_screen *screen, 340 struct r300_resource *tex) 341{ 342 /* The tile size of 1 DWORD is: 343 * 344 * GPU Pipes 4x4 mode 8x8 mode 345 * ------------------------------------------ 346 * R580 4P/1Z 32x32 64x64 347 * RV570 3P/1Z 48x16 96x32 348 * RV530 1P/2Z 32x16 64x32 349 * 1P/1Z 16x16 32x32 350 */ 351 static unsigned num_blocks_x_per_dw[4] = {4, 8, 12, 8}; 352 static unsigned num_blocks_y_per_dw[4] = {4, 4, 4, 8}; 353 354 if (util_format_is_depth_or_stencil(tex->b.b.b.format) && 355 util_format_get_blocksizebits(tex->b.b.b.format) == 32 && 356 tex->tex.microtile) { 357 unsigned i, pipes; 358 359 if (screen->caps.family == CHIP_FAMILY_RV530) { 360 pipes = screen->caps.num_z_pipes; 361 } else { 362 pipes = screen->caps.num_frag_pipes; 363 } 364 365 for (i = 0; i <= tex->b.b.b.last_level; i++) { 366 unsigned numdw, compsize; 367 368 /* The 8x8 compression mode needs macrotiling. */ 369 compsize = screen->caps.z_compress == R300_ZCOMP_8X8 && 370 tex->tex.macrotile[i] && 371 tex->b.b.b.nr_samples <= 1 ? 8 : 4; 372 373 /* Get the zbuffer size (with the aligned width and height). */ 374 numdw = align(tex->tex.stride_in_pixels[i], 375 num_blocks_x_per_dw[pipes-1] * compsize) * 376 align(u_minify(tex->b.b.b.height0, i), 377 num_blocks_y_per_dw[pipes-1] * compsize); 378 379 /* Convert pixels -> dwords. */ 380 numdw = ALIGN_DIVUP(numdw, num_blocks_x_per_dw[pipes-1] * compsize * 381 num_blocks_y_per_dw[pipes-1] * compsize); 382 383 /* Check that we have enough ZMASK memory. */ 384 if (numdw <= screen->caps.zmask_ram * pipes) { 385 tex->tex.zmask_dwords[i] = numdw; 386 tex->tex.zcomp8x8[i] = compsize == 8; 387 } else { 388 tex->tex.zmask_dwords[i] = 0; 389 tex->tex.zcomp8x8[i] = FALSE; 390 } 391 } 392 } 393} 394 395static void r300_setup_tiling(struct r300_screen *screen, 396 struct r300_resource *tex) 397{ 398 struct r300_winsys_screen *rws = screen->rws; 399 enum pipe_format format = tex->b.b.b.format; 400 boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; 401 boolean is_zb = util_format_is_depth_or_stencil(format); 402 boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); 403 404 if (!util_format_is_plain(format)) { 405 return; 406 } 407 408 /* If height == 1, disable microtiling except for zbuffer. */ 409 if (!is_zb && (tex->b.b.b.height0 == 1 || dbg_no_tiling)) { 410 return; 411 } 412 413 /* Set microtiling. */ 414 switch (util_format_get_blocksize(format)) { 415 case 1: 416 case 4: 417 case 8: 418 tex->tex.microtile = R300_BUFFER_TILED; 419 break; 420 421 case 2: 422 if (rws->get_value(rws, R300_VID_DRM_2_1_0)) { 423 tex->tex.microtile = R300_BUFFER_SQUARETILED; 424 } 425 break; 426 } 427 428 if (dbg_no_tiling) { 429 return; 430 } 431 432 /* Set macrotiling. */ 433 if (r300_texture_macro_switch(tex, 0, rv350_mode, DIM_WIDTH) && 434 r300_texture_macro_switch(tex, 0, rv350_mode, DIM_HEIGHT)) { 435 tex->tex.macrotile[0] = R300_BUFFER_TILED; 436 } 437} 438 439static void r300_tex_print_info(struct r300_resource *tex, 440 const char *func) 441{ 442 fprintf(stderr, 443 "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, " 444 "LastLevel: %i, Size: %i, Format: %s\n", 445 func, 446 tex->tex.macrotile[0] ? "YES" : " NO", 447 tex->tex.microtile ? "YES" : " NO", 448 tex->tex.stride_in_pixels[0], 449 tex->b.b.b.width0, tex->b.b.b.height0, tex->b.b.b.depth0, 450 tex->b.b.b.last_level, tex->tex.size_in_bytes, 451 util_format_short_name(tex->b.b.b.format)); 452} 453 454boolean r300_texture_desc_init(struct r300_screen *rscreen, 455 struct r300_resource *tex, 456 const struct pipe_resource *base, 457 enum r300_buffer_tiling microtile, 458 enum r300_buffer_tiling macrotile, 459 unsigned stride_in_bytes_override, 460 unsigned max_buffer_size) 461{ 462 tex->b.b.b = *base; 463 tex->b.b.b.screen = &rscreen->screen; 464 tex->tex.stride_in_bytes_override = stride_in_bytes_override; 465 tex->tex.width0 = base->width0; 466 tex->tex.height0 = base->height0; 467 tex->tex.depth0 = base->depth0; 468 469 r300_setup_flags(tex); 470 471 /* Align a 3D NPOT texture to POT. */ 472 if (base->target == PIPE_TEXTURE_3D && tex->tex.is_npot) { 473 tex->tex.width0 = util_next_power_of_two(tex->tex.width0); 474 tex->tex.height0 = util_next_power_of_two(tex->tex.height0); 475 tex->tex.depth0 = util_next_power_of_two(tex->tex.depth0); 476 } 477 478 /* Setup tiling. */ 479 if (microtile == R300_BUFFER_SELECT_LAYOUT || 480 macrotile == R300_BUFFER_SELECT_LAYOUT) { 481 r300_setup_tiling(rscreen, tex); 482 } else { 483 tex->tex.microtile = microtile; 484 tex->tex.macrotile[0] = macrotile; 485 assert(tex->b.b.b.last_level == 0); 486 } 487 488 r300_setup_cbzb_flags(rscreen, tex); 489 490 /* Setup the miptree description. */ 491 r300_setup_miptree(rscreen, tex, TRUE); 492 /* If the required buffer size is larger the given max size, 493 * try again without the alignment for the CBZB clear. */ 494 if (max_buffer_size && tex->tex.size_in_bytes > max_buffer_size) { 495 r300_setup_miptree(rscreen, tex, FALSE); 496 } 497 498 r300_texture_3d_fix_mipmapping(rscreen, tex); 499 r300_setup_zmask_flags(rscreen, tex); 500 501 if (max_buffer_size) { 502 /* Make sure the buffer we got is large enough. */ 503 if (tex->tex.size_in_bytes > max_buffer_size) { 504 fprintf(stderr, "r300: texture_desc_init: The buffer is not " 505 "large enough. Got: %i, Need: %i, Info:\n", 506 max_buffer_size, tex->tex.size_in_bytes); 507 r300_tex_print_info(tex, "texture_desc_init"); 508 return FALSE; 509 } 510 511 tex->tex.buffer_size_in_bytes = max_buffer_size; 512 } else { 513 tex->tex.buffer_size_in_bytes = tex->tex.size_in_bytes; 514 } 515 516 if (SCREEN_DBG_ON(rscreen, DBG_TEX)) 517 r300_tex_print_info(tex, "texture_desc_init"); 518 519 return TRUE; 520} 521 522unsigned r300_texture_get_offset(struct r300_resource *tex, 523 unsigned level, unsigned layer) 524{ 525 unsigned offset = tex->tex.offset_in_bytes[level]; 526 527 switch (tex->b.b.b.target) { 528 case PIPE_TEXTURE_3D: 529 case PIPE_TEXTURE_CUBE: 530 return offset + layer * tex->tex.layer_size_in_bytes[level]; 531 532 default: 533 assert(layer == 0); 534 return offset; 535 } 536} 537