Blender V5.0
GPU_vertex_format.hh
Go to the documentation of this file.
1/* SPDX-FileCopyrightText: 2016 by Mike Erwin. All rights reserved.
2 *
3 * SPDX-License-Identifier: GPL-2.0-or-later */
4
10
11#pragma once
12
13#include "BLI_assert.h"
14#include "BLI_compiler_compat.h"
16#include "BLI_string_ref.hh"
17#include "BLI_sys_types.h"
18
19#include "GPU_format.hh"
20
21namespace blender::gpu {
22
23enum class VertAttrType : uint8_t {
25
26#define DECLARE(a, b, c, blender_enum, d, e, f, g, h) blender_enum = int(DataFormat::blender_enum),
27
28#define GPU_VERTEX_FORMAT_EXPAND(impl) \
29 SNORM_8_8_8_8_(impl) \
30\
31 SNORM_16_16_(impl) \
32 SNORM_16_16_16_16_(impl) \
33\
34 UNORM_8_8_8_8_(impl) \
35\
36 UNORM_16_16_(impl) \
37 UNORM_16_16_16_16_(impl) \
38\
39 SINT_8_8_8_8_(impl) \
40\
41 SINT_16_16_(impl) \
42 SINT_16_16_16_16_(impl) \
43\
44 SINT_32_(impl) \
45 SINT_32_32_(impl) \
46 SINT_32_32_32_(impl) \
47 SINT_32_32_32_32_(impl) \
48\
49 UINT_8_8_8_8_(impl) \
50\
51 UINT_16_16_(impl) \
52 UINT_16_16_16_16_(impl) \
53\
54 UINT_32_(impl) \
55 UINT_32_32_(impl) \
56 UINT_32_32_32_(impl) \
57 UINT_32_32_32_32_(impl) \
58\
59 SFLOAT_32_(impl) \
60 SFLOAT_32_32_(impl) \
61 SFLOAT_32_32_32_(impl) \
62 SFLOAT_32_32_32_32_(impl) \
63\
64 SNORM_10_10_10_2_(impl) \
65 UNORM_10_10_10_2_(impl) \
66\
67 /* UFLOAT_11_11_10_(impl) Available on Metal (and maybe VK) but not on GL. */ \
68 /* UFLOAT_9_9_9_EXP_5_(impl) Available on Metal (and maybe VK) but not on GL. */
69
71#undef DECLARE
72
73#define DECLARE(a, b, c, blender_enum, d, e, f, g, h) \
74 blender_enum##_DEPRECATED = int(DataFormat::blender_enum),
75
76/* Deprecated formats. To be removed in 5.0. Needed for python shaders. */
77#define GPU_VERTEX_DEPRECATED_FORMAT_EXPAND(impl) \
78 SNORM_8_(impl) \
79 SNORM_8_8_(impl) \
80 SNORM_8_8_8_(impl) \
81 SNORM_16_(impl) \
82 SNORM_16_16_16_(impl) \
83 UNORM_8_(impl) \
84 UNORM_8_8_(impl) \
85 UNORM_8_8_8_(impl) \
86 UNORM_16_(impl) \
87 UNORM_16_16_16_(impl) \
88 SINT_8_(impl) \
89 SINT_8_8_(impl) \
90 SINT_8_8_8_(impl) \
91 SINT_16_(impl) \
92 SINT_16_16_16_(impl) \
93 UINT_8_(impl) \
94 UINT_8_8_(impl) \
95 UINT_8_8_8_(impl) \
96 UINT_16_(impl) \
97 UINT_16_16_16_(impl)
98
100
101#undef DECLARE
102};
103
104/* TODO: Should reuse GPU_VERTEX_FORMAT_EXPAND, but we need to have `s/unorm` types first. */
105#define GPU_VERTEX_FORMAT_EXPAND_TYPED(impl) \
106 SINT_8_8_8_8_(impl) \
107\
108 SINT_16_16_(impl) \
109 SINT_16_16_16_16_(impl) \
110\
111 SINT_32_(impl) \
112 SINT_32_32_(impl) \
113 SINT_32_32_32_(impl) \
114 SINT_32_32_32_32_(impl) \
115\
116 UINT_8_8_8_8_(impl) \
117\
118 UINT_16_16_(impl) \
119 UINT_16_16_16_16_(impl) \
120\
121 UINT_32_(impl) \
122 UINT_32_32_(impl) \
123 UINT_32_32_32_(impl) \
124 UINT_32_32_32_32_(impl) \
125\
126 SFLOAT_32_(impl) \
127 SFLOAT_32_32_(impl) \
128 SFLOAT_32_32_32_(impl) \
129 SFLOAT_32_32_32_32_(impl) \
130\
131 /* UFLOAT_11_11_10_(impl) Available on Metal (and maybe VK) but not on GL. */ \
132 /* UFLOAT_9_9_9_EXP_5_(impl) Available on Metal (and maybe VK) but not on GL. */
133
134/* Must be implemented for each type used in vertex format.
135 * Should contain the associated VertAttrType just like below. */
136template<typename T> struct AttrType {};
137
138#define ATTR_TYPE_MAPPING(_type, b, c, blender_enum, d, e, f, g, h) \
139 template<> struct AttrType<_type> { \
140 static constexpr VertAttrType type = VertAttrType::blender_enum; \
141 };
142
144
145#undef ATTR_TYPE_MAPPING
146
148{
149 return DataFormat(int(format));
150}
151
152class Shader;
153
154} // namespace blender::gpu
155
156constexpr static int GPU_VERT_ATTR_MAX_LEN = 16;
157constexpr static int GPU_VERT_ATTR_MAX_NAMES = 6;
158constexpr static int GPU_VERT_ATTR_NAMES_BUF_LEN = 256;
159constexpr static int GPU_VERT_FORMAT_MAX_NAMES = 63; /* More than enough, actual max is ~30. */
160/* Computed as GPU_VERT_ATTR_NAMES_BUF_LEN / 30 (actual max format name). */
161constexpr static int GPU_MAX_SAFE_ATTR_NAME = 12;
162
178
182 GPU_FETCH_INT_TO_FLOAT_UNIT, /* 127 (ubyte) -> 0.5 (and so on for other int types) */
183 /* Warning! adjust GPUVertAttr if changing. */
184};
185
187 /* To replace fetch_mode, comp_type, comp_len, size. */
188 struct Type {
190
191 size_t size() const
192 {
193 return to_bytesize(to_data_format(format));
194 };
195
196 int comp_len() const
197 {
198 return format_component_len(to_data_format(format));
199 }
200
204 /* from beginning of vertex, in bytes */
205 uint8_t offset;
206 /* up to GPU_VERT_ATTR_MAX_NAMES */
207 uint8_t name_len;
209};
210
212 "We use uchar as index inside the name buffer "
213 "so GPU_VERT_ATTR_NAMES_BUF_LEN needs to be "
214 "smaller than GPUVertFormat->name_offset and "
215 "GPUVertAttr->names maximum value");
216
237
238#define GPU_VERTEX_FORMAT_ADD_ATTR(attr) \
239 format.attribute_add( \
240 #attr, blender::gpu::AttrType<decltype(attr)>::type, offsetof(VertT, attr)); \
241 BLI_STATIC_ASSERT(offsetof(VertT, attr) < 255, #attr " has offset greater than 255") \
242 BLI_STATIC_ASSERT(offsetof(VertT, attr) % 4 == 0, #attr " is not aligned to 4 bytes")
243
244#define _ATTR_EXPAND1(a) GPU_VERTEX_FORMAT_ADD_ATTR(a)
245#define _ATTR_EXPAND2(a, b) \
246 _ATTR_EXPAND1(a) \
247 GPU_VERTEX_FORMAT_ADD_ATTR(b)
248#define _ATTR_EXPAND3(a, b, c) \
249 _ATTR_EXPAND2(a, b) \
250 GPU_VERTEX_FORMAT_ADD_ATTR(c)
251#define _ATTR_EXPAND4(a, b, c, d) \
252 _ATTR_EXPAND3(a, b, c) \
253 GPU_VERTEX_FORMAT_ADD_ATTR(d)
254#define _ATTR_EXPAND5(a, b, c, d, e) \
255 _ATTR_EXPAND4(a, b, c, d) \
256 GPU_VERTEX_FORMAT_ADD_ATTR(e)
257#define _ATTR_EXPAND6(a, b, c, d, e, f) \
258 _ATTR_EXPAND5(a, b, c, d, e) \
259 GPU_VERTEX_FORMAT_ADD_ATTR(f)
260#define _ATTR_EXPAND7(a, b, c, d, e, f, g) \
261 _ATTR_EXPAND6(a, b, c, d, e, f) \
262 GPU_VERTEX_FORMAT_ADD_ATTR(g)
263#define _ATTR_EXPAND8(a, b, c, d, e, f, g, h) \
264 _ATTR_EXPAND7(a, b, c, d, e, f, g) \
265 GPU_VERTEX_FORMAT_ADD_ATTR(h)
266#define _ATTR_EXPAND9(a, b, c, d, e, f, g, h, i) \
267 _ATTR_EXPAND8(a, b, c, d, e, f, g, h) \
268 GPU_VERTEX_FORMAT_ADD_ATTR(i)
269#define _ATTR_EXPAND10(a, b, c, d, e, f, g, h, i, j) \
270 _ATTR_EXPAND9(a, b, c, d, e, f, g, h, i) \
271 GPU_VERTEX_FORMAT_ADD_ATTR(j)
272#define _ATTR_EXPAND11(a, b, c, d, e, f, g, h, i, j, k) \
273 _ATTR_EXPAND10(a, b, c, d, e, f, g, h, i, j) \
274 GPU_VERTEX_FORMAT_ADD_ATTR(k)
275#define _ATTR_EXPAND12(a, b, c, d, e, f, g, h, i, j, k, l) \
276 _ATTR_EXPAND11(a, b, c, d, e, f, g, h, i, j, k) \
277 GPU_VERTEX_FORMAT_ADD_ATTR(l)
278#define _ATTR_EXPAND13(a, b, c, d, e, f, g, h, i, j, k, l, m) \
279 _ATTR_EXPAND12(a, b, c, d, e, f, g, h, i, j, k, l) \
280 GPU_VERTEX_FORMAT_ADD_ATTR(m)
281#define _ATTR_EXPAND14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
282 _ATTR_EXPAND13(a, b, c, d, e, f, g, h, i, j, k, l, m) \
283 GPU_VERTEX_FORMAT_ADD_ATTR(n)
284#define _ATTR_EXPAND15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
285 _ATTR_EXPAND14(a, b, c, d, e, f, g, h, i, j, k, l, m, n) \
286 GPU_VERTEX_FORMAT_ADD_ATTR(o)
287#define _ATTR_EXPAND16(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o, p) \
288 _ATTR_EXPAND15(a, b, c, d, e, f, g, h, i, j, k, l, m, n, o) \
289 GPU_VERTEX_FORMAT_ADD_ATTR(p)
290/* We only support up to GPU_VERT_ATTR_MAX_LEN attribute per format. */
291
292#define GPU_VERTEX_FORMAT_ADD_ATTR_EXPAND(...) VA_NARGS_CALL_OVERLOAD(_ATTR_EXPAND, __VA_ARGS__)
293
294#define GPU_VERTEX_FORMAT_FUNC(_VertT, ...) \
295 static GPUVertFormat &format() \
296 { \
297 using VertT = _VertT; \
298 static GPUVertFormat format = {}; \
299 if (format.attr_len == 0) { \
300 GPU_VERTEX_FORMAT_ADD_ATTR_EXPAND(__VA_ARGS__) \
301 format.stride = sizeof(VertT); \
302 BLI_STATIC_ASSERT(sizeof(VertT) < 1024, "Vertex format is too big") \
303 format.packed = true; \
304 BLI_STATIC_ASSERT_ALIGN(VertT, 4) \
305 } \
306 return format; \
307 }
308
309namespace blender::gpu {
310
316
317template<> struct GenericVertexFormat<int8_t> {
318 /* This is a workaround to reinterpret int8_t into padded vertex format to be able to upload it
319 * on any GPU. The shaders then need to read uint32_t and use shifts and mask to decode in
320 * individual bytes. */
321 uint32_t attr;
323};
324
325template<> struct GenericVertexFormat<uint8_t> {
326 /* This is a workaround to reinterpret uint8_t into padded vertex format to be able to upload it
327 * on any GPU. The shaders then need to read uint32_t and use shifts and mask to decode in
328 * individual bytes. */
329 uint32_t attr;
331};
332
333template<> struct GenericVertexFormat<bool> {
334 /* This is a workaround to reinterpret bool into padded vertex format to be able to upload it
335 * on any GPU. The shaders then need to read uint32_t and use shifts and mask to decode in
336 * individual bytes. */
337 uint32_t attr;
339};
340
341} // namespace blender::gpu
342
344void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat &src);
346
350/* Legacy/unsafe version.
351 * TODO: Replace by vertex_format_combine. */
354
356
363
376
392
394
396 const GPUVertAttr *attr,
397 uint n_idx)
398{
399 return format->names + attr->names[n_idx];
400}
401
406void GPU_vertformat_attr_rename(GPUVertFormat *format, int attr, const char *new_name);
407
412void GPU_vertformat_safe_attr_name(blender::StringRef attr_name, char *r_safe_name, uint max_len);
#define BLI_STATIC_ASSERT(a, msg)
Definition BLI_assert.h:83
#define BLI_INLINE
unsigned char uchar
unsigned int uint
#define DECLARE(a, b, c, blender_enum, d, e, f, g, h)
void GPU_vertformat_attr_rename(GPUVertFormat *format, int attr, const char *new_name)
static constexpr int GPU_VERT_ATTR_MAX_LEN
BLI_INLINE const char * GPU_vertformat_attr_name_get(const GPUVertFormat *format, const GPUVertAttr *attr, uint n_idx)
int GPU_vertformat_attr_id_get(const GPUVertFormat *, blender::StringRef name)
static constexpr int GPU_VERT_ATTR_MAX_NAMES
GPUVertFetchMode
@ GPU_FETCH_FLOAT
@ GPU_FETCH_INT_TO_FLOAT_UNIT
@ GPU_FETCH_INT
#define ATTR_TYPE_MAPPING(_type, b, c, blender_enum, d, e, f, g, h)
uint GPU_vertformat_attr_add_legacy(GPUVertFormat *, blender::StringRef name, GPUVertCompType, uint comp_len, GPUVertFetchMode)
static constexpr int GPU_VERT_FORMAT_MAX_NAMES
void GPU_vertformat_from_shader(GPUVertFormat *format, const blender::gpu::Shader *shader)
void GPU_vertformat_alias_add(GPUVertFormat *, blender::StringRef alias)
GPUVertFormat GPU_vertformat_from_attribute(blender::StringRef name, blender::gpu::VertAttrType type)
#define GPU_VERTEX_DEPRECATED_FORMAT_EXPAND(impl)
void GPU_vertformat_safe_attr_name(blender::StringRef attr_name, char *r_safe_name, uint max_len)
static constexpr int GPU_VERT_ATTR_NAMES_BUF_LEN
void GPU_vertformat_multiload_enable(GPUVertFormat *format, int load_count)
void GPU_vertformat_clear(GPUVertFormat *)
void GPU_vertformat_copy(GPUVertFormat *dest, const GPUVertFormat &src)
static constexpr int GPU_MAX_SAFE_ATTR_NAME
uint GPU_vertformat_attr_add(GPUVertFormat *format, blender::StringRef name, blender::gpu::VertAttrType type)
#define GPU_VERTEX_FORMAT_EXPAND(impl)
void GPU_vertformat_deinterleave(GPUVertFormat *format)
#define GPU_VERTEX_FORMAT_EXPAND_TYPED(impl)
GPUVertCompType
@ GPU_COMP_U16
@ GPU_COMP_MAX
@ GPU_COMP_I10
@ GPU_COMP_F32
@ GPU_COMP_I32
@ GPU_COMP_I8
@ GPU_COMP_U32
@ GPU_COMP_I16
@ GPU_COMP_U8
format
#define T
constexpr DataFormat to_data_format(TextureFormat format)
const char * name
blender::gpu::VertAttrType format
GPUVertFetchMode fetch_mode() const
GPUVertCompType comp_type() const
struct GPUVertAttr::Type type
uchar names[GPU_VERT_ATTR_MAX_NAMES]
GPUVertAttr attrs[GPU_VERT_ATTR_MAX_LEN]
char names[GPU_VERT_ATTR_NAMES_BUF_LEN]
uint attribute_add(blender::StringRef name, blender::gpu::VertAttrType type, size_t offset=-1)
GPU_VERTEX_FORMAT_FUNC(GenericVertexFormat, attr)
GPU_VERTEX_FORMAT_FUNC(GenericVertexFormat, attr)
GPU_VERTEX_FORMAT_FUNC(GenericVertexFormat, attr)
GPU_VERTEX_FORMAT_FUNC(GenericVertexFormat, attr)