static bool tex_create_hiz(struct ilo_texture *tex) { const struct pipe_resource *templ = &tex->base; struct ilo_screen *is = ilo_screen(tex->base.screen); unsigned lv; tex->aux_bo = intel_winsys_alloc_bo(is->winsys, "hiz texture", INTEL_TILING_Y, tex->layout.aux_stride, tex->layout.aux_height, false); if (!tex->aux_bo) return false; for (lv = 0; lv <= templ->last_level; lv++) { if (tex->layout.aux_enables & (1 << lv)) { const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ? u_minify(templ->depth0, lv) : templ->array_size; unsigned flags = ILO_TEXTURE_HIZ; /* this will trigger a HiZ resolve */ if (tex->imported) flags |= ILO_TEXTURE_CPU_WRITE; ilo_texture_set_slice_flags(tex, lv, 0, num_slices, flags, flags); } } return true; }
static bool tex_create_hiz(struct ilo_texture *tex, const struct tex_layout *layout) { struct ilo_screen *is = ilo_screen(tex->base.screen); const struct pipe_resource *templ = layout->templ; const int hz_align_j = 8; unsigned hz_width, hz_height, lv; unsigned long pitch; /* * See the Sandy Bridge PRM, volume 2 part 1, page 312, and the Ivy Bridge * PRM, volume 2 part 1, page 312-313. * * It seems HiZ buffer is aligned to 8x8, with every two rows packed into a * memory row. */ hz_width = align(layout->levels[0].w, 16); if (templ->target == PIPE_TEXTURE_3D) { hz_height = 0; for (lv = 0; lv <= templ->last_level; lv++) { const unsigned h = align(layout->levels[lv].h, hz_align_j); hz_height += h * layout->levels[lv].d; } hz_height /= 2; } else { const unsigned h0 = align(layout->levels[0].h, hz_align_j); unsigned hz_qpitch = h0; if (layout->array_spacing_full) { const unsigned h1 = align(layout->levels[1].h, hz_align_j); const unsigned htail = ((layout->dev->gen >= ILO_GEN(7)) ? 12 : 11) * hz_align_j; hz_qpitch += h1 + htail; } hz_height = hz_qpitch * templ->array_size / 2; if (layout->dev->gen >= ILO_GEN(7)) hz_height = align(hz_height, 8); } tex->hiz.bo = intel_winsys_alloc_texture(is->winsys, "hiz texture", hz_width, hz_height, 1, INTEL_TILING_Y, INTEL_ALLOC_FOR_RENDER, &pitch); if (!tex->hiz.bo) return false; tex->hiz.bo_stride = pitch; /* * From the Sandy Bridge PRM, volume 2 part 1, page 313-314: * * "A rectangle primitive representing the clear area is delivered. The * primitive must adhere to the following restrictions on size: * * - If Number of Multisamples is NUMSAMPLES_1, the rectangle must be * aligned to an 8x4 pixel block relative to the upper left corner * of the depth buffer, and contain an integer number of these pixel * blocks, and all 8x4 pixels must be lit. * * - If Number of Multisamples is NUMSAMPLES_4, the rectangle must be * aligned to a 4x2 pixel block (8x4 sample block) relative to the * upper left corner of the depth buffer, and contain an integer * number of these pixel blocks, and all samples of the 4x2 pixels * must be lit * * - If Number of Multisamples is NUMSAMPLES_8, the rectangle must be * aligned to a 2x2 pixel block (8x4 sample block) relative to the * upper left corner of the depth buffer, and contain an integer * number of these pixel blocks, and all samples of the 2x2 pixels * must be list." * * "The following is required when performing a depth buffer resolve: * * - A rectangle primitive of the same size as the previous depth * buffer clear operation must be delivered, and depth buffer state * cannot have changed since the previous depth buffer clear * operation." * * Experiments on Haswell show that depth buffer resolves have the same * alignment requirements, and aligning the RECTLIST primitive and * 3DSTATE_DRAWING_RECTANGLE alone are not enough. The mipmap size must be * aligned. */ for (lv = 0; lv <= templ->last_level; lv++) { unsigned align_w = 8, align_h = 4; switch (templ->nr_samples) { case 0: case 1: break; case 2: align_w /= 2; break; case 4: align_w /= 2; align_h /= 2; break; case 8: default: align_w /= 4; align_h /= 2; break; } if (u_minify(templ->width0, lv) % align_w == 0 && u_minify(templ->height0, lv) % align_h == 0) { const unsigned num_slices = (templ->target == PIPE_TEXTURE_3D) ? u_minify(templ->depth0, lv) : templ->array_size; ilo_texture_set_slice_flags(tex, lv, 0, num_slices, ILO_TEXTURE_HIZ, ILO_TEXTURE_HIZ); } } return true; }