1/*
2 * Copyright 2010-2019 Branimir Karadzic. All rights reserved.
3 * License: https://github.com/bkaradzic/bx#license-bsd-2-clause
4 */
5
6#ifndef BX_PIXEL_FORMAT_H_HEADER_GUARD
7#	error "Must be included from bx/pixelformat.h"
8#endif // BX_PIXEL_FORMAT_H_HEADER_GUARD
9
10namespace bx
11{
12	inline uint32_t toUnorm(float _value, float _scale)
13	{
14		return uint32_t(round(clamp(_value, 0.0f, 1.0f) * _scale) );
15	}
16
17	inline float fromUnorm(uint32_t _value, float _scale)
18	{
19		return float(_value) / _scale;
20	}
21
22	inline int32_t toSnorm(float _value, float _scale)
23	{
24		return int32_t(round(
25					clamp(_value, -1.0f, 1.0f) * _scale)
26					);
27	}
28
29	inline float fromSnorm(int32_t _value, float _scale)
30	{
31		return max(-1.0f, float(_value) / _scale);
32	}
33
34	// A8
35	inline void packA8(void* _dst, const float* _src)
36	{
37		uint8_t* dst = (uint8_t*)_dst;
38		dst[0] = uint8_t(toUnorm(_src[3], 255.0f) );
39	}
40
41	inline void unpackA8(float* _dst, const void* _src)
42	{
43		const uint8_t* src = (const uint8_t*)_src;
44		const float aa = fromUnorm(src[0], 255.0f);
45		_dst[0] = aa;
46		_dst[1] = aa;
47		_dst[2] = aa;
48		_dst[3] = aa;
49	}
50
51	// R8
52	inline void packR8(void* _dst, const float* _src)
53	{
54		uint8_t* dst = (uint8_t*)_dst;
55		dst[0] = uint8_t(toUnorm(_src[0], 255.0f) );
56	}
57
58	inline void unpackR8(float* _dst, const void* _src)
59	{
60		const uint8_t* src = (const uint8_t*)_src;
61		_dst[0] = fromUnorm(src[0], 255.0f);
62		_dst[1] = 0.0f;
63		_dst[2] = 0.0f;
64		_dst[3] = 1.0f;
65	}
66
67	// R8S
68	inline void packR8S(void* _dst, const float* _src)
69	{
70		int8_t* dst = (int8_t*)_dst;
71		dst[0] = int8_t(toSnorm(_src[0], 127.0f) );
72	}
73
74	inline void unpackR8S(float* _dst, const void* _src)
75	{
76		const int8_t* src = (const int8_t*)_src;
77		_dst[0] = fromSnorm(src[0], 127.0f);
78		_dst[1] = 0.0f;
79		_dst[2] = 0.0f;
80		_dst[3] = 1.0f;
81	}
82
83	// R8I
84	inline void packR8I(void* _dst, const float* _src)
85	{
86		int8_t* dst = (int8_t*)_dst;
87		dst[0] = int8_t(_src[0]);
88	}
89
90	inline void unpackR8I(float* _dst, const void* _src)
91	{
92		const int8_t* src = (const int8_t*)_src;
93		_dst[0] = float(src[0]);
94		_dst[1] = 0.0f;
95		_dst[2] = 0.0f;
96		_dst[3] = 1.0f;
97	}
98
99	// R8U
100	inline void packR8U(void* _dst, const float* _src)
101	{
102		uint8_t* dst = (uint8_t*)_dst;
103		dst[0] = uint8_t(_src[0]);
104	}
105
106	inline void unpackR8U(float* _dst, const void* _src)
107	{
108		const uint8_t* src = (const uint8_t*)_src;
109		_dst[0] = float(src[0]);
110		_dst[1] = 0.0f;
111		_dst[2] = 0.0f;
112		_dst[3] = 1.0f;
113	}
114
115	// RG8
116	inline void packRg8(void* _dst, const float* _src)
117	{
118		uint8_t* dst = (uint8_t*)_dst;
119		dst[0] = uint8_t(toUnorm(_src[0], 255.0f) );
120		dst[1] = uint8_t(toUnorm(_src[1], 255.0f) );
121	}
122
123	inline void unpackRg8(float* _dst, const void* _src)
124	{
125		const uint8_t* src = (const uint8_t*)_src;
126		_dst[0] = fromUnorm(src[0], 255.0f);
127		_dst[1] = fromUnorm(src[1], 255.0f);
128		_dst[2] = 0.0f;
129		_dst[3] = 1.0f;
130	}
131
132	// RG8S
133	inline void packRg8S(void* _dst, const float* _src)
134	{
135		int8_t* dst = (int8_t*)_dst;
136		dst[0] = int8_t(toSnorm(_src[0], 127.0f) );
137		dst[1] = int8_t(toSnorm(_src[1], 127.0f) );
138	}
139
140	inline void unpackRg8S(float* _dst, const void* _src)
141	{
142		const int8_t* src = (const int8_t*)_src;
143		_dst[0] = fromSnorm(src[0], 127.0f);
144		_dst[1] = fromSnorm(src[1], 127.0f);
145		_dst[2] = 0.0f;
146		_dst[3] = 1.0f;
147	}
148
149	// RG8I
150	inline void packRg8I(void* _dst, const float* _src)
151	{
152		int8_t* dst = (int8_t*)_dst;
153		dst[0] = int8_t(_src[0]);
154		dst[1] = int8_t(_src[1]);
155	}
156
157	inline void unpackRg8I(float* _dst, const void* _src)
158	{
159		const int8_t* src = (const int8_t*)_src;
160		_dst[0] = float(src[0]);
161		_dst[1] = float(src[1]);
162		_dst[2] = 0.0f;
163		_dst[3] = 1.0f;
164	}
165
166	// RG8U
167	inline void packRg8U(void* _dst, const float* _src)
168	{
169		uint8_t* dst = (uint8_t*)_dst;
170		dst[0] = uint8_t(_src[0]);
171		dst[1] = uint8_t(_src[1]);
172	}
173
174	inline void unpackRg8U(float* _dst, const void* _src)
175	{
176		const uint8_t* src = (const uint8_t*)_src;
177		_dst[0] = float(src[0]);
178		_dst[1] = float(src[1]);
179		_dst[2] = 0.0f;
180		_dst[3] = 1.0f;
181	}
182
183	// RGB8
184	inline void packRgb8(void* _dst, const float* _src)
185	{
186		uint8_t* dst = (uint8_t*)_dst;
187		dst[0] = uint8_t(toUnorm(_src[0], 255.0f) );
188		dst[1] = uint8_t(toUnorm(_src[1], 255.0f) );
189		dst[2] = uint8_t(toUnorm(_src[2], 255.0f) );
190	}
191
192	inline void unpackRgb8(float* _dst, const void* _src)
193	{
194		const uint8_t* src = (const uint8_t*)_src;
195		_dst[0] = fromUnorm(src[0], 255.0f);
196		_dst[1] = fromUnorm(src[1], 255.0f);
197		_dst[2] = fromUnorm(src[2], 255.0f);
198		_dst[3] = 1.0f;
199	}
200
201	// RGB8S
202	inline void packRgb8S(void* _dst, const float* _src)
203	{
204		int8_t* dst = (int8_t*)_dst;
205		dst[0] = int8_t(toSnorm(_src[0], 127.0f) );
206		dst[1] = int8_t(toSnorm(_src[1], 127.0f) );
207		dst[2] = int8_t(toSnorm(_src[2], 127.0f) );
208	}
209
210	inline void unpackRgb8S(float* _dst, const void* _src)
211	{
212		const int8_t* src = (const int8_t*)_src;
213		_dst[0] = fromSnorm(src[0], 127.0f);
214		_dst[1] = fromSnorm(src[1], 127.0f);
215		_dst[2] = fromSnorm(src[2], 127.0f);
216		_dst[3] = 1.0f;
217	}
218
219	// RGB8I
220	inline void packRgb8I(void* _dst, const float* _src)
221	{
222		int8_t* dst = (int8_t*)_dst;
223		dst[0] = int8_t(_src[0]);
224		dst[1] = int8_t(_src[1]);
225		dst[2] = int8_t(_src[2]);
226	}
227
228	inline void unpackRgb8I(float* _dst, const void* _src)
229	{
230		const int8_t* src = (const int8_t*)_src;
231		_dst[0] = float(src[0]);
232		_dst[1] = float(src[1]);
233		_dst[2] = float(src[2]);
234		_dst[3] = 1.0f;
235	}
236
237	// RGB8U
238	inline void packRgb8U(void* _dst, const float* _src)
239	{
240		uint8_t* dst = (uint8_t*)_dst;
241		dst[0] = uint8_t(_src[0]);
242		dst[1] = uint8_t(_src[1]);
243		dst[2] = uint8_t(_src[2]);
244	}
245
246	inline void unpackRgb8U(float* _dst, const void* _src)
247	{
248		const uint8_t* src = (const uint8_t*)_src;
249		_dst[0] = float(src[0]);
250		_dst[1] = float(src[1]);
251		_dst[2] = float(src[2]);
252		_dst[3] = 1.0f;
253	}
254
255	// BGRA8
256	inline void packBgra8(void* _dst, const float* _src)
257	{
258		uint8_t* dst = (uint8_t*)_dst;
259		dst[2] = uint8_t(toUnorm(_src[0], 255.0f) );
260		dst[1] = uint8_t(toUnorm(_src[1], 255.0f) );
261		dst[0] = uint8_t(toUnorm(_src[2], 255.0f) );
262		dst[3] = uint8_t(toUnorm(_src[3], 255.0f) );
263	}
264
265	inline void unpackBgra8(float* _dst, const void* _src)
266	{
267		const uint8_t* src = (const uint8_t*)_src;
268		_dst[0] = fromUnorm(src[2], 255.0f);
269		_dst[1] = fromUnorm(src[1], 255.0f);
270		_dst[2] = fromUnorm(src[0], 255.0f);
271		_dst[3] = fromUnorm(src[3], 255.0f);
272	}
273
274	// RGBA8
275	inline void packRgba8(void* _dst, const float* _src)
276	{
277		uint8_t* dst = (uint8_t*)_dst;
278		dst[0] = uint8_t(toUnorm(_src[0], 255.0f) );
279		dst[1] = uint8_t(toUnorm(_src[1], 255.0f) );
280		dst[2] = uint8_t(toUnorm(_src[2], 255.0f) );
281		dst[3] = uint8_t(toUnorm(_src[3], 255.0f) );
282	}
283
284	inline void unpackRgba8(float* _dst, const void* _src)
285	{
286		const uint8_t* src = (const uint8_t*)_src;
287		_dst[0] = fromUnorm(src[0], 255.0f);
288		_dst[1] = fromUnorm(src[1], 255.0f);
289		_dst[2] = fromUnorm(src[2], 255.0f);
290		_dst[3] = fromUnorm(src[3], 255.0f);
291	}
292
293	// RGBA8S
294	inline void packRgba8S(void* _dst, const float* _src)
295	{
296		int8_t* dst = (int8_t*)_dst;
297		dst[0] = int8_t(toSnorm(_src[0], 127.0f) );
298		dst[1] = int8_t(toSnorm(_src[1], 127.0f) );
299		dst[2] = int8_t(toSnorm(_src[2], 127.0f) );
300		dst[3] = int8_t(toSnorm(_src[3], 127.0f) );
301	}
302
303	inline void unpackRgba8S(float* _dst, const void* _src)
304	{
305		const int8_t* src = (const int8_t*)_src;
306		_dst[0] = fromSnorm(src[0], 127.0f);
307		_dst[1] = fromSnorm(src[1], 127.0f);
308		_dst[2] = fromSnorm(src[2], 127.0f);
309		_dst[3] = fromSnorm(src[3], 127.0f);
310	}
311
312	// RGBA8I
313	inline void packRgba8I(void* _dst, const float* _src)
314	{
315		int8_t* dst = (int8_t*)_dst;
316		dst[0] = int8_t(_src[0]);
317		dst[1] = int8_t(_src[1]);
318		dst[2] = int8_t(_src[2]);
319		dst[3] = int8_t(_src[3]);
320	}
321
322	inline void unpackRgba8I(float* _dst, const void* _src)
323	{
324		const int8_t* src = (const int8_t*)_src;
325		_dst[0] = float(src[0]);
326		_dst[1] = float(src[1]);
327		_dst[2] = float(src[2]);
328		_dst[3] = float(src[3]);
329	}
330
331	// RGBA8U
332	inline void packRgba8U(void* _dst, const float* _src)
333	{
334		uint8_t* dst = (uint8_t*)_dst;
335		dst[0] = uint8_t(_src[0]);
336		dst[1] = uint8_t(_src[1]);
337		dst[2] = uint8_t(_src[2]);
338		dst[3] = uint8_t(_src[3]);
339	}
340
341	inline void unpackRgba8U(float* _dst, const void* _src)
342	{
343		const uint8_t* src = (const uint8_t*)_src;
344		_dst[0] = float(src[0]);
345		_dst[1] = float(src[1]);
346		_dst[2] = float(src[2]);
347		_dst[3] = float(src[3]);
348	}
349
350	// R16
351	inline void packR16(void* _dst, const float* _src)
352	{
353		uint16_t* dst = (uint16_t*)_dst;
354		dst[0] = uint16_t(toUnorm(_src[0], 65535.0f) );
355	}
356
357	inline void unpackR16(float* _dst, const void* _src)
358	{
359		const uint16_t* src = (const uint16_t*)_src;
360		_dst[0] = fromUnorm(src[0], 65535.0f);
361		_dst[1] = 0.0f;
362		_dst[2] = 0.0f;
363		_dst[3] = 1.0f;
364	}
365
366	// R16S
367	inline void packR16S(void* _dst, const float* _src)
368	{
369		int16_t* dst = (int16_t*)_dst;
370		dst[0] = int16_t(toSnorm(_src[0], 32767.0f) );
371	}
372
373	inline void unpackR16S(float* _dst, const void* _src)
374	{
375		const int16_t* src = (const int16_t*)_src;
376		_dst[0] = fromSnorm(src[0], 32767.0f);
377		_dst[1] = 0.0f;
378		_dst[2] = 0.0f;
379		_dst[3] = 1.0f;
380	}
381
382	// R16I
383	inline void packR16I(void* _dst, const float* _src)
384	{
385		int16_t* dst = (int16_t*)_dst;
386		dst[0] = int16_t(_src[0]);
387	}
388
389	inline void unpackR16I(float* _dst, const void* _src)
390	{
391		const int16_t* src = (const int16_t*)_src;
392		_dst[0] = float(src[0]);
393		_dst[1] = 0.0f;
394		_dst[2] = 0.0f;
395		_dst[3] = 1.0f;
396	}
397
398	// R16U
399	inline void packR16U(void* _dst, const float* _src)
400	{
401		uint16_t* dst = (uint16_t*)_dst;
402		dst[0] = uint16_t(_src[0]);
403	}
404
405	inline void unpackR16U(float* _dst, const void* _src)
406	{
407		const uint16_t* src = (const uint16_t*)_src;
408		_dst[0] = float(src[0]);
409	}
410
411	// R16F
412	inline void packR16F(void* _dst, const float* _src)
413	{
414		uint16_t* dst = (uint16_t*)_dst;
415		dst[0] = halfFromFloat(_src[0]);
416	}
417
418	inline void unpackR16F(float* _dst, const void* _src)
419	{
420		const uint16_t* src = (const uint16_t*)_src;
421		_dst[0] = halfToFloat(src[0]);
422		_dst[1] = 0.0f;
423		_dst[2] = 0.0f;
424		_dst[3] = 1.0f;
425	}
426
427	// RG16
428	inline void packRg16(void* _dst, const float* _src)
429	{
430		uint16_t* dst = (uint16_t*)_dst;
431		dst[0] = uint16_t(toUnorm(_src[0], 65535.0f) );
432		dst[1] = uint16_t(toUnorm(_src[1], 65535.0f) );
433	}
434
435	inline void unpackRg16(float* _dst, const void* _src)
436	{
437		const uint16_t* src = (const uint16_t*)_src;
438		_dst[0] = fromUnorm(src[0], 65535.0f);
439		_dst[1] = fromUnorm(src[1], 65535.0f);
440		_dst[2] = 0.0f;
441		_dst[3] = 1.0f;
442	}
443
444	// RG16S
445	inline void packRg16S(void* _dst, const float* _src)
446	{
447		int16_t* dst = (int16_t*)_dst;
448		dst[0] = int16_t(toSnorm(_src[0], 32767.0f) );
449		dst[1] = int16_t(toSnorm(_src[1], 32767.0f) );
450	}
451
452	inline void unpackRg16S(float* _dst, const void* _src)
453	{
454		const int16_t* src = (const int16_t*)_src;
455		_dst[0] = fromSnorm(src[0], 32767.0f);
456		_dst[1] = fromSnorm(src[1], 32767.0f);
457		_dst[2] = 0.0f;
458		_dst[3] = 1.0f;
459	}
460
461	// RG16I
462	inline void packRg16I(void* _dst, const float* _src)
463	{
464		int16_t* dst = (int16_t*)_dst;
465		dst[0] = int16_t(_src[0]);
466		dst[1] = int16_t(_src[1]);
467	}
468
469	inline void unpackRg16I(float* _dst, const void* _src)
470	{
471		const int16_t* src = (const int16_t*)_src;
472		_dst[0] = float(src[0]);
473		_dst[1] = float(src[1]);
474		_dst[2] = 0.0f;
475		_dst[3] = 1.0f;
476	}
477
478	// RG16U
479	inline void packRg16U(void* _dst, const float* _src)
480	{
481		uint16_t* dst = (uint16_t*)_dst;
482		dst[0] = uint16_t(_src[0]);
483		dst[1] = uint16_t(_src[1]);
484	}
485
486	inline void unpackRg16U(float* _dst, const void* _src)
487	{
488		const uint16_t* src = (const uint16_t*)_src;
489		_dst[0] = float(src[0]);
490		_dst[1] = float(src[1]);
491		_dst[2] = 0.0f;
492		_dst[3] = 1.0f;
493	}
494
495	// RG16F
496	inline void packRg16F(void* _dst, const float* _src)
497	{
498		uint16_t* dst = (uint16_t*)_dst;
499		dst[0] = halfFromFloat(_src[0]);
500		dst[1] = halfFromFloat(_src[1]);
501	}
502
503	inline void unpackRg16F(float* _dst, const void* _src)
504	{
505		const uint16_t* src = (const uint16_t*)_src;
506		_dst[0] = halfToFloat(src[0]);
507		_dst[1] = halfToFloat(src[1]);
508		_dst[2] = 0.0f;
509		_dst[3] = 1.0f;
510	}
511
512	// RGBA16
513	inline void packRgba16(void* _dst, const float* _src)
514	{
515		uint16_t* dst = (uint16_t*)_dst;
516		dst[0] = uint16_t(toUnorm(_src[0], 65535.0f) );
517		dst[1] = uint16_t(toUnorm(_src[1], 65535.0f) );
518		dst[2] = uint16_t(toUnorm(_src[2], 65535.0f) );
519		dst[3] = uint16_t(toUnorm(_src[3], 65535.0f) );
520	}
521
522	inline void unpackRgba16(float* _dst, const void* _src)
523	{
524		const uint16_t* src = (const uint16_t*)_src;
525		_dst[0] = fromUnorm(src[0], 65535.0f);
526		_dst[1] = fromUnorm(src[1], 65535.0f);
527		_dst[2] = fromUnorm(src[2], 65535.0f);
528		_dst[3] = fromUnorm(src[3], 65535.0f);
529	}
530
531	// RGBA16S
532	inline void packRgba16S(void* _dst, const float* _src)
533	{
534		int16_t* dst = (int16_t*)_dst;
535		dst[0] = int16_t(toSnorm(_src[0], 32767.0f) );
536		dst[1] = int16_t(toSnorm(_src[1], 32767.0f) );
537		dst[2] = int16_t(toSnorm(_src[2], 32767.0f) );
538		dst[3] = int16_t(toSnorm(_src[3], 32767.0f) );
539	}
540
541	inline void unpackRgba16S(float* _dst, const void* _src)
542	{
543		const int16_t* src = (const int16_t*)_src;
544		_dst[0] = fromSnorm(src[0], 32767.0f);
545		_dst[1] = fromSnorm(src[1], 32767.0f);
546		_dst[2] = fromSnorm(src[2], 32767.0f);
547		_dst[3] = fromSnorm(src[3], 32767.0f);
548	}
549
550	// RGBA16I
551	inline void packRgba16I(void* _dst, const float* _src)
552	{
553		int16_t* dst = (int16_t*)_dst;
554		dst[0] = int16_t(_src[0]);
555		dst[1] = int16_t(_src[1]);
556		dst[2] = int16_t(_src[2]);
557		dst[3] = int16_t(_src[3]);
558	}
559
560	inline void unpackRgba16I(float* _dst, const void* _src)
561	{
562		const int16_t* src = (const int16_t*)_src;
563		_dst[0] = float(src[0]);
564		_dst[1] = float(src[1]);
565		_dst[2] = float(src[2]);
566		_dst[3] = float(src[3]);
567	}
568
569	// RGBA16U
570	inline void packRgba16U(void* _dst, const float* _src)
571	{
572		uint16_t* dst = (uint16_t*)_dst;
573		dst[0] = uint16_t(_src[0]);
574		dst[1] = uint16_t(_src[1]);
575		dst[2] = uint16_t(_src[2]);
576		dst[3] = uint16_t(_src[3]);
577	}
578
579	inline void unpackRgba16U(float* _dst, const void* _src)
580	{
581		const uint16_t* src = (const uint16_t*)_src;
582		_dst[0] = float(src[0]);
583		_dst[1] = float(src[1]);
584		_dst[2] = float(src[2]);
585		_dst[3] = float(src[3]);
586	}
587
588	// RGBA16F
589	inline void packRgba16F(void* _dst, const float* _src)
590	{
591		uint16_t* dst = (uint16_t*)_dst;
592		dst[0] = halfFromFloat(_src[0]);
593		dst[1] = halfFromFloat(_src[1]);
594		dst[2] = halfFromFloat(_src[2]);
595		dst[3] = halfFromFloat(_src[3]);
596	}
597
598	inline void unpackRgba16F(float* _dst, const void* _src)
599	{
600		const uint16_t* src = (const uint16_t*)_src;
601		_dst[0] = halfToFloat(src[0]);
602		_dst[1] = halfToFloat(src[1]);
603		_dst[2] = halfToFloat(src[2]);
604		_dst[3] = halfToFloat(src[3]);
605	}
606
607	// R24
608	inline void packR24(void* _dst, const float* _src)
609	{
610		uint8_t* dst = (uint8_t*)_dst;
611		const uint32_t rr = uint32_t(toUnorm(_src[0], 16777216.0f) );
612		dst[0] = uint8_t(rr    );
613		dst[1] = uint8_t(rr>> 8);
614		dst[2] = uint8_t(rr>>16);
615	}
616
617	inline void unpackR24(float* _dst, const void* _src)
618	{
619		const uint8_t* src = (const uint8_t*)_src;
620		const uint32_t rr = 0
621			| (src[0]    )
622			| (src[1]<< 8)
623			| (src[2]<<16)
624			;
625
626		_dst[0] = fromUnorm(rr, 16777216.0f);
627		_dst[1] = 0.0f;
628		_dst[2] = 0.0f;
629		_dst[3] = 1.0f;
630	}
631
632	// R24G8
633	inline void packR24G8(void* _dst, const float* _src)
634	{
635		uint8_t* dst = (uint8_t*)_dst;
636		const uint32_t rr = uint32_t(toUnorm(_src[0], 16777216.0f) );
637		dst[0] = uint8_t(rr    );
638		dst[1] = uint8_t(rr>> 8);
639		dst[2] = uint8_t(rr>>16);
640		dst[3] = uint8_t(toUnorm(_src[1], 255.0f) );
641	}
642
643	inline void unpackR24G8(float* _dst, const void* _src)
644	{
645		const uint8_t* src = (const uint8_t*)_src;
646		const uint32_t rr = 0
647			| (src[0]    )
648			| (src[1]<< 8)
649			| (src[2]<<16)
650			;
651
652		_dst[0] = fromUnorm(rr, 16777216.0f);
653		_dst[1] = fromUnorm(src[3], 255.0f);
654		_dst[2] = 0.0f;
655		_dst[3] = 1.0f;
656	}
657
658	// R32I
659	inline void packR32I(void* _dst, const float* _src)
660	{
661		memCopy(_dst, _src, 4);
662	}
663
664	inline void unpackR32I(float* _dst, const void* _src)
665	{
666		memCopy(_dst, _src, 4);
667	}
668
669	// R32U
670	inline void packR32U(void* _dst, const float* _src)
671	{
672		memCopy(_dst, _src, 4);
673	}
674
675	inline void unpackR32U(float* _dst, const void* _src)
676	{
677		memCopy(_dst, _src, 4);
678	}
679
680	// R32F
681	inline void packR32F(void* _dst, const float* _src)
682	{
683		memCopy(_dst, _src, 4);
684	}
685
686	inline void unpackR32F(float* _dst, const void* _src)
687	{
688		memCopy(_dst, _src, 4);
689	}
690
691	// RG32I
692	inline void packRg32I(void* _dst, const float* _src)
693	{
694		memCopy(_dst, _src, 8);
695	}
696
697	inline void unpackRg32I(float* _dst, const void* _src)
698	{
699		memCopy(_dst, _src, 8);
700	}
701
702	// RG32U
703	inline void packRg32U(void* _dst, const float* _src)
704	{
705		memCopy(_dst, _src, 8);
706	}
707
708	inline void unpackRg32U(float* _dst, const void* _src)
709	{
710		memCopy(_dst, _src, 8);
711	}
712
713	// RG32F
714	inline void packRg32F(void* _dst, const float* _src)
715	{
716		memCopy(_dst, _src, 8);
717	}
718
719	inline void unpackRg32F(float* _dst, const void* _src)
720	{
721		memCopy(_dst, _src, 8);
722	}
723
724	template<int32_t MantissaBits, int32_t ExpBits>
725	inline void encodeRgbE(float* _dst, const float* _src)
726	{
727		// Reference(s):
728		// - https://web.archive.org/web/20181126040035/https://www.khronos.org/registry/OpenGL/extensions/EXT/EXT_texture_shared_exponent.txt
729		//
730		const int32_t expMax  = (1<<ExpBits) - 1;
731		const int32_t expBias = (1<<(ExpBits - 1) ) - 1;
732		const float   sharedExpMax = float(expMax) / float(expMax + 1) * float(1 << (expMax - expBias) );
733
734		const float rr = clamp(_src[0], 0.0f, sharedExpMax);
735		const float gg = clamp(_src[1], 0.0f, sharedExpMax);
736		const float bb = clamp(_src[2], 0.0f, sharedExpMax);
737		const float mm = max(rr, gg, bb);
738		union { float ff; uint32_t ui; } cast = { mm };
739		int32_t expShared = int32_t(uint32_imax(uint32_t(-expBias-1), ( ( (cast.ui>>23) & 0xff) - 127) ) ) + 1 + expBias;
740		float denom = pow(2.0f, float(expShared - expBias - MantissaBits) );
741
742		if ( (1<<MantissaBits) == int32_t(round(mm/denom) ) )
743		{
744			denom *= 2.0f;
745			++expShared;
746		}
747
748		const float invDenom = 1.0f/denom;
749		_dst[0] = round(rr * invDenom);
750		_dst[1] = round(gg * invDenom);
751		_dst[2] = round(bb * invDenom);
752		_dst[3] = float(expShared);
753	}
754
755	template<int32_t MantissaBits, int32_t ExpBits>
756	inline void decodeRgbE(float* _dst, const float* _src)
757	{
758		const int32_t expBias = (1<<(ExpBits - 1) ) - 1;
759		const float exponent  = _src[3]-float(expBias-MantissaBits);
760		const float scale     = pow(2.0f, exponent);
761		_dst[0] = _src[0] * scale;
762		_dst[1] = _src[1] * scale;
763		_dst[2] = _src[2] * scale;
764	}
765
766	// RGB9E5F
767	inline void packRgb9E5F(void* _dst, const float* _src)
768	{
769		float tmp[4];
770		encodeRgbE<9, 5>(tmp, _src);
771
772		*( (uint32_t*)_dst) = 0
773			| (uint32_t(tmp[0])     )
774			| (uint32_t(tmp[1]) << 9)
775			| (uint32_t(tmp[2]) <<18)
776			| (uint32_t(tmp[3]) <<27)
777			;
778	}
779
780	inline void unpackRgb9E5F(float* _dst, const void* _src)
781	{
782		uint32_t packed = *( (const uint32_t*)_src);
783
784		float tmp[4];
785		tmp[0] = float( ( (packed    ) & 0x1ff) ) / 511.0f;
786		tmp[1] = float( ( (packed>> 9) & 0x1ff) ) / 511.0f;
787		tmp[2] = float( ( (packed>>18) & 0x1ff) ) / 511.0f;
788		tmp[3] = float( ( (packed>>27) &  0x1f) );
789
790		decodeRgbE<9, 5>(_dst, tmp);
791	}
792
793	// RGBA32I
794	inline void packRgba32I(void* _dst, const float* _src)
795	{
796		memCopy(_dst, _src, 16);
797	}
798
799	inline void unpackRgba32I(float* _dst, const void* _src)
800	{
801		memCopy(_dst, _src, 16);
802	}
803
804	// RGBA32U
805	inline void packRgba32U(void* _dst, const float* _src)
806	{
807		memCopy(_dst, _src, 16);
808	}
809
810	inline void unpackRgba32U(float* _dst, const void* _src)
811	{
812		memCopy(_dst, _src, 16);
813	}
814
815	// RGBA32F
816	inline void packRgba32F(void* _dst, const float* _src)
817	{
818		memCopy(_dst, _src, 16);
819	}
820
821	inline void unpackRgba32F(float* _dst, const void* _src)
822	{
823		memCopy(_dst, _src, 16);
824	}
825
826	// R5G6B5
827	inline void packR5G6B5(void* _dst, const float* _src)
828	{
829		*( (uint16_t*)_dst) = 0
830			| uint16_t(toUnorm(_src[0], 31.0f)<<11)
831			| uint16_t(toUnorm(_src[1], 63.0f)<< 5)
832			| uint16_t(toUnorm(_src[2], 31.0f)    )
833			;
834	}
835
836	inline void unpackR5G6B5(float* _dst, const void* _src)
837	{
838		uint16_t packed = *( (const uint16_t*)_src);
839		_dst[0] = float( ( (packed>>11) & 0x1f) ) / 31.0f;
840		_dst[1] = float( ( (packed>> 5) & 0x3f) ) / 63.0f;
841		_dst[2] = float( ( (packed    ) & 0x1f) ) / 31.0f;
842		_dst[3] = 1.0f;
843	}
844
845	// RGBA4
846	inline void packRgba4(void* _dst, const float* _src)
847	{
848		*( (uint16_t*)_dst) = 0
849			| uint16_t(toUnorm(_src[0], 15.0f)    )
850			| uint16_t(toUnorm(_src[1], 15.0f)<< 4)
851			| uint16_t(toUnorm(_src[2], 15.0f)<< 8)
852			| uint16_t(toUnorm(_src[3], 15.0f)<<12)
853			;
854	}
855
856	inline void unpackRgba4(float* _dst, const void* _src)
857	{
858		uint16_t packed = *( (const uint16_t*)_src);
859		_dst[0] = float( ( (packed    ) & 0xf) ) / 15.0f;
860		_dst[1] = float( ( (packed>> 4) & 0xf) ) / 15.0f;
861		_dst[2] = float( ( (packed>> 8) & 0xf) ) / 15.0f;
862		_dst[3] = float( ( (packed>>12) & 0xf) ) / 15.0f;
863	}
864
865	// RGBA4
866	inline void packBgra4(void* _dst, const float* _src)
867	{
868		*( (uint16_t*)_dst) = 0
869			| uint16_t(toUnorm(_src[0], 15.0f)<< 8)
870			| uint16_t(toUnorm(_src[1], 15.0f)<< 4)
871			| uint16_t(toUnorm(_src[2], 15.0f)    )
872			| uint16_t(toUnorm(_src[3], 15.0f)<<12)
873			;
874	}
875
876	inline void unpackBgra4(float* _dst, const void* _src)
877	{
878		uint16_t packed = *( (const uint16_t*)_src);
879		_dst[0] = float( ( (packed>> 8) & 0xf) ) / 15.0f;
880		_dst[1] = float( ( (packed>> 4) & 0xf) ) / 15.0f;
881		_dst[2] = float( ( (packed    ) & 0xf) ) / 15.0f;
882		_dst[3] = float( ( (packed>>12) & 0xf) ) / 15.0f;
883	}
884
885	// RGB5A1
886	inline void packRgb5a1(void* _dst, const float* _src)
887	{
888		*( (uint16_t*)_dst) = 0
889			| uint16_t(toUnorm(_src[0], 31.0f)    )
890			| uint16_t(toUnorm(_src[1], 31.0f)<< 5)
891			| uint16_t(toUnorm(_src[2], 31.0f)<<10)
892			| uint16_t(toUnorm(_src[3],  1.0f)<<15)
893			;
894	}
895
896	inline void unpackRgb5a1(float* _dst, const void* _src)
897	{
898		uint16_t packed = *( (const uint16_t*)_src);
899		_dst[0] = float( ( (packed    ) & 0x1f) ) / 31.0f;
900		_dst[1] = float( ( (packed>> 5) & 0x1f) ) / 31.0f;
901		_dst[2] = float( ( (packed>>10) & 0x1f) ) / 31.0f;
902		_dst[3] = float( ( (packed>>14) &  0x1) );
903	}
904
905	// BGR5A1
906	inline void packBgr5a1(void* _dst, const float* _src)
907	{
908		*( (uint16_t*)_dst) = 0
909			| uint16_t(toUnorm(_src[0], 31.0f)<<10)
910			| uint16_t(toUnorm(_src[1], 31.0f)<< 5)
911			| uint16_t(toUnorm(_src[2], 31.0f)    )
912			| uint16_t(toUnorm(_src[3],  1.0f)<<15)
913			;
914	}
915
916	inline void unpackBgr5a1(float* _dst, const void* _src)
917	{
918		uint16_t packed = *( (const uint16_t*)_src);
919		_dst[0] = float( ( (packed>>10) & 0x1f) ) / 31.0f;
920		_dst[1] = float( ( (packed>> 5) & 0x1f) ) / 31.0f;
921		_dst[2] = float( ( (packed    ) & 0x1f) ) / 31.0f;
922		_dst[3] = float( ( (packed>>14) &  0x1) );
923	}
924
925	// RGB10A2
926	inline void packRgb10A2(void* _dst, const float* _src)
927	{
928		*( (uint32_t*)_dst) = 0
929			| (toUnorm(_src[0], 1023.0f)    )
930			| (toUnorm(_src[1], 1023.0f)<<10)
931			| (toUnorm(_src[2], 1023.0f)<<20)
932			| (toUnorm(_src[3],    3.0f)<<30)
933			;
934	}
935
936	inline void unpackRgb10A2(float* _dst, const void* _src)
937	{
938		uint32_t packed = *( (const uint32_t*)_src);
939		_dst[0] = float( ( (packed    ) & 0x3ff) ) / 1023.0f;
940		_dst[1] = float( ( (packed>>10) & 0x3ff) ) / 1023.0f;
941		_dst[2] = float( ( (packed>>20) & 0x3ff) ) / 1023.0f;
942		_dst[3] = float( ( (packed>>30) &   0x3) ) /    3.0f;
943	}
944
945	// RG11B10F
946	inline void packRG11B10F(void* _dst, const float* _src)
947	{
948		*( (uint32_t*)_dst) = 0
949			| ( (halfFromFloat(_src[0])>> 4) &      0x7ff)
950			| ( (halfFromFloat(_src[0])<< 7) &   0x3ff800)
951			| ( (halfFromFloat(_src[0])<<17) & 0xffc00000)
952			;
953	}
954
955	inline void unpackRG11B10F(float* _dst, const void* _src)
956	{
957		uint32_t packed = *( (const uint32_t*)_src);
958		_dst[0] = halfToFloat( (packed<< 4) & 0x7ff0);
959		_dst[1] = halfToFloat( (packed>> 7) & 0x7ff0);
960		_dst[2] = halfToFloat( (packed>>17) & 0x7fe0);
961		_dst[3] = 1.0f;
962	}
963} // namespace bx
964