diff options
Diffstat (limited to 'src/gallium/drivers/ilo')
-rw-r--r-- | src/gallium/drivers/ilo/ilo_gpe_gen6.c | 3 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_gpe_gen7.c | 13 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_resource.c | 118 | ||||
-rw-r--r-- | src/gallium/drivers/ilo/ilo_resource.h | 2 |
4 files changed, 117 insertions, 19 deletions
diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen6.c b/src/gallium/drivers/ilo/ilo_gpe_gen6.c index bbab416ca3b..159a117272f 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen6.c +++ b/src/gallium/drivers/ilo/ilo_gpe_gen6.c @@ -3742,6 +3742,9 @@ gen6_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev, /* non-full array spacing is supported only on GEN7+ */ assert(res->array_spacing_full); + /* non-interleaved samples are supported only on GEN7+ */ + if (res->base.nr_samples > 1) + assert(res->interleaved); /* * Compute the offset to the layer manually. diff --git a/src/gallium/drivers/ilo/ilo_gpe_gen7.c b/src/gallium/drivers/ilo/ilo_gpe_gen7.c index 44c4a77912c..f6282b4fbec 100644 --- a/src/gallium/drivers/ilo/ilo_gpe_gen7.c +++ b/src/gallium/drivers/ilo/ilo_gpe_gen7.c @@ -1488,6 +1488,19 @@ gen7_fill_normal_SURFACE_STATE(const struct ilo_dev_info *dev, dw[4] = first_layer << 18 | (depth - 1) << 7; + /* + * MSFMT_MSS means the samples are not interleaved and MSFMT_DEPTH_STENCIL + * means the samples are interleaved. The layouts are the same when the + * number of samples is 1. + */ + if (res->interleaved && res->base.nr_samples > 1) { + assert(!is_rt); + dw[4] |= GEN7_SURFACE_MSFMT_DEPTH_STENCIL; + } + else { + dw[4] |= GEN7_SURFACE_MSFMT_MSS; + } + if (res->base.nr_samples > 4) dw[4] |= GEN7_SURFACE_MULTISAMPLECOUNT_8; else if (res->base.nr_samples > 2) diff --git a/src/gallium/drivers/ilo/ilo_resource.c b/src/gallium/drivers/ilo/ilo_resource.c index a1f414035dc..b480601371a 100644 --- a/src/gallium/drivers/ilo/ilo_resource.c +++ b/src/gallium/drivers/ilo/ilo_resource.c @@ -442,6 +442,7 @@ struct layout_tex_info { int block_width, block_height; int align_i, align_j; bool array_spacing_full; + bool interleaved; int qpitch; struct { @@ -629,24 +630,45 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info) if (is->dev.gen >= ILO_GEN(7)) { /* - * From the Ivy Bridge PRM, volume 1 part 1, page 111: + * It is not explicitly states, but render targets are expected to be + * UMS/CMS (samples non-interleaved) and depth/stencil buffers are + * expected to be IMS (samples interleaved). * - * "note that the depth buffer and stencil buffer have an implied - * value of ARYSPC_FULL" - * - * From the Ivy Bridge PRM, volume 4 part 1, page 66: - * - * "If Multisampled Surface Storage Format is MSFMT_MSS and Number - * of Multisamples is not MULTISAMPLECOUNT_1, this field (Surface - * Array Spacing) must be set to ARYSPC_LOD0." - * - * We use ARYSPC_FULL only when needed, and as such, we never use - * ARYSPC_FULL for multisampled resources. + * See "Multisampled Surface Storage Format" field of SURFACE_STATE. */ - info->array_spacing_full = (templ->last_level > 0 || - util_format_is_depth_or_stencil(templ->format)); + if (util_format_is_depth_or_stencil(templ->format)) { + info->interleaved = true; + + /* + * 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" + */ + info->array_spacing_full = true; + } + else { + info->interleaved = false; + + /* + * From the Ivy Bridge PRM, volume 4 part 1, page 66: + * + * "If Multisampled Surface Storage Format is MSFMT_MSS and + * Number of Multisamples is not MULTISAMPLECOUNT_1, this field + * (Surface Array Spacing) must be set to ARYSPC_LOD0." + * + * As multisampled resources are not mipmapped, we never use + * ARYSPC_FULL for them. + */ + if (templ->nr_samples > 1) + assert(templ->last_level == 0); + info->array_spacing_full = (templ->last_level > 0); + } } else { + /* GEN6 supports only interleaved samples */ + info->interleaved = true; + /* * From the Sandy Bridge PRM, volume 1 part 1, page 115: * @@ -695,10 +717,61 @@ layout_tex_init(const struct ilo_resource *res, struct layout_tex_info *info) * * W_L = ceiling(W_L / 2) * 4 * H_L = ceiling(H_L / 2) * 4" + * + * From the Ivy Bridge PRM, volume 1 part 1, page 108: + * + * "If the surface is multisampled and it is a depth or stencil + * surface or Multisampled Surface StorageFormat in SURFACE_STATE + * is MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows + * before proceeding: + * + * #samples W_L = H_L = + * 2 ceiling(W_L / 2) * 4 HL [no adjustment] + * 4 ceiling(W_L / 2) * 4 ceiling(H_L / 2) * 4 + * 8 ceiling(W_L / 2) * 8 ceiling(H_L / 2) * 4 + * 16 ceiling(W_L / 2) * 8 ceiling(H_L / 2) * 8" + * + * For interleaved samples (4x), where pixels + * + * (x, y ) (x+1, y ) + * (x, y+1) (x+1, y+1) + * + * would be is occupied by + * + * (x, y , si0) (x+1, y , si0) (x, y , si1) (x+1, y , si1) + * (x, y+1, si0) (x+1, y+1, si0) (x, y+1, si1) (x+1, y+1, si1) + * (x, y , si2) (x+1, y , si2) (x, y , si3) (x+1, y , si3) + * (x, y+1, si2) (x+1, y+1, si2) (x, y+1, si3) (x+1, y+1, si3) + * + * Thus the need to + * + * w = align(w, 2) * 2; + * y = align(y, 2) * 2; */ - if (templ->nr_samples > 1) { - w = align(w, 2) * 2; - h = align(h, 2) * 2; + if (info->interleaved) { + switch (templ->nr_samples) { + case 0: + case 1: + break; + case 2: + w = align(w, 2) * 2; + break; + case 4: + w = align(w, 2) * 2; + h = align(h, 2) * 2; + break; + case 8: + w = align(w, 2) * 4; + h = align(h, 2) * 2; + break; + case 16: + w = align(w, 2) * 4; + h = align(h, 2) * 4; + break; + default: + assert(!"unsupported sample count"); + break; + } } info->sizes[lv].w = w; @@ -767,7 +840,7 @@ static void layout_tex_2d(struct ilo_resource *res, const struct layout_tex_info *info) { const struct pipe_resource *templ = &res->base; - unsigned int level_x, level_y; + unsigned int level_x, level_y, num_slices; int lv; res->bo_width = 0; @@ -799,8 +872,13 @@ layout_tex_2d(struct ilo_resource *res, const struct layout_tex_info *info) level_y += align(level_h, info->align_j); } + num_slices = templ->array_size; + /* samples of the same index are stored in a slice */ + if (templ->nr_samples > 1 && !info->interleaved) + num_slices *= templ->nr_samples; + /* we did not take slices into consideration in the computation above */ - res->bo_height += info->qpitch * (templ->array_size - 1); + res->bo_height += info->qpitch * (num_slices - 1); } /** @@ -987,6 +1065,7 @@ init_texture(struct ilo_resource *res) res->halign_8 = (info.align_i == 8); res->valign_4 = (info.align_j == 4); res->array_spacing_full = info.array_spacing_full; + res->interleaved = info.interleaved; switch (res->base.target) { case PIPE_TEXTURE_1D: @@ -1030,6 +1109,7 @@ init_buffer(struct ilo_resource *res) res->halign_8 = false; res->valign_4 = false; res->array_spacing_full = false; + res->interleaved = false; } static struct pipe_resource * diff --git a/src/gallium/drivers/ilo/ilo_resource.h b/src/gallium/drivers/ilo/ilo_resource.h index 96464724942..89ad8c20811 100644 --- a/src/gallium/drivers/ilo/ilo_resource.h +++ b/src/gallium/drivers/ilo/ilo_resource.h @@ -69,6 +69,8 @@ struct ilo_resource { bool halign_8, valign_4; /* true if space is reserved between layers */ bool array_spacing_full; + /* true if samples are interleaved */ + bool interleaved; /* 2D offsets into a layer/slice/face */ struct { |