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).
This commit is contained in:
Chad Versace
2015-12-11 17:14:52 -08:00
parent 53504b884e
commit 64f0ee73e0
5 changed files with 357 additions and 2 deletions
+21
View File
@@ -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
+122 -2
View File
@@ -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;
}
}
+16
View File
@@ -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
+1
View File
@@ -0,0 +1 @@
/isl_surf_get_image_offset_test
@@ -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();
}