diff options
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_image.c | 236 |
1 files changed, 148 insertions, 88 deletions
diff --git a/src/gallium/drivers/ilo/core/ilo_image.c b/src/gallium/drivers/ilo/core/ilo_image.c index d28cb075fb5..c2a84876312 100644 --- a/src/gallium/drivers/ilo/core/ilo_image.c +++ b/src/gallium/drivers/ilo/core/ilo_image.c @@ -60,6 +60,13 @@ struct ilo_image_layout { int align_i; int align_j; + + struct ilo_image_lod *lods; + int walk_layer_h0; + int walk_layer_h1; + int walk_layer_height; + int monolithic_width; + int monolithic_height; }; static enum ilo_image_walk_type @@ -534,9 +541,9 @@ image_get_gen7_alignments(const struct ilo_dev *dev, } static bool -image_get_gen6_layout(const struct ilo_dev *dev, - const struct ilo_image_info *info, - struct ilo_image_layout *layout) +image_init_gen6_hardware_layout(const struct ilo_dev *dev, + const struct ilo_image_info *info, + struct ilo_image_layout *layout) { ILO_DEV_ASSERT(dev, 6, 8); @@ -570,34 +577,22 @@ image_get_gen6_layout(const struct ilo_dev *dev, &layout->align_i, &layout->align_j); } - /* - * the fact that align i and j are multiples of block width and height - * respectively is what makes the size of the bo a multiple of the block - * size, slices start at block boundaries, and many of the computations - * work. - */ - assert(layout->align_i % info->block_width == 0); - assert(layout->align_j % info->block_height == 0); - - /* make sure align() works */ - assert(util_is_power_of_two(layout->align_i) && - util_is_power_of_two(layout->align_j)); - assert(util_is_power_of_two(info->block_width) && - util_is_power_of_two(info->block_height)); - return true; } static void -img_get_slice_size(const struct ilo_image *img, - const struct ilo_image_params *params, - unsigned level, unsigned *width, unsigned *height) +image_get_gen6_slice_size(const struct ilo_dev *dev, + const struct ilo_image_info *info, + const struct ilo_image_layout *layout, + uint8_t level, + int *width, int *height) { - const struct ilo_image_info *info = params->info; - unsigned w, h; + int w, h; + + ILO_DEV_ASSERT(dev, 6, 8); - w = u_minify(img->width0, level); - h = u_minify(img->height0, level); + w = u_minify(info->width, level); + h = u_minify(info->height, level); /* * From the Sandy Bridge PRM, volume 1 part 1, page 114: @@ -606,8 +601,8 @@ img_get_slice_size(const struct ilo_image *img, * sizing algorithm presented in Non-Power-of-Two Mipmaps above. Then, * if necessary, they are padded out to compression block boundaries." */ - w = align(w, img->block_width); - h = align(h, img->block_height); + w = align(w, info->block_width); + h = align(h, info->block_height); /* * From the Sandy Bridge PRM, volume 1 part 1, page 111: @@ -648,7 +643,7 @@ img_get_slice_size(const struct ilo_image *img, * w = align(w, 2) * 2; * y = align(y, 2) * 2; */ - if (img->interleaved_samples) { + if (layout->interleaved_samples) { switch (info->sample_count) { case 1: break; @@ -682,40 +677,50 @@ img_get_slice_size(const struct ilo_image *img, * To make things easier (for transfer), we will just double the stencil * stride in 3DSTATE_STENCIL_BUFFER. */ - w = align(w, img->align_i); - h = align(h, img->align_j); + w = align(w, layout->align_i); + h = align(h, layout->align_j); *width = w; *height = h; } -static unsigned -img_get_num_layers(const struct ilo_image *img, - const struct ilo_image_params *params) +static int +image_get_gen6_layer_count(const struct ilo_dev *dev, + const struct ilo_image_info *info, + const struct ilo_image_layout *layout) { - const struct ilo_image_info *info = params->info; - unsigned num_layers = info->array_size; + int count = info->array_size; + + ILO_DEV_ASSERT(dev, 6, 8); /* samples of the same index are stored in a layer */ - if (info->sample_count > 1 && !img->interleaved_samples) - num_layers *= info->sample_count; + if (!layout->interleaved_samples) + count *= info->sample_count; - return num_layers; + return count; } static void -img_init_layer_height(struct ilo_image *img, - struct ilo_image_params *params) +image_get_gen6_walk_layer_heights(const struct ilo_dev *dev, + const struct ilo_image_info *info, + struct ilo_image_layout *layout) { - const struct ilo_image_info *info = params->info; - unsigned num_layers; + ILO_DEV_ASSERT(dev, 6, 8); - if (img->walk != ILO_IMAGE_WALK_LAYER) - return; + layout->walk_layer_h0 = layout->lods[0].slice_height; - num_layers = img_get_num_layers(img, params); - if (num_layers <= 1) + if (info->level_count > 1) { + layout->walk_layer_h1 = layout->lods[1].slice_height; + } else { + int dummy; + image_get_gen6_slice_size(dev, info, layout, 1, + &dummy, &layout->walk_layer_h1); + } + + if (image_get_gen6_layer_count(dev, info, layout) == 1) { + layout->walk_layer_height = 0; return; + } /* * From the Sandy Bridge PRM, volume 1 part 1, page 115: @@ -751,38 +756,44 @@ img_init_layer_height(struct ilo_image *img, * slices. Since we use texel rows everywhere, we do not need to divide * QPitch by 4. */ - img->walk_layer_height = params->h0 + params->h1 + - ((ilo_dev_gen(params->dev) >= ILO_GEN(7)) ? 12 : 11) * img->align_j; + layout->walk_layer_height = layout->walk_layer_h0 + layout->walk_layer_h1 + + ((ilo_dev_gen(dev) >= ILO_GEN(7)) ? 12 : 11) * layout->align_j; - if (ilo_dev_gen(params->dev) == ILO_GEN(6) && info->sample_count > 1 && - img->height0 % 4 == 1) - img->walk_layer_height += 4; - - params->max_y += img->walk_layer_height * (num_layers - 1); + if (ilo_dev_gen(dev) == ILO_GEN(6) && info->sample_count > 1 && + info->height % 4 == 1) + layout->walk_layer_height += 4; } static void -img_init_lods(struct ilo_image *img, - struct ilo_image_params *params) +image_get_gen6_lods(const struct ilo_dev *dev, + const struct ilo_image_info *info, + struct ilo_image_layout *layout) { - const struct ilo_image_info *info = params->info; - unsigned cur_x, cur_y; - unsigned lv; + const int layer_count = image_get_gen6_layer_count(dev, info, layout); + int cur_x, cur_y, max_x, max_y; + uint8_t lv; + + ILO_DEV_ASSERT(dev, 6, 8); cur_x = 0; cur_y = 0; + max_x = 0; + max_y = 0; for (lv = 0; lv < info->level_count; lv++) { - unsigned lod_w, lod_h; + int slice_w, slice_h, lod_w, lod_h; - img_get_slice_size(img, params, lv, &lod_w, &lod_h); + image_get_gen6_slice_size(dev, info, layout, lv, &slice_w, &slice_h); - img->lods[lv].x = cur_x; - img->lods[lv].y = cur_y; - img->lods[lv].slice_width = lod_w; - img->lods[lv].slice_height = lod_h; + layout->lods[lv].x = cur_x; + layout->lods[lv].y = cur_y; + layout->lods[lv].slice_width = slice_w; + layout->lods[lv].slice_height = slice_h; - switch (img->walk) { + switch (layout->walk) { case ILO_IMAGE_WALK_LAYER: + lod_w = slice_w; + lod_h = slice_h; + /* MIPLAYOUT_BELOW */ if (lv == 1) cur_x += lod_w; @@ -790,7 +801,9 @@ img_init_lods(struct ilo_image *img, cur_y += lod_h; break; case ILO_IMAGE_WALK_LOD: - lod_h *= img_get_num_layers(img, params); + lod_w = slice_w; + lod_h = slice_h * layer_count; + if (lv == 1) cur_x += lod_w; else @@ -798,40 +811,83 @@ img_init_lods(struct ilo_image *img, /* every LOD begins at tile boundaries */ if (info->level_count > 1) { - assert(img->format == GEN6_FORMAT_R8_UINT); + assert(info->format == GEN6_FORMAT_R8_UINT); cur_x = align(cur_x, 64); cur_y = align(cur_y, 64); } break; case ILO_IMAGE_WALK_3D: { - const unsigned num_slices = u_minify(info->depth, lv); - const unsigned num_slices_per_row = 1 << lv; - const unsigned num_rows = - (num_slices + num_slices_per_row - 1) / num_slices_per_row; + const int slice_count = u_minify(info->depth, lv); + const int slice_count_per_row = 1 << lv; + const int row_count = + (slice_count + slice_count_per_row - 1) / slice_count_per_row; - lod_w *= num_slices_per_row; - lod_h *= num_rows; - - cur_y += lod_h; + lod_w = slice_w * slice_count_per_row; + lod_h = slice_h * row_count; } + + cur_y += lod_h; + break; + default: + assert(!"unknown walk type"); + lod_w = 0; + lod_h = 0; break; } - if (params->max_x < img->lods[lv].x + lod_w) - params->max_x = img->lods[lv].x + lod_w; - if (params->max_y < img->lods[lv].y + lod_h) - params->max_y = img->lods[lv].y + lod_h; + if (max_x < layout->lods[lv].x + lod_w) + max_x = layout->lods[lv].x + lod_w; + if (max_y < layout->lods[lv].y + lod_h) + max_y = layout->lods[lv].y + lod_h; } - if (img->walk == ILO_IMAGE_WALK_LAYER) { - params->h0 = img->lods[0].slice_height; - - if (info->level_count > 1) - params->h1 = img->lods[1].slice_height; - else - img_get_slice_size(img, params, 1, &cur_x, ¶ms->h1); + if (layout->walk == ILO_IMAGE_WALK_LAYER) { + image_get_gen6_walk_layer_heights(dev, info, layout); + if (layer_count > 1) + max_y += layout->walk_layer_height * (layer_count - 1); + } else { + layout->walk_layer_h0 = 0; + layout->walk_layer_h1 = 0; + layout->walk_layer_height = 0; } + + layout->monolithic_width = max_x; + layout->monolithic_height = max_y; +} + +static bool +image_get_gen6_layout(const struct ilo_dev *dev, + const struct ilo_image_info *info, + struct ilo_image_layout *layout) +{ + ILO_DEV_ASSERT(dev, 6, 8); + + if (!image_init_gen6_hardware_layout(dev, info, layout)) + return false; + + /* + * the fact that align i and j are multiples of block width and height + * respectively is what makes the size of the bo a multiple of the block + * size, slices start at block boundaries, and many of the computations + * work. + */ + assert(layout->align_i % info->block_width == 0); + assert(layout->align_j % info->block_height == 0); + + /* make sure align() works */ + assert(util_is_power_of_two(layout->align_i) && + util_is_power_of_two(layout->align_j)); + assert(util_is_power_of_two(info->block_width) && + util_is_power_of_two(info->block_height)); + + image_get_gen6_lods(dev, info, layout); + + assert(layout->walk_layer_height % info->block_height == 0); + assert(layout->monolithic_width % info->block_width == 0); + assert(layout->monolithic_height % info->block_height == 0); + + return true; } static void @@ -1337,6 +1393,7 @@ img_init(struct ilo_image *img, struct ilo_image_layout layout; memset(&layout, 0, sizeof(layout)); + layout.lods = img->lods; if (!image_get_gen6_layout(params->dev, params->info, &layout)) return false; @@ -1356,8 +1413,11 @@ img_init(struct ilo_image *img, img->align_i = layout.align_i; img->align_j = layout.align_j; - img_init_lods(img, params); - img_init_layer_height(img, params); + params->max_x = layout.monolithic_width; + params->max_y = layout.monolithic_height; + params->h0 = layout.walk_layer_h0; + params->h1 = layout.walk_layer_h1; + img->walk_layer_height = layout.walk_layer_height; img_align(img, params); img_calculate_bo_size(img, params); |