[Mesa-dev] [PATCH 06/12] util: Add tests for fast integer division by constants
Marek Olšák
maraeo at gmail.com
Sat Oct 6 18:51:49 UTC 2018
With my comments addressed, patches 2 - 6 are:
Reviewed-by: Marek Olšák <marek.olsak at amd.com>
Since I will need to compute the division terms during draw calls, I
may need to switch the math to uint32_t for my case (e.g. via a C++
template).
Marek
On Sat, Oct 6, 2018 at 12:11 AM Jason Ekstrand <jason at jlekstrand.net> wrote:
>> While I generally trust rediculousfish to have done his homework, we've
> made some adjustments to suite the needs of mesa and it'd be good to
> test those. Also, there's no better place than unit tests to clearly
> document the different edge cases of the different methods.
> ---
> configure.ac | 1 +
> src/util/Makefile.am | 3 +-
> src/util/meson.build | 1 +
> src/util/tests/fast_idiv_by_const/Makefile.am | 43 ++
> .../fast_idiv_by_const_test.cpp | 472 ++++++++++++++++++
> src/util/tests/fast_idiv_by_const/meson.build | 30 ++
> 6 files changed, 549 insertions(+), 1 deletion(-)
> create mode 100644 src/util/tests/fast_idiv_by_const/Makefile.am
> create mode 100644 src/util/tests/fast_idiv_by_const/fast_idiv_by_const_test.cpp
> create mode 100644 src/util/tests/fast_idiv_by_const/meson.build
>
> diff --git a/configure.ac b/configure.ac
> index 34689826c98..7b0b2b20ba2 100644
> --- a/configure.ac
> +++ b/configure.ac
> @@ -3198,6 +3198,7 @@ AC_CONFIG_FILES([Makefile
> src/util/tests/hash_table/Makefile
> src/util/tests/set/Makefile
> src/util/tests/string_buffer/Makefile
> + src/util/tests/uint_inverse/Makefile
> src/util/tests/vma/Makefile
> src/util/xmlpool/Makefile
> src/vulkan/Makefile])
> diff --git a/src/util/Makefile.am b/src/util/Makefile.am
> index d79f2b320be..9e633bf65d5 100644
> --- a/src/util/Makefile.am
> +++ b/src/util/Makefile.am
> @@ -24,7 +24,8 @@ SUBDIRS = . \
> tests/fast_idiv_by_const \
> tests/hash_table \
> tests/string_buffer \
> - tests/set
> + tests/set \
> + tests/uint_inverse
>
> if HAVE_STD_CXX11
> SUBDIRS += tests/vma
> diff --git a/src/util/meson.build b/src/util/meson.build
> index cdbad98e7cb..49d84c16ebe 100644
> --- a/src/util/meson.build
> +++ b/src/util/meson.build
> @@ -170,6 +170,7 @@ if with_tests
> )
> )
>
> + subdir('tests/fast_idiv_by_const')
> subdir('tests/hash_table')
> subdir('tests/string_buffer')
> subdir('tests/vma')
> diff --git a/src/util/tests/fast_idiv_by_const/Makefile.am b/src/util/tests/fast_idiv_by_const/Makefile.am
> new file mode 100644
> index 00000000000..1ebee09f59b
> --- /dev/null
> +++ b/src/util/tests/fast_idiv_by_const/Makefile.am
> @@ -0,0 +1,43 @@
> +# Copyright © 2018 Intel
> +#
> +# 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.
> +
> +AM_CPPFLAGS = \
> + -I$(top_srcdir)/src \
> + -I$(top_srcdir)/include \
> + -I$(top_srcdir)/src/gallium/include \
> + -I$(top_srcdir)/src/gtest/include \
> + $(PTHREAD_CFLAGS) \
> + $(DEFINES)
> +
> +TESTS = fast_idiv_by_const_test
> +
> +check_PROGRAMS = $(TESTS)
> +
> +fast_idiv_by_const_test_SOURCES = \
> + fast_idiv_by_const_test.cpp
> +
> +fast_idiv_by_const_test_LDADD = \
> + $(top_builddir)/src/gtest/libgtest.la \
> + $(top_builddir)/src/util/libmesautil.la \
> + $(PTHREAD_LIBS) \
> + $(DLOPEN_LIBS)
> +
> +EXTRA_DIST = meson.build
> diff --git a/src/util/tests/fast_idiv_by_const/fast_idiv_by_const_test.cpp b/src/util/tests/fast_idiv_by_const/fast_idiv_by_const_test.cpp
> new file mode 100644
> index 00000000000..34b149e1c6f
> --- /dev/null
> +++ b/src/util/tests/fast_idiv_by_const/fast_idiv_by_const_test.cpp
> @@ -0,0 +1,472 @@
> +/*
> + * Copyright © 2018 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 <gtest/gtest.h>
> +#include "util/bigmath.h"
> +#include "util/fast_idiv_by_const.h"
> +#include "util/u_math.h"
> +
> +#define RAND_TEST_ITERATIONS 100000
> +
> +#define MAX_UINT(bits) \
> + (((bits) == 64) ? UINT64_MAX : ((1ull << (bits)) - 1))
> +
> +static inline uint64_t
> +utrunc(uint64_t x, unsigned num_bits)
> +{
> + if (num_bits == 64)
> + return x;
> +
> + return (x << (64 - num_bits)) >> (64 - num_bits);
> +}
> +
> +static inline int64_t
> +strunc(int64_t x, unsigned num_bits)
> +{
> + if (num_bits == 64)
> + return x;
> +
> + return (x << (64 - num_bits)) >> (64 - num_bits);
> +}
> +
> +static inline bool
> +uint_is_in_range(uint64_t x, unsigned num_bits)
> +{
> + if (num_bits == 64)
> + return true;
> +
> + return x < (1ull << num_bits);
> +}
> +
> +static inline bool
> +sint_is_in_range(int64_t x, unsigned num_bits)
> +{
> + if (num_bits == 64)
> + return true;
> +
> + return x >= -(1ll << (num_bits - 1)) &&
> + x < (1ll << (num_bits - 1));
> +}
> +
> +static inline uint64_t
> +uadd_sat(uint64_t a, uint64_t b, unsigned num_bits)
> +{
> + assert(uint_is_in_range(a, num_bits));
> + assert(uint_is_in_range(b, num_bits));
> +
> + uint64_t sum = a + b;
> + if (num_bits == 64) {
> + /* Standard overflow check */
> + return sum < a ? UINT64_MAX : sum;
> + } else {
> + /* Check if sum is more than num_bits */
> + return (sum >> num_bits) ? MAX_UINT(num_bits) : sum;
> + }
> +}
> +
> +static inline uint64_t
> +umul_add_high(uint64_t a, uint64_t b, uint64_t c, unsigned num_bits)
> +{
> + assert(uint_is_in_range(a, num_bits));
> + assert(uint_is_in_range(b, num_bits));
> + assert(uint_is_in_range(c, num_bits));
> +
> + if (num_bits == 64) {
> + uint32_t a32[2] = { (uint32_t)a, (uint32_t)(a >> 32) };
> + uint32_t b32[2] = { (uint32_t)b, (uint32_t)(b >> 32) };
> + uint32_t c32[2] = { (uint32_t)c, (uint32_t)(c >> 32) };
> +
> + uint32_t ab32[4];
> + ubm_mul_u32arr(ab32, a32, b32);
> +
> + uint32_t abc32[4];
> + ubm_add_u32arr(abc32, ab32, c32);
> +
> + return abc32[2] | ((uint64_t)abc32[3] << 32);
> + } else {
> + assert(num_bits <= 32);
> + return utrunc(((a * b) + c) >> num_bits, num_bits);
> + }
> +}
> +
> +static inline int64_t
> +smul_high(int64_t a, int64_t b, unsigned num_bits)
> +{
> + assert(sint_is_in_range(a, num_bits));
> + assert(sint_is_in_range(b, num_bits));
> +
> + if (num_bits == 64) {
> + uint32_t a32[4] = {
> + (uint32_t)a,
> + (uint32_t)(a >> 32),
> + (uint32_t)(a >> 63), /* sign extend */
> + (uint32_t)(a >> 63), /* sign extend */
> + };
> + uint32_t b32[4] = {
> + (uint32_t)b,
> + (uint32_t)(b >> 32),
> + (uint32_t)(b >> 63), /* sign extend */
> + (uint32_t)(b >> 63), /* sign extend */
> + };
> +
> + uint32_t ab32[4];
> + ubm_mul_u32arr(ab32, a32, b32);
> +
> + return ab32[2] | ((uint64_t)ab32[3] << 32);
> + } else {
> + assert(num_bits <= 32);
> + return strunc((a * b) >> num_bits, num_bits);
> + }
> +}
> +
> +static inline uint64_t
> +fast_udiv_add_sat(uint64_t n, struct util_fast_udiv_info m, unsigned num_bits)
> +{
> + assert(uint_is_in_range(n, num_bits));
> + assert(uint_is_in_range(m.multiplier, num_bits));
> +
> + n = n >> m.pre_shift;
> + n = uadd_sat(n, m.increment, num_bits);
> + n = umul_add_high(n, m.multiplier, 0, num_bits);
> + n = n >> m.post_shift;
> +
> + return n;
> +}
> +
> +static inline uint64_t
> +fast_udiv_mul_add(uint64_t n, struct util_fast_udiv_info m, unsigned num_bits)
> +{
> + assert(uint_is_in_range(n, num_bits));
> + assert(uint_is_in_range(m.multiplier, num_bits));
> +
> + n = n >> m.pre_shift;
> + n = umul_add_high(n, m.multiplier,
> + m.increment ? m.multiplier : 0,
> + num_bits);
> + n = n >> m.post_shift;
> +
> + return n;
> +}
> +
> +static inline uint64_t
> +fast_sdiv(int64_t n, int64_t d, struct util_fast_sdiv_info m, unsigned num_bits)
> +{
> + assert(sint_is_in_range(n, num_bits));
> + assert(sint_is_in_range(d, num_bits));
> + assert(sint_is_in_range(m.multiplier, num_bits));
> +
> + int64_t res;
> + res = smul_high(n, m.multiplier, num_bits);
> + if (d > 0 && m.multiplier < 0)
> + res = strunc(res + n, num_bits);
> + if (d < 0 && m.multiplier > 0)
> + res = strunc(res - n, num_bits);
> + res = res >> m.shift;
> + res = res - (res >> (num_bits - 1));
> +
> + return res;
> +}
> +
> +static uint64_t
> +rand_uint(unsigned bits, unsigned min)
> +{
> + assert(bits >= 4);
> +
> + /* Make sure we get some small and large numbers and powers of two every
> + * once in a while
> + */
> + int k = rand() % 64;
> + if (k == 17) {
> + return min + (rand() % 16);
> + } else if (k == 42) {
> + return MAX_UINT(bits) - (rand() % 16);
> + } else if (k == 9) {
> + uint64_t r;
> + do {
> + r = 1ull << (rand() % bits);
> + } while (r < min);
> + return r;
> + }
> +
> + if (min == 0) {
> + assert(bits <= 64);
> + uint64_t r = 0;
> + for (unsigned i = 0; i < 8; i++)
> + r |= ((uint64_t)rand() & 0xf) << i * 8;
> + return r >> (63 - (rand() % bits));
> + } else {
> + uint64_t r;
> + do {
> + r = rand_uint(bits, 0);
> + } while (r < min);
> + return r;
> + }
> +}
> +
> +static int64_t
> +rand_sint(unsigned bits, unsigned min_abs)
> +{
> + /* Make sure we hit MIN_INT every once in a while */
> + if (rand() % 64 == 37)
> + return -(1 << (bits - 1));
> +
> + int64_t s = rand_uint(bits - 1, min_abs);
> + return rand() & 1 ? s : -s;
> +}
> +
> +static uint64_t
> +udiv(uint64_t a, uint64_t b, unsigned bit_size)
> +{
> + switch (bit_size) {
> + case 64: return (uint64_t)a / (uint64_t)b;
> + case 32: return (uint32_t)a / (uint32_t)b;
> + case 16: return (uint16_t)a / (uint16_t)b;
> + case 8: return (uint8_t)a / (uint8_t)b;
> + default:
> + assert(!"Invalid bit size");
> + return 0;
> + }
> +}
> +
> +static int64_t
> +sdiv(int64_t a, int64_t b, unsigned bit_size)
> +{
> + switch (bit_size) {
> + case 64: return (int64_t)a / (int64_t)b;
> + case 32: return (int32_t)a / (int32_t)b;
> + case 16: return (int16_t)a / (int16_t)b;
> + case 8: return (int8_t)a / (int8_t)b;
> + default:
> + assert(!"Invalid bit size");
> + return 0;
> + }
> +}
> +
> +static void
> +random_udiv_add_sat_test(unsigned bits, bool bounded)
> +{
> + for (unsigned i = 0; i < RAND_TEST_ITERATIONS; i++) {
> + uint64_t n = rand_uint(bits, 0);
> + uint64_t d = rand_uint(bits, 2);
> + assert(uint_is_in_range(n, bits));
> + assert(uint_is_in_range(d, bits) && d >= 2);
> +
> + unsigned n_bits = bounded ? util_logbase2_64(MAX2(n, 1)) + 1 : bits;
> +
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, n_bits, bits);
> + EXPECT_EQ(fast_udiv_add_sat(n, m, bits), udiv(n, d, bits));
> + }
> +}
> +
> +static void
> +random_udiv_mul_add_test(unsigned bits, bool bounded)
> +{
> + for (unsigned i = 0; i < RAND_TEST_ITERATIONS; i++) {
> + uint64_t n = rand_uint(bits, 0);
> + uint64_t d = rand_uint(bits, 1);
> + assert(uint_is_in_range(n, bits));
> + assert(uint_is_in_range(d, bits) && d >= 1);
> +
> + unsigned n_bits = bounded ? util_logbase2_64(MAX2(n, 1)) + 1: bits;
> +
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, n_bits, bits);
> + EXPECT_EQ(fast_udiv_mul_add(n, m, bits), udiv(n, d, bits));
> + }
> +}
> +
> +static void
> +random_sdiv_test(unsigned bits)
> +{
> + for (unsigned i = 0; i < RAND_TEST_ITERATIONS; i++) {
> + int64_t n = rand_sint(bits, 0);
> + int64_t d;
> + do {
> + d = rand_sint(bits, 2);
> + } while (util_is_power_of_two_or_zero64(llabs(d)));
> +
> + assert(sint_is_in_range(n, bits));
> + assert(sint_is_in_range(d, bits) && llabs(d) >= 2);
> +
> + struct util_fast_sdiv_info m =
> + util_compute_fast_sdiv_info(d, bits);
> + EXPECT_EQ(fast_sdiv(n, d, m, bits), sdiv(n, d, bits));
> + }
> +}
> +
> +TEST(fast_idiv_by_const, uint8_add_sat)
> +{
> + /* 8-bit is small enough we can brute-force the entire space */
> + for (unsigned d = 2; d < 256; d++) {
> + for (unsigned n_bits = 1; n_bits <= 8; n_bits++) {
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, n_bits, 8);
> +
> + for (unsigned n = 0; n < (1u << n_bits); n++)
> + EXPECT_EQ(fast_udiv_add_sat(n, m, 8), udiv(n, d, 8));
> + }
> + }
> +}
> +
> +TEST(fast_idiv_by_const, uint8_mul_add)
> +{
> + /* 8-bit is small enough we can brute-force the entire space */
> + for (unsigned d = 2; d < 256; d++) {
> + for (unsigned n_bits = 1; n_bits <= 8; n_bits++) {
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, n_bits, 8);
> +
> + for (unsigned n = 0; n < (1u << n_bits); n++)
> + EXPECT_EQ(fast_udiv_mul_add(n, m, 8), udiv(n, d, 8));
> + }
> + }
> +}
> +
> +TEST(fast_idiv_by_const, int8)
> +{
> + /* 8-bit is small enough we can brute-force the entire space */
> + for (int n = -128; n < 128; n++) {
> + for (int d = -128; d < 128; d++) {
> + if (util_is_power_of_two_or_zero(abs(d)))
> + continue;
> +
> + struct util_fast_sdiv_info m =
> + util_compute_fast_sdiv_info(d, 8);
> + EXPECT_EQ(fast_sdiv(n, d, m, 8), sdiv(n, d, 8));
> + }
> + }
> +}
> +
> +TEST(fast_idiv_by_const, uint16_add_sat_bounded)
> +{
> + random_udiv_add_sat_test(16, true);
> +}
> +
> +TEST(fast_idiv_by_const, uint16_add_sat_full)
> +{
> + random_udiv_add_sat_test(16, false);
> +}
> +
> +TEST(fast_idiv_by_const, uint16_mul_add_bounded)
> +{
> + random_udiv_mul_add_test(16, true);
> +}
> +
> +TEST(fast_idiv_by_const, uint16_mul_add_full)
> +{
> + random_udiv_mul_add_test(16, false);
> +}
> +
> +TEST(fast_idiv_by_const, int16)
> +{
> + random_sdiv_test(16);
> +}
> +
> +TEST(fast_idiv_by_const, uint32_add_sat_bounded)
> +{
> + random_udiv_add_sat_test(32, true);
> +}
> +
> +TEST(fast_idiv_by_const, uint32_add_sat_full)
> +{
> + random_udiv_add_sat_test(32, false);
> +}
> +
> +TEST(fast_idiv_by_const, uint32_mul_add_bounded)
> +{
> + random_udiv_mul_add_test(32, true);
> +}
> +
> +TEST(fast_idiv_by_const, uint32_mul_add_full)
> +{
> + random_udiv_mul_add_test(32, false);
> +}
> +
> +TEST(fast_idiv_by_const, int32)
> +{
> + random_sdiv_test(32);
> +}
> +
> +TEST(fast_idiv_by_const, util_fast_udiv32)
> +{
> + for (unsigned i = 0; i < RAND_TEST_ITERATIONS; i++) {
> + uint32_t n = rand_uint(32, 0);
> + uint32_t d = rand_uint(32, 1);
> +
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, 32, 32);
> + EXPECT_EQ(util_fast_udiv32(n, m), n / d);
> + }
> +}
> +
> +TEST(fast_idiv_by_const, util_fast_udiv32_nuw)
> +{
> + for (unsigned i = 0; i < RAND_TEST_ITERATIONS; i++) {
> + uint32_t n = rand_uint(32, 0);
> + if (n == UINT32_MAX)
> + continue;
> + uint32_t d = rand_uint(32, 1);
> +
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, 32, 32);
> + EXPECT_EQ(util_fast_udiv32(n, m), n / d);
> + }
> +}
> +
> +TEST(fast_idiv_by_const, util_fast_udiv32_u31_d_not_one)
> +{
> + for (unsigned i = 0; i < RAND_TEST_ITERATIONS; i++) {
> + uint32_t n = rand_uint(31, 0);
> + uint32_t d = rand_uint(31, 2);
> +
> + struct util_fast_udiv_info m =
> + util_compute_fast_udiv_info(d, 31, 32);
> + EXPECT_EQ(util_fast_udiv32_u31_d_not_one(n, m), n / d);
> + }
> +}
> +
> +TEST(fast_idiv_by_const, uint64_add_sat_bounded)
> +{
> + random_udiv_add_sat_test(64, true);
> +}
> +
> +TEST(fast_idiv_by_const, uint64_add_sat_full)
> +{
> + random_udiv_add_sat_test(64, false);
> +}
> +
> +TEST(fast_idiv_by_const, uint64_mul_add_bounded)
> +{
> + random_udiv_mul_add_test(64, true);
> +}
> +
> +TEST(fast_idiv_by_const, uint64_mul_add_full)
> +{
> + random_udiv_mul_add_test(64, false);
> +}
> +
> +TEST(fast_idiv_by_const, int64)
> +{
> + random_sdiv_test(64);
> +}
> diff --git a/src/util/tests/fast_idiv_by_const/meson.build b/src/util/tests/fast_idiv_by_const/meson.build
> new file mode 100644
> index 00000000000..8c3b79493ff
> --- /dev/null
> +++ b/src/util/tests/fast_idiv_by_const/meson.build
> @@ -0,0 +1,30 @@
> +# Copyright © 2018 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 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.
> +
> +test(
> + 'fast_idiv_by_const',
> + executable(
> + 'fast_idiv_by_const_test',
> + 'fast_idiv_by_const_test.cpp',
> + dependencies : [dep_thread, dep_dl, idep_gtest],
> + include_directories : inc_common,
> + link_with : [libmesa_util],
> + )
> +)
> --
> 2.19.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev
More information about the mesa-dev
mailing list