2023-01-06 17:05:09 +01:00
|
|
|
// Copyright (C) 2023 RozK
|
|
|
|
//
|
|
|
|
// This program is free software: you can redistribute it and/or modify
|
|
|
|
// it under the terms of the GNU Affero General Public License as published by
|
|
|
|
// the Free Software Foundation, either version 3 of the License, or
|
|
|
|
// (at your option) any later version.
|
|
|
|
//
|
|
|
|
// This program 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 Affero General Public License for more details.
|
|
|
|
//
|
|
|
|
// You should have received a copy of the GNU Affero General Public License
|
|
|
|
// along with this program. If not, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
|
|
|
#ifndef RK_ENGINE_VERTEX_FORMAT_H
|
|
|
|
#define RK_ENGINE_VERTEX_FORMAT_H
|
|
|
|
|
|
|
|
#include "render_opengles.hpp"
|
|
|
|
#include <limits>
|
|
|
|
|
|
|
|
namespace rk_vertex {
|
|
|
|
|
|
|
|
#pragma pack(push, 1)
|
|
|
|
|
|
|
|
template<typename _type>
|
|
|
|
struct alignas(alignof(_type)) rk_input {
|
|
|
|
_type input;
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _type, typename _input, bool _signed, bool _normalized>
|
|
|
|
struct alignas(alignof(_type)) rk_output {
|
|
|
|
_type output;
|
|
|
|
|
|
|
|
[[RK_FAST]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input<_input> const & __restrict src) {
|
|
|
|
output = static_cast<_type>(src.input);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _type, bool _signed>
|
|
|
|
struct alignas(alignof(_type)) rk_output<_type, rk_float, _signed, true> {
|
|
|
|
_type output;
|
|
|
|
|
|
|
|
[[RK_FAST]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input<rk_float> const & __restrict src) {
|
|
|
|
enum : _type { max = std::numeric_limits<_type>::max() };
|
|
|
|
output = static_cast<_type>(src.input * static_cast<float>(max));
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#pragma pack(4)
|
|
|
|
|
|
|
|
template<typename _input, unsigned _cols>
|
|
|
|
struct alignas(4) rk_input_row {
|
|
|
|
rk_input<_input> input_col[_cols];
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _output, typename _input, unsigned _cols, bool _signed, bool _normalized>
|
|
|
|
struct alignas(4) rk_output_row {
|
|
|
|
rk_output<_output, _input, _signed, _normalized> output_col[_cols];
|
|
|
|
|
|
|
|
[[RK_FAST, RK_FLATTEN, RK_UNROLLED]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_row<_input, _cols> const & __restrict src) {
|
|
|
|
for (unsigned col = 0; col < _cols; ++col) {
|
|
|
|
output_col[col].convert(src.input_col[col]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _input, unsigned _cols, bool _signed, bool _normalized>
|
|
|
|
struct alignas(4) rk_output_row<rk_packed<_signed, _cols>, _input, _cols, _signed, _normalized> {
|
|
|
|
rk_output<rk_packed<_signed, _cols>, _input, _signed, _normalized> output_cols;
|
|
|
|
|
|
|
|
[[RK_FAST, RK_FLATTEN]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_row<_input, _cols> const & __restrict src) {
|
|
|
|
output_cols.convert(src);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _input, unsigned _cols, unsigned _rows>
|
|
|
|
struct alignas(4) rk_input_format {
|
|
|
|
rk_input_row<_input, _cols> input_row[_rows];
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _output, typename _input, unsigned _cols, unsigned _rows, bool _signed, bool _normalized>
|
|
|
|
struct alignas(4) rk_output_format {
|
|
|
|
rk_output_row<_output, _input, _cols, _signed, _normalized> output_row[_rows];
|
|
|
|
|
|
|
|
[[RK_FAST, RK_FLATTEN, RK_UNROLLED]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_format<_input, _cols, _rows> const & __restrict src) {
|
|
|
|
for (unsigned row = 0; row < _rows; ++row) {
|
|
|
|
output_row[row].convert(src.input_row[row]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _input, bool _signed, bool _normalized>
|
|
|
|
struct alignas(alignof(rk_packed<_signed, 3>)) rk_output<rk_packed<_signed, 3>, _input, _signed, _normalized> {
|
|
|
|
rk_packed<_signed, 3> output;
|
|
|
|
|
|
|
|
[[RK_FAST]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_row<_input, 3> const & __restrict src) {
|
|
|
|
typedef typename rk_packed<_signed, 3>::type packed_type;
|
|
|
|
output.packed =
|
|
|
|
((static_cast<packed_type>(src.input_col[0].input) & 1023)) |
|
|
|
|
((static_cast<packed_type>(src.input_col[1].input) & 1023) << 10) |
|
|
|
|
((static_cast<packed_type>(src.input_col[2].input) & 1023) << 20);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<typename _input, bool _signed, bool _normalized>
|
|
|
|
struct alignas(alignof(rk_packed<_signed, 4>)) rk_output<rk_packed<_signed, 4>, _input, _signed, _normalized> {
|
|
|
|
rk_packed<_signed, 4> output;
|
|
|
|
|
|
|
|
[[RK_FAST]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_row<_input, 4> const & __restrict src) {
|
|
|
|
typedef typename rk_packed<_signed, 4>::type packed_type;
|
|
|
|
output.packed =
|
|
|
|
((static_cast<packed_type>(src.input_col[0].input) & 1023)) |
|
|
|
|
((static_cast<packed_type>(src.input_col[1].input) & 1023) << 10) |
|
|
|
|
((static_cast<packed_type>(src.input_col[2].input) & 1023) << 20) |
|
|
|
|
((static_cast<packed_type>(src.input_col[3].input) & 3) << 30);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct alignas(alignof(rk_packed<true, 3>)) rk_output<rk_packed<true, 3>, rk_float, true, true> {
|
|
|
|
rk_packed<true, 3> output;
|
|
|
|
|
|
|
|
[[RK_FAST]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_row<rk_float, 3> const & __restrict src) {
|
|
|
|
output.packed =
|
|
|
|
((static_cast<rk_int>(src.input_col[0].input * 511.f) & 1023)) |
|
|
|
|
((static_cast<rk_int>(src.input_col[1].input * 511.f) & 1023) << 10) |
|
|
|
|
((static_cast<rk_int>(src.input_col[2].input * 511.f) & 1023) << 20);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
template<>
|
|
|
|
struct alignas(alignof(rk_packed<true, 4>)) rk_output<rk_packed<true, 4>, rk_float, true, true> {
|
|
|
|
rk_packed<true, 4> output;
|
|
|
|
|
|
|
|
[[RK_FAST]]
|
|
|
|
inline void convert(
|
|
|
|
rk_input_row<rk_float, 4> const & __restrict src) {
|
|
|
|
output.packed =
|
|
|
|
((static_cast<rk_uint>(src.input_col[0].input * 511.f) & 1023)) |
|
|
|
|
((static_cast<rk_uint>(src.input_col[1].input * 511.f) & 1023) << 10) |
|
|
|
|
((static_cast<rk_uint>(src.input_col[2].input * 511.f) & 1023) << 20) |
|
|
|
|
((static_cast<rk_uint>(src.input_col[3].input) & 3) << 30);
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
#pragma pack(pop)
|
|
|
|
|
|
|
|
template<typename _output, typename _input, unsigned _cols, unsigned _rows, bool _signed, bool _normalized>
|
|
|
|
struct rk_format {
|
|
|
|
typedef rk_input<_input> input;
|
|
|
|
typedef rk_output<_output, input, _signed, _normalized> output;
|
|
|
|
|
|
|
|
typedef rk_input_row<_input, _cols> input_row;
|
|
|
|
typedef rk_output_row<_output, _input, _cols, _signed, _normalized> output_row;
|
|
|
|
|
|
|
|
typedef rk_input_format<_input, _cols, _rows> input_format;
|
|
|
|
typedef rk_output_format<_output, _input, _cols, _rows, _signed, _normalized> output_format;
|
|
|
|
|
|
|
|
static_assert(sizeof(input) == sizeof(_input));
|
|
|
|
static_assert(sizeof(output) == sizeof(_output));
|
|
|
|
static_assert((sizeof(input_row) % sizeof(rk_vertex_input)) == 0);
|
|
|
|
static_assert((sizeof(output_row) % sizeof(rk_vertex_output)) == 0);
|
|
|
|
static_assert((sizeof(input_format) % sizeof(rk_vertex_input)) == 0);
|
|
|
|
static_assert((sizeof(output_format) % sizeof(rk_vertex_output)) == 0);
|
|
|
|
|
|
|
|
static unsigned get_input_size() {
|
|
|
|
return sizeof(input_format);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned get_output_size() {
|
|
|
|
return sizeof(output_format);
|
|
|
|
}
|
|
|
|
|
|
|
|
static unsigned get_output_offset(unsigned const index) {
|
|
|
|
return index * sizeof(output_row);
|
|
|
|
}
|
|
|
|
|
|
|
|
[[RK_FAST, RK_FLATTEN]]
|
|
|
|
inline static void convert(
|
|
|
|
output_format & __restrict dst,
|
|
|
|
input_format const & __restrict src) {
|
|
|
|
dst.convert(src);
|
|
|
|
}
|
|
|
|
|
|
|
|
[[RK_HOT, RK_FAST, RK_FLATTEN]]
|
|
|
|
static void param_packer(
|
|
|
|
unsigned const count,
|
|
|
|
rk_instance_index const * const __restrict indices,
|
|
|
|
rk_param_output * __restrict _dst,
|
|
|
|
rk_param_input const * const __restrict _src) {
|
|
|
|
rk_instance_index const * const last_index = indices + count;
|
|
|
|
output_format * __restrict dst = reinterpret_cast<output_format *>(_dst);
|
|
|
|
input_format const * const __restrict src = reinterpret_cast<input_format const *>(_src);
|
|
|
|
for (rk_instance_index const * __restrict index = indices; index < last_index; ++index, ++dst) {
|
|
|
|
dst->convert(src[*index]);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
};
|
|
|
|
|
|
|
|
} // namepace rk_vertex
|
|
|
|
|
2023-01-06 18:15:19 +01:00
|
|
|
typedef rk_vertex::rk_format<rk_float, rk_float, 3, 1, true, false> rk_vec3_float;
|
|
|
|
typedef rk_vertex::rk_format<rk_short, rk_float, 3, 1, true, false> rk_vec3_short;
|
|
|
|
typedef rk_vertex::rk_format<rk_short, rk_float, 3, 1, true, true> rk_vec3_short_norm;
|
|
|
|
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 1, true, false> rk_vec3_int10;
|
|
|
|
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 1, true, true> rk_vec3_int10_norm;
|
|
|
|
typedef rk_vertex::rk_format<rk_packed<false, 3>, rk_float, 3, 1, false, false> rk_vec3_uint10;
|
|
|
|
typedef rk_vertex::rk_format<rk_packed<false, 3>, rk_float, 3, 1, false, true> rk_vec3_uint10_norm;
|
|
|
|
typedef rk_vertex::rk_format<rk_float, rk_float, 3, 3, true, false> rk_mat3_float;
|
|
|
|
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 3, true, false> rk_mat3_int10;
|
|
|
|
typedef rk_vertex::rk_format<rk_packed<true, 3>, rk_float, 3, 3, true, true> rk_mat3_int10_norm;
|
2023-01-06 17:05:09 +01:00
|
|
|
|
|
|
|
#endif // RK_ENGINE_VERTEX_FORMAT_H
|