1
0
mirror of https://github.com/FFmpeg/FFmpeg.git synced 2024-12-28 20:53:54 +02:00
FFmpeg/libavcodec/vulkan/common.comp
2024-11-28 10:03:01 +09:00

181 lines
4.5 KiB
Plaintext

/*
* Copyright (c) 2024 Lynne <dev@lynne.ee>
*
* This file is part of FFmpeg.
*
* FFmpeg is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* FFmpeg is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with FFmpeg; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
layout(buffer_reference, buffer_reference_align = 1) buffer u8buf {
uint8_t v;
};
layout(buffer_reference, buffer_reference_align = 2) buffer u16buf {
uint16_t v;
};
layout(buffer_reference, buffer_reference_align = 4) buffer u32buf {
uint32_t v;
};
layout(buffer_reference, buffer_reference_align = 4) buffer u32vec2buf {
u32vec2 v;
};
layout(buffer_reference, buffer_reference_align = 8) buffer u64buf {
uint64_t v;
};
#define OFFBUF(type, b, l) \
type(uint64_t(b) + uint64_t(l))
#define zero_extend(a, p) \
((a) & ((1 << (p)) - 1))
#define sign_extend(val, bits) \
bitfieldExtract(val, 0, bits)
#define fold(diff, bits) \
sign_extend(diff, bits)
#define mid_pred(a, b, c) \
max(min((a), (b)), min(max((a), (b)), (c)))
/* TODO: optimize */
uint align(uint src, uint a)
{
uint res = src % a;
if (res == 0)
return src;
return src + a - res;
}
/* TODO: optimize */
uint64_t align64(uint64_t src, uint64_t a)
{
uint64_t res = src % a;
if (res == 0)
return src;
return src + a - res;
}
#define reverse4(src) \
(pack32(unpack8(uint32_t(src)).wzyx))
u32vec2 reverse8(uint64_t src)
{
u32vec2 tmp = unpack32(src);
tmp.x = reverse4(tmp.x);
tmp.y = reverse4(tmp.y);
return tmp.yx;
}
#ifdef PB_32
#define BIT_BUF_TYPE uint32_t
#define BUF_TYPE u32buf
#define BUF_REVERSE(src) reverse4(src)
#define BUF_BITS uint8_t(32)
#define BUF_BYTES uint8_t(4)
#define BYTE_EXTRACT(src, byte_off) \
(uint8_t(bitfieldExtract((src), ((byte_off) << 3), 8)))
#else
#define BIT_BUF_TYPE uint64_t
#define BUF_TYPE u32vec2buf
#define BUF_REVERSE(src) reverse8(src)
#define BUF_BITS uint8_t(64)
#define BUF_BYTES uint8_t(8)
#define BYTE_EXTRACT(src, byte_off) \
(uint8_t(((src) >> ((byte_off) << 3)) & 0xFF))
#endif
struct PutBitContext {
uint64_t buf_start;
uint64_t buf;
BIT_BUF_TYPE bit_buf;
uint8_t bit_left;
};
void put_bits(inout PutBitContext pb, const uint32_t n, uint32_t value)
{
if (n < pb.bit_left) {
pb.bit_buf = (pb.bit_buf << n) | value;
pb.bit_left -= uint8_t(n);
} else {
pb.bit_buf <<= pb.bit_left;
pb.bit_buf |= (value >> (n - pb.bit_left));
#ifdef PB_UNALIGNED
u8buf bs = u8buf(pb.buf);
[[unroll]]
for (uint8_t i = uint8_t(0); i < BUF_BYTES; i++)
bs[i].v = BYTE_EXTRACT(pb.bit_buf, BUF_BYTES - uint8_t(1) - i);
#else
#ifdef DEBUG
if ((pb.buf % BUF_BYTES) != 0)
debugPrintfEXT("put_bits buffer is not aligned!");
#endif
BUF_TYPE bs = BUF_TYPE(pb.buf);
bs.v = BUF_REVERSE(pb.bit_buf);
#endif
pb.buf = uint64_t(bs) + BUF_BYTES;
pb.bit_left += BUF_BITS - uint8_t(n);
pb.bit_buf = value;
}
}
uint32_t flush_put_bits(inout PutBitContext pb)
{
/* Align bits to MSBs */
if (pb.bit_left < BUF_BITS)
pb.bit_buf <<= pb.bit_left;
if (pb.bit_left < BUF_BITS) {
uint to_write = ((BUF_BITS - pb.bit_left - 1) >> 3) + 1;
u8buf bs = u8buf(pb.buf);
for (int i = 0; i < to_write; i++)
bs[i].v = BYTE_EXTRACT(pb.bit_buf, BUF_BYTES - uint8_t(1) - i);
pb.buf = uint64_t(bs) + to_write;
}
pb.bit_left = BUF_BITS;
pb.bit_buf = 0x0;
return uint32_t(pb.buf - pb.buf_start);
}
void init_put_bits(out PutBitContext pb, u8buf data, uint64_t len)
{
pb.buf_start = uint64_t(data);
pb.buf = uint64_t(data);
pb.bit_buf = 0;
pb.bit_left = BUF_BITS;
}
uint64_t put_bits_count(in PutBitContext pb)
{
return (pb.buf - pb.buf_start)*8 + BUF_BITS - pb.bit_left;
}
uint32_t put_bytes_count(in PutBitContext pb)
{
uint64_t num_bytes = (pb.buf - pb.buf_start) + ((BUF_BITS - pb.bit_left) >> 3);
return uint32_t(num_bytes);
}