From 64f0ee73e0ade5b6f888b143a1db58ffabfffd99 Mon Sep 17 00:00:00 2001 From: Chad Versace Date: Fri, 11 Dec 2015 17:14:52 -0800 Subject: [PATCH] isl: Add func isl_surf_get_image_offset_sa The function calculates the offset to a subimage within the surface, in units of surface samples. All unit tests pass with `make check`. (Admittedly, though, there are too few unit tests). --- src/isl/Makefile.am | 21 ++ src/isl/isl.c | 124 ++++++++++- src/isl/isl.h | 16 ++ src/isl/tests/.gitignore | 1 + .../tests/isl_surf_get_image_offset_test.c | 197 ++++++++++++++++++ 5 files changed, 357 insertions(+), 2 deletions(-) create mode 100644 src/isl/tests/.gitignore create mode 100644 src/isl/tests/isl_surf_get_image_offset_test.c diff --git a/src/isl/Makefile.am b/src/isl/Makefile.am index 6a5c29c67cb..134e62ad105 100644 --- a/src/isl/Makefile.am +++ b/src/isl/Makefile.am @@ -23,6 +23,8 @@ SUBDIRS = . noinst_LTLIBRARIES = libisl.la +EXTRA_DIST = tests + # The gallium includes are for the util/u_math.h include from main/macros.h AM_CPPFLAGS = \ $(INTEL_CFLAGS) \ @@ -64,4 +66,23 @@ isl_format_layout.c: isl_format_layout_gen.bash \ $(AM_V_GEN)$(srcdir)/isl_format_layout_gen.bash \ <$(srcdir)/isl_format_layout.csv >$@ +# ---------------------------------------------------------------------------- +# Tests +# ---------------------------------------------------------------------------- + +TESTS = tests/isl_surf_get_image_offset_test + +check_PROGRAMS = $(TESTS) + +# Link tests to lib965_compiler.la for brw_get_device_info(). +tests_ldadd = \ + libisl.la \ + $(top_builddir)/src/mesa/drivers/dri/i965/libi965_compiler.la + +tests_isl_surf_get_image_offset_test_SOURCES = \ + tests/isl_surf_get_image_offset_test.c +tests_isl_surf_get_image_offset_test_LDADD = $(tests_ldadd) + +# ---------------------------------------------------------------------------- + include $(top_srcdir)/install-lib-links.mk diff --git a/src/isl/isl.c b/src/isl/isl.c index 333a517f274..df0aeed01df 100644 --- a/src/isl/isl.c +++ b/src/isl/isl.c @@ -225,8 +225,10 @@ isl_msaa_interleaved_scale_px_to_sa(uint32_t samples, * MSFMT_DEPTH_STENCIL, W_L and H_L must be adjusted as follows before * proceeding: [...] */ - *width = isl_align(*width, 2) << ((ffs(samples) - 0) / 2); - *height = isl_align(*height, 2) << ((ffs(samples) - 1) / 2); + if (width) + *width = isl_align(*width, 2) << ((ffs(samples) - 0) / 2); + if (height) + *height = isl_align(*height, 2) << ((ffs(samples) - 1) / 2); } static enum isl_array_pitch_span @@ -1045,3 +1047,121 @@ isl_surf_init_s(const struct isl_device *dev, return true; } + +/** + * A variant of isl_surf_get_image_offset_sa() specific to + * ISL_DIM_LAYOUT_GEN4_2D. + */ +static void +get_image_offset_sa_gen4_2d(const struct isl_surf *surf, + uint32_t level, uint32_t layer, + uint32_t *x_offset_sa, + uint32_t *y_offset_sa) +{ + assert(level < surf->levels); + assert(layer < surf->phys_level0_sa.array_len); + assert(surf->phys_level0_sa.depth == 1); + + const struct isl_extent3d image_align_sa = + isl_surf_get_image_alignment_sa(surf); + + const uint32_t W0 = surf->phys_level0_sa.width; + const uint32_t H0 = surf->phys_level0_sa.height; + + uint32_t x = 0; + uint32_t y = layer * isl_surf_get_array_pitch_sa_rows(surf); + + for (uint32_t l = 0; l < level; ++l) { + if (l == 1) { + uint32_t W = isl_minify(W0, l); + + if (surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED) + isl_msaa_interleaved_scale_px_to_sa(surf->samples, &W, NULL); + + x += isl_align_npot(W, image_align_sa.w); + } else { + uint32_t H = isl_minify(H0, l); + + if (surf->msaa_layout == ISL_MSAA_LAYOUT_INTERLEAVED) + isl_msaa_interleaved_scale_px_to_sa(surf->samples, NULL, &H); + + y += isl_align_npot(H, image_align_sa.h); + } + } + + *x_offset_sa = x; + *y_offset_sa = y; +} + +/** + * A variant of isl_surf_get_image_offset_sa() specific to + * ISL_DIM_LAYOUT_GEN4_3D. + */ +static void +get_image_offset_sa_gen4_3d(const struct isl_surf *surf, + uint32_t level, uint32_t logical_z_offset_px, + uint32_t *x_offset_sa, + uint32_t *y_offset_sa) +{ + assert(level < surf->levels); + assert(logical_z_offset_px < isl_minify(surf->phys_level0_sa.depth, level)); + assert(surf->phys_level0_sa.array_len == 1); + + const struct isl_extent3d image_align_sa = + isl_surf_get_image_alignment_sa(surf); + + const uint32_t W0 = surf->phys_level0_sa.width; + const uint32_t H0 = surf->phys_level0_sa.height; + const uint32_t D0 = surf->phys_level0_sa.depth; + + uint32_t x = 0; + uint32_t y = 0; + + for (uint32_t l = 0; l < level; ++l) { + const uint32_t level_h = isl_align_npot(isl_minify(H0, l), image_align_sa.h); + const uint32_t level_d = isl_align_npot(isl_minify(D0, l), image_align_sa.d); + const uint32_t max_layers_vert = isl_align(level_d, 1u << l) / (1u << l); + + y += level_h * max_layers_vert; + } + + const uint32_t level_w = isl_align_npot(isl_minify(W0, level), image_align_sa.w); + const uint32_t level_h = isl_align_npot(isl_minify(H0, level), image_align_sa.h); + const uint32_t level_d = isl_align_npot(isl_minify(D0, level), image_align_sa.d); + + const uint32_t max_layers_horiz = MIN(level_d, 1u << level); + const uint32_t max_layers_vert = isl_align_div(level_d, 1u << level); + + x += level_w * (logical_z_offset_px % max_layers_horiz); + y += level_h * (logical_z_offset_px / max_layers_vert); + + *x_offset_sa = x; + *y_offset_sa = y; +} + +void +isl_surf_get_image_offset_sa(const struct isl_surf *surf, + uint32_t level, + uint32_t logical_array_layer, + uint32_t logical_z_offset_px, + uint32_t *x_offset_sa, + uint32_t *y_offset_sa) +{ + assert(level < surf->levels); + assert(logical_array_layer < surf->logical_level0_px.array_len); + assert(logical_z_offset_px + < isl_minify(surf->logical_level0_px.depth, level)); + + switch (surf->dim_layout) { + case ISL_DIM_LAYOUT_GEN9_1D: + isl_finishme("%s:%s: gen9 1d surfaces", __FILE__, __func__); + case ISL_DIM_LAYOUT_GEN4_2D: + get_image_offset_sa_gen4_2d(surf, level, logical_array_layer, + x_offset_sa, y_offset_sa); + break; + case ISL_DIM_LAYOUT_GEN4_3D: + get_image_offset_sa_gen4_3d(surf, level, logical_z_offset_px, + x_offset_sa, y_offset_sa); + break; + } +} diff --git a/src/isl/isl.h b/src/isl/isl.h index 184b0c5f70a..6baac38bc2a 100644 --- a/src/isl/isl.h +++ b/src/isl/isl.h @@ -912,6 +912,22 @@ isl_surf_get_array_pitch(const struct isl_surf *surf) return isl_surf_get_array_pitch_sa_rows(surf) * surf->row_pitch; } +/** + * Get the offset to an subimage within the surface, in units of surface + * samples. + * + * @invariant level < surface levels + * @invariant logical_array_layer < logical array length of surface + * @invariant logical_z_offset_px < logical depth of surface at level + */ +void +isl_surf_get_image_offset_sa(const struct isl_surf *surf, + uint32_t level, + uint32_t logical_array_layer, + uint32_t logical_z_offset_px, + uint32_t *x_offset_sa, + uint32_t *y_offset_sa); + #ifdef __cplusplus } #endif diff --git a/src/isl/tests/.gitignore b/src/isl/tests/.gitignore new file mode 100644 index 00000000000..ba70ecfbee4 --- /dev/null +++ b/src/isl/tests/.gitignore @@ -0,0 +1 @@ +/isl_surf_get_image_offset_test diff --git a/src/isl/tests/isl_surf_get_image_offset_test.c b/src/isl/tests/isl_surf_get_image_offset_test.c new file mode 100644 index 00000000000..78362be4310 --- /dev/null +++ b/src/isl/tests/isl_surf_get_image_offset_test.c @@ -0,0 +1,197 @@ +/* + * Copyright 2015 Intel Corporation + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice (including the next + * paragraph) shall be included in all copies or substantial portions of the + * Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER + * DEALINGS IN THE SOFTWARE. + */ + +#include +#include +#include +#include + +#include "brw_device_info.h" +#include "isl.h" + +#define BDW_GT2_DEVID 0x161a + +// An asssert that works regardless of NDEBUG. +#define t_assert(cond) \ + do { \ + if (!(cond)) { \ + fprintf(stderr, "%s:%d: assertion failed\n", __FILE__, __LINE__); \ + abort(); \ + } \ + } while (0) + +static void +t_assert_extent4d(const struct isl_extent4d *e, uint32_t width, + uint32_t height, uint32_t depth, uint32_t array_len) +{ + t_assert(e->width == width); + t_assert(e->height == height); + t_assert(e->depth == depth); + t_assert(e->array_len == array_len); +} + +static void +t_assert_image_alignment_el(const struct isl_surf *surf, + uint32_t w, uint32_t h, uint32_t d) +{ + struct isl_extent3d align_el; + + align_el = isl_surf_get_image_alignment_el(surf); + t_assert(align_el.w == w); + t_assert(align_el.h == h); + t_assert(align_el.d == d); + +} + +static void +t_assert_image_alignment_sa(const struct isl_surf *surf, + uint32_t w, uint32_t h, uint32_t d) +{ + struct isl_extent3d align_sa; + + align_sa = isl_surf_get_image_alignment_sa(surf); + t_assert(align_sa.w == w); + t_assert(align_sa.h == h); + t_assert(align_sa.d == d); + +} + +static void +t_assert_offset(const struct isl_surf *surf, + uint32_t level, + uint32_t logical_array_layer, + uint32_t logical_z_offset_px, + uint32_t expected_x_offset_sa, + uint32_t expected_y_offset_sa) +{ + uint32_t x, y; + isl_surf_get_image_offset_sa(surf, level, logical_array_layer, + logical_z_offset_px, &x, &y); + + t_assert(x == expected_x_offset_sa); + t_assert(y == expected_y_offset_sa); +} + +static void +t_assert_phys_level0_sa(const struct isl_surf *surf, uint32_t width, + uint32_t height, uint32_t depth, uint32_t array_len) +{ + t_assert_extent4d(&surf->phys_level0_sa, width, height, depth, array_len); +} + +static void +test_bdw_2d_r8g8b8a8_unorm_512x512_a1_s1_noaux_y0(void) +{ + bool ok; + + struct isl_device dev; + isl_device_init(&dev, brw_get_device_info(BDW_GT2_DEVID)); + + struct isl_surf surf; + ok = isl_surf_init(&dev, &surf, + .dim = ISL_SURF_DIM_2D, + .format = ISL_FORMAT_R8G8B8A8_UNORM, + .width = 512, + .height = 512, + .depth = 1, + .levels = 10, + .array_len = 1, + .samples = 1, + .usage = ISL_SURF_USAGE_TEXTURE_BIT | + ISL_SURF_USAGE_DISABLE_AUX_BIT, + .tiling_flags = ISL_TILING_Y0_BIT); + t_assert(ok); + + t_assert_image_alignment_el(&surf, 4, 4, 1); + t_assert_image_alignment_sa(&surf, 4, 4, 1); + t_assert_phys_level0_sa(&surf, 512, 512, 1, 1); + t_assert(isl_surf_get_array_pitch_el_rows(&surf) >= 772); + t_assert(isl_surf_get_array_pitch_sa_rows(&surf) >= 772); + + t_assert_offset(&surf, 0, 0, 0, 0, 0); // +0, +0 + t_assert_offset(&surf, 1, 0, 0, 0, 512); // +0, +512 + t_assert_offset(&surf, 2, 0, 0, 256, 512); // +256, +0 + t_assert_offset(&surf, 3, 0, 0, 256, 640); // +0, +128 + t_assert_offset(&surf, 4, 0, 0, 256, 704); // +0, +64 + t_assert_offset(&surf, 5, 0, 0, 256, 736); // +0, +32 + t_assert_offset(&surf, 6, 0, 0, 256, 752); // +0, +16 + t_assert_offset(&surf, 7, 0, 0, 256, 760); // +0, +8 + t_assert_offset(&surf, 8, 0, 0, 256, 764); // +0, +4 + t_assert_offset(&surf, 9, 0, 0, 256, 768); // +0, +4 +} + +static void +test_bdw_2d_r8g8b8a8_unorm_1024x1024_a6_s1_noaux_y0(void) +{ + bool ok; + + struct isl_device dev; + isl_device_init(&dev, brw_get_device_info(BDW_GT2_DEVID)); + + struct isl_surf surf; + ok = isl_surf_init(&dev, &surf, + .dim = ISL_SURF_DIM_2D, + .format = ISL_FORMAT_R8G8B8A8_UNORM, + .width = 1024, + .height = 1024, + .depth = 1, + .levels = 11, + .array_len = 6, + .samples = 1, + .usage = ISL_SURF_USAGE_TEXTURE_BIT | + ISL_SURF_USAGE_DISABLE_AUX_BIT, + .tiling_flags = ISL_TILING_Y0_BIT); + t_assert(ok); + + t_assert_image_alignment_el(&surf, 4, 4, 1); + t_assert_image_alignment_sa(&surf, 4, 4, 1); + t_assert_image_alignment_sa(&surf, 4, 4, 1); + t_assert(isl_surf_get_array_pitch_el_rows(&surf) >= 1540); + t_assert(isl_surf_get_array_pitch_sa_rows(&surf) >= 1540); + + for (uint32_t a = 0; a < 6; ++a) { + uint32_t b = a * isl_surf_get_array_pitch_sa_rows(&surf); + + t_assert_offset(&surf, 0, a, 0, 0, b + 0); // +0, +0 + t_assert_offset(&surf, 1, a, 0, 0, b + 1024); // +0, +1024 + t_assert_offset(&surf, 2, a, 0, 512, b + 1024); // +512, +0 + t_assert_offset(&surf, 3, a, 0, 512, b + 1280); // +0, +256 + t_assert_offset(&surf, 4, a, 0, 512, b + 1408); // +0, +128 + t_assert_offset(&surf, 5, a, 0, 512, b + 1472); // +0, +64 + t_assert_offset(&surf, 6, a, 0, 512, b + 1504); // +0, +32 + t_assert_offset(&surf, 7, a, 0, 512, b + 1520); // +0, +16 + t_assert_offset(&surf, 8, a, 0, 512, b + 1528); // +0, +8 + t_assert_offset(&surf, 9, a, 0, 512, b + 1532); // +0, +4 + t_assert_offset(&surf, 10, a, 0, 512, b + 1536); // +0, +4 + } +} + +int main(void) +{ + /* FINISHME: Add tests for npot sizes */ + /* FINISHME: Add tests for 1D surfaces */ + /* FINISHME: Add tests for 3D surfaces */ + + test_bdw_2d_r8g8b8a8_unorm_512x512_a1_s1_noaux_y0(); + test_bdw_2d_r8g8b8a8_unorm_1024x1024_a6_s1_noaux_y0(); +} -- 2.30.2