r300_texture_desc.c revision d19b5cbd317620f3977e68fffb7a74793436b7e2
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_texture_desc *desc, 94 unsigned level, 95 boolean rv350_mode, 96 enum r300_dim dim) 97{ 98 unsigned tile, texdim; 99 100 tile = r300_get_pixel_alignment(desc->b.b.format, desc->b.b.nr_samples, 101 desc->microtile, R300_BUFFER_TILED, dim, 0); 102 if (dim == DIM_WIDTH) { 103 texdim = u_minify(desc->width0, level); 104 } else { 105 texdim = u_minify(desc->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_texture_desc *desc, 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 (desc->stride_in_bytes_override) 130 return desc->stride_in_bytes_override; 131 132 /* Check the level. */ 133 if (level > desc->b.b.last_level) { 134 SCREEN_DBG(screen, DBG_TEX, "%s: level (%u) > last_level (%u)\n", 135 __FUNCTION__, level, desc->b.b.last_level); 136 return 0; 137 } 138 139 width = u_minify(desc->width0, level); 140 141 if (util_format_is_plain(desc->b.b.format)) { 142 tile_width = r300_get_pixel_alignment(desc->b.b.format, 143 desc->b.b.nr_samples, 144 desc->microtile, 145 desc->macrotile[level], 146 DIM_WIDTH, is_rs690); 147 width = align(width, tile_width); 148 149 stride = util_format_get_stride(desc->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(desc->b.b.format, width), is_rs690 ? 64 : 32); 154 } 155} 156 157static unsigned r300_texture_get_nblocksy(struct r300_texture_desc *desc, 158 unsigned level, 159 boolean *out_aligned_for_cbzb) 160{ 161 unsigned height, tile_height; 162 163 height = u_minify(desc->height0, level); 164 165 if (util_format_is_plain(desc->b.b.format)) { 166 tile_height = r300_get_pixel_alignment(desc->b.b.format, 167 desc->b.b.nr_samples, 168 desc->microtile, 169 desc->macrotile[level], 170 DIM_HEIGHT, 0); 171 height = align(height, tile_height); 172 173 /* This is needed for the kernel checker, unfortunately. */ 174 if ((desc->b.b.target != PIPE_TEXTURE_1D && 175 desc->b.b.target != PIPE_TEXTURE_2D && 176 desc->b.b.target != PIPE_TEXTURE_RECT) || 177 desc->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 (desc->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 && desc->b.b.last_level == 0 && 193 (desc->b.b.target == PIPE_TEXTURE_1D || 194 desc->b.b.target == PIPE_TEXTURE_2D || 195 desc->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(desc->b.b.format, height); 208} 209 210static void r300_texture_3d_fix_mipmapping(struct r300_screen *screen, 211 struct r300_texture_desc *desc) 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 desc->b.b.target == PIPE_TEXTURE_3D && 220 desc->b.b.last_level > 0) { 221 size = 0; 222 223 for (i = 0; i <= desc->b.b.last_level; i++) { 224 size += desc->stride_in_bytes[i] * 225 r300_texture_get_nblocksy(desc, i, FALSE); 226 } 227 228 size *= desc->depth0; 229 desc->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_texture_desc *desc, 243 boolean align_for_cbzb) 244{ 245 struct pipe_resource *base = &desc->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 desc->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 desc->macrotile[i] = 259 (desc->macrotile[0] == R300_BUFFER_TILED && 260 r300_texture_macro_switch(desc, i, rv350_mode, DIM_WIDTH) && 261 r300_texture_macro_switch(desc, i, rv350_mode, DIM_HEIGHT)) ? 262 R300_BUFFER_TILED : R300_BUFFER_LINEAR; 263 264 stride = r300_texture_get_stride(screen, desc, 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 && desc->cbzb_allowed[i]) 270 nblocksy = r300_texture_get_nblocksy(desc, i, &aligned_for_cbzb); 271 else 272 nblocksy = r300_texture_get_nblocksy(desc, 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(desc->depth0, i); 284 285 desc->offset_in_bytes[i] = desc->size_in_bytes; 286 desc->size_in_bytes = desc->offset_in_bytes[i] + size; 287 desc->layer_size_in_bytes[i] = layer_size; 288 desc->stride_in_bytes[i] = stride; 289 desc->stride_in_pixels[i] = stride_to_width(desc->b.b.format, stride); 290 desc->cbzb_allowed[i] = desc->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(desc->width0, i), u_minify(desc->height0, i), 295 u_minify(desc->depth0, i), stride, desc->size_in_bytes, 296 desc->macrotile[i] ? "TRUE" : "FALSE"); 297 } 298} 299 300static void r300_setup_flags(struct r300_texture_desc *desc) 301{ 302 desc->uses_stride_addressing = 303 !util_is_power_of_two(desc->b.b.width0) || 304 (desc->stride_in_bytes_override && 305 stride_to_width(desc->b.b.format, 306 desc->stride_in_bytes_override) != desc->b.b.width0); 307 308 desc->is_npot = 309 desc->uses_stride_addressing || 310 !util_is_power_of_two(desc->b.b.height0) || 311 !util_is_power_of_two(desc->b.b.depth0); 312} 313 314static void r300_setup_cbzb_flags(struct r300_screen *rscreen, 315 struct r300_texture_desc *desc) 316{ 317 unsigned i, bpp; 318 boolean first_level_valid; 319 320 bpp = util_format_get_blocksizebits(desc->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 = desc->b.b.nr_samples <= 1 && 327 (bpp == 16 || bpp == 32) && 328 desc->macrotile[0]; 329 330 if (SCREEN_DBG_ON(rscreen, DBG_NO_CBZB)) 331 first_level_valid = FALSE; 332 333 for (i = 0; i <= desc->b.b.last_level; i++) 334 desc->cbzb_allowed[i] = first_level_valid && desc->macrotile[i]; 335} 336 337static void r300_setup_tiling(struct r300_screen *screen, 338 struct r300_texture_desc *desc) 339{ 340 struct r300_winsys_screen *rws = screen->rws; 341 enum pipe_format format = desc->b.b.format; 342 boolean rv350_mode = screen->caps.family >= CHIP_FAMILY_R350; 343 boolean is_zb = util_format_is_depth_or_stencil(format); 344 boolean dbg_no_tiling = SCREEN_DBG_ON(screen, DBG_NO_TILING); 345 346 if (!util_format_is_plain(format)) { 347 return; 348 } 349 350 /* If height == 1, disable microtiling except for zbuffer. */ 351 if (!is_zb && (desc->b.b.height0 == 1 || dbg_no_tiling)) { 352 return; 353 } 354 355 /* Set microtiling. */ 356 switch (util_format_get_blocksize(format)) { 357 case 1: 358 case 4: 359 case 8: 360 desc->microtile = R300_BUFFER_TILED; 361 break; 362 363 case 2: 364 if (rws->get_value(rws, R300_VID_SQUARE_TILING_SUPPORT)) { 365 desc->microtile = R300_BUFFER_SQUARETILED; 366 } 367 break; 368 } 369 370 if (dbg_no_tiling) { 371 return; 372 } 373 374 /* Set macrotiling. */ 375 if (r300_texture_macro_switch(desc, 0, rv350_mode, DIM_WIDTH) && 376 r300_texture_macro_switch(desc, 0, rv350_mode, DIM_HEIGHT)) { 377 desc->macrotile[0] = R300_BUFFER_TILED; 378 } 379} 380 381static void r300_tex_print_info(struct r300_screen *rscreen, 382 struct r300_texture_desc *desc, 383 const char *func) 384{ 385 fprintf(stderr, 386 "r300: %s: Macro: %s, Micro: %s, Pitch: %i, Dim: %ix%ix%i, " 387 "LastLevel: %i, Size: %i, Format: %s\n", 388 func, 389 desc->macrotile[0] ? "YES" : " NO", 390 desc->microtile ? "YES" : " NO", 391 desc->stride_in_pixels[0], 392 desc->b.b.width0, desc->b.b.height0, desc->b.b.depth0, 393 desc->b.b.last_level, desc->size_in_bytes, 394 util_format_short_name(desc->b.b.format)); 395} 396 397boolean r300_texture_desc_init(struct r300_screen *rscreen, 398 struct r300_texture_desc *desc, 399 const struct pipe_resource *base, 400 enum r300_buffer_tiling microtile, 401 enum r300_buffer_tiling macrotile, 402 unsigned stride_in_bytes_override, 403 unsigned max_buffer_size) 404{ 405 desc->b.b = *base; 406 desc->b.b.screen = &rscreen->screen; 407 desc->stride_in_bytes_override = stride_in_bytes_override; 408 desc->width0 = base->width0; 409 desc->height0 = base->height0; 410 desc->depth0 = base->depth0; 411 412 r300_setup_flags(desc); 413 414 /* Align a 3D NPOT texture to POT. */ 415 if (base->target == PIPE_TEXTURE_3D && desc->is_npot) { 416 desc->width0 = util_next_power_of_two(desc->width0); 417 desc->height0 = util_next_power_of_two(desc->height0); 418 desc->depth0 = util_next_power_of_two(desc->depth0); 419 } 420 421 /* Setup tiling. */ 422 if (microtile == R300_BUFFER_SELECT_LAYOUT || 423 macrotile == R300_BUFFER_SELECT_LAYOUT) { 424 r300_setup_tiling(rscreen, desc); 425 } else { 426 desc->microtile = microtile; 427 desc->macrotile[0] = macrotile; 428 assert(desc->b.b.last_level == 0); 429 } 430 431 r300_setup_cbzb_flags(rscreen, desc); 432 433 /* Setup the miptree description. */ 434 r300_setup_miptree(rscreen, desc, TRUE); 435 /* If the required buffer size is larger the given max size, 436 * try again without the alignment for the CBZB clear. */ 437 if (max_buffer_size && desc->size_in_bytes > max_buffer_size) { 438 r300_setup_miptree(rscreen, desc, FALSE); 439 } 440 441 r300_texture_3d_fix_mipmapping(rscreen, desc); 442 443 if (max_buffer_size) { 444 /* Make sure the buffer we got is large enough. */ 445 if (desc->size_in_bytes > max_buffer_size) { 446 fprintf(stderr, "r300: texture_desc_init: The buffer is not " 447 "large enough. Got: %i, Need: %i, Info:\n", 448 max_buffer_size, desc->size_in_bytes); 449 r300_tex_print_info(rscreen, desc, "texture_desc_init"); 450 return FALSE; 451 } 452 453 desc->buffer_size_in_bytes = max_buffer_size; 454 } else { 455 desc->buffer_size_in_bytes = desc->size_in_bytes; 456 } 457 458 if (SCREEN_DBG_ON(rscreen, DBG_TEX)) 459 r300_tex_print_info(rscreen, desc, "texture_desc_init"); 460 461 return TRUE; 462} 463 464unsigned r300_texture_get_offset(struct r300_texture_desc *desc, 465 unsigned level, unsigned layer) 466{ 467 unsigned offset = desc->offset_in_bytes[level]; 468 469 switch (desc->b.b.target) { 470 case PIPE_TEXTURE_3D: 471 case PIPE_TEXTURE_CUBE: 472 return offset + layer * desc->layer_size_in_bytes[level]; 473 474 default: 475 assert(layer == 0); 476 return offset; 477 } 478} 479