summaryrefslogtreecommitdiffstats
path: root/src/isl
diff options
context:
space:
mode:
authorChad Versace <[email protected]>2015-12-11 17:14:52 -0800
committerChad Versace <[email protected]>2015-12-15 08:46:09 -0800
commit64f0ee73e0ade5b6f888b143a1db58ffabfffd99 (patch)
treebbcb82e2e71afb6e5e0190ab3b2c2007d4db1c1d /src/isl
parent53504b884e58af6bcf92e3fd258c7d9d3332c1fc (diff)
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).
Diffstat (limited to 'src/isl')
-rw-r--r--src/isl/Makefile.am21
-rw-r--r--src/isl/isl.c124
-rw-r--r--src/isl/isl.h16
-rw-r--r--src/isl/tests/.gitignore1
-rw-r--r--src/isl/tests/isl_surf_get_image_offset_test.c197
5 files changed, 357 insertions, 2 deletions
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 <assert.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#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();
+}