| 927 | |
| 928 | #if defined(SIMD_SSE) || defined(SIMD_AVX) || defined(SIMD_NEON) || defined(SIMD_WASM) |
| 929 | SIMD_TARGET |
| 930 | static const unsigned char* decodeBytesSimd(const unsigned char* data, const unsigned char* data_end, unsigned char* buffer, size_t buffer_size) |
| 931 | { |
| 932 | assert(buffer_size % kByteGroupSize == 0); |
| 933 | assert(kByteGroupSize == 16); |
| 934 | |
| 935 | const unsigned char* header = data; |
| 936 | |
| 937 | // round number of groups to 4 to get number of header bytes |
| 938 | size_t header_size = (buffer_size / kByteGroupSize + 3) / 4; |
| 939 | |
| 940 | if (size_t(data_end - data) < header_size) |
| 941 | return NULL; |
| 942 | |
| 943 | data += header_size; |
| 944 | |
| 945 | size_t i = 0; |
| 946 | |
| 947 | // fast-path: process 4 groups at a time, do a shared bounds check - each group reads <=24b |
| 948 | for (; i + kByteGroupSize * 4 <= buffer_size && size_t(data_end - data) >= kByteGroupDecodeLimit * 4; i += kByteGroupSize * 4) |
| 949 | { |
| 950 | size_t header_offset = i / kByteGroupSize; |
| 951 | unsigned char header_byte = header[header_offset / 4]; |
| 952 | |
| 953 | data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 0, (header_byte >> 0) & 3); |
| 954 | data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 1, (header_byte >> 2) & 3); |
| 955 | data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 2, (header_byte >> 4) & 3); |
| 956 | data = decodeBytesGroupSimd(data, buffer + i + kByteGroupSize * 3, (header_byte >> 6) & 3); |
| 957 | } |
| 958 | |
| 959 | // slow-path: process remaining groups |
| 960 | for (; i < buffer_size; i += kByteGroupSize) |
| 961 | { |
| 962 | if (size_t(data_end - data) < kByteGroupDecodeLimit) |
| 963 | return NULL; |
| 964 | |
| 965 | size_t header_offset = i / kByteGroupSize; |
| 966 | |
| 967 | int bitslog2 = (header[header_offset / 4] >> ((header_offset % 4) * 2)) & 3; |
| 968 | |
| 969 | data = decodeBytesGroupSimd(data, buffer + i, bitslog2); |
| 970 | } |
| 971 | |
| 972 | return data; |
| 973 | } |
| 974 | |
| 975 | SIMD_TARGET |
| 976 | static const unsigned char* decodeVertexBlockSimd(const unsigned char* data, const unsigned char* data_end, unsigned char* vertex_data, size_t vertex_count, size_t vertex_size, unsigned char last_vertex[256]) |
no test coverage detected