diff --git a/include/private/vkd3d_common.h b/include/private/vkd3d_common.h index c696f885..1ac8a63b 100644 --- a/include/private/vkd3d_common.h +++ b/include/private/vkd3d_common.h @@ -23,6 +23,8 @@ #include "vkd3d_windows.h" #include +#include +#include #ifndef ARRAY_SIZE # define ARRAY_SIZE(x) (sizeof(x) / sizeof(*(x))) @@ -58,6 +60,21 @@ static inline unsigned int vkd3d_popcount(unsigned int v) #endif } +static inline bool vkd3d_bitmask_is_contiguous(unsigned int mask) +{ + unsigned int i, j; + + for (i = 0, j = 0; i < sizeof(mask) * CHAR_BIT; ++i) + { + if (mask & (1u << i)) + ++j; + else if (j) + break; + } + + return vkd3d_popcount(mask) == j; +} + /* Undefined for x == 0. */ static inline unsigned int vkd3d_log2i(unsigned int x) { diff --git a/libs/vkd3d-shader/spirv.c b/libs/vkd3d-shader/spirv.c index ee409539..f17c7fa1 100644 --- a/libs/vkd3d-shader/spirv.c +++ b/libs/vkd3d-shader/spirv.c @@ -3807,22 +3807,6 @@ static uint32_t vkd3d_dxbc_compiler_emit_builtin_variable(struct vkd3d_dxbc_comp return id; } -static bool vkd3d_write_mask_is_contiguous(unsigned int mask) -{ - unsigned int i, j; - - assert(mask); - for (i = 0, j = 0; i < VKD3D_VEC4_SIZE; ++i) - { - if (mask & (1u << i)) - ++j; - else if (j) - break; - } - - return vkd3d_write_mask_component_count(mask) == j; -} - static bool needs_private_io_variable(const struct vkd3d_shader_signature *signature, unsigned int reg_idx, const struct vkd3d_spirv_builtin *builtin, unsigned int *component_count, unsigned int *out_write_mask) @@ -3854,7 +3838,7 @@ static bool needs_private_io_variable(const struct vkd3d_shader_signature *signa if (builtin || have_sysval) return true; - if (!vkd3d_write_mask_is_contiguous(write_mask)) + if (!vkd3d_bitmask_is_contiguous(write_mask)) { FIXME("Write mask %#x is non-contiguous.\n", write_mask); return true; diff --git a/tests/vkd3d_common.c b/tests/vkd3d_common.c index 379c8b06..85f17161 100644 --- a/tests/vkd3d_common.c +++ b/tests/vkd3d_common.c @@ -43,7 +43,78 @@ static void test_parse_version(void) check_version("2.3.0", 2, 3); } +static void check_contiguous(uint32_t mask, bool expected_result) +{ + bool r = vkd3d_bitmask_is_contiguous(mask); + ok(r == expected_result, "Got %#x for bitmask %#"PRIx32".\n", r, mask); +} + +static void test_bitmask_is_contiguous(void) +{ + check_contiguous(0x00000000, true); + + check_contiguous(0x00000001, true); + check_contiguous(0x00000002, true); + check_contiguous(0x00000003, true); + check_contiguous(0x00000004, true); + check_contiguous(0x00000005, false); + check_contiguous(0x00000006, true); + check_contiguous(0x00000007, true); + check_contiguous(0x00000008, true); + check_contiguous(0x00000009, false); + check_contiguous(0x0000000a, false); + check_contiguous(0x0000000b, false); + check_contiguous(0x0000000c, true); + check_contiguous(0x0000000d, false); + check_contiguous(0x0000000e, true); + check_contiguous(0x0000000f, true); + + check_contiguous(0x10000000, true); + check_contiguous(0x20000000, true); + check_contiguous(0x30000000, true); + check_contiguous(0x40000000, true); + check_contiguous(0x50000000, false); + check_contiguous(0x60000000, true); + check_contiguous(0x70000000, true); + check_contiguous(0x80000000, true); + check_contiguous(0x90000000, false); + check_contiguous(0xa0000000, false); + check_contiguous(0xb0000000, false); + check_contiguous(0xc0000000, true); + check_contiguous(0xd0000000, false); + check_contiguous(0xe0000000, true); + check_contiguous(0xf0000000, true); + + check_contiguous(0xf000000f, false); + check_contiguous(0x0f0000f0, false); + check_contiguous(0x00f00f00, false); + + check_contiguous(0x000000ff, true); + check_contiguous(0x00000ff0, true); + check_contiguous(0x0000ff00, true); + check_contiguous(0x000ff000, true); + check_contiguous(0x00ff0000, true); + check_contiguous(0xff000000, true); + + check_contiguous(0xfff00000, true); + check_contiguous(0xffff0000, true); + check_contiguous(0xffff0000, true); + check_contiguous(0xfffff000, true); + check_contiguous(0xffffff00, true); + check_contiguous(0xfffffff0, true); + check_contiguous(0xffffffff, true); + + check_contiguous(0x0000001c, true); + check_contiguous(0x000001c0, true); + check_contiguous(0x00001c00, true); + check_contiguous(0x0001c000, true); + check_contiguous(0x001c0000, true); + check_contiguous(0x01c00000, true); + check_contiguous(0x1c000000, true); +} + START_TEST(vkd3d_common) { run_test(test_parse_version); + run_test(test_bitmask_is_contiguous); }