On Mon, 10 Feb 2020 at 23:06, Matteo Bruni <mbruni(a)codeweavers.com> wrote:
+typedef HRESULT (CDECL *wined3d_device_shader_constant_setter)(struct wined3d_device *device, + unsigned int start_idx, unsigned int count, const void *constants); + +static void device_apply_shader_constants(struct wined3d_device *device, + const struct wined3d_stateblock_state *state, + DWORD *bitmap, unsigned int bit_count, const void *data, unsigned int stride, + wined3d_device_shader_constant_setter shader_constant_setter) +{ + const unsigned int word_bit_count = sizeof(DWORD) * CHAR_BIT; + unsigned int i, j, idx, start, last; + const BYTE *byte_data = data; + DWORD map; + + start = last = ~0u; + for (i = 0; i < (bit_count + word_bit_count - 1) / word_bit_count; ++i) + { + map = bitmap[i]; + + if (map == ~0u) + { + if (last != ~0u && last != i * word_bit_count - 1) + { + shader_constant_setter(device, start, last - start + 1, &byte_data[start * stride]); + start = i * word_bit_count; + } + if (start == ~0u) + start = i * word_bit_count; + last = i * word_bit_count + word_bit_count - 1; + continue; + } + while (map) + { + j = wined3d_bit_scan(&map); + idx = i * word_bit_count + j; + + if (start == ~0u) + { + start = last = idx; + } + else if (last != idx - 1) + { + shader_constant_setter(device, start, last - start + 1, &byte_data[start * stride]); + start = last = idx; + } + else + { + last = idx; + } + } + } + if (start != ~0u) + shader_constant_setter(device, start, last - start + 1, &byte_data[start * stride]); +} + This looks like it's a fair bit more complicated than it needs to be. I think the primitives you want are something like the following:
unsigned int wined3d_bitmap_ffs(uint32_t *bitmap, unsigned int start, unsigned int count); unsigned int wined3d_bitmap_ffz(uint32_t *bitmap, unsigned int start, unsigned int count); and then you can extract the ranges relatively trivially.