diff options
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_image.c | 281 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/core/ilo_image.h | 43 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_resource.c | 97 |
3 files changed, 242 insertions, 179 deletions
diff --git a/src/gallium/drivers/ilo/core/ilo_image.c b/src/gallium/drivers/ilo/core/ilo_image.c index ed9b2883ac0..39c6daaafd3 100644 --- a/src/gallium/drivers/ilo/core/ilo_image.c +++ b/src/gallium/drivers/ilo/core/ilo_image.c @@ -42,7 +42,7 @@ enum { struct ilo_image_params { const struct ilo_dev *dev; - const struct pipe_resource *templ; + const struct ilo_image_info *info; unsigned valid_tilings; bool compressed; @@ -56,7 +56,7 @@ img_get_slice_size(const struct ilo_image *img, const struct ilo_image_params *params, unsigned level, unsigned *width, unsigned *height) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; unsigned w, h; w = u_minify(img->width0, level); @@ -112,8 +112,7 @@ img_get_slice_size(const struct ilo_image *img, * y = align(y, 2) * 2; */ if (img->interleaved_samples) { - switch (templ->nr_samples) { - case 0: + switch (info->sample_count) { case 1: break; case 2: @@ -157,12 +156,12 @@ static unsigned img_get_num_layers(const struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; - unsigned num_layers = templ->array_size; + const struct ilo_image_info *info = params->info; + unsigned num_layers = info->array_size; /* samples of the same index are stored in a layer */ - if (templ->nr_samples > 1 && !img->interleaved_samples) - num_layers *= templ->nr_samples; + if (info->sample_count > 1 && !img->interleaved_samples) + num_layers *= info->sample_count; return num_layers; } @@ -171,7 +170,7 @@ static void img_init_layer_height(struct ilo_image *img, struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; unsigned num_layers; if (img->walk != ILO_IMAGE_WALK_LAYER) @@ -218,7 +217,7 @@ img_init_layer_height(struct ilo_image *img, img->walk_layer_height = params->h0 + params->h1 + ((ilo_dev_gen(params->dev) >= ILO_GEN(7)) ? 12 : 11) * img->align_j; - if (ilo_dev_gen(params->dev) == ILO_GEN(6) && templ->nr_samples > 1 && + if (ilo_dev_gen(params->dev) == ILO_GEN(6) && info->sample_count > 1 && img->height0 % 4 == 1) img->walk_layer_height += 4; @@ -229,13 +228,13 @@ static void img_init_lods(struct ilo_image *img, struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; unsigned cur_x, cur_y; unsigned lv; cur_x = 0; cur_y = 0; - for (lv = 0; lv <= templ->last_level; lv++) { + for (lv = 0; lv < info->level_count; lv++) { unsigned lod_w, lod_h; img_get_slice_size(img, params, lv, &lod_w, &lod_h); @@ -261,7 +260,7 @@ img_init_lods(struct ilo_image *img, cur_y += lod_h; /* every LOD begins at tile boundaries */ - if (templ->last_level > 0) { + if (info->level_count > 1) { assert(img->format == PIPE_FORMAT_S8_UINT); cur_x = align(cur_x, 64); cur_y = align(cur_y, 64); @@ -269,7 +268,7 @@ img_init_lods(struct ilo_image *img, break; case ILO_IMAGE_WALK_3D: { - const unsigned num_slices = u_minify(templ->depth0, lv); + 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; @@ -291,7 +290,7 @@ img_init_lods(struct ilo_image *img, if (img->walk == ILO_IMAGE_WALK_LAYER) { params->h0 = img->lods[0].slice_height; - if (templ->last_level > 0) + if (info->level_count > 1) params->h1 = img->lods[1].slice_height; else img_get_slice_size(img, params, 1, &cur_x, ¶ms->h1); @@ -302,7 +301,7 @@ static void img_init_alignments(struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; /* * From the Sandy Bridge PRM, volume 1 part 1, page 113: @@ -396,7 +395,7 @@ img_init_alignments(struct ilo_image *img, /* this happens to be the case */ img->align_i = img->block_width; img->align_j = img->block_height; - } else if (templ->bind & PIPE_BIND_DEPTH_STENCIL) { + } else if (info->bind_zs) { if (ilo_dev_gen(params->dev) >= ILO_GEN(7)) { switch (img->format) { case PIPE_FORMAT_Z16_UNORM: @@ -426,11 +425,11 @@ img_init_alignments(struct ilo_image *img, } } else { const bool valign_4 = - (templ->nr_samples > 1) || + (info->sample_count > 1) || (ilo_dev_gen(params->dev) >= ILO_GEN(8)) || (ilo_dev_gen(params->dev) >= ILO_GEN(7) && img->tiling == GEN6_TILING_Y && - (templ->bind & PIPE_BIND_RENDER_TARGET)); + info->bind_surface_dp_render); if (ilo_dev_gen(params->dev) >= ILO_GEN(7) && ilo_dev_gen(params->dev) <= ILO_GEN(7.5) && valign_4) @@ -460,14 +459,14 @@ static void img_init_tiling(struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; unsigned preferred_tilings = params->valid_tilings; /* no fencing nor BLT support */ if (preferred_tilings & ~IMAGE_TILING_W) preferred_tilings &= ~IMAGE_TILING_W; - if (templ->bind & (PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW)) { + if (info->bind_surface_dp_render || info->bind_surface_sampler) { /* * heuristically set a minimum width/height for enabling tiling */ @@ -499,7 +498,7 @@ static void img_init_walk_gen7(struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; /* * It is not explicitly states, but render targets are expected to be @@ -508,14 +507,14 @@ img_init_walk_gen7(struct ilo_image *img, * * See "Multisampled Surface Storage Format" field of SURFACE_STATE. */ - if (templ->bind & PIPE_BIND_DEPTH_STENCIL) { + if (info->bind_zs) { /* * From the Ivy Bridge PRM, volume 1 part 1, page 111: * * "note that the depth buffer and stencil buffer have an implied * value of ARYSPC_FULL" */ - img->walk = (templ->target == PIPE_TEXTURE_3D) ? + img->walk = (info->target == PIPE_TEXTURE_3D) ? ILO_IMAGE_WALK_3D : ILO_IMAGE_WALK_LAYER; img->interleaved_samples = true; @@ -530,12 +529,12 @@ img_init_walk_gen7(struct ilo_image *img, * As multisampled resources are not mipmapped, we never use * ARYSPC_FULL for them. */ - if (templ->nr_samples > 1) - assert(templ->last_level == 0); + if (info->sample_count > 1) + assert(info->level_count == 1); img->walk = - (templ->target == PIPE_TEXTURE_3D) ? ILO_IMAGE_WALK_3D : - (templ->last_level > 0) ? ILO_IMAGE_WALK_LAYER : + (info->target == PIPE_TEXTURE_3D) ? ILO_IMAGE_WALK_3D : + (info->level_count > 1) ? ILO_IMAGE_WALK_LAYER : ILO_IMAGE_WALK_LOD; img->interleaved_samples = false; @@ -558,7 +557,7 @@ img_init_walk_gen6(struct ilo_image *img, * GEN6 does not support compact spacing otherwise. */ img->walk = - (params->templ->target == PIPE_TEXTURE_3D) ? ILO_IMAGE_WALK_3D : + (params->info->target == PIPE_TEXTURE_3D) ? ILO_IMAGE_WALK_3D : (img->format == PIPE_FORMAT_S8_UINT) ? ILO_IMAGE_WALK_LOD : ILO_IMAGE_WALK_LAYER; @@ -580,7 +579,7 @@ static unsigned img_get_valid_tilings(const struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; const enum pipe_format format = img->format; unsigned valid_tilings = params->valid_tilings; @@ -590,7 +589,7 @@ img_get_valid_tilings(const struct ilo_image *img, * "Display/Overlay Y-Major not supported. * X-Major required for Async Flips" */ - if (unlikely(templ->bind & PIPE_BIND_SCANOUT)) + if (unlikely(info->bind_scanout)) valid_tilings &= IMAGE_TILING_X; /* @@ -599,7 +598,7 @@ img_get_valid_tilings(const struct ilo_image *img, * "The cursor surface address must be 4K byte aligned. The cursor must * be in linear memory, it cannot be tiled." */ - if (unlikely(templ->bind & (PIPE_BIND_CURSOR | PIPE_BIND_LINEAR))) + if (unlikely(info->bind_cursor)) valid_tilings &= IMAGE_TILING_NONE; /* @@ -614,7 +613,7 @@ img_get_valid_tilings(const struct ilo_image *img, * * "W-Major Tile Format is used for separate stencil." */ - if (templ->bind & PIPE_BIND_DEPTH_STENCIL) { + if (info->bind_zs) { switch (format) { case PIPE_FORMAT_S8_UINT: valid_tilings &= IMAGE_TILING_W; @@ -625,7 +624,7 @@ img_get_valid_tilings(const struct ilo_image *img, } } - if (templ->bind & PIPE_BIND_RENDER_TARGET) { + if (info->bind_surface_dp_render) { /* * From the Sandy Bridge PRM, volume 1 part 2, page 32: * @@ -656,7 +655,7 @@ img_get_valid_tilings(const struct ilo_image *img, valid_tilings &= ~IMAGE_TILING_W; } - if (templ->bind & PIPE_BIND_SAMPLER_VIEW) { + if (info->bind_surface_sampler) { if (ilo_dev_gen(params->dev) < ILO_GEN(8)) valid_tilings &= ~IMAGE_TILING_W; } @@ -671,17 +670,17 @@ static void img_init_size_and_format(struct ilo_image *img, struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; - enum pipe_format format = templ->format; + const struct ilo_image_info *info = params->info; + enum pipe_format format = info->format; bool require_separate_stencil = false; - img->target = templ->target; - img->width0 = templ->width0; - img->height0 = templ->height0; - img->depth0 = templ->depth0; - img->array_size = templ->array_size; - img->level_count = templ->last_level + 1; - img->sample_count = (templ->nr_samples) ? templ->nr_samples : 1; + img->target = info->target; + img->width0 = info->width; + img->height0 = info->height; + img->depth0 = info->depth; + img->array_size = info->array_size; + img->level_count = info->level_count; + img->sample_count = info->sample_count; /* * From the Sandy Bridge PRM, volume 2 part 1, page 317: @@ -691,7 +690,7 @@ img_init_size_and_format(struct ilo_image *img, * * GEN7+ requires separate stencil buffers. */ - if (templ->bind & PIPE_BIND_DEPTH_STENCIL) { + if (info->bind_zs) { if (ilo_dev_gen(params->dev) >= ILO_GEN(7)) require_separate_stencil = true; else @@ -731,15 +730,14 @@ static bool img_want_mcs(const struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; bool want_mcs = false; /* MCS is for RT on GEN7+ */ if (ilo_dev_gen(params->dev) < ILO_GEN(7)) return false; - if (templ->target != PIPE_TEXTURE_2D || - !(templ->bind & PIPE_BIND_RENDER_TARGET)) + if (info->target != PIPE_TEXTURE_2D || !info->bind_surface_dp_render) return false; /* @@ -752,9 +750,9 @@ img_want_mcs(const struct ilo_image *img, * "This field must be set to 0 for all SINT MSRTs when all RT channels * are not written" */ - if (templ->nr_samples > 1 && !util_format_is_pure_sint(templ->format)) { + if (info->sample_count > 1 && !util_format_is_pure_sint(info->format)) { want_mcs = true; - } else if (templ->nr_samples <= 1) { + } else if (info->sample_count == 1 && !info->aux_disable) { /* * From the Ivy Bridge PRM, volume 2 part 1, page 326: * @@ -770,7 +768,7 @@ img_want_mcs(const struct ilo_image *img, * ..." */ if (img->tiling != GEN6_TILING_NONE && - templ->last_level == 0 && templ->array_size == 1) { + info->level_count == 1 && info->array_size == 1) { switch (img->block_size) { case 4: case 8: @@ -790,25 +788,24 @@ static bool img_want_hiz(const struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; const struct util_format_description *desc = - util_format_description(templ->format); + util_format_description(info->format); if (ilo_debug & ILO_DEBUG_NOHIZ) return false; - /* we want 8x4 aligned levels */ - if (templ->target == PIPE_TEXTURE_1D) + if (info->aux_disable) return false; - if (!(templ->bind & PIPE_BIND_DEPTH_STENCIL)) + /* we want 8x4 aligned levels */ + if (info->target == PIPE_TEXTURE_1D) return false; - if (!util_format_has_depth(desc)) + if (!info->bind_zs) return false; - /* no point in having HiZ */ - if (templ->usage == PIPE_USAGE_STAGING) + if (!util_format_has_depth(desc)) return false; /* @@ -819,8 +816,8 @@ img_want_hiz(const struct ilo_image *img, * can result in incompatible formats. */ if (ilo_dev_gen(params->dev) == ILO_GEN(6) && - templ->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && - templ->last_level) + info->format == PIPE_FORMAT_Z32_FLOAT_S8X24_UINT && + info->level_count > 1) return false; return true; @@ -839,7 +836,7 @@ img_init_aux(struct ilo_image *img, static void img_align(struct ilo_image *img, struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; int align_w = 1, align_h = 1, pad_h = 0; /* @@ -864,11 +861,11 @@ img_align(struct ilo_image *img, struct ilo_image_params *params) * padding purposes. The value of 4 for j still applies for mip level * alignment and QPitch calculation." */ - if (templ->bind & PIPE_BIND_SAMPLER_VIEW) { + if (info->bind_surface_sampler) { align_w = MAX2(align_w, img->align_i); align_h = MAX2(align_h, img->align_j); - if (templ->target == PIPE_TEXTURE_CUBE) + if (info->target == PIPE_TEXTURE_CUBE) pad_h += 2; if (params->compressed) @@ -881,7 +878,7 @@ img_align(struct ilo_image *img, struct ilo_image_params *params) * "If the surface contains an odd number of rows of data, a final row * below the surface must be allocated." */ - if (templ->bind & PIPE_BIND_RENDER_TARGET) + if (info->bind_surface_dp_render) align_h = MAX2(align_h, 2); /* @@ -889,9 +886,9 @@ img_align(struct ilo_image *img, struct ilo_image_params *params) * for unaligned non-mipmapped and non-array images. */ if (img->aux.type == ILO_IMAGE_AUX_HIZ && - templ->last_level == 0 && - templ->array_size == 1 && - templ->depth0 == 1) { + info->level_count == 1 && + info->array_size == 1 && + info->depth == 1) { align_w = MAX2(align_w, 8); align_h = MAX2(align_h, 4); } @@ -925,7 +922,7 @@ img_calculate_bo_size(struct ilo_image *img, * required above." */ if (ilo_dev_gen(params->dev) >= ILO_GEN(7.5) && - (params->templ->bind & PIPE_BIND_SAMPLER_VIEW) && + params->info->bind_surface_sampler && img->tiling == GEN6_TILING_NONE) h += (64 + img->bo_stride - 1) / img->bo_stride; @@ -943,7 +940,7 @@ img_calculate_bo_size(struct ilo_image *img, * * Different requirements may exist when the bo is used in different * places, but our alignments here should be good enough that we do not - * need to check params->templ->bind. + * need to check params->info->bind_x. */ switch (img->tiling) { case GEN6_TILING_X: @@ -994,7 +991,7 @@ img_calculate_bo_size(struct ilo_image *img, img->tiling = GEN6_TILING_NONE; /* MCS support for non-MSRTs is limited to tiled RTs */ if (img->aux.type == ILO_IMAGE_AUX_MCS && - params->templ->nr_samples <= 1) + params->info->sample_count == 1) img->aux.type = ILO_IMAGE_AUX_NONE; continue; @@ -1014,7 +1011,7 @@ static void img_calculate_hiz_size(struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; const unsigned hz_align_j = 8; enum ilo_image_walk_type hz_walk; unsigned hz_width, hz_height, lv; @@ -1059,7 +1056,7 @@ img_calculate_hiz_size(struct ilo_image *img, hz_width = align(img->lods[0].slice_width, 16); - hz_height = hz_qpitch * templ->array_size / 2; + hz_height = hz_qpitch * info->array_size / 2; if (ilo_dev_gen(params->dev) >= ILO_GEN(7)) hz_height = align(hz_height, 8); @@ -1077,7 +1074,7 @@ img_calculate_hiz_size(struct ilo_image *img, hz_height = 0; cur_tx = 0; cur_ty = 0; - for (lv = 0; lv <= templ->last_level; lv++) { + for (lv = 0; lv < info->level_count; lv++) { unsigned tw, th; lod_tx[lv] = cur_tx; @@ -1085,7 +1082,7 @@ img_calculate_hiz_size(struct ilo_image *img, tw = align(img->lods[lv].slice_width, 16); th = align(img->lods[lv].slice_height, hz_align_j) * - templ->array_size / 2; + info->array_size / 2; /* convert to Y-tiles */ tw = align(tw, 128) / 128; th = align(th, 32) / 32; @@ -1102,7 +1099,7 @@ img_calculate_hiz_size(struct ilo_image *img, } /* convert tile offsets to memory offsets */ - for (lv = 0; lv <= templ->last_level; lv++) { + for (lv = 0; lv < info->level_count; lv++) { img->aux.walk_lod_offsets[lv] = (lod_ty[lv] * hz_width + lod_tx[lv]) * 4096; } @@ -1114,10 +1111,10 @@ img_calculate_hiz_size(struct ilo_image *img, hz_width = align(img->lods[0].slice_width, 16); hz_height = 0; - for (lv = 0; lv <= templ->last_level; lv++) { + for (lv = 0; lv < info->level_count; lv++) { const unsigned h = align(img->lods[lv].slice_height, hz_align_j); /* according to the formula, slices are packed together vertically */ - hz_height += h * u_minify(templ->depth0, lv); + hz_height += h * u_minify(info->depth, lv); } hz_height /= 2; break; @@ -1136,8 +1133,7 @@ img_calculate_hiz_size(struct ilo_image *img, */ hz_clear_w = 8; hz_clear_h = 4; - switch (templ->nr_samples) { - case 0: + switch (info->sample_count) { case 1: default: break; @@ -1158,7 +1154,7 @@ img_calculate_hiz_size(struct ilo_image *img, break; } - for (lv = 0; lv <= templ->last_level; lv++) { + for (lv = 0; lv < info->level_count; lv++) { if (u_minify(img->width0, lv) % hz_clear_w || u_minify(img->height0, lv) % hz_clear_h) break; @@ -1166,7 +1162,7 @@ img_calculate_hiz_size(struct ilo_image *img, } /* we padded to allow this in img_align() */ - if (templ->last_level == 0 && templ->array_size == 1 && templ->depth0 == 1) + if (info->level_count == 1 && info->array_size == 1 && info->depth == 1) img->aux.enables |= 0x1; /* align to Y-tile */ @@ -1178,13 +1174,13 @@ static void img_calculate_mcs_size(struct ilo_image *img, const struct ilo_image_params *params) { - const struct pipe_resource *templ = params->templ; + const struct ilo_image_info *info = params->info; int mcs_width, mcs_height, mcs_cpp; int downscale_x, downscale_y; assert(img->aux.type == ILO_IMAGE_AUX_MCS); - if (templ->nr_samples > 1) { + if (info->sample_count > 1) { /* * From the Ivy Bridge PRM, volume 2 part 1, page 326, the clear * rectangle is scaled down by 8x2 for 4X MSAA and 2x2 for 8X MSAA. The @@ -1198,7 +1194,7 @@ img_calculate_mcs_size(struct ilo_image *img, * RT. Similarly, we could reason that an OWord in 4X MCS maps to a 8x2 * pixel block in the RT. */ - switch (templ->nr_samples) { + switch (info->sample_count) { case 2: case 4: downscale_x = 8; @@ -1295,13 +1291,13 @@ img_calculate_mcs_size(struct ilo_image *img, mcs_cpp = 16; /* an OWord */ } - img->aux.enables = (1 << (templ->last_level + 1)) - 1; + img->aux.enables = (1 << info->level_count) - 1; /* align to Y-tile */ img->aux.bo_stride = align(mcs_width * mcs_cpp, 128); img->aux.bo_height = align(mcs_height, 32); } -static void +static bool img_init(struct ilo_image *img, struct ilo_image_params *params) { @@ -1318,7 +1314,7 @@ img_init(struct ilo_image *img, img_align(img, params); img_calculate_bo_size(img, params); - img->scanout = (params->templ->bind & PIPE_BIND_SCANOUT); + img->scanout = params->info->bind_scanout; switch (img->aux.type) { case ILO_IMAGE_AUX_HIZ: @@ -1330,6 +1326,8 @@ img_init(struct ilo_image *img, default: break; } + + return true; } /** @@ -1339,29 +1337,29 @@ img_init(struct ilo_image *img, static void img_init_for_transfer(struct ilo_image *img, const struct ilo_dev *dev, - const struct pipe_resource *templ) + const struct ilo_image_info *info) { - const unsigned num_layers = (templ->target == PIPE_TEXTURE_3D) ? - templ->depth0 : templ->array_size; + const unsigned num_layers = (info->target == PIPE_TEXTURE_3D) ? + info->depth : info->array_size; unsigned layer_width, layer_height; - assert(templ->last_level == 0); - assert(templ->nr_samples <= 1); + assert(info->level_count == 1); + assert(info->sample_count == 1); img->aux.type = ILO_IMAGE_AUX_NONE; - img->target = templ->target; - img->width0 = templ->width0; - img->height0 = templ->height0; - img->depth0 = templ->depth0; - img->array_size = templ->array_size; + img->target = info->target; + img->width0 = info->width; + img->height0 = info->height; + img->depth0 = info->depth; + img->array_size = info->array_size; img->level_count = 1; img->sample_count = 1; - img->format = templ->format; - img->block_width = util_format_get_blockwidth(templ->format); - img->block_height = util_format_get_blockheight(templ->format); - img->block_size = util_format_get_blocksize(templ->format); + img->format = info->format; + img->block_width = util_format_get_blockwidth(info->format); + img->block_height = util_format_get_blockheight(info->format); + img->block_size = util_format_get_blocksize(info->format); img->walk = ILO_IMAGE_WALK_LOD; @@ -1374,8 +1372,8 @@ img_init_for_transfer(struct ilo_image *img, util_is_power_of_two(img->block_height)); /* use packed layout */ - layer_width = align(templ->width0, img->align_i); - layer_height = align(templ->height0, img->align_j); + layer_width = align(info->width, img->align_i); + layer_height = align(info->height, img->align_j); img->lods[0].slice_width = layer_width; img->lods[0].slice_height = layer_height; @@ -1386,66 +1384,57 @@ img_init_for_transfer(struct ilo_image *img, img->bo_height = (layer_height / img->block_height) * num_layers; } +static bool +img_is_bind_gpu(const struct ilo_image_info *info) +{ + return (info->bind_surface_sampler || + info->bind_surface_dp_render || + info->bind_surface_dp_typed || + info->bind_zs || + info->bind_scanout || + info->bind_cursor); +} + /** * Initialize the image. Callers should zero-initialize \p img first. */ -void ilo_image_init(struct ilo_image *img, - const struct ilo_dev *dev, - const struct pipe_resource *templ) +bool +ilo_image_init(struct ilo_image *img, + const struct ilo_dev *dev, + const struct ilo_image_info *info) { struct ilo_image_params params; - bool transfer_only; assert(ilo_is_zeroed(img, sizeof(*img))); /* use transfer layout when the texture is never bound to GPU */ - transfer_only = !(templ->bind & ~(PIPE_BIND_TRANSFER_WRITE | - PIPE_BIND_TRANSFER_READ)); - if (transfer_only && templ->last_level == 0 && templ->nr_samples <= 1) { - img_init_for_transfer(img, dev, templ); - return; + if (!img_is_bind_gpu(info) && + info->level_count == 1 && + info->sample_count == 1) { + img_init_for_transfer(img, dev, info); + return true; } memset(¶ms, 0, sizeof(params)); params.dev = dev; - params.templ = templ; - params.valid_tilings = IMAGE_TILING_ALL; + params.info = info; + params.valid_tilings = (info->valid_tilings) ? + info->valid_tilings : IMAGE_TILING_ALL; - img_init(img, ¶ms); -} - -bool -ilo_image_init_for_imported(struct ilo_image *img, - const struct ilo_dev *dev, - const struct pipe_resource *templ, - enum gen_surface_tiling tiling, - unsigned bo_stride) -{ - struct ilo_image_params params; - - assert(ilo_is_zeroed(img, sizeof(*img))); - - if ((tiling == GEN6_TILING_X && bo_stride % 512) || - (tiling == GEN6_TILING_Y && bo_stride % 128) || - (tiling == GEN8_TILING_W && bo_stride % 64)) + if (!img_init(img, ¶ms)) return false; - memset(¶ms, 0, sizeof(params)); - params.dev = dev; - params.templ = templ; - params.valid_tilings = 1 << tiling; + if (info->force_bo_stride) { + if ((img->tiling == GEN6_TILING_X && info->force_bo_stride % 512) || + (img->tiling == GEN6_TILING_Y && info->force_bo_stride % 128) || + (img->tiling == GEN8_TILING_W && info->force_bo_stride % 64)) + return false; - img_init(img, ¶ms); + if (img->bo_stride > info->force_bo_stride) + return false; - assert(img->tiling == tiling); - if (img->bo_stride > bo_stride) - return false; - - img->bo_stride = bo_stride; - - /* assume imported RTs are also scanouts */ - if (!img->scanout) - img->scanout = (templ->bind & PIPE_BIND_RENDER_TARGET); + img->bo_stride = info->force_bo_stride; + } return true; } diff --git a/src/gallium/drivers/ilo/core/ilo_image.h b/src/gallium/drivers/ilo/core/ilo_image.h index e5dcc4319b6..e488bef0d3f 100644 --- a/src/gallium/drivers/ilo/core/ilo_image.h +++ b/src/gallium/drivers/ilo/core/ilo_image.h @@ -67,6 +67,36 @@ enum ilo_image_walk_type { ILO_IMAGE_WALK_3D, }; +struct ilo_image_info { + enum pipe_texture_target target; + + enum pipe_format format; + + /* image size */ + uint16_t width; + uint16_t height; + uint16_t depth; + uint16_t array_size; + uint8_t level_count; + uint8_t sample_count; + + /* disable optional aux */ + bool aux_disable; + + /* tilings to consider, if any bit is set */ + uint8_t valid_tilings; + + /* force a stride */ + uint32_t force_bo_stride; + + bool bind_surface_sampler; + bool bind_surface_dp_render; + bool bind_surface_dp_typed; + bool bind_zs; + bool bind_scanout; + bool bind_cursor; +}; + /* * When the walk type is ILO_IMAGE_WALK_LAYER, there is only a slice in each * LOD and this is used to describe LODs in the first array layer. Otherwise, @@ -143,19 +173,10 @@ struct ilo_image { } aux; }; -struct pipe_resource; - -void +bool ilo_image_init(struct ilo_image *img, const struct ilo_dev *dev, - const struct pipe_resource *templ); - -bool -ilo_image_init_for_imported(struct ilo_image *img, - const struct ilo_dev *dev, - const struct pipe_resource *templ, - enum gen_surface_tiling tiling, - unsigned bo_stride); + const struct ilo_image_info *info); static inline bool ilo_image_can_enable_aux(const struct ilo_image *img, unsigned level) diff --git a/src/gallium/drivers/ilo/ilo_resource.c b/src/gallium/drivers/ilo/ilo_resource.c index 3b8e607862c..0b0f69c30be 100644 --- a/src/gallium/drivers/ilo/ilo_resource.c +++ b/src/gallium/drivers/ilo/ilo_resource.c @@ -87,6 +87,38 @@ resource_get_cpu_init(const struct pipe_resource *templ) PIPE_BIND_STREAM_OUTPUT)) ? false : true; } +static void +resource_get_image_info(const struct pipe_resource *templ, + const struct ilo_dev *dev, + enum pipe_format image_format, + struct ilo_image_info *info) +{ + memset(info, 0, sizeof(*info)); + + info->target = templ->target; + info->format = image_format; + + info->width = templ->width0; + info->height = templ->height0; + info->depth = templ->depth0; + info->array_size = templ->array_size; + info->level_count = templ->last_level + 1; + info->sample_count = (templ->nr_samples) ? templ->nr_samples : 1; + + info->aux_disable = (templ->usage == PIPE_USAGE_STAGING); + + if (templ->bind & PIPE_BIND_LINEAR) + info->valid_tilings = 1 << GEN6_TILING_NONE; + + info->bind_surface_sampler = (templ->bind & PIPE_BIND_SAMPLER_VIEW); + info->bind_surface_dp_render = (templ->bind & PIPE_BIND_RENDER_TARGET); + info->bind_surface_dp_typed = (templ->bind & + (PIPE_BIND_SHADER_RESOURCE | PIPE_BIND_COMPUTE_RESOURCE)); + info->bind_zs = (templ->bind & PIPE_BIND_DEPTH_STENCIL); + info->bind_scanout = (templ->bind & PIPE_BIND_SCANOUT); + info->bind_cursor = (templ->bind & PIPE_BIND_CURSOR); +} + static enum gen_surface_tiling winsys_to_surface_tiling(enum intel_tiling_mode tiling) { @@ -306,9 +338,10 @@ tex_alloc_bos(struct ilo_texture *tex) return true; } -static bool +static struct intel_bo * tex_import_handle(struct ilo_texture *tex, - const struct winsys_handle *handle) + const struct winsys_handle *handle, + struct ilo_image_info *info) { struct ilo_screen *is = ilo_screen(tex->base.screen); const struct pipe_resource *templ = &tex->base; @@ -319,23 +352,24 @@ tex_import_handle(struct ilo_texture *tex, bo = intel_winsys_import_handle(is->dev.winsys, name, handle, tex->image.bo_height, &tiling, &pitch); - if (!bo) - return false; + /* modify image info */ + if (bo) { + const uint8_t valid_tilings = 1 << winsys_to_surface_tiling(tiling); - if (!ilo_image_init_for_imported(&tex->image, &is->dev, templ, - winsys_to_surface_tiling(tiling), pitch)) { - ilo_err("failed to import handle for texture\n"); - intel_bo_unref(bo); - return false; - } + if (info->valid_tilings && !(info->valid_tilings & valid_tilings)) { + intel_bo_unref(bo); + return NULL; + } - ilo_vma_init(&tex->vma, &is->dev, - tex->image.bo_stride * tex->image.bo_height, 4096); - ilo_vma_set_bo(&tex->vma, &is->dev, bo, 0); + info->valid_tilings = valid_tilings; + info->force_bo_stride = pitch; - tex->imported = true; + /* assume imported RTs are also scanouts */ + if (!info->bind_scanout) + info->bind_scanout = (templ->usage & PIPE_BIND_RENDER_TARGET); + } - return true; + return bo; } static bool @@ -345,18 +379,33 @@ tex_init_image(struct ilo_texture *tex, struct ilo_screen *is = ilo_screen(tex->base.screen); const struct pipe_resource *templ = &tex->base; struct ilo_image *img = &tex->image; + struct intel_bo *imported_bo = NULL;; + struct ilo_image_info info; + + resource_get_image_info(templ, &is->dev, templ->format, &info); if (handle) { - if (!tex_import_handle(tex, handle)) + imported_bo = tex_import_handle(tex, handle, &info); + if (!imported_bo) return false; - } else { - ilo_image_init(img, &is->dev, templ); - ilo_vma_init(&tex->vma, &is->dev, - img->bo_stride * img->bo_height, 4096); } - if (img->bo_height > ilo_max_resource_size / img->bo_stride) + if (!ilo_image_init(img, &is->dev, &info)) { + intel_bo_unref(imported_bo); return false; + } + + if (img->bo_height > ilo_max_resource_size / img->bo_stride || + !ilo_vma_init(&tex->vma, &is->dev, img->bo_stride * img->bo_height, + 4096)) { + intel_bo_unref(imported_bo); + return false; + } + + if (imported_bo) { + ilo_vma_set_bo(&tex->vma, &is->dev, imported_bo, 0); + tex->imported = true; + } if (templ->flags & PIPE_RESOURCE_FLAG_MAP_PERSISTENT) { /* require on-the-fly tiling/untiling or format conversion */ @@ -500,13 +549,17 @@ static boolean ilo_can_create_resource(struct pipe_screen *screen, const struct pipe_resource *templ) { + struct ilo_screen *is = ilo_screen(screen); + struct ilo_image_info info; struct ilo_image img; if (templ->target == PIPE_BUFFER) return (templ->width0 <= ilo_max_resource_size); + resource_get_image_info(templ, &is->dev, templ->format, &info); + memset(&img, 0, sizeof(img)); - ilo_image_init(&img, &ilo_screen(screen)->dev, templ); + ilo_image_init(&img, &ilo_screen(screen)->dev, &info); return (img.bo_height <= ilo_max_resource_size / img.bo_stride); } |