Initial code commit
This commit is contained in:
parent
7485d9cbe1
commit
029dc67524
25 changed files with 21809 additions and 0 deletions
109
LICENCE.txt
Normal file
109
LICENCE.txt
Normal file
|
@ -0,0 +1,109 @@
|
|||
TextureTaffy
|
||||
============
|
||||
|
||||
MIT License
|
||||
|
||||
Copyright (c) 2023 leblane
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
stb_image and stb_image_resize
|
||||
------------------------------
|
||||
[stb_image and stb_image_resize] are available under 2 licenses -- choose whichever you prefer.
|
||||
|
||||
ALTERNATIVE A - MIT License
|
||||
Copyright (c) 2017 Sean Barrett
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
ALTERNATIVE B - Public Domain (www.unlicense.org)
|
||||
This is free and unencumbered software released into the public domain.
|
||||
Anyone is free to copy, modify, publish, use, compile, sell, or distribute this
|
||||
software, either in source code form or as a compiled binary, for any purpose,
|
||||
commercial or non-commercial, and by any means.
|
||||
In jurisdictions that recognize copyright laws, the author or authors of this
|
||||
software dedicate any and all copyright interest in the software to the public
|
||||
domain. We make this dedication for the benefit of the public at large and to
|
||||
the detriment of our heirs and successors. We intend this dedication to be an
|
||||
overt act of relinquishment in perpetuity of all present and future rights to
|
||||
this software under copyright law.
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
|
||||
ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
ISPC Texture Compressor
|
||||
-----------------------
|
||||
|
||||
Copyright 2017 Intel Corporation
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy of
|
||||
this software and associated documentation files (the "Software"), to deal in
|
||||
the Software without restriction, including without limitation the rights to
|
||||
use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
|
||||
of the Software, and to permit persons to whom the Software is furnished to do
|
||||
so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
||||
|
||||
Khronos DFD Components
|
||||
----------------------
|
||||
|
||||
** Copyright 2015-2020 The Khronos Group Inc.
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
14
README.md
Normal file
14
README.md
Normal file
|
@ -0,0 +1,14 @@
|
|||
# TextureTaffy
|
||||
|
||||
A utility to create compressed textures, in BC1 (DXT1), BC3 (DXT5), BC4, BC5, BC6(U)H and BC7 compression formats, with the [KTX File Format Version 2.0](https://registry.khronos.org/KTX/specs/2.0/ktxspec.v2.html) (KTX2).
|
||||
|
||||
## Requirements
|
||||
|
||||
* [The Meson build system](https://mesonbuild.com/)
|
||||
* [Intel® Implicit SPMD Program Compiler](https://ispc.github.io/)
|
||||
|
||||
## Building
|
||||
|
||||
|
||||
|
||||
## Notes and limitations
|
1039
Source/HalfFloat.cpp
Normal file
1039
Source/HalfFloat.cpp
Normal file
File diff suppressed because it is too large
Load diff
8
Source/HalfFloat.h
Normal file
8
Source/HalfFloat.h
Normal file
|
@ -0,0 +1,8 @@
|
|||
#pragma once
|
||||
|
||||
#include <cstdint>
|
||||
|
||||
namespace HalfFloat
|
||||
{
|
||||
uint16_t FromFloat(float x);
|
||||
};
|
619
Source/KHR/khr_df.h
Normal file
619
Source/KHR/khr_df.h
Normal file
|
@ -0,0 +1,619 @@
|
|||
/* The Khronos Data Format Specification (version 1.3) */
|
||||
/*
|
||||
** Copyright 2015-2020 The Khronos Group Inc.
|
||||
** SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/* This header defines a structure that can describe the layout of image
|
||||
formats in memory. This means that the data format is transparent to
|
||||
the application, and the expectation is that this should be used when
|
||||
the layout is defined external to the API. Many Khronos APIs deliberately
|
||||
keep the internal layout of images opaque, to allow proprietary layouts
|
||||
and optimisations. This structure is not appropriate for describing
|
||||
opaque layouts. */
|
||||
|
||||
/* We stick to standard C89 constructs for simplicity and portability. */
|
||||
|
||||
#ifndef _KHR_DATA_FORMAT_H_
|
||||
#define _KHR_DATA_FORMAT_H_
|
||||
|
||||
/* Accessors */
|
||||
typedef enum _khr_word_e {
|
||||
KHR_DF_WORD_VENDORID = 0U,
|
||||
KHR_DF_WORD_DESCRIPTORTYPE = 0U,
|
||||
KHR_DF_WORD_VERSIONNUMBER = 1U,
|
||||
KHR_DF_WORD_DESCRIPTORBLOCKSIZE = 1U,
|
||||
KHR_DF_WORD_MODEL = 2U,
|
||||
KHR_DF_WORD_PRIMARIES = 2U,
|
||||
KHR_DF_WORD_TRANSFER = 2U,
|
||||
KHR_DF_WORD_FLAGS = 2U,
|
||||
KHR_DF_WORD_TEXELBLOCKDIMENSION0 = 3U,
|
||||
KHR_DF_WORD_TEXELBLOCKDIMENSION1 = 3U,
|
||||
KHR_DF_WORD_TEXELBLOCKDIMENSION2 = 3U,
|
||||
KHR_DF_WORD_TEXELBLOCKDIMENSION3 = 3U,
|
||||
KHR_DF_WORD_BYTESPLANE0 = 4U,
|
||||
KHR_DF_WORD_BYTESPLANE1 = 4U,
|
||||
KHR_DF_WORD_BYTESPLANE2 = 4U,
|
||||
KHR_DF_WORD_BYTESPLANE3 = 4U,
|
||||
KHR_DF_WORD_BYTESPLANE4 = 5U,
|
||||
KHR_DF_WORD_BYTESPLANE5 = 5U,
|
||||
KHR_DF_WORD_BYTESPLANE6 = 5U,
|
||||
KHR_DF_WORD_BYTESPLANE7 = 5U,
|
||||
KHR_DF_WORD_SAMPLESTART = 6U,
|
||||
KHR_DF_WORD_SAMPLEWORDS = 4U
|
||||
} khr_df_word_e;
|
||||
|
||||
typedef enum _khr_df_shift_e {
|
||||
KHR_DF_SHIFT_VENDORID = 0U,
|
||||
KHR_DF_SHIFT_DESCRIPTORTYPE = 17U,
|
||||
KHR_DF_SHIFT_VERSIONNUMBER = 0U,
|
||||
KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE = 16U,
|
||||
KHR_DF_SHIFT_MODEL = 0U,
|
||||
KHR_DF_SHIFT_PRIMARIES = 8U,
|
||||
KHR_DF_SHIFT_TRANSFER = 16U,
|
||||
KHR_DF_SHIFT_FLAGS = 24U,
|
||||
KHR_DF_SHIFT_TEXELBLOCKDIMENSION0 = 0U,
|
||||
KHR_DF_SHIFT_TEXELBLOCKDIMENSION1 = 8U,
|
||||
KHR_DF_SHIFT_TEXELBLOCKDIMENSION2 = 16U,
|
||||
KHR_DF_SHIFT_TEXELBLOCKDIMENSION3 = 24U,
|
||||
KHR_DF_SHIFT_BYTESPLANE0 = 0U,
|
||||
KHR_DF_SHIFT_BYTESPLANE1 = 8U,
|
||||
KHR_DF_SHIFT_BYTESPLANE2 = 16U,
|
||||
KHR_DF_SHIFT_BYTESPLANE3 = 24U,
|
||||
KHR_DF_SHIFT_BYTESPLANE4 = 0U,
|
||||
KHR_DF_SHIFT_BYTESPLANE5 = 8U,
|
||||
KHR_DF_SHIFT_BYTESPLANE6 = 16U,
|
||||
KHR_DF_SHIFT_BYTESPLANE7 = 24U
|
||||
} khr_df_shift_e;
|
||||
|
||||
typedef enum _khr_df_mask_e {
|
||||
KHR_DF_MASK_VENDORID = 0x1FFFFU,
|
||||
KHR_DF_MASK_DESCRIPTORTYPE = 0x7FFFU,
|
||||
KHR_DF_MASK_VERSIONNUMBER = 0xFFFFU,
|
||||
KHR_DF_MASK_DESCRIPTORBLOCKSIZE = 0xFFFFU,
|
||||
KHR_DF_MASK_MODEL = 0xFFU,
|
||||
KHR_DF_MASK_PRIMARIES = 0xFFU,
|
||||
KHR_DF_MASK_TRANSFER = 0xFFU,
|
||||
KHR_DF_MASK_FLAGS = 0xFFU,
|
||||
KHR_DF_MASK_TEXELBLOCKDIMENSION0 = 0xFFU,
|
||||
KHR_DF_MASK_TEXELBLOCKDIMENSION1 = 0xFFU,
|
||||
KHR_DF_MASK_TEXELBLOCKDIMENSION2 = 0xFFU,
|
||||
KHR_DF_MASK_TEXELBLOCKDIMENSION3 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE0 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE1 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE2 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE3 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE4 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE5 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE6 = 0xFFU,
|
||||
KHR_DF_MASK_BYTESPLANE7 = 0xFFU
|
||||
} khr_df_mask_e;
|
||||
|
||||
/* Helper macro:
|
||||
Extract field X from basic descriptor block BDB */
|
||||
#define KHR_DFDVAL(BDB, X) \
|
||||
(((BDB)[KHR_DF_WORD_ ## X] >> (KHR_DF_SHIFT_ ## X)) \
|
||||
& (KHR_DF_MASK_ ## X))
|
||||
|
||||
/* Helper macro:
|
||||
Set field X of basic descriptor block BDB */
|
||||
#define KHR_DFDSETVAL(BDB, X, val) \
|
||||
((BDB)[KHR_DF_WORD_ ## X] = \
|
||||
((BDB)[KHR_DF_WORD_ ## X] & \
|
||||
~((KHR_DF_MASK_ ## X) << (KHR_DF_SHIFT_ ## X))) | \
|
||||
(((val) & (KHR_DF_MASK_ ## X)) << (KHR_DF_SHIFT_ ## X)))
|
||||
|
||||
/* Offsets relative to the start of a sample */
|
||||
typedef enum _khr_df_sampleword_e {
|
||||
KHR_DF_SAMPLEWORD_BITOFFSET = 0U,
|
||||
KHR_DF_SAMPLEWORD_BITLENGTH = 0U,
|
||||
KHR_DF_SAMPLEWORD_CHANNELID = 0U,
|
||||
KHR_DF_SAMPLEWORD_QUALIFIERS = 0U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLEPOSITION0 = 1U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLEPOSITION1 = 1U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLEPOSITION2 = 1U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLEPOSITION3 = 1U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL = 1U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLELOWER = 2U,
|
||||
KHR_DF_SAMPLEWORD_SAMPLEUPPER = 3U
|
||||
} khr_df_sampleword_e;
|
||||
|
||||
typedef enum _khr_df_sampleshift_e {
|
||||
KHR_DF_SAMPLESHIFT_BITOFFSET = 0U,
|
||||
KHR_DF_SAMPLESHIFT_BITLENGTH = 16U,
|
||||
KHR_DF_SAMPLESHIFT_CHANNELID = 24U,
|
||||
/* N.B. Qualifiers are defined as an offset into a byte */
|
||||
KHR_DF_SAMPLESHIFT_QUALIFIERS = 24U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION0 = 0U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION1 = 8U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION2 = 16U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION3 = 24U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLEPOSITION_ALL = 0U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLELOWER = 0U,
|
||||
KHR_DF_SAMPLESHIFT_SAMPLEUPPER = 0U
|
||||
} khr_df_sampleshift_e;
|
||||
|
||||
typedef enum _khr_df_samplemask_e {
|
||||
KHR_DF_SAMPLEMASK_BITOFFSET = 0xFFFFU,
|
||||
KHR_DF_SAMPLEMASK_BITLENGTH = 0xFF,
|
||||
KHR_DF_SAMPLEMASK_CHANNELID = 0xF,
|
||||
/* N.B. Qualifiers are defined as an offset into a byte */
|
||||
KHR_DF_SAMPLEMASK_QUALIFIERS = 0xF0,
|
||||
KHR_DF_SAMPLEMASK_SAMPLEPOSITION0 = 0xFF,
|
||||
KHR_DF_SAMPLEMASK_SAMPLEPOSITION1 = 0xFF,
|
||||
KHR_DF_SAMPLEMASK_SAMPLEPOSITION2 = 0xFF,
|
||||
KHR_DF_SAMPLEMASK_SAMPLEPOSITION3 = 0xFF,
|
||||
/* ISO C restricts enum values to range of int hence the
|
||||
cast. We do it verbosely instead of using -1 to ensure
|
||||
it is a 32-bit value even if int is 64 bits. */
|
||||
KHR_DF_SAMPLEMASK_SAMPLEPOSITION_ALL = (int) 0xFFFFFFFFU,
|
||||
KHR_DF_SAMPLEMASK_SAMPLELOWER = (int) 0xFFFFFFFFU,
|
||||
KHR_DF_SAMPLEMASK_SAMPLEUPPER = (int) 0xFFFFFFFFU
|
||||
} khr_df_samplemask_e;
|
||||
|
||||
/* Helper macro:
|
||||
Extract field X of sample S from basic descriptor block BDB */
|
||||
#define KHR_DFDSVAL(BDB, S, X) \
|
||||
(((BDB)[KHR_DF_WORD_SAMPLESTART + \
|
||||
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
|
||||
KHR_DF_SAMPLEWORD_ ## X] >> (KHR_DF_SAMPLESHIFT_ ## X)) \
|
||||
& (KHR_DF_SAMPLEMASK_ ## X))
|
||||
|
||||
/* Helper macro:
|
||||
Set field X of sample S of basic descriptor block BDB */
|
||||
#define KHR_DFDSETSVAL(BDB, S, X, val) \
|
||||
((BDB)[KHR_DF_WORD_SAMPLESTART + \
|
||||
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
|
||||
KHR_DF_SAMPLEWORD_ ## X] = \
|
||||
((BDB)[KHR_DF_WORD_SAMPLESTART + \
|
||||
((S) * KHR_DF_WORD_SAMPLEWORDS) + \
|
||||
KHR_DF_SAMPLEWORD_ ## X] & \
|
||||
~((uint32_t)(KHR_DF_SAMPLEMASK_ ## X) << (KHR_DF_SAMPLESHIFT_ ## X))) | \
|
||||
(((val) & (uint32_t)(KHR_DF_SAMPLEMASK_ ## X)) << (KHR_DF_SAMPLESHIFT_ ## X)))
|
||||
|
||||
/* Helper macro:
|
||||
Number of samples in basic descriptor block BDB */
|
||||
#define KHR_DFDSAMPLECOUNT(BDB) \
|
||||
(((KHR_DFDVAL(BDB, DESCRIPTORBLOCKSIZE) >> 2) - \
|
||||
KHR_DF_WORD_SAMPLESTART) \
|
||||
/ KHR_DF_WORD_SAMPLEWORDS)
|
||||
|
||||
/* Helper macro:
|
||||
Size in words of basic descriptor block for S samples */
|
||||
#define KHR_DFDSIZEWORDS(S) \
|
||||
(KHR_DF_WORD_SAMPLESTART + \
|
||||
(S) * KHR_DF_WORD_SAMPLEWORDS)
|
||||
|
||||
/* Vendor ids */
|
||||
typedef enum _khr_df_vendorid_e {
|
||||
/* Standard Khronos descriptor */
|
||||
KHR_DF_VENDORID_KHRONOS = 0U,
|
||||
KHR_DF_VENDORID_MAX = 0x1FFFFU
|
||||
} khr_df_vendorid_e;
|
||||
|
||||
/* Descriptor types */
|
||||
typedef enum _khr_df_khr_descriptortype_e {
|
||||
/* Default Khronos basic descriptor block */
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT = 0U,
|
||||
/* Extension descriptor block for additional planes */
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_PLANES = 0x6001U,
|
||||
/* Extension descriptor block for additional dimensions */
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_ADDITIONAL_DIMENSIONS = 0x6002U,
|
||||
/* Bit indicates modifying requires understanding this extension */
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_WRITE_BIT = 0x2000U,
|
||||
/* Bit indicates processing requires understanding this extension */
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_NEEDED_FOR_DECODE_BIT = 0x4000U,
|
||||
KHR_DF_KHR_DESCRIPTORTYPE_MAX = 0x7FFFU
|
||||
} khr_df_khr_descriptortype_e;
|
||||
|
||||
/* Descriptor block version */
|
||||
typedef enum _khr_df_versionnumber_e {
|
||||
/* Standard Khronos descriptor */
|
||||
KHR_DF_VERSIONNUMBER_1_0 = 0U, /* Version 1.0 of the specification */
|
||||
KHR_DF_VERSIONNUMBER_1_1 = 0U, /* Version 1.1 did not bump the version number */
|
||||
KHR_DF_VERSIONNUMBER_1_2 = 1U, /* Version 1.2 increased the version number */
|
||||
KHR_DF_VERSIONNUMBER_1_3 = 2U, /* Version 1.3 increased the version number */
|
||||
KHR_DF_VERSIONNUMBER_LATEST = KHR_DF_VERSIONNUMBER_1_3,
|
||||
KHR_DF_VERSIONNUMBER_MAX = 0xFFFFU
|
||||
} khr_df_versionnumber_e;
|
||||
|
||||
/* Model in which the color coordinate space is defined.
|
||||
There is no requirement that a color format use all the
|
||||
channel types that are defined in the color model. */
|
||||
typedef enum _khr_df_model_e {
|
||||
/* No interpretation of color channels defined */
|
||||
KHR_DF_MODEL_UNSPECIFIED = 0U,
|
||||
/* Color primaries (red, green, blue) + alpha, depth and stencil */
|
||||
KHR_DF_MODEL_RGBSDA = 1U,
|
||||
/* Color differences (Y', Cb, Cr) + alpha, depth and stencil */
|
||||
KHR_DF_MODEL_YUVSDA = 2U,
|
||||
/* Color differences (Y', I, Q) + alpha, depth and stencil */
|
||||
KHR_DF_MODEL_YIQSDA = 3U,
|
||||
/* Perceptual color (CIE L*a*b*) + alpha, depth and stencil */
|
||||
KHR_DF_MODEL_LABSDA = 4U,
|
||||
/* Subtractive colors (cyan, magenta, yellow, black) + alpha */
|
||||
KHR_DF_MODEL_CMYKA = 5U,
|
||||
/* Non-color coordinate data (X, Y, Z, W) */
|
||||
KHR_DF_MODEL_XYZW = 6U,
|
||||
/* Hue, saturation, value, hue angle on color circle, plus alpha */
|
||||
KHR_DF_MODEL_HSVA_ANG = 7U,
|
||||
/* Hue, saturation, lightness, hue angle on color circle, plus alpha */
|
||||
KHR_DF_MODEL_HSLA_ANG = 8U,
|
||||
/* Hue, saturation, value, hue on color hexagon, plus alpha */
|
||||
KHR_DF_MODEL_HSVA_HEX = 9U,
|
||||
/* Hue, saturation, lightness, hue on color hexagon, plus alpha */
|
||||
KHR_DF_MODEL_HSLA_HEX = 10U,
|
||||
/* Lightweight approximate color difference (luma, orange, green) */
|
||||
KHR_DF_MODEL_YCGCOA = 11U,
|
||||
/* ITU BT.2020 constant luminance YcCbcCrc */
|
||||
KHR_DF_MODEL_YCCBCCRC = 12U,
|
||||
/* ITU BT.2100 constant intensity ICtCp */
|
||||
KHR_DF_MODEL_ICTCP = 13U,
|
||||
/* CIE 1931 XYZ color coordinates (X, Y, Z) */
|
||||
KHR_DF_MODEL_CIEXYZ = 14U,
|
||||
/* CIE 1931 xyY color coordinates (X, Y, Y) */
|
||||
KHR_DF_MODEL_CIEXYY = 15U,
|
||||
|
||||
/* Compressed formats start at 128. */
|
||||
/* These compressed formats should generally have a single sample,
|
||||
sited at the 0,0 position of the texel block. Where multiple
|
||||
channels are used to distinguish formats, these should be cosited. */
|
||||
/* Direct3D (and S3) compressed formats */
|
||||
/* Note that premultiplied status is recorded separately */
|
||||
/* DXT1 "channels" are RGB (0), Alpha (1) */
|
||||
/* DXT1/BC1 with one channel is opaque */
|
||||
/* DXT1/BC1 with a cosited alpha sample is transparent */
|
||||
KHR_DF_MODEL_DXT1A = 128U,
|
||||
KHR_DF_MODEL_BC1A = 128U,
|
||||
/* DXT2/DXT3/BC2, with explicit 4-bit alpha */
|
||||
KHR_DF_MODEL_DXT2 = 129U,
|
||||
KHR_DF_MODEL_DXT3 = 129U,
|
||||
KHR_DF_MODEL_BC2 = 129U,
|
||||
/* DXT4/DXT5/BC3, with interpolated alpha */
|
||||
KHR_DF_MODEL_DXT4 = 130U,
|
||||
KHR_DF_MODEL_DXT5 = 130U,
|
||||
KHR_DF_MODEL_BC3 = 130U,
|
||||
/* BC4 - single channel interpolated 8-bit data */
|
||||
/* (The UNORM/SNORM variation is recorded in the channel data) */
|
||||
KHR_DF_MODEL_BC4 = 131U,
|
||||
/* BC5 - two channel interpolated 8-bit data */
|
||||
/* (The UNORM/SNORM variation is recorded in the channel data) */
|
||||
KHR_DF_MODEL_BC5 = 132U,
|
||||
/* BC6H - DX11 format for 16-bit float channels */
|
||||
KHR_DF_MODEL_BC6H = 133U,
|
||||
/* BC7 - DX11 format */
|
||||
KHR_DF_MODEL_BC7 = 134U,
|
||||
/* Gap left for future desktop expansion */
|
||||
|
||||
/* Mobile compressed formats follow */
|
||||
/* A format of ETC1 indicates that the format shall be decodable
|
||||
by an ETC1-compliant decoder and not rely on ETC2 features */
|
||||
KHR_DF_MODEL_ETC1 = 160U,
|
||||
/* A format of ETC2 is permitted to use ETC2 encodings on top of
|
||||
the baseline ETC1 specification */
|
||||
/* The ETC2 format has channels "red", "green", "RGB" and "alpha",
|
||||
which should be cosited samples */
|
||||
/* Punch-through alpha can be distinguished from full alpha by
|
||||
the plane size in bytes required for the texel block */
|
||||
KHR_DF_MODEL_ETC2 = 161U,
|
||||
/* Adaptive Scalable Texture Compression */
|
||||
/* ASTC HDR vs LDR is determined by the float flag in the channel */
|
||||
/* ASTC block size can be distinguished by texel block size */
|
||||
KHR_DF_MODEL_ASTC = 162U,
|
||||
/* ETC1S is a simplified subset of ETC1 */
|
||||
KHR_DF_MODEL_ETC1S = 163U,
|
||||
/* PowerVR Texture Compression */
|
||||
KHR_DF_MODEL_PVRTC = 164U,
|
||||
KHR_DF_MODEL_PVRTC2 = 165U,
|
||||
KHR_DF_MODEL_UASTC = 166U,
|
||||
/* Proprietary formats (ATITC, etc.) should follow */
|
||||
KHR_DF_MODEL_MAX = 0xFFU
|
||||
} khr_df_model_e;
|
||||
|
||||
/* Definition of channel names for each color model */
|
||||
typedef enum _khr_df_model_channels_e {
|
||||
/* Unspecified format with nominal channel numbering */
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_0 = 0U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_1 = 1U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_2 = 2U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_3 = 3U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_4 = 4U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_5 = 5U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_6 = 6U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_7 = 7U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_8 = 8U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_9 = 9U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_10 = 10U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_11 = 11U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_12 = 12U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_13 = 13U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_14 = 14U,
|
||||
KHR_DF_CHANNEL_UNSPECIFIED_15 = 15U,
|
||||
/* MODEL_RGBSDA - red, green, blue, stencil, depth, alpha */
|
||||
KHR_DF_CHANNEL_RGBSDA_RED = 0U,
|
||||
KHR_DF_CHANNEL_RGBSDA_R = 0U,
|
||||
KHR_DF_CHANNEL_RGBSDA_GREEN = 1U,
|
||||
KHR_DF_CHANNEL_RGBSDA_G = 1U,
|
||||
KHR_DF_CHANNEL_RGBSDA_BLUE = 2U,
|
||||
KHR_DF_CHANNEL_RGBSDA_B = 2U,
|
||||
KHR_DF_CHANNEL_RGBSDA_STENCIL = 13U,
|
||||
KHR_DF_CHANNEL_RGBSDA_S = 13U,
|
||||
KHR_DF_CHANNEL_RGBSDA_DEPTH = 14U,
|
||||
KHR_DF_CHANNEL_RGBSDA_D = 14U,
|
||||
KHR_DF_CHANNEL_RGBSDA_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_RGBSDA_A = 15U,
|
||||
/* MODEL_YUVSDA - luma, Cb, Cr, stencil, depth, alpha */
|
||||
KHR_DF_CHANNEL_YUVSDA_Y = 0U,
|
||||
KHR_DF_CHANNEL_YUVSDA_CB = 1U,
|
||||
KHR_DF_CHANNEL_YUVSDA_U = 1U,
|
||||
KHR_DF_CHANNEL_YUVSDA_CR = 2U,
|
||||
KHR_DF_CHANNEL_YUVSDA_V = 2U,
|
||||
KHR_DF_CHANNEL_YUVSDA_STENCIL = 13U,
|
||||
KHR_DF_CHANNEL_YUVSDA_S = 13U,
|
||||
KHR_DF_CHANNEL_YUVSDA_DEPTH = 14U,
|
||||
KHR_DF_CHANNEL_YUVSDA_D = 14U,
|
||||
KHR_DF_CHANNEL_YUVSDA_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_YUVSDA_A = 15U,
|
||||
/* MODEL_YIQSDA - luma, in-phase, quadrature, stencil, depth, alpha */
|
||||
KHR_DF_CHANNEL_YIQSDA_Y = 0U,
|
||||
KHR_DF_CHANNEL_YIQSDA_I = 1U,
|
||||
KHR_DF_CHANNEL_YIQSDA_Q = 2U,
|
||||
KHR_DF_CHANNEL_YIQSDA_STENCIL = 13U,
|
||||
KHR_DF_CHANNEL_YIQSDA_S = 13U,
|
||||
KHR_DF_CHANNEL_YIQSDA_DEPTH = 14U,
|
||||
KHR_DF_CHANNEL_YIQSDA_D = 14U,
|
||||
KHR_DF_CHANNEL_YIQSDA_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_YIQSDA_A = 15U,
|
||||
/* MODEL_LABSDA - CIELAB/L*a*b* luma, red-green, blue-yellow, stencil, depth, alpha */
|
||||
KHR_DF_CHANNEL_LABSDA_L = 0U,
|
||||
KHR_DF_CHANNEL_LABSDA_A = 1U,
|
||||
KHR_DF_CHANNEL_LABSDA_B = 2U,
|
||||
KHR_DF_CHANNEL_LABSDA_STENCIL = 13U,
|
||||
KHR_DF_CHANNEL_LABSDA_S = 13U,
|
||||
KHR_DF_CHANNEL_LABSDA_DEPTH = 14U,
|
||||
KHR_DF_CHANNEL_LABSDA_D = 14U,
|
||||
KHR_DF_CHANNEL_LABSDA_ALPHA = 15U,
|
||||
/* NOTE: KHR_DF_CHANNEL_LABSDA_A is not a synonym for alpha! */
|
||||
/* MODEL_CMYKA - cyan, magenta, yellow, key/blacK, alpha */
|
||||
KHR_DF_CHANNEL_CMYKSDA_CYAN = 0U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_C = 0U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_MAGENTA = 1U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_M = 1U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_YELLOW = 2U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_Y = 2U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_KEY = 3U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_BLACK = 3U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_K = 3U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_CMYKSDA_A = 15U,
|
||||
/* MODEL_XYZW - coordinates x, y, z, w */
|
||||
KHR_DF_CHANNEL_XYZW_X = 0U,
|
||||
KHR_DF_CHANNEL_XYZW_Y = 1U,
|
||||
KHR_DF_CHANNEL_XYZW_Z = 2U,
|
||||
KHR_DF_CHANNEL_XYZW_W = 3U,
|
||||
/* MODEL_HSVA_ANG - value (luma), saturation, hue, alpha, angular projection, conical space */
|
||||
KHR_DF_CHANNEL_HSVA_ANG_VALUE = 0U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_V = 0U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_SATURATION = 1U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_S = 1U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_HUE = 2U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_H = 2U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_HSVA_ANG_A = 15U,
|
||||
/* MODEL_HSLA_ANG - lightness (luma), saturation, hue, alpha, angular projection, double conical space */
|
||||
KHR_DF_CHANNEL_HSLA_ANG_LIGHTNESS = 0U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_L = 0U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_SATURATION = 1U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_S = 1U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_HUE = 2U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_H = 2U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_HSLA_ANG_A = 15U,
|
||||
/* MODEL_HSVA_HEX - value (luma), saturation, hue, alpha, hexagonal projection, conical space */
|
||||
KHR_DF_CHANNEL_HSVA_HEX_VALUE = 0U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_V = 0U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_SATURATION = 1U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_S = 1U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_HUE = 2U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_H = 2U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_HSVA_HEX_A = 15U,
|
||||
/* MODEL_HSLA_HEX - lightness (luma), saturation, hue, alpha, hexagonal projection, double conical space */
|
||||
KHR_DF_CHANNEL_HSLA_HEX_LIGHTNESS = 0U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_L = 0U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_SATURATION = 1U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_S = 1U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_HUE = 2U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_H = 2U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_HSLA_HEX_A = 15U,
|
||||
/* MODEL_YCGCOA - luma, green delta, orange delta, alpha */
|
||||
KHR_DF_CHANNEL_YCGCOA_Y = 0U,
|
||||
KHR_DF_CHANNEL_YCGCOA_CG = 1U,
|
||||
KHR_DF_CHANNEL_YCGCOA_CO = 2U,
|
||||
KHR_DF_CHANNEL_YCGCOA_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_YCGCOA_A = 15U,
|
||||
/* MODEL_CIEXYZ - CIE 1931 X, Y, Z */
|
||||
KHR_DF_CHANNEL_CIEXYZ_X = 0U,
|
||||
KHR_DF_CHANNEL_CIEXYZ_Y = 1U,
|
||||
KHR_DF_CHANNEL_CIEXYZ_Z = 2U,
|
||||
/* MODEL_CIEXYY - CIE 1931 x, y, Y */
|
||||
KHR_DF_CHANNEL_CIEXYY_X = 0U,
|
||||
KHR_DF_CHANNEL_CIEXYY_YCHROMA = 1U,
|
||||
KHR_DF_CHANNEL_CIEXYY_YLUMA = 2U,
|
||||
|
||||
/* Compressed formats */
|
||||
/* MODEL_DXT1A/MODEL_BC1A */
|
||||
KHR_DF_CHANNEL_DXT1A_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_BC1A_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_DXT1A_ALPHAPRESENT = 1U,
|
||||
KHR_DF_CHANNEL_DXT1A_ALPHA = 1U,
|
||||
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT = 1U,
|
||||
KHR_DF_CHANNEL_BC1A_ALPHA = 1U,
|
||||
/* MODEL_DXT2/3/MODEL_BC2 */
|
||||
KHR_DF_CHANNEL_DXT2_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_DXT3_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_BC2_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_DXT2_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_DXT3_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_BC2_ALPHA = 15U,
|
||||
/* MODEL_DXT4/5/MODEL_BC3 */
|
||||
KHR_DF_CHANNEL_DXT4_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_DXT5_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_BC3_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_DXT4_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_DXT5_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_BC3_ALPHA = 15U,
|
||||
/* MODEL_BC4 */
|
||||
KHR_DF_CHANNEL_BC4_DATA = 0U,
|
||||
/* MODEL_BC5 */
|
||||
KHR_DF_CHANNEL_BC5_RED = 0U,
|
||||
KHR_DF_CHANNEL_BC5_R = 0U,
|
||||
KHR_DF_CHANNEL_BC5_GREEN = 1U,
|
||||
KHR_DF_CHANNEL_BC5_G = 1U,
|
||||
/* MODEL_BC6H */
|
||||
KHR_DF_CHANNEL_BC6H_COLOR = 0U,
|
||||
KHR_DF_CHANNEL_BC6H_DATA = 0U,
|
||||
/* MODEL_BC7 */
|
||||
KHR_DF_CHANNEL_BC7_DATA = 0U,
|
||||
KHR_DF_CHANNEL_BC7_COLOR = 0U,
|
||||
/* MODEL_ETC1 */
|
||||
KHR_DF_CHANNEL_ETC1_DATA = 0U,
|
||||
KHR_DF_CHANNEL_ETC1_COLOR = 0U,
|
||||
/* MODEL_ETC2 */
|
||||
KHR_DF_CHANNEL_ETC2_RED = 0U,
|
||||
KHR_DF_CHANNEL_ETC2_R = 0U,
|
||||
KHR_DF_CHANNEL_ETC2_GREEN = 1U,
|
||||
KHR_DF_CHANNEL_ETC2_G = 1U,
|
||||
KHR_DF_CHANNEL_ETC2_COLOR = 2U,
|
||||
KHR_DF_CHANNEL_ETC2_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_ETC2_A = 15U,
|
||||
/* MODEL_ASTC */
|
||||
KHR_DF_CHANNEL_ASTC_DATA = 0U,
|
||||
/* MODEL_ETC1S */
|
||||
KHR_DF_CHANNEL_ETC1S_RGB = 0U,
|
||||
KHR_DF_CHANNEL_ETC1S_RRR = 3U,
|
||||
KHR_DF_CHANNEL_ETC1S_GGG = 4U,
|
||||
KHR_DF_CHANNEL_ETC1S_AAA = 15U,
|
||||
/* MODEL_PVRTC */
|
||||
KHR_DF_CHANNEL_PVRTC_DATA = 0U,
|
||||
KHR_DF_CHANNEL_PVRTC_COLOR = 0U,
|
||||
/* MODEL_PVRTC2 */
|
||||
KHR_DF_CHANNEL_PVRTC2_DATA = 0U,
|
||||
KHR_DF_CHANNEL_PVRTC2_COLOR = 0U,
|
||||
/* MODEL UASTC */
|
||||
KHR_DF_CHANNEL_UASTC_DATA = 0U,
|
||||
KHR_DF_CHANNEL_UASTC_RGB = 0U,
|
||||
KHR_DF_CHANNEL_UASTC_RGBA = 3U,
|
||||
KHR_DF_CHANNEL_UASTC_RRR = 4U,
|
||||
KHR_DF_CHANNEL_UASTC_RRRG = 5U,
|
||||
KHR_DF_CHANNEL_UASTC_RG = 6U,
|
||||
|
||||
/* Common channel names shared by multiple formats */
|
||||
KHR_DF_CHANNEL_COMMON_LUMA = 0U,
|
||||
KHR_DF_CHANNEL_COMMON_L = 0U,
|
||||
KHR_DF_CHANNEL_COMMON_STENCIL = 13U,
|
||||
KHR_DF_CHANNEL_COMMON_S = 13U,
|
||||
KHR_DF_CHANNEL_COMMON_DEPTH = 14U,
|
||||
KHR_DF_CHANNEL_COMMON_D = 14U,
|
||||
KHR_DF_CHANNEL_COMMON_ALPHA = 15U,
|
||||
KHR_DF_CHANNEL_COMMON_A = 15U
|
||||
} khr_df_model_channels_e;
|
||||
|
||||
/* Definition of the primary colors in color coordinates.
|
||||
This is implicitly responsible for defining the conversion
|
||||
between RGB an YUV color spaces.
|
||||
LAB and related absolute color models should use
|
||||
KHR_DF_PRIMARIES_CIEXYZ. */
|
||||
typedef enum _khr_df_primaries_e {
|
||||
/* No color primaries defined */
|
||||
KHR_DF_PRIMARIES_UNSPECIFIED = 0U,
|
||||
/* Color primaries of ITU-R BT.709 and sRGB */
|
||||
KHR_DF_PRIMARIES_BT709 = 1U,
|
||||
/* Synonym for KHR_DF_PRIMARIES_BT709 */
|
||||
KHR_DF_PRIMARIES_SRGB = 1U,
|
||||
/* Color primaries of ITU-R BT.601 (625-line EBU variant) */
|
||||
KHR_DF_PRIMARIES_BT601_EBU = 2U,
|
||||
/* Color primaries of ITU-R BT.601 (525-line SMPTE C variant) */
|
||||
KHR_DF_PRIMARIES_BT601_SMPTE = 3U,
|
||||
/* Color primaries of ITU-R BT.2020 */
|
||||
KHR_DF_PRIMARIES_BT2020 = 4U,
|
||||
/* CIE theoretical color coordinate space */
|
||||
KHR_DF_PRIMARIES_CIEXYZ = 5U,
|
||||
/* Academy Color Encoding System primaries */
|
||||
KHR_DF_PRIMARIES_ACES = 6U,
|
||||
/* Color primaries of ACEScc */
|
||||
KHR_DF_PRIMARIES_ACESCC = 7U,
|
||||
/* Legacy NTSC 1953 primaries */
|
||||
KHR_DF_PRIMARIES_NTSC1953 = 8U,
|
||||
/* Legacy PAL 525-line primaries */
|
||||
KHR_DF_PRIMARIES_PAL525 = 9U,
|
||||
/* Color primaries of Display P3 */
|
||||
KHR_DF_PRIMARIES_DISPLAYP3 = 10U,
|
||||
/* Color primaries of Adobe RGB (1998) */
|
||||
KHR_DF_PRIMARIES_ADOBERGB = 11U,
|
||||
KHR_DF_PRIMARIES_MAX = 0xFFU
|
||||
} khr_df_primaries_e;
|
||||
|
||||
/* Definition of the optical to digital transfer function
|
||||
("gamma correction"). Most transfer functions are not a pure
|
||||
power function and also include a linear element.
|
||||
LAB and related absolute color representations should use
|
||||
KHR_DF_TRANSFER_UNSPECIFIED. */
|
||||
typedef enum _khr_df_transfer_e {
|
||||
/* No transfer function defined */
|
||||
KHR_DF_TRANSFER_UNSPECIFIED = 0U,
|
||||
/* Linear transfer function (value proportional to intensity) */
|
||||
KHR_DF_TRANSFER_LINEAR = 1U,
|
||||
/* Perceptually-linear transfer function of sRGH (~2.4) */
|
||||
KHR_DF_TRANSFER_SRGB = 2U,
|
||||
/* Perceptually-linear transfer function of ITU BT.601, BT.709 and BT.2020 (~1/.45) */
|
||||
KHR_DF_TRANSFER_ITU = 3U,
|
||||
/* SMTPE170M (digital NTSC) defines an alias for the ITU transfer function (~1/.45) */
|
||||
KHR_DF_TRANSFER_SMTPE170M = 3U,
|
||||
/* Perceptually-linear gamma function of original NTSC (simple 2.2 gamma) */
|
||||
KHR_DF_TRANSFER_NTSC = 4U,
|
||||
/* Sony S-log used by Sony video cameras */
|
||||
KHR_DF_TRANSFER_SLOG = 5U,
|
||||
/* Sony S-log 2 used by Sony video cameras */
|
||||
KHR_DF_TRANSFER_SLOG2 = 6U,
|
||||
/* ITU BT.1886 EOTF */
|
||||
KHR_DF_TRANSFER_BT1886 = 7U,
|
||||
/* ITU BT.2100 HLG OETF */
|
||||
KHR_DF_TRANSFER_HLG_OETF = 8U,
|
||||
/* ITU BT.2100 HLG EOTF */
|
||||
KHR_DF_TRANSFER_HLG_EOTF = 9U,
|
||||
/* ITU BT.2100 PQ EOTF */
|
||||
KHR_DF_TRANSFER_PQ_EOTF = 10U,
|
||||
/* ITU BT.2100 PQ OETF */
|
||||
KHR_DF_TRANSFER_PQ_OETF = 11U,
|
||||
/* DCI P3 transfer function */
|
||||
KHR_DF_TRANSFER_DCIP3 = 12U,
|
||||
/* Legacy PAL OETF */
|
||||
KHR_DF_TRANSFER_PAL_OETF = 13U,
|
||||
/* Legacy PAL 625-line EOTF */
|
||||
KHR_DF_TRANSFER_PAL625_EOTF = 14U,
|
||||
/* Legacy ST240 transfer function */
|
||||
KHR_DF_TRANSFER_ST240 = 15U,
|
||||
/* ACEScc transfer function */
|
||||
KHR_DF_TRANSFER_ACESCC = 16U,
|
||||
/* ACEScct transfer function */
|
||||
KHR_DF_TRANSFER_ACESCCT = 17U,
|
||||
/* Adobe RGB (1998) transfer function */
|
||||
KHR_DF_TRANSFER_ADOBERGB = 18U,
|
||||
KHR_DF_TRANSFER_MAX = 0xFFU
|
||||
} khr_df_transfer_e;
|
||||
|
||||
typedef enum _khr_df_flags_e {
|
||||
KHR_DF_FLAG_ALPHA_STRAIGHT = 0U,
|
||||
KHR_DF_FLAG_ALPHA_PREMULTIPLIED = 1U
|
||||
} khr_df_flags_e;
|
||||
|
||||
typedef enum _khr_df_sample_datatype_qualifiers_e {
|
||||
KHR_DF_SAMPLE_DATATYPE_LINEAR = 1U << 4U,
|
||||
KHR_DF_SAMPLE_DATATYPE_EXPONENT = 1U << 5U,
|
||||
KHR_DF_SAMPLE_DATATYPE_SIGNED = 1U << 6U,
|
||||
KHR_DF_SAMPLE_DATATYPE_FLOAT = 1U << 7U
|
||||
} khr_df_sample_datatype_qualifiers_e;
|
||||
|
||||
#endif
|
619
Source/Main.cpp
Normal file
619
Source/Main.cpp
Normal file
|
@ -0,0 +1,619 @@
|
|||
#include <iostream>
|
||||
#include <string>
|
||||
#include <map>
|
||||
#include <tuple>
|
||||
#include <algorithm>
|
||||
#include <vulkan/vulkan.hpp>
|
||||
#include <math.h>
|
||||
#include <thread>
|
||||
#include <mutex>
|
||||
#include <numeric>
|
||||
#include <fstream>
|
||||
#include <iomanip>
|
||||
#include <vector>
|
||||
#include "stb_image_resize.h"
|
||||
#include "stb_image.h"
|
||||
#include "dfd.h"
|
||||
#include "ispc_texcomp/ispc_texcomp.h"
|
||||
#include "HalfFloat.h"
|
||||
|
||||
const std::vector<std::string> formatOrder = {
|
||||
"BC1",
|
||||
"BC1_SRGB",
|
||||
"BC4",
|
||||
"BC5",
|
||||
"BC3",
|
||||
"BC3_SRGB",
|
||||
"BC6H",
|
||||
"BC7",
|
||||
"BC7_SRGB"
|
||||
};
|
||||
|
||||
const std::map<std::string, std::tuple<std::string, int, vk::Format>> formats = {
|
||||
{"BC1", {"(DXT1) 5:6:5 Color, 1 bit alpha. 8 bytes per block.", 8, vk::Format::eBc1RgbUnormBlock}},
|
||||
{"BC1_SRGB", {"(DXT1) 5:6:5 Color, 1 bit alpha. 8 bytes per block.", 8, vk::Format::eBc1RgbSrgbBlock}},
|
||||
{"BC4", {"Greyscale, 8 bytes per block.", 8, vk::Format::eBc4UnormBlock}},
|
||||
{"BC5", {"2x BC4 images. 16 bytes per block.", 16, vk::Format::eBc5UnormBlock}},
|
||||
{"BC3", {"(DXT5) BC1 Color, BC4 Alpha, 16 bytes per block.", 16, vk::Format::eBc3UnormBlock}},
|
||||
{"BC3_SRGB", {"(DXT5) BC1 Color, BC4 Alpha, 16 bytes per block.", 16, vk::Format::eBc3SrgbBlock}},
|
||||
{"BC6H", {"16 bit RGB, no alpha. Signed. 16 bytes per block.", 16, vk::Format::eBc6HUfloatBlock}},
|
||||
{"BC7", {"8 bit RGBA - Good general purpose. 16 bytes per block.", 16, vk::Format::eBc7UnormBlock}},
|
||||
{"BC7_SRGB", {"8 bit RGBA - Good general purpose. 16 bytes per block.", 16, vk::Format::eBc7SrgbBlock}}
|
||||
};
|
||||
|
||||
const std::string usage = "Usage: TextureConverter [cube|array] <input> [input2, input3...] <output> <format> [fast|slow|veryslow]";
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
ISPCInit();
|
||||
|
||||
if (argc < 4) {
|
||||
std::cout << usage << std::endl;
|
||||
std::cout << "Formats:" << std::endl;
|
||||
for (auto & formatName : formatOrder) {
|
||||
auto format = formats.at(formatName);
|
||||
std::cout << " " << formatName << " - " << std::get<0>(format) << std::endl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int numInputs = argc - 3;
|
||||
unsigned int inputsStart = 1;
|
||||
std::vector<std::string> inputs;
|
||||
std::string output;
|
||||
std::string option(argv[1]);
|
||||
if (option == "cube" || option == "array") {
|
||||
numInputs -= 1;
|
||||
inputsStart += 1;
|
||||
} else {
|
||||
option = "none";
|
||||
}
|
||||
|
||||
std::string speed(argv[argc - 1]);
|
||||
std::string formatString;
|
||||
bool fastMode = true;
|
||||
bool verySlow = false;
|
||||
if (speed == "fast" || speed == "slow" || speed == "veryslow") {
|
||||
formatString = std::string(argv[argc - 2]);
|
||||
numInputs -= 1;
|
||||
|
||||
if (speed == "slow") {
|
||||
fastMode = false;
|
||||
} else if (speed == "veryslow") {
|
||||
fastMode = false;
|
||||
verySlow = true;
|
||||
}
|
||||
} else {
|
||||
formatString = std::string(argv[argc - 1]);
|
||||
}
|
||||
|
||||
if (numInputs < 1) {
|
||||
std::cout << usage << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (option == "cube" && numInputs != 6) {
|
||||
std::cout << "Cube maps must have 6 inputs." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (option == "array" && numInputs < 2) {
|
||||
std::cout << "Array maps must have at least 2 inputs." << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (formats.find(formatString) == formats.end()) {
|
||||
std::cout << "Invalid format: " << formatString << std::endl;
|
||||
std::cout << usage << std::endl;
|
||||
std::cout << "Formats:" << std::endl;
|
||||
for (auto & formatName : formatOrder) {
|
||||
auto format = formats.at(formatName);
|
||||
std::cout << " " << formatName << " - " << std::get<0>(format) << std::endl;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* Check if it ends in SRGB */
|
||||
bool srgb = false;
|
||||
if (formatString.length() > 5 && formatString.substr(formatString.length() - 5, 5) == "_SRGB") {
|
||||
srgb = true;
|
||||
}
|
||||
|
||||
bool hdr = false;
|
||||
if (formatString.substr(0, 3) == "BC6") {
|
||||
hdr = true;
|
||||
}
|
||||
|
||||
for (int i = inputsStart; i < (int)(inputsStart + numInputs); i++) {
|
||||
inputs.push_back(std::string(argv[i]));
|
||||
}
|
||||
|
||||
output = std::string(argv[inputsStart + numInputs]);
|
||||
|
||||
/* Print inputs and output */
|
||||
std::cout << "Inputs: " << std::endl;
|
||||
for (auto & input : inputs) {
|
||||
std::cout << " " << input << std::endl;
|
||||
}
|
||||
std::cout << "Output: " << output << std::endl;
|
||||
std::cout << "Format: " << formatString << std::endl;
|
||||
std::cout << "Speed: " << (fastMode ? "Fast" : verySlow ? "Very slow" : "Slow") << std::endl;
|
||||
|
||||
int isa;
|
||||
isa = ISPCIsa();
|
||||
|
||||
std::string isaName;
|
||||
switch(isa) {
|
||||
case 0:
|
||||
isaName = "SSE2";
|
||||
break;
|
||||
case 1:
|
||||
isaName = "SSE4";
|
||||
break;
|
||||
case 2:
|
||||
isaName = "AVX2";
|
||||
break;
|
||||
default:
|
||||
isaName = "Unknown";
|
||||
};
|
||||
|
||||
std::cout << "ISPC ISA: " << isaName << std::endl;
|
||||
|
||||
unsigned char * ldrBufferA, * ldrBufferB, * ldrBufferMain, * ldrBufferOther;
|
||||
float * hdrBufferA, * hdrBufferB, * hdrBufferMain, * hdrBufferOther;
|
||||
int width, height, channels;
|
||||
|
||||
int copyChannels = 4;
|
||||
int forcedChannels = 4;
|
||||
if (formatString == "BC4") {
|
||||
copyChannels = 1;
|
||||
} else if (formatString == "BC5") {
|
||||
copyChannels = 2;
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::vector<unsigned char>>> ldrLevels;
|
||||
std::vector<std::vector<std::vector<float>>> hdrLevels;
|
||||
|
||||
std::vector<std::vector<std::vector<std::vector<unsigned char>>>> ldrLevelBlocks;
|
||||
std::vector<std::vector<std::vector<std::vector<uint16_t>>>> hdrLevelBlocks;
|
||||
|
||||
if (hdr) {
|
||||
hdrLevels.resize(numInputs);
|
||||
hdrLevelBlocks.resize(numInputs);
|
||||
} else {
|
||||
ldrLevels.resize(numInputs);
|
||||
ldrLevelBlocks.resize(numInputs);
|
||||
}
|
||||
|
||||
uint32_t levelCount;
|
||||
|
||||
for (int input = 0; input < numInputs; input++) {
|
||||
int level = 0;
|
||||
|
||||
std::cout << "Loading/scaling " << input << ": " << inputs[input] << std::endl;
|
||||
|
||||
if (hdr) {
|
||||
hdrBufferA = stbi_loadf(inputs[input].c_str(), &width, &height, &channels, forcedChannels);
|
||||
if (hdrBufferA == nullptr) {
|
||||
std::cout << "Failed to load image: " << inputs[input] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
hdrBufferB = new float[width * height * forcedChannels];
|
||||
hdrBufferMain = hdrBufferA;
|
||||
hdrBufferOther = hdrBufferB;
|
||||
} else {
|
||||
ldrBufferA = stbi_load(inputs[input].c_str(), &width, &height, &channels, forcedChannels);
|
||||
if (ldrBufferA == nullptr) {
|
||||
std::cout << "Failed to load image: " << inputs[input] << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
ldrBufferB = new unsigned char[width * height * forcedChannels];
|
||||
ldrBufferMain = ldrBufferA;
|
||||
ldrBufferOther = ldrBufferB;
|
||||
}
|
||||
|
||||
int oldWidth = width;
|
||||
int oldHeight = height;
|
||||
|
||||
levelCount = 1;
|
||||
{
|
||||
int levelWidth = width;
|
||||
int levelHeight = height;
|
||||
while (levelWidth > 1 || levelHeight > 1) {
|
||||
levelWidth = std::max(1, (int)floorf((float)levelWidth / 2));
|
||||
levelHeight = std::max(1, (int)floorf((float)levelHeight / 2));
|
||||
levelCount++;
|
||||
}
|
||||
}
|
||||
|
||||
while(1) {
|
||||
if (hdr) {
|
||||
hdrLevels[input].push_back(std::vector<float>(hdrBufferMain, hdrBufferMain + oldWidth * oldHeight * forcedChannels));
|
||||
} else {
|
||||
ldrLevels[input].push_back(std::vector<uint8_t>(ldrBufferMain, ldrBufferMain + oldWidth * oldHeight * forcedChannels));
|
||||
}
|
||||
|
||||
if (oldWidth == 1 && oldHeight == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
int newWidth = std::max(1, (int)floorf((float)oldWidth / 2));
|
||||
int newHeight = std::max(1, (int)floorf((float)oldHeight / 2));
|
||||
|
||||
stbir_colorspace colorspace = srgb ? STBIR_COLORSPACE_SRGB : STBIR_COLORSPACE_LINEAR;
|
||||
int alphaChannel = channels == 4 ? 3 : STBIR_ALPHA_CHANNEL_NONE;
|
||||
|
||||
if (hdr) {
|
||||
int rv = stbir_resize_float_generic(hdrBufferMain, oldWidth, oldHeight, 0, hdrBufferOther, newWidth, newHeight, 0, forcedChannels, alphaChannel, 0, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, colorspace, nullptr);
|
||||
if (rv != 1) {
|
||||
std::cerr << "Error resizing" << std::endl;
|
||||
}
|
||||
std::swap(hdrBufferMain, hdrBufferOther);
|
||||
} else {
|
||||
int rv = stbir_resize_uint8_generic(ldrBufferMain, oldWidth, oldHeight, 0, ldrBufferOther, newWidth, newHeight, 0, forcedChannels, alphaChannel, 0, STBIR_EDGE_CLAMP, STBIR_FILTER_MITCHELL, colorspace, nullptr);
|
||||
if (rv != 1) {
|
||||
std::cerr << "Error resizing" << std::endl;
|
||||
}
|
||||
std::swap(ldrBufferMain, ldrBufferOther);
|
||||
}
|
||||
|
||||
oldWidth = newWidth;
|
||||
oldHeight = newHeight;
|
||||
level++;
|
||||
}
|
||||
|
||||
oldWidth = width;
|
||||
oldHeight = height;
|
||||
level = 0;
|
||||
if (hdr) {
|
||||
free(hdrBufferA);
|
||||
delete[] hdrBufferB;
|
||||
} else {
|
||||
free(ldrBufferA);
|
||||
delete[] ldrBufferB;
|
||||
}
|
||||
}
|
||||
|
||||
bc6h_enc_settings bc6henc;
|
||||
bc7_enc_settings bc7enc;
|
||||
|
||||
if (formatString == "BC6H") {
|
||||
if (fastMode) {
|
||||
GetProfile_bc6h_basic(&bc6henc);
|
||||
} else {
|
||||
if (verySlow) {
|
||||
GetProfile_bc6h_veryslow(&bc6henc);
|
||||
} else {
|
||||
GetProfile_bc6h_slow(&bc6henc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (channels == 3) {
|
||||
if (fastMode) {
|
||||
GetProfile_basic(&bc7enc);
|
||||
} else {
|
||||
GetProfile_slow(&bc7enc);
|
||||
}
|
||||
} else {
|
||||
if (fastMode) {
|
||||
GetProfile_alpha_basic(&bc7enc);
|
||||
} else {
|
||||
GetProfile_alpha_slow(&bc7enc);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::vector<std::vector<unsigned char>>> levelBlocksCompressed(numInputs);
|
||||
std::tuple<std::string, int, vk::Format> format = formats.find(formatString)->second;
|
||||
size_t blockSize = std::get<1>(format);
|
||||
|
||||
for (int input = 0; input < numInputs; input++) {
|
||||
if (numInputs > 1) {
|
||||
if (option == "cube") {
|
||||
std::cout << "Face " << input << std::endl;
|
||||
} else {
|
||||
std::cout << "Layer " << input << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
if (hdr) {
|
||||
hdrLevelBlocks[input].resize(levelCount);
|
||||
} else {
|
||||
ldrLevelBlocks[input].resize(levelCount);
|
||||
}
|
||||
int level = 0;
|
||||
|
||||
int oldWidth = width;
|
||||
int oldHeight = height;
|
||||
|
||||
while(1) {
|
||||
unsigned int blocksWidth = (oldWidth + 3) / 4;
|
||||
unsigned int blocksHeight = (oldHeight + 3) / 4;
|
||||
|
||||
if (hdr) {
|
||||
hdrLevelBlocks[input][level].resize(blocksWidth * blocksHeight);
|
||||
|
||||
for (unsigned int y = 0; y < blocksHeight; y++) {
|
||||
for (unsigned int x = 0; x < blocksWidth; x++) {
|
||||
std::vector<uint16_t> block(16 * copyChannels);
|
||||
|
||||
for (unsigned int pixelY = y * 4; pixelY < y * 4 + 4; pixelY++) {
|
||||
for (unsigned int pixelX = x * 4; pixelX < x * 4 + 4; pixelX++) {
|
||||
unsigned int clampedY = std::min(pixelY, (unsigned int)oldHeight - 1);
|
||||
unsigned int clampedX = std::min(pixelX, (unsigned int)oldWidth - 1);
|
||||
|
||||
for (int channel = 0; channel < copyChannels; channel++) {
|
||||
float value = hdrLevels[input][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel];
|
||||
if (value < 0.0f) {
|
||||
value = 0.0f;
|
||||
}
|
||||
|
||||
if (value > 65504.0f) {
|
||||
value = 65504.0f;
|
||||
}
|
||||
|
||||
block[((pixelY % 4) * 4 + (pixelX % 4)) * copyChannels + channel] = HalfFloat::FromFloat(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hdrLevelBlocks[input][level][blocksWidth * y + x] = block;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
ldrLevelBlocks[input][level].resize(blocksWidth * blocksHeight);
|
||||
|
||||
for (unsigned int y = 0; y < blocksHeight; y++) {
|
||||
for (unsigned int x = 0; x < blocksWidth; x++) {
|
||||
std::vector<uint8_t> block(16 * copyChannels);
|
||||
|
||||
for (unsigned int pixelY = y * 4; pixelY < y * 4 + 4; pixelY++) {
|
||||
for (unsigned int pixelX = x * 4; pixelX < x * 4 + 4; pixelX++) {
|
||||
unsigned int clampedY = std::min(pixelY, (unsigned int)oldHeight - 1);
|
||||
unsigned int clampedX = std::min(pixelX, (unsigned int)oldWidth - 1);
|
||||
|
||||
for (int channel = 0; channel < copyChannels; channel++) {
|
||||
block[((pixelY % 4) * 4 + (pixelX % 4)) * copyChannels + channel] = ldrLevels[input][level][(clampedY * oldWidth + clampedX) * forcedChannels + channel];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
ldrLevelBlocks[input][level][blocksWidth * y + x] = block;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (oldWidth == 1 && oldHeight == 1) {
|
||||
break;
|
||||
}
|
||||
|
||||
oldWidth = std::max(1, (int)floorf((float)oldWidth / 2));
|
||||
oldHeight = std::max(1, (int)floorf((float)oldHeight / 2));
|
||||
level++;
|
||||
}
|
||||
|
||||
|
||||
/* Compress */
|
||||
levelBlocksCompressed[input].resize(levelCount);
|
||||
for (unsigned int l = 0; l < levelCount; l++) {
|
||||
if (hdr) {
|
||||
levelBlocksCompressed[input][l].resize(hdrLevelBlocks[input][l].size() * blockSize);
|
||||
} else {
|
||||
levelBlocksCompressed[input][l].resize(ldrLevelBlocks[input][l].size() * blockSize);
|
||||
}
|
||||
}
|
||||
|
||||
std::mutex mutex;
|
||||
std::vector<unsigned int> completedBlocks(levelCount, 0);
|
||||
|
||||
unsigned int numThreads = std::thread::hardware_concurrency();
|
||||
std::vector<std::thread> threads;
|
||||
unsigned int maxLevel = 0;
|
||||
for (unsigned t = 0; t < numThreads; t++) {
|
||||
threads.push_back(std::thread([&, t](){
|
||||
for (unsigned int l = 0; l < levelCount; l++) {
|
||||
unsigned int blocksPerThread;
|
||||
if (hdr) {
|
||||
blocksPerThread = hdrLevelBlocks[input][l].size() / numThreads;
|
||||
} else {
|
||||
blocksPerThread = ldrLevelBlocks[input][l].size() / numThreads;
|
||||
}
|
||||
unsigned int startBlock = t * blocksPerThread;
|
||||
unsigned int endBlock = startBlock + blocksPerThread;
|
||||
|
||||
if (hdr) {
|
||||
if (t == numThreads - 1) {
|
||||
endBlock = hdrLevelBlocks[input][l].size();
|
||||
}
|
||||
} else {
|
||||
if (t == numThreads - 1) {
|
||||
endBlock = ldrLevelBlocks[input][l].size();
|
||||
}
|
||||
}
|
||||
|
||||
for (unsigned int b = startBlock; b < endBlock; b++) {
|
||||
if (formatString == "BC6H") {
|
||||
rgba_surface surface;
|
||||
surface.ptr = (uint8_t *)hdrLevelBlocks[input][l][b].data();
|
||||
surface.width = 4;
|
||||
surface.height = 4;
|
||||
surface.stride = copyChannels * 4 * 2;
|
||||
|
||||
CompressBlocksBC6H(&surface, &levelBlocksCompressed[input][l][b * blockSize], &bc6henc);
|
||||
} else {
|
||||
rgba_surface surface;
|
||||
surface.ptr = ldrLevelBlocks[input][l][b].data();
|
||||
surface.width = 4;
|
||||
surface.height = 4;
|
||||
surface.stride = copyChannels * 4;
|
||||
|
||||
if (formatString == "BC1" || formatString == "BC1_SRGB") {
|
||||
CompressBlocksBC1(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
|
||||
} else if (formatString == "BC3" || formatString == "BC3_SRGB") {
|
||||
CompressBlocksBC3(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
|
||||
} else if (formatString == "BC4") {
|
||||
CompressBlocksBC4(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
|
||||
} else if (formatString == "BC5") {
|
||||
CompressBlocksBC5(&surface, &levelBlocksCompressed[input][l][b * blockSize]);
|
||||
} else if (formatString == "BC7" || formatString == "BC7_SRGB") {
|
||||
CompressBlocksBC7(&surface, &levelBlocksCompressed[input][l][b * blockSize], &bc7enc);
|
||||
}
|
||||
}
|
||||
|
||||
std::lock_guard<std::mutex> lock(mutex);
|
||||
completedBlocks[l]++;
|
||||
if (completedBlocks[l] % 100 == 0) {
|
||||
maxLevel = std::max(l, maxLevel);
|
||||
if (l == maxLevel) {
|
||||
float progress;
|
||||
if (hdr) {
|
||||
progress = (float)completedBlocks[l] / hdrLevelBlocks[input][l].size();
|
||||
} else {
|
||||
progress = (float)completedBlocks[l] / ldrLevelBlocks[input][l].size();
|
||||
}
|
||||
int barWidth = 70;
|
||||
|
||||
std::cout << std::setw(2) << l << " [";
|
||||
int pos = barWidth * progress;
|
||||
for (int i = 0; i < barWidth; ++i) {
|
||||
if (i < pos) std::cout << "=";
|
||||
else if (i == pos) std::cout << ">";
|
||||
else std::cout << " ";
|
||||
}
|
||||
std::cout << "] " << std::setw(2) << int(progress * 100.0) << " %\r";
|
||||
std::cout.flush();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}));
|
||||
}
|
||||
|
||||
for (unsigned t = 0; t < numThreads; t++) {
|
||||
threads[t].join();
|
||||
}
|
||||
|
||||
if (hdr) {
|
||||
hdrLevelBlocks[input].clear();
|
||||
} else {
|
||||
ldrLevelBlocks[input].clear();
|
||||
}
|
||||
|
||||
int barWidth = 70;
|
||||
std::cout << std::setw(2) << (levelCount - 1) << " [";
|
||||
int pos = barWidth;
|
||||
for (int i = 0; i < barWidth; ++i) {
|
||||
if (i < pos) std::cout << "=";
|
||||
else if (i == pos) std::cout << ">";
|
||||
else std::cout << " ";
|
||||
}
|
||||
std::cout << "] " << std::setw(2) << 100 << " %\r";
|
||||
std::cout.flush();
|
||||
|
||||
std::cout << std::endl;
|
||||
}
|
||||
|
||||
/* Write KTX2 */
|
||||
std::ofstream fh (output, std::ios::out | std::ios::binary);
|
||||
if (!fh.is_open()) {
|
||||
std::cout << "Failed to open output file: " << output << std::endl;
|
||||
return 1;
|
||||
}
|
||||
|
||||
const uint8_t identifier[] = {0xAB, 0x4B, 0x54, 0x58, 0x20, 0x32, 0x30, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A};
|
||||
fh.write((char *)identifier, sizeof(identifier));
|
||||
vk::Format vkformat = std::get<2>(formats.at(formatString));
|
||||
fh.write((char *)&vkformat, sizeof(vkformat));
|
||||
uint32_t typeSize = 1; // Fix for uncompressed vkformats, size of an individual component
|
||||
fh.write((char *)&typeSize, sizeof(typeSize));
|
||||
uint32_t pixelWidth = width;
|
||||
uint32_t pixelHeight = height;
|
||||
uint32_t pixelDepth = 0;
|
||||
|
||||
uint32_t layerCount;
|
||||
uint32_t faceCount;
|
||||
if (numInputs > 1) {
|
||||
if (option == "cube") {
|
||||
layerCount = 0;
|
||||
faceCount = 6;
|
||||
} else {
|
||||
layerCount = numInputs;
|
||||
faceCount = 1;
|
||||
}
|
||||
} else {
|
||||
layerCount = 0;
|
||||
faceCount = 1;
|
||||
}
|
||||
uint32_t supercompressionScheme = 0;
|
||||
fh.write((char *)&pixelWidth, sizeof(pixelWidth));
|
||||
fh.write((char *)&pixelHeight, sizeof(pixelHeight));
|
||||
fh.write((char *)&pixelDepth, sizeof(pixelDepth));
|
||||
fh.write((char *)&layerCount, sizeof(layerCount));
|
||||
fh.write((char *)&faceCount, sizeof(faceCount));
|
||||
fh.write((char *)&levelCount, sizeof(levelCount));
|
||||
fh.write((char *)&supercompressionScheme, sizeof(supercompressionScheme));
|
||||
|
||||
uint32_t * dfd = vk2dfd(*(VkFormat *)&vkformat);
|
||||
|
||||
uint32_t dfdByteOffset = 0;
|
||||
uint32_t dfdByteLength = dfd[0];
|
||||
uint32_t kvdByteOffset = 0;
|
||||
uint32_t kvdByteLength = 0;
|
||||
uint64_t sgdByteOffset = 0;
|
||||
uint64_t sgdByteLength = 0;
|
||||
|
||||
auto dfdByteOffsetPosition = fh.tellp();
|
||||
|
||||
fh.write((char *)&dfdByteOffset, sizeof(dfdByteOffset));
|
||||
fh.write((char *)&dfdByteLength, sizeof(dfdByteLength));
|
||||
fh.write((char *)&kvdByteOffset, sizeof(kvdByteOffset));
|
||||
fh.write((char *)&kvdByteLength, sizeof(kvdByteLength));
|
||||
fh.write((char *)&sgdByteOffset, sizeof(sgdByteOffset));
|
||||
fh.write((char *)&sgdByteLength, sizeof(sgdByteLength));
|
||||
|
||||
auto levelOffsetBytePosition = fh.tellp();
|
||||
for (unsigned int i = 0; i < levelCount; i++) {
|
||||
uint64_t byteOffset = 0;
|
||||
uint64_t byteLength = 0;
|
||||
uint64_t uncompressedByteLength = 0;
|
||||
fh.write((char *)&byteOffset, sizeof(byteOffset));
|
||||
fh.write((char *)&byteLength, sizeof(byteLength));
|
||||
fh.write((char *)&uncompressedByteLength, sizeof(uncompressedByteLength));
|
||||
}
|
||||
|
||||
dfdByteOffset = fh.tellp();
|
||||
fh.write((char *)dfd, dfdByteLength);
|
||||
free(dfd);
|
||||
|
||||
kvdByteOffset = fh.tellp();
|
||||
fh.seekp(dfdByteOffsetPosition);
|
||||
fh.write((char *)&dfdByteOffset, sizeof(dfdByteOffset));
|
||||
fh.seekp(kvdByteOffset);
|
||||
|
||||
size_t alignment = std::lcm((size_t)4, (size_t)std::get<1>(formats.at(formatString)));
|
||||
|
||||
for (int level = levelCount - 1; level >= 0; level--) {
|
||||
// Alignment
|
||||
while (fh.tellp() % alignment != 0) {
|
||||
uint8_t padding = 0;
|
||||
fh.write((char *)&padding, sizeof(padding));
|
||||
}
|
||||
|
||||
auto levelBytePosition = fh.tellp();
|
||||
fh.seekp(levelOffsetBytePosition + (std::ofstream::pos_type)(level * 24));
|
||||
uint64_t byteOffset = levelBytePosition;
|
||||
fh.write((char *)&byteOffset, sizeof(byteOffset));
|
||||
uint64_t byteLength = levelBlocksCompressed[0][level].size() * numInputs;
|
||||
fh.write((char *)&byteLength, sizeof(byteLength));
|
||||
fh.write((char *)&byteLength, sizeof(byteLength));
|
||||
fh.seekp(levelBytePosition);
|
||||
|
||||
for (int input = 0; input < numInputs; input++) {
|
||||
fh.write((char *)levelBlocksCompressed[input][level].data(), levelBlocksCompressed[input][level].size());
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
659
Source/createdfd.cpp
Normal file
659
Source/createdfd.cpp
Normal file
|
@ -0,0 +1,659 @@
|
|||
/* -*- tab-width: 4; -*- */
|
||||
/* vi: set sw=2 ts=4 expandtab: */
|
||||
|
||||
/* Copyright 2019-2020 The Khronos Group Inc.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @~English
|
||||
* @brief Utilities for creating data format descriptors.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Andrew Garrard
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <KHR/khr_df.h>
|
||||
|
||||
#include "dfd.h"
|
||||
|
||||
typedef enum { i_COLOR, i_NON_COLOR } channels_infotype;
|
||||
|
||||
static uint32_t *writeHeader(int numSamples, int bytes, int suffix,
|
||||
channels_infotype infotype)
|
||||
{
|
||||
uint32_t *DFD = (uint32_t *) malloc(sizeof(uint32_t) *
|
||||
(1 + KHR_DF_WORD_SAMPLESTART +
|
||||
numSamples * KHR_DF_WORD_SAMPLEWORDS));
|
||||
uint32_t* BDFD = DFD+1;
|
||||
DFD[0] = sizeof(uint32_t) *
|
||||
(1 + KHR_DF_WORD_SAMPLESTART +
|
||||
numSamples * KHR_DF_WORD_SAMPLEWORDS);
|
||||
BDFD[KHR_DF_WORD_VENDORID] =
|
||||
(KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
|
||||
(KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
|
||||
BDFD[KHR_DF_WORD_VERSIONNUMBER] =
|
||||
(KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
|
||||
(((uint32_t)sizeof(uint32_t) *
|
||||
(KHR_DF_WORD_SAMPLESTART +
|
||||
numSamples * KHR_DF_WORD_SAMPLEWORDS)
|
||||
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
|
||||
BDFD[KHR_DF_WORD_MODEL] =
|
||||
((KHR_DF_MODEL_RGBSDA << KHR_DF_SHIFT_MODEL) | /* Only supported model */
|
||||
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
|
||||
if (infotype == i_COLOR) {
|
||||
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES; /* Assumed */
|
||||
} else {
|
||||
BDFD[KHR_DF_WORD_PRIMARIES] |= KHR_DF_PRIMARIES_UNSPECIFIED << KHR_DF_SHIFT_PRIMARIES;
|
||||
}
|
||||
if (suffix == s_SRGB) {
|
||||
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
|
||||
} else {
|
||||
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
|
||||
}
|
||||
BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] = 0; /* Only 1x1x1x1 texel blocks supported */
|
||||
BDFD[KHR_DF_WORD_BYTESPLANE0] = bytes; /* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
|
||||
BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
|
||||
return DFD;
|
||||
}
|
||||
|
||||
static uint32_t setChannelFlags(uint32_t channel, enum VkSuffix suffix)
|
||||
{
|
||||
switch (suffix) {
|
||||
case s_UNORM: break;
|
||||
case s_SNORM:
|
||||
channel |=
|
||||
KHR_DF_SAMPLE_DATATYPE_SIGNED;
|
||||
break;
|
||||
case s_USCALED: break;
|
||||
case s_SSCALED:
|
||||
channel |=
|
||||
KHR_DF_SAMPLE_DATATYPE_SIGNED;
|
||||
break;
|
||||
case s_UINT: break;
|
||||
case s_SINT:
|
||||
channel |=
|
||||
KHR_DF_SAMPLE_DATATYPE_SIGNED;
|
||||
break;
|
||||
case s_SFLOAT:
|
||||
channel |=
|
||||
KHR_DF_SAMPLE_DATATYPE_FLOAT |
|
||||
KHR_DF_SAMPLE_DATATYPE_SIGNED;
|
||||
break;
|
||||
case s_UFLOAT:
|
||||
channel |=
|
||||
KHR_DF_SAMPLE_DATATYPE_FLOAT;
|
||||
break;
|
||||
case s_SRGB:
|
||||
if (channel == KHR_DF_CHANNEL_RGBSDA_ALPHA) {
|
||||
channel |= KHR_DF_SAMPLE_DATATYPE_LINEAR;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return channel;
|
||||
}
|
||||
|
||||
static void writeSample(uint32_t *DFD, int sampleNo, int channel,
|
||||
int bits, int offset,
|
||||
int topSample, int bottomSample, enum VkSuffix suffix)
|
||||
{
|
||||
// Use this to avoid type-punning complaints from the gcc optimizer
|
||||
// with -Wall.
|
||||
union {
|
||||
uint32_t i;
|
||||
float f;
|
||||
} lower, upper;
|
||||
uint32_t *sample = DFD + 1 + KHR_DF_WORD_SAMPLESTART + sampleNo * KHR_DF_WORD_SAMPLEWORDS;
|
||||
if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
|
||||
|
||||
if (channel == 3) channel = KHR_DF_CHANNEL_RGBSDA_ALPHA;
|
||||
channel = setChannelFlags(channel, suffix);
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
|
||||
(offset << KHR_DF_SAMPLESHIFT_BITOFFSET) |
|
||||
((bits - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
|
||||
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
|
||||
|
||||
switch (suffix) {
|
||||
case s_UNORM:
|
||||
case s_SRGB:
|
||||
default:
|
||||
if (bits > 32) {
|
||||
upper.i = 0xFFFFFFFFU;
|
||||
} else {
|
||||
upper.i = (uint32_t)((1U << bits) - 1U);
|
||||
}
|
||||
lower.i = 0U;
|
||||
break;
|
||||
case s_SNORM:
|
||||
if (bits > 32) {
|
||||
upper.i = 0x7FFFFFFF;
|
||||
} else {
|
||||
upper.i = topSample ? (1U << (bits - 1)) - 1 : (1U << bits) - 1;
|
||||
}
|
||||
lower.i = ~upper.i;
|
||||
if (bottomSample) lower.i += 1;
|
||||
break;
|
||||
case s_USCALED:
|
||||
case s_UINT:
|
||||
upper.i = bottomSample ? 1U : 0U;
|
||||
lower.i = 0U;
|
||||
break;
|
||||
case s_SSCALED:
|
||||
case s_SINT:
|
||||
upper.i = bottomSample ? 1U : 0U;
|
||||
lower.i = ~0U;
|
||||
break;
|
||||
case s_SFLOAT:
|
||||
upper.f = 1.0f;
|
||||
lower.f = -1.0f;
|
||||
break;
|
||||
case s_UFLOAT:
|
||||
upper.f = 1.0f;
|
||||
lower.f = 0.0f;
|
||||
break;
|
||||
}
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
|
||||
}
|
||||
|
||||
/**
|
||||
* @~English
|
||||
* @brief Create a Data Format Descriptor for an unpacked format.
|
||||
*
|
||||
* @param bigEndian Set to 1 for big-endian byte ordering and
|
||||
0 for little-endian byte ordering.
|
||||
* @param numChannels The number of color channels.
|
||||
* @param bytes The number of bytes per channel.
|
||||
* @param redBlueSwap Normally channels appear in consecutive R, G, B, A order
|
||||
* in memory; redBlueSwap inverts red and blue, allowing
|
||||
* B, G, R, A.
|
||||
* @param suffix Indicates the format suffix for the type.
|
||||
*
|
||||
* @return A data format descriptor in malloc'd data. The caller is responsible
|
||||
* for freeing the descriptor.
|
||||
**/
|
||||
uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
|
||||
int redBlueSwap, enum VkSuffix suffix)
|
||||
{
|
||||
uint32_t *DFD;
|
||||
if (bigEndian) {
|
||||
int channelCounter, channelByte;
|
||||
/* Number of samples = number of channels * bytes per channel */
|
||||
DFD = writeHeader(numChannels * bytes, numChannels * bytes, suffix, i_COLOR);
|
||||
/* First loop over the channels */
|
||||
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
|
||||
int channel = channelCounter;
|
||||
if (redBlueSwap && (channel == 0 || channel == 2)) {
|
||||
channel ^= 2;
|
||||
}
|
||||
/* Loop over the bytes that constitute a channel */
|
||||
for (channelByte = 0; channelByte < bytes; ++channelByte) {
|
||||
writeSample(DFD, channelCounter * bytes + channelByte, channel,
|
||||
8, 8 * (channelCounter * bytes + bytes - channelByte - 1),
|
||||
channelByte == bytes-1, channelByte == 0, suffix);
|
||||
}
|
||||
}
|
||||
|
||||
} else { /* Little-endian */
|
||||
|
||||
int sampleCounter;
|
||||
/* One sample per channel */
|
||||
DFD = writeHeader(numChannels, numChannels * bytes, suffix, i_COLOR);
|
||||
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
|
||||
int channel = sampleCounter;
|
||||
if (redBlueSwap && (channel == 0 || channel == 2)) {
|
||||
channel ^= 2;
|
||||
}
|
||||
writeSample(DFD, sampleCounter, channel,
|
||||
8 * bytes, 8 * sampleCounter * bytes,
|
||||
1, 1, suffix);
|
||||
}
|
||||
}
|
||||
return DFD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @~English
|
||||
* @brief Create a Data Format Descriptor for a packed format.
|
||||
*
|
||||
* @param bigEndian Big-endian flag: Set to 1 for big-endian byte ordering and
|
||||
* 0 for little-endian byte ordering.
|
||||
* @param numChannels The number of color channels.
|
||||
* @param bits[] An array of length numChannels.
|
||||
* Each entry is the number of bits composing the channel, in
|
||||
* order starting at bit 0 of the packed type.
|
||||
* @param channels[] An array of length numChannels.
|
||||
* Each entry enumerates the channel type: 0 = red, 1 = green,
|
||||
* 2 = blue, 15 = alpha, in order starting at bit 0 of the
|
||||
* packed type. These values match channel IDs for RGBSDA in
|
||||
* the Khronos Data Format header. To simplify iteration
|
||||
* through channels, channel id 3 is a synonym for alpha.
|
||||
* @param suffix Indicates the format suffix for the type.
|
||||
*
|
||||
* @return A data format descriptor in malloc'd data. The caller is responsible
|
||||
* for freeing the descriptor.
|
||||
**/
|
||||
uint32_t *createDFDPacked(int bigEndian, int numChannels,
|
||||
int bits[], int channels[],
|
||||
enum VkSuffix suffix)
|
||||
{
|
||||
uint32_t *DFD = 0;
|
||||
if (numChannels == 6) {
|
||||
/* Special case E5B9G9R9 */
|
||||
DFD = writeHeader(numChannels, 4, s_UFLOAT, i_COLOR);
|
||||
writeSample(DFD, 0, 0,
|
||||
9, 0,
|
||||
1, 1, s_UNORM);
|
||||
KHR_DFDSETSVAL((DFD+1), 0, SAMPLEUPPER, 8448);
|
||||
writeSample(DFD, 1, 0 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
|
||||
5, 27,
|
||||
1, 1, s_UNORM);
|
||||
KHR_DFDSETSVAL((DFD+1), 1, SAMPLELOWER, 15);
|
||||
KHR_DFDSETSVAL((DFD+1), 1, SAMPLEUPPER, 31);
|
||||
writeSample(DFD, 2, 1,
|
||||
9, 9,
|
||||
1, 1, s_UNORM);
|
||||
KHR_DFDSETSVAL((DFD+1), 2, SAMPLEUPPER, 8448);
|
||||
writeSample(DFD, 3, 1 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
|
||||
5, 27,
|
||||
1, 1, s_UNORM);
|
||||
KHR_DFDSETSVAL((DFD+1), 3, SAMPLELOWER, 15);
|
||||
KHR_DFDSETSVAL((DFD+1), 3, SAMPLEUPPER, 31);
|
||||
writeSample(DFD, 4, 2,
|
||||
9, 18,
|
||||
1, 1, s_UNORM);
|
||||
KHR_DFDSETSVAL((DFD+1), 4, SAMPLEUPPER, 8448);
|
||||
writeSample(DFD, 5, 2 | KHR_DF_SAMPLE_DATATYPE_EXPONENT,
|
||||
5, 27,
|
||||
1, 1, s_UNORM);
|
||||
KHR_DFDSETSVAL((DFD+1), 5, SAMPLELOWER, 15);
|
||||
KHR_DFDSETSVAL((DFD+1), 5, SAMPLEUPPER, 31);
|
||||
} else if (bigEndian) {
|
||||
/* No packed format is larger than 32 bits. */
|
||||
/* No packed channel crosses more than two bytes. */
|
||||
int totalBits = 0;
|
||||
int bitChannel[32];
|
||||
int beChannelStart[4];
|
||||
int channelCounter;
|
||||
int bitOffset = 0;
|
||||
int BEMask;
|
||||
int numSamples = numChannels;
|
||||
int sampleCounter;
|
||||
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
|
||||
beChannelStart[channelCounter] = totalBits;
|
||||
totalBits += bits[channelCounter];
|
||||
}
|
||||
BEMask = (totalBits - 1) & 0x18;
|
||||
for (channelCounter = 0; channelCounter < numChannels; ++channelCounter) {
|
||||
bitChannel[bitOffset ^ BEMask] = channelCounter;
|
||||
if (((bitOffset + bits[channelCounter] - 1) & ~7) != (bitOffset & ~7)) {
|
||||
/* Continuation sample */
|
||||
bitChannel[((bitOffset + bits[channelCounter] - 1) & ~7) ^ BEMask] = channelCounter;
|
||||
numSamples++;
|
||||
}
|
||||
bitOffset += bits[channelCounter];
|
||||
}
|
||||
DFD = writeHeader(numSamples, totalBits >> 3, suffix, i_COLOR);
|
||||
|
||||
sampleCounter = 0;
|
||||
for (bitOffset = 0; bitOffset < totalBits;) {
|
||||
if (bitChannel[bitOffset] == -1) {
|
||||
/* Done this bit, so this is the lower half of something. */
|
||||
/* We must therefore jump to the end of the byte and continue. */
|
||||
bitOffset = (bitOffset + 8) & ~7;
|
||||
} else {
|
||||
/* Start of a channel? */
|
||||
int thisChannel = bitChannel[bitOffset];
|
||||
if ((beChannelStart[thisChannel] ^ BEMask) == bitOffset) {
|
||||
/* Must be just one sample if we hit it first. */
|
||||
writeSample(DFD, sampleCounter++, channels[thisChannel],
|
||||
bits[thisChannel], bitOffset,
|
||||
1, 1, suffix);
|
||||
bitOffset += bits[thisChannel];
|
||||
} else {
|
||||
/* Two samples. Move to the end of the first one we hit when we're done. */
|
||||
int firstSampleBits = 8 - (beChannelStart[thisChannel] & 0x7); /* Rest of the byte */
|
||||
int secondSampleBits = bits[thisChannel] - firstSampleBits; /* Rest of the bits */
|
||||
writeSample(DFD, sampleCounter++, channels[thisChannel],
|
||||
firstSampleBits, beChannelStart[thisChannel] ^ BEMask,
|
||||
0, 1, suffix);
|
||||
/* Mark that we've already handled this sample */
|
||||
bitChannel[beChannelStart[thisChannel] ^ BEMask] = -1;
|
||||
writeSample(DFD, sampleCounter++, channels[thisChannel],
|
||||
secondSampleBits, bitOffset,
|
||||
1, 0, suffix);
|
||||
bitOffset += secondSampleBits;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else { /* Little-endian */
|
||||
|
||||
int sampleCounter;
|
||||
int totalBits = 0;
|
||||
int bitOffset = 0;
|
||||
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
|
||||
totalBits += bits[sampleCounter];
|
||||
}
|
||||
|
||||
/* One sample per channel */
|
||||
DFD = writeHeader(numChannels, totalBits >> 3, suffix, i_COLOR);
|
||||
for (sampleCounter = 0; sampleCounter < numChannels; ++sampleCounter) {
|
||||
writeSample(DFD, sampleCounter, channels[sampleCounter],
|
||||
bits[sampleCounter], bitOffset,
|
||||
1, 1, suffix);
|
||||
bitOffset += bits[sampleCounter];
|
||||
}
|
||||
}
|
||||
return DFD;
|
||||
}
|
||||
|
||||
static khr_df_model_e compModelMapping[] = {
|
||||
KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, no alpha. */
|
||||
KHR_DF_MODEL_BC1A, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
KHR_DF_MODEL_BC2, /*!< BC2, aka DXT2 and DXT3. */
|
||||
KHR_DF_MODEL_BC3, /*!< BC3, aka DXT4 and DXT5. */
|
||||
KHR_DF_MODEL_BC4, /*!< BC4. */
|
||||
KHR_DF_MODEL_BC5, /*!< BC5. */
|
||||
KHR_DF_MODEL_BC6H, /*!< BC6h HDR format. */
|
||||
KHR_DF_MODEL_BC7, /*!< BC7. */
|
||||
KHR_DF_MODEL_ETC2, /*!< ETC2 no alpha. */
|
||||
KHR_DF_MODEL_ETC2, /*!< ETC2 punch-through alpha. */
|
||||
KHR_DF_MODEL_ETC2, /*!< ETC2 independent alpha. */
|
||||
KHR_DF_MODEL_ETC2, /*!< R11 ETC2 single-channel. */
|
||||
KHR_DF_MODEL_ETC2, /*!< R11G11 ETC2 dual-channel. */
|
||||
KHR_DF_MODEL_ASTC, /*!< ASTC. */
|
||||
KHR_DF_MODEL_ETC1S, /*!< ETC1S. */
|
||||
KHR_DF_MODEL_PVRTC, /*!< PVRTC(1). */
|
||||
KHR_DF_MODEL_PVRTC2 /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
static uint32_t compSampleCount[] = {
|
||||
1U, /*!< BC1, aka DXT1, no alpha. */
|
||||
1U, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
2U, /*!< BC2, aka DXT2 and DXT3. */
|
||||
2U, /*!< BC3, aka DXT4 and DXT5. */
|
||||
1U, /*!< BC4. */
|
||||
2U, /*!< BC5. */
|
||||
1U, /*!< BC6h HDR format. */
|
||||
1U, /*!< BC7. */
|
||||
1U, /*!< ETC2 no alpha. */
|
||||
2U, /*!< ETC2 punch-through alpha. */
|
||||
2U, /*!< ETC2 independent alpha. */
|
||||
1U, /*!< R11 ETC2 single-channel. */
|
||||
2U, /*!< R11G11 ETC2 dual-channel. */
|
||||
1U, /*!< ASTC. */
|
||||
1U, /*!< ETC1S. */
|
||||
1U, /*!< PVRTC. */
|
||||
1U /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
static khr_df_model_channels_e compFirstChannel[] = {
|
||||
KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
|
||||
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
KHR_DF_CHANNEL_BC2_ALPHA, /*!< BC2, aka DXT2 and DXT3. */
|
||||
KHR_DF_CHANNEL_BC3_ALPHA, /*!< BC3, aka DXT4 and DXT5. */
|
||||
KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
|
||||
KHR_DF_CHANNEL_BC5_RED, /*!< BC5. */
|
||||
KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
|
||||
KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
|
||||
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
|
||||
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 punch-through alpha. */
|
||||
KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 independent alpha. */
|
||||
KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
|
||||
KHR_DF_CHANNEL_ETC2_RED, /*!< R11G11 ETC2 dual-channel. */
|
||||
KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
|
||||
KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
|
||||
KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
|
||||
KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
static khr_df_model_channels_e compSecondChannel[] = {
|
||||
KHR_DF_CHANNEL_BC1A_COLOR, /*!< BC1, aka DXT1, no alpha. */
|
||||
KHR_DF_CHANNEL_BC1A_ALPHAPRESENT, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
KHR_DF_CHANNEL_BC2_COLOR, /*!< BC2, aka DXT2 and DXT3. */
|
||||
KHR_DF_CHANNEL_BC3_COLOR, /*!< BC3, aka DXT4 and DXT5. */
|
||||
KHR_DF_CHANNEL_BC4_DATA, /*!< BC4. */
|
||||
KHR_DF_CHANNEL_BC5_GREEN, /*!< BC5. */
|
||||
KHR_DF_CHANNEL_BC6H_COLOR, /*!< BC6h HDR format. */
|
||||
KHR_DF_CHANNEL_BC7_COLOR, /*!< BC7. */
|
||||
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 no alpha. */
|
||||
KHR_DF_CHANNEL_ETC2_ALPHA, /*!< ETC2 punch-through alpha. */
|
||||
KHR_DF_CHANNEL_ETC2_COLOR, /*!< ETC2 independent alpha. */
|
||||
KHR_DF_CHANNEL_ETC2_RED, /*!< R11 ETC2 single-channel. */
|
||||
KHR_DF_CHANNEL_ETC2_GREEN, /*!< R11G11 ETC2 dual-channel. */
|
||||
KHR_DF_CHANNEL_ASTC_DATA, /*!< ASTC. */
|
||||
KHR_DF_CHANNEL_ETC1S_RGB, /*!< ETC1S. */
|
||||
KHR_DF_CHANNEL_PVRTC_COLOR, /*!< PVRTC. */
|
||||
KHR_DF_CHANNEL_PVRTC2_COLOR /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
static uint32_t compSecondChannelOffset[] = {
|
||||
0U, /*!< BC1, aka DXT1, no alpha. */
|
||||
0U, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
64U, /*!< BC2, aka DXT2 and DXT3. */
|
||||
64U, /*!< BC3, aka DXT4 and DXT5. */
|
||||
0U, /*!< BC4. */
|
||||
64U, /*!< BC5. */
|
||||
0U, /*!< BC6h HDR format. */
|
||||
0U, /*!< BC7. */
|
||||
0U, /*!< ETC2 no alpha. */
|
||||
0U, /*!< ETC2 punch-through alpha. */
|
||||
64U, /*!< ETC2 independent alpha. */
|
||||
0U, /*!< R11 ETC2 single-channel. */
|
||||
64U, /*!< R11G11 ETC2 dual-channel. */
|
||||
0U, /*!< ASTC. */
|
||||
0U, /*!< ETC1S. */
|
||||
0U, /*!< PVRTC. */
|
||||
0U /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
static uint32_t compChannelBits[] = {
|
||||
64U, /*!< BC1, aka DXT1, no alpha. */
|
||||
64U, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
64U, /*!< BC2, aka DXT2 and DXT3. */
|
||||
64U, /*!< BC3, aka DXT4 and DXT5. */
|
||||
64U, /*!< BC4. */
|
||||
64U, /*!< BC5. */
|
||||
128U, /*!< BC6h HDR format. */
|
||||
128U, /*!< BC7. */
|
||||
64U, /*!< ETC2 no alpha. */
|
||||
64U, /*!< ETC2 punch-through alpha. */
|
||||
64U, /*!< ETC2 independent alpha. */
|
||||
64U, /*!< R11 ETC2 single-channel. */
|
||||
64U, /*!< R11G11 ETC2 dual-channel. */
|
||||
128U, /*!< ASTC. */
|
||||
64U, /*!< ETC1S. */
|
||||
64U, /*!< PVRTC. */
|
||||
64U /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
static uint32_t compBytes[] = {
|
||||
8U, /*!< BC1, aka DXT1, no alpha. */
|
||||
8U, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
16U, /*!< BC2, aka DXT2 and DXT3. */
|
||||
16U, /*!< BC3, aka DXT4 and DXT5. */
|
||||
8U, /*!< BC4. */
|
||||
16U, /*!< BC5. */
|
||||
16U, /*!< BC6h HDR format. */
|
||||
16U, /*!< BC7. */
|
||||
8U, /*!< ETC2 no alpha. */
|
||||
8U, /*!< ETC2 punch-through alpha. */
|
||||
16U, /*!< ETC2 independent alpha. */
|
||||
8U, /*!< R11 ETC2 single-channel. */
|
||||
16U, /*!< R11G11 ETC2 dual-channel. */
|
||||
16U, /*!< ASTC. */
|
||||
8U, /*!< ETC1S. */
|
||||
8U, /*!< PVRTC. */
|
||||
8U /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @~English
|
||||
* @brief Create a Data Format Descriptor for a compressed format.
|
||||
*
|
||||
* @param compScheme Vulkan-style compression scheme enumeration.
|
||||
* @param bwidth Block width in texel coordinates.
|
||||
* @param bheight Block height in texel coordinates.
|
||||
* @param bdepth Block depth in texel coordinates.
|
||||
* @author Mark Callow, Edgewise Consulting.
|
||||
* @param suffix Indicates the format suffix for the type.
|
||||
*
|
||||
* @return A data format descriptor in malloc'd data. The caller is responsible
|
||||
* for freeing the descriptor.
|
||||
**/
|
||||
uint32_t *createDFDCompressed(enum VkCompScheme compScheme, int bwidth, int bheight, int bdepth,
|
||||
enum VkSuffix suffix)
|
||||
{
|
||||
uint32_t *DFD = 0;
|
||||
uint32_t numSamples = compSampleCount[compScheme];
|
||||
uint32_t* BDFD;
|
||||
uint32_t *sample;
|
||||
uint32_t channel;
|
||||
// Use union to avoid type-punning complaints from gcc optimizer
|
||||
// with -Wall.
|
||||
union {
|
||||
uint32_t i;
|
||||
float f;
|
||||
} lower, upper;
|
||||
|
||||
DFD = (uint32_t *) malloc(sizeof(uint32_t) *
|
||||
(1 + KHR_DF_WORD_SAMPLESTART +
|
||||
numSamples * KHR_DF_WORD_SAMPLEWORDS));
|
||||
BDFD = DFD+1;
|
||||
DFD[0] = sizeof(uint32_t) *
|
||||
(1 + KHR_DF_WORD_SAMPLESTART +
|
||||
numSamples * KHR_DF_WORD_SAMPLEWORDS);
|
||||
BDFD[KHR_DF_WORD_VENDORID] =
|
||||
(KHR_DF_VENDORID_KHRONOS << KHR_DF_SHIFT_VENDORID) |
|
||||
(KHR_DF_KHR_DESCRIPTORTYPE_BASICFORMAT << KHR_DF_SHIFT_DESCRIPTORTYPE);
|
||||
BDFD[KHR_DF_WORD_VERSIONNUMBER] =
|
||||
(KHR_DF_VERSIONNUMBER_LATEST << KHR_DF_SHIFT_VERSIONNUMBER) |
|
||||
(((uint32_t)sizeof(uint32_t) *
|
||||
(KHR_DF_WORD_SAMPLESTART +
|
||||
numSamples * KHR_DF_WORD_SAMPLEWORDS)
|
||||
<< KHR_DF_SHIFT_DESCRIPTORBLOCKSIZE));
|
||||
BDFD[KHR_DF_WORD_MODEL] =
|
||||
((compModelMapping[compScheme] << KHR_DF_SHIFT_MODEL) |
|
||||
(KHR_DF_PRIMARIES_BT709 << KHR_DF_SHIFT_PRIMARIES) | /* Assumed */
|
||||
(KHR_DF_FLAG_ALPHA_STRAIGHT << KHR_DF_SHIFT_FLAGS));
|
||||
|
||||
if (suffix == s_SRGB) {
|
||||
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_SRGB << KHR_DF_SHIFT_TRANSFER;
|
||||
} else {
|
||||
BDFD[KHR_DF_WORD_TRANSFER] |= KHR_DF_TRANSFER_LINEAR << KHR_DF_SHIFT_TRANSFER;
|
||||
}
|
||||
BDFD[KHR_DF_WORD_TEXELBLOCKDIMENSION0] =
|
||||
(bwidth - 1) | ((bheight - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION1) | ((bdepth - 1) << KHR_DF_SHIFT_TEXELBLOCKDIMENSION2);
|
||||
/* bytesPlane0 = bytes, bytesPlane3..1 = 0 */
|
||||
BDFD[KHR_DF_WORD_BYTESPLANE0] = compBytes[compScheme];
|
||||
BDFD[KHR_DF_WORD_BYTESPLANE4] = 0; /* bytesPlane7..5 = 0 */
|
||||
|
||||
sample = BDFD + KHR_DF_WORD_SAMPLESTART;
|
||||
channel = compFirstChannel[compScheme];
|
||||
channel = setChannelFlags(channel, suffix);
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
|
||||
(0 << KHR_DF_SAMPLESHIFT_BITOFFSET) |
|
||||
((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
|
||||
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
|
||||
switch (suffix) {
|
||||
case s_UNORM:
|
||||
case s_SRGB:
|
||||
default:
|
||||
upper.i = 0xFFFFFFFFU;
|
||||
lower.i = 0U;
|
||||
break;
|
||||
case s_SNORM:
|
||||
upper.i = 0x7FFFFFFF;
|
||||
lower.i = ~upper.i;
|
||||
break;
|
||||
case s_USCALED:
|
||||
case s_UINT:
|
||||
upper.i = 1U;
|
||||
lower.i = 0U;
|
||||
break;
|
||||
case s_SSCALED:
|
||||
case s_SINT:
|
||||
upper.i = 1U;
|
||||
lower.i = ~0U;
|
||||
break;
|
||||
case s_SFLOAT:
|
||||
upper.f = 1.0f;
|
||||
lower.f = -1.0f;
|
||||
break;
|
||||
case s_UFLOAT:
|
||||
upper.f = 1.0f;
|
||||
lower.f = 0.0f;
|
||||
break;
|
||||
}
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
|
||||
|
||||
if (compSampleCount[compScheme] > 1) {
|
||||
sample += KHR_DF_WORD_SAMPLEWORDS;
|
||||
channel = compSecondChannel[compScheme];
|
||||
channel = setChannelFlags(channel, suffix);
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_BITOFFSET] =
|
||||
(compSecondChannelOffset[compScheme] << KHR_DF_SAMPLESHIFT_BITOFFSET) |
|
||||
((compChannelBits[compScheme] - 1) << KHR_DF_SAMPLESHIFT_BITLENGTH) |
|
||||
(channel << KHR_DF_SAMPLESHIFT_CHANNELID);
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLEPOSITION_ALL] = 0;
|
||||
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLELOWER] = lower.i;
|
||||
sample[KHR_DF_SAMPLEWORD_SAMPLEUPPER] = upper.i;
|
||||
}
|
||||
return DFD;
|
||||
}
|
||||
|
||||
/**
|
||||
* @~English
|
||||
* @brief Create a Data Format Descriptor for a depth-stencil format.
|
||||
*
|
||||
* @param depthBits The numeber of bits in the depth channel.
|
||||
* @param stencilBits The numeber of bits in the stencil channel.
|
||||
* @param sizeBytes The total byte size of the texel.
|
||||
*
|
||||
* @return A data format descriptor in malloc'd data. The caller is responsible
|
||||
* for freeing the descriptor.
|
||||
**/
|
||||
uint32_t *createDFDDepthStencil(int depthBits,
|
||||
int stencilBits,
|
||||
int sizeBytes)
|
||||
{
|
||||
/* N.B. Little-endian is assumed. */
|
||||
uint32_t *DFD = 0;
|
||||
DFD = writeHeader((depthBits > 0) + (stencilBits > 0),
|
||||
sizeBytes, s_UNORM, i_NON_COLOR);
|
||||
if (depthBits == 32) {
|
||||
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
|
||||
32, 0,
|
||||
1, 1, s_SFLOAT);
|
||||
} else if (depthBits > 0) {
|
||||
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_DEPTH,
|
||||
depthBits, 0,
|
||||
1, 1, s_UNORM);
|
||||
}
|
||||
if (stencilBits > 0) {
|
||||
if (depthBits > 0) {
|
||||
writeSample(DFD, 1, KHR_DF_CHANNEL_RGBSDA_STENCIL,
|
||||
stencilBits, depthBits,
|
||||
1, 1, s_UINT);
|
||||
} else {
|
||||
writeSample(DFD, 0, KHR_DF_CHANNEL_RGBSDA_STENCIL,
|
||||
stencilBits, 0,
|
||||
1, 1, s_UINT);
|
||||
}
|
||||
}
|
||||
return DFD;
|
||||
}
|
173
Source/dfd.h
Normal file
173
Source/dfd.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
/* -*- tab-width: 4; -*- */
|
||||
/* vi: set sw=2 ts=4 expandtab: */
|
||||
|
||||
/* Copyright 2019-2020 The Khronos Group Inc.
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @~English
|
||||
* @brief Header file defining the data format descriptor utilities API.
|
||||
*/
|
||||
|
||||
/*
|
||||
* Author: Andrew Garrard
|
||||
*/
|
||||
|
||||
#ifndef _DFD_H_
|
||||
#define _DFD_H_
|
||||
|
||||
#include <vulkan/vulkan.h>
|
||||
#include <KHR/khr_df.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** Qualifier suffix to the format, in Vulkan terms. */
|
||||
enum VkSuffix {
|
||||
s_UNORM, /*!< Unsigned normalized format. */
|
||||
s_SNORM, /*!< Signed normalized format. */
|
||||
s_USCALED, /*!< Unsigned scaled format. */
|
||||
s_SSCALED, /*!< Signed scaled format. */
|
||||
s_UINT, /*!< Unsigned integer format. */
|
||||
s_SINT, /*!< Signed integer format. */
|
||||
s_SFLOAT, /*!< Signed float format. */
|
||||
s_UFLOAT, /*!< Unsigned float format. */
|
||||
s_SRGB /*!< sRGB normalized format. */
|
||||
};
|
||||
|
||||
/** Compression scheme, in Vulkan terms. */
|
||||
enum VkCompScheme {
|
||||
c_BC1_RGB, /*!< BC1, aka DXT1, no alpha. */
|
||||
c_BC1_RGBA, /*!< BC1, aka DXT1, punch-through alpha. */
|
||||
c_BC2, /*!< BC2, aka DXT2 and DXT3. */
|
||||
c_BC3, /*!< BC3, aka DXT4 and DXT5. */
|
||||
c_BC4, /*!< BC4. */
|
||||
c_BC5, /*!< BC5. */
|
||||
c_BC6H, /*!< BC6h HDR format. */
|
||||
c_BC7, /*!< BC7. */
|
||||
c_ETC2_R8G8B8, /*!< ETC2 no alpha. */
|
||||
c_ETC2_R8G8B8A1, /*!< ETC2 punch-through alpha. */
|
||||
c_ETC2_R8G8B8A8, /*!< ETC2 independent alpha. */
|
||||
c_EAC_R11, /*!< R11 ETC2 single-channel. */
|
||||
c_EAC_R11G11, /*!< R11G11 ETC2 dual-channel. */
|
||||
c_ASTC, /*!< ASTC. */
|
||||
c_ETC1S, /*!< ETC1S. */
|
||||
c_PVRTC, /*!< PVRTC(1). */
|
||||
c_PVRTC2 /*!< PVRTC2. */
|
||||
};
|
||||
|
||||
#if !defined(uint32_t)
|
||||
typedef unsigned int uint32_t;
|
||||
#endif
|
||||
|
||||
#if !defined(LIBKTX)
|
||||
#include <vulkan/vulkan_core.h>
|
||||
#else
|
||||
#include "../vkformat_enum.h"
|
||||
#endif
|
||||
|
||||
uint32_t* vk2dfd(enum VkFormat format);
|
||||
|
||||
/* Create a Data Format Descriptor for an unpacked format. */
|
||||
uint32_t *createDFDUnpacked(int bigEndian, int numChannels, int bytes,
|
||||
int redBlueSwap, enum VkSuffix suffix);
|
||||
|
||||
/* Create a Data Format Descriptor for a packed format. */
|
||||
uint32_t *createDFDPacked(int bigEndian, int numChannels,
|
||||
int bits[], int channels[],
|
||||
enum VkSuffix suffix);
|
||||
|
||||
/* Create a Data Format Descriptor for a compressed format. */
|
||||
uint32_t *createDFDCompressed(enum VkCompScheme compScheme,
|
||||
int bwidth, int bheight, int bdepth,
|
||||
enum VkSuffix suffix);
|
||||
|
||||
/* Create a Data Format Descriptor for a depth/stencil format. */
|
||||
uint32_t *createDFDDepthStencil(int depthBits,
|
||||
int stencilBits,
|
||||
int sizeBytes);
|
||||
|
||||
/** @brief Result of interpreting the data format descriptor. */
|
||||
enum InterpretDFDResult {
|
||||
i_LITTLE_ENDIAN_FORMAT_BIT = 0, /*!< Confirmed little-endian (default for 8bpc). */
|
||||
i_BIG_ENDIAN_FORMAT_BIT = 1, /*!< Confirmed big-endian. */
|
||||
i_PACKED_FORMAT_BIT = 2, /*!< Packed format. */
|
||||
i_SRGB_FORMAT_BIT = 4, /*!< sRGB transfer function. */
|
||||
i_NORMALIZED_FORMAT_BIT = 8, /*!< Normalized (UNORM or SNORM). */
|
||||
i_SIGNED_FORMAT_BIT = 16, /*!< Format is signed. */
|
||||
i_FLOAT_FORMAT_BIT = 32, /*!< Format is floating point. */
|
||||
i_UNSUPPORTED_ERROR_BIT = 64, /*!< Format not successfully interpreted. */
|
||||
/** "NONTRIVIAL_ENDIANNESS" means not big-endian, not little-endian
|
||||
* (a channel has bits that are not consecutive in either order). **/
|
||||
i_UNSUPPORTED_NONTRIVIAL_ENDIANNESS = i_UNSUPPORTED_ERROR_BIT,
|
||||
/** "MULTIPLE_SAMPLE_LOCATIONS" is an error because only single-sample
|
||||
* texel blocks (with coordinates 0,0,0,0 for all samples) are supported. **/
|
||||
i_UNSUPPORTED_MULTIPLE_SAMPLE_LOCATIONS = i_UNSUPPORTED_ERROR_BIT + 1,
|
||||
/** "MULTIPLE_PLANES" is an error because only contiguous data is supported. */
|
||||
i_UNSUPPORTED_MULTIPLE_PLANES = i_UNSUPPORTED_ERROR_BIT + 2,
|
||||
/** Only channels R, G, B and A are supported. */
|
||||
i_UNSUPPORTED_CHANNEL_TYPES = i_UNSUPPORTED_ERROR_BIT + 3,
|
||||
/** Only channels with the same flags are supported
|
||||
* (e.g. we don't support float red with integer green). */
|
||||
i_UNSUPPORTED_MIXED_CHANNELS = i_UNSUPPORTED_ERROR_BIT + 4
|
||||
};
|
||||
|
||||
/** @brief Interpretation of a channel from the data format descriptor. */
|
||||
typedef struct _InterpretedDFDChannel {
|
||||
uint32_t offset; /*!< Offset in bits for packed, bytes for unpacked. */
|
||||
uint32_t size; /*!< Size in bits for packed, bytes for unpacked. */
|
||||
} InterpretedDFDChannel;
|
||||
|
||||
/* Interpret a Data Format Descriptor. */
|
||||
enum InterpretDFDResult interpretDFD(const uint32_t *DFD,
|
||||
InterpretedDFDChannel *R,
|
||||
InterpretedDFDChannel *G,
|
||||
InterpretedDFDChannel *B,
|
||||
InterpretedDFDChannel *A,
|
||||
uint32_t *wordBytes);
|
||||
|
||||
/* Print a human-readable interpretation of a data format descriptor. */
|
||||
void printDFD(uint32_t *DFD);
|
||||
|
||||
/* Get the number of components & component size from a DFD for an
|
||||
* unpacked format.
|
||||
*/
|
||||
void
|
||||
getDFDComponentInfoUnpacked(const uint32_t* DFD, uint32_t* numComponents,
|
||||
uint32_t* componentByteLength);
|
||||
|
||||
/* Return the number of components described by a DFD. */
|
||||
uint32_t getDFDNumComponents(const uint32_t* DFD);
|
||||
|
||||
/* Recreate and return the value of bytesPlane0 as it should be for the data
|
||||
* post-inflation from variable-rate compression.
|
||||
*/
|
||||
void
|
||||
recreateBytesPlane0FromSampleInfo(const uint32_t* DFD, uint32_t* bytesPlane0);
|
||||
|
||||
/** @brief Colourspace primaries information.
|
||||
*
|
||||
* Structure to store the 1931 CIE x,y chromaticities of the red, green, and blue
|
||||
* display primaries and the reference white point of a colourspace.
|
||||
*/
|
||||
typedef struct _Primaries {
|
||||
float Rx; /*!< Red x. */
|
||||
float Ry; /*!< Red y. */
|
||||
float Gx; /*!< Green x. */
|
||||
float Gy; /*!< Green y. */
|
||||
float Bx; /*!< Blue x. */
|
||||
float By; /*!< Blue y. */
|
||||
float Wx; /*!< White x. */
|
||||
float Wy; /*!< White y. */
|
||||
} Primaries;
|
||||
|
||||
khr_df_primaries_e findMapping(Primaries *p, float latitude);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _DFD_H_ */
|
557
Source/ispc_texcomp/ispc_texcomp.cpp
Normal file
557
Source/ispc_texcomp/ispc_texcomp.cpp
Normal file
|
@ -0,0 +1,557 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2016-2019, Intel Corporation
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ispc_texcomp.h"
|
||||
#include "kernel_ispc.h"
|
||||
#include <memory.h> // memcpy
|
||||
|
||||
namespace ispc {
|
||||
extern "C" {
|
||||
extern int32_t ISPCIsa_ispc_sse4();
|
||||
extern "C" void CompressBlocksBC1_ispc_sse4(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC3_ispc_sse4(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC4_ispc_sse4(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC5_ispc_sse4(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC6H_ispc_sse4(const rgba_surface* src, uint8_t* dst, bc6h_enc_settings* settings);
|
||||
extern "C" void CompressBlocksBC7_ispc_sse4(const rgba_surface* src, uint8_t* dst, bc7_enc_settings* settings);
|
||||
extern "C" void CompressBlocksETC1_ispc_sse4(const rgba_surface* src, uint8_t* dst, etc_enc_settings* settings);
|
||||
extern "C" void CompressBlocksASTC_ispc_sse4(const rgba_surface* src, uint8_t* dst, astc_enc_settings* settings);
|
||||
}
|
||||
}
|
||||
|
||||
static bool isAmd = false;
|
||||
|
||||
void ISPCInit()
|
||||
{
|
||||
#if defined(_MSC_VER)
|
||||
{
|
||||
int CPUInfo[4];
|
||||
__cpuid(CPUInfo, 0x80000001);
|
||||
isAmd = (CPUInfo[2] & (1 << 6)) != 0;
|
||||
}
|
||||
#else
|
||||
{
|
||||
unsigned int eax = 0x80000001;
|
||||
unsigned int ebx = 0;
|
||||
unsigned int ecx = 0;
|
||||
unsigned int edx = 0;
|
||||
asm volatile("cpuid"
|
||||
: "=a"(eax), "=b"(ebx), "=c"(ecx), "=d"(edx)
|
||||
: "a"(eax));
|
||||
isAmd = (ecx & (1 << 6)) != 0;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void GetProfile_ultrafast(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 3;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = false;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode13
|
||||
settings->mode_selection[1] = false;
|
||||
settings->fastSkipTreshold_mode1 = 3;
|
||||
settings->fastSkipTreshold_mode3 = 1;
|
||||
settings->fastSkipTreshold_mode7 = 0;
|
||||
|
||||
settings->refineIterations[1] = 2;
|
||||
settings->refineIterations[3] = 1;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = false;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 0;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 1;
|
||||
}
|
||||
|
||||
void GetProfile_veryfast(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 3;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = false;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode13
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 3;
|
||||
settings->fastSkipTreshold_mode3 = 1;
|
||||
settings->fastSkipTreshold_mode7 = 0;
|
||||
|
||||
settings->refineIterations[1] = 2;
|
||||
settings->refineIterations[3] = 1;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = false;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 0;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 1;
|
||||
}
|
||||
|
||||
void GetProfile_fast(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 3;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = false;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode13
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 12;
|
||||
settings->fastSkipTreshold_mode3 = 4;
|
||||
settings->fastSkipTreshold_mode7 = 0;
|
||||
|
||||
settings->refineIterations[1] = 2;
|
||||
settings->refineIterations[3] = 1;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = false;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 0;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2;
|
||||
}
|
||||
|
||||
void GetProfile_basic(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 3;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = true;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode13
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 8+4;
|
||||
settings->fastSkipTreshold_mode3 = 8;
|
||||
settings->fastSkipTreshold_mode7 = 0;
|
||||
|
||||
settings->refineIterations[1] = 2;
|
||||
settings->refineIterations[3] = 2;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 2;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2;
|
||||
}
|
||||
|
||||
void GetProfile_slow(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 3;
|
||||
|
||||
int moreRefine = 2;
|
||||
// mode02
|
||||
settings->mode_selection[0] = true;
|
||||
settings->skip_mode2 = false;
|
||||
|
||||
settings->refineIterations[0] = 2+moreRefine;
|
||||
settings->refineIterations[2] = 2+moreRefine;
|
||||
|
||||
// mode13
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 64;
|
||||
settings->fastSkipTreshold_mode3 = 64;
|
||||
settings->fastSkipTreshold_mode7 = 0;
|
||||
|
||||
settings->refineIterations[1] = 2+moreRefine;
|
||||
settings->refineIterations[3] = 2+moreRefine;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 2+moreRefine;
|
||||
settings->refineIterations[4] = 2+moreRefine;
|
||||
settings->refineIterations[5] = 2+moreRefine;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2+moreRefine;
|
||||
}
|
||||
|
||||
void GetProfile_alpha_ultrafast(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 4;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = false;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode137
|
||||
settings->mode_selection[1] = false;
|
||||
settings->fastSkipTreshold_mode1 = 0;
|
||||
settings->fastSkipTreshold_mode3 = 0;
|
||||
settings->fastSkipTreshold_mode7 = 4;
|
||||
|
||||
settings->refineIterations[1] = 1;
|
||||
settings->refineIterations[3] = 1;
|
||||
settings->refineIterations[7] = 2;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 3;
|
||||
settings->refineIterations_channel = 1;
|
||||
settings->refineIterations[4] = 1;
|
||||
settings->refineIterations[5] = 1;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2;
|
||||
}
|
||||
|
||||
void GetProfile_alpha_veryfast(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 4;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = false;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode137
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 0;
|
||||
settings->fastSkipTreshold_mode3 = 0;
|
||||
settings->fastSkipTreshold_mode7 = 4;
|
||||
|
||||
settings->refineIterations[1] = 1;
|
||||
settings->refineIterations[3] = 1;
|
||||
settings->refineIterations[7] = 2;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 3;
|
||||
settings->refineIterations_channel = 2;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2;
|
||||
}
|
||||
|
||||
void GetProfile_alpha_fast(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 4;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = false;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode137
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 4;
|
||||
settings->fastSkipTreshold_mode3 = 4;
|
||||
settings->fastSkipTreshold_mode7 = 8;
|
||||
|
||||
settings->refineIterations[1] = 1;
|
||||
settings->refineIterations[3] = 1;
|
||||
settings->refineIterations[7] = 2;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 3;
|
||||
settings->refineIterations_channel = 2;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2;
|
||||
}
|
||||
|
||||
void GetProfile_alpha_basic(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 4;
|
||||
|
||||
// mode02
|
||||
settings->mode_selection[0] = true;
|
||||
settings->skip_mode2 = true;
|
||||
|
||||
settings->refineIterations[0] = 2;
|
||||
settings->refineIterations[2] = 2;
|
||||
|
||||
// mode137
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 8+4;
|
||||
settings->fastSkipTreshold_mode3 = 8;
|
||||
settings->fastSkipTreshold_mode7 = 8;
|
||||
|
||||
settings->refineIterations[1] = 2;
|
||||
settings->refineIterations[3] = 2;
|
||||
settings->refineIterations[7] = 2;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 2;
|
||||
settings->refineIterations[4] = 2;
|
||||
settings->refineIterations[5] = 2;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2;
|
||||
}
|
||||
|
||||
void GetProfile_alpha_slow(bc7_enc_settings* settings)
|
||||
{
|
||||
settings->channels = 4;
|
||||
|
||||
int moreRefine = 2;
|
||||
// mode02
|
||||
settings->mode_selection[0] = true;
|
||||
settings->skip_mode2 = false;
|
||||
|
||||
settings->refineIterations[0] = 2+moreRefine;
|
||||
settings->refineIterations[2] = 2+moreRefine;
|
||||
|
||||
// mode137
|
||||
settings->mode_selection[1] = true;
|
||||
settings->fastSkipTreshold_mode1 = 64;
|
||||
settings->fastSkipTreshold_mode3 = 64;
|
||||
settings->fastSkipTreshold_mode7 = 64;
|
||||
|
||||
settings->refineIterations[1] = 2+moreRefine;
|
||||
settings->refineIterations[3] = 2+moreRefine;
|
||||
settings->refineIterations[7] = 2+moreRefine;
|
||||
|
||||
// mode45
|
||||
settings->mode_selection[2] = true;
|
||||
|
||||
settings->mode45_channel0 = 0;
|
||||
settings->refineIterations_channel = 2+moreRefine;
|
||||
settings->refineIterations[4] = 2+moreRefine;
|
||||
settings->refineIterations[5] = 2+moreRefine;
|
||||
|
||||
// mode6
|
||||
settings->mode_selection[3] = true;
|
||||
|
||||
settings->refineIterations[6] = 2+moreRefine;
|
||||
}
|
||||
|
||||
void GetProfile_bc6h_veryfast(bc6h_enc_settings* settings)
|
||||
{
|
||||
settings->slow_mode = false;
|
||||
settings->fast_mode = true;
|
||||
settings->fastSkipTreshold = 0;
|
||||
settings->refineIterations_1p = 0;
|
||||
settings->refineIterations_2p = 0;
|
||||
}
|
||||
|
||||
void GetProfile_bc6h_fast(bc6h_enc_settings* settings)
|
||||
{
|
||||
settings->slow_mode = false;
|
||||
settings->fast_mode = true;
|
||||
settings->fastSkipTreshold = 2;
|
||||
settings->refineIterations_1p = 0;
|
||||
settings->refineIterations_2p = 1;
|
||||
}
|
||||
|
||||
void GetProfile_bc6h_basic(bc6h_enc_settings* settings)
|
||||
{
|
||||
settings->slow_mode = false;
|
||||
settings->fast_mode = false;
|
||||
settings->fastSkipTreshold = 4;
|
||||
settings->refineIterations_1p = 2;
|
||||
settings->refineIterations_2p = 2;
|
||||
}
|
||||
|
||||
void GetProfile_bc6h_slow(bc6h_enc_settings* settings)
|
||||
{
|
||||
settings->slow_mode = true;
|
||||
settings->fast_mode = false;
|
||||
settings->fastSkipTreshold = 10;
|
||||
settings->refineIterations_1p = 2;
|
||||
settings->refineIterations_2p = 2;
|
||||
}
|
||||
|
||||
void GetProfile_bc6h_veryslow(bc6h_enc_settings* settings)
|
||||
{
|
||||
settings->slow_mode = true;
|
||||
settings->fast_mode = false;
|
||||
settings->fastSkipTreshold = 32;
|
||||
settings->refineIterations_1p = 2;
|
||||
settings->refineIterations_2p = 2;
|
||||
}
|
||||
|
||||
void GetProfile_etc_slow(etc_enc_settings* settings)
|
||||
{
|
||||
settings->fastSkipTreshold = 6;
|
||||
}
|
||||
|
||||
void ReplicateBorders(rgba_surface* dst_slice, const rgba_surface* src_tex, int start_x, int start_y, int bpp)
|
||||
{
|
||||
int bytes_per_pixel = bpp >> 3;
|
||||
|
||||
bool aliasing = false;
|
||||
if (&src_tex->ptr[src_tex->stride * start_y + bytes_per_pixel * start_x] == dst_slice->ptr) aliasing = true;
|
||||
|
||||
for (int y = 0; y < dst_slice->height; y++)
|
||||
for (int x = 0; x < dst_slice->width; x++)
|
||||
{
|
||||
int xx = start_x + x;
|
||||
int yy = start_y + y;
|
||||
|
||||
if (aliasing && xx < src_tex->width && yy < src_tex->height) continue;
|
||||
|
||||
if (xx >= src_tex->width) xx = src_tex->width - 1;
|
||||
if (yy >= src_tex->height) yy = src_tex->height - 1;
|
||||
|
||||
void* dst = &dst_slice->ptr[dst_slice->stride * y + bytes_per_pixel * x];
|
||||
void* src = &src_tex->ptr[src_tex->stride * yy + bytes_per_pixel * xx];
|
||||
|
||||
memcpy(dst, src, bytes_per_pixel);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksBC1(const rgba_surface* src, uint8_t* dst)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksBC1_ispc_sse4((ispc::rgba_surface*)src, dst);
|
||||
} else {
|
||||
ispc::CompressBlocksBC1_ispc((ispc::rgba_surface*)src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksBC3(const rgba_surface* src, uint8_t* dst)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksBC3_ispc_sse4((ispc::rgba_surface*)src, dst);
|
||||
} else {
|
||||
ispc::CompressBlocksBC3_ispc((ispc::rgba_surface*)src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksBC4(const rgba_surface* src, uint8_t* dst)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksBC4_ispc_sse4((ispc::rgba_surface*)src, dst);
|
||||
} else {
|
||||
ispc::CompressBlocksBC4_ispc((ispc::rgba_surface*)src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksBC5(const rgba_surface* src, uint8_t* dst)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksBC5_ispc_sse4((ispc::rgba_surface*)src, dst);
|
||||
} else {
|
||||
ispc::CompressBlocksBC5_ispc((ispc::rgba_surface*)src, dst);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksBC7(const rgba_surface* src, uint8_t* dst, bc7_enc_settings* settings)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksBC7_ispc_sse4((ispc::rgba_surface*)src, dst, (ispc::bc7_enc_settings*)settings);
|
||||
} else {
|
||||
ispc::CompressBlocksBC7_ispc((ispc::rgba_surface*)src, dst, (ispc::bc7_enc_settings*)settings);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksBC6H(const rgba_surface* src, uint8_t* dst, bc6h_enc_settings* settings)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksBC6H_ispc_sse4((ispc::rgba_surface*)src, dst, (ispc::bc6h_enc_settings*)settings);
|
||||
} else {
|
||||
ispc::CompressBlocksBC6H_ispc((ispc::rgba_surface*)src, dst, (ispc::bc6h_enc_settings*)settings);
|
||||
}
|
||||
}
|
||||
|
||||
void CompressBlocksETC1(const rgba_surface* src, uint8_t* dst, etc_enc_settings* settings)
|
||||
{
|
||||
if (isAmd) {
|
||||
ispc::CompressBlocksETC1_ispc_sse4((ispc::rgba_surface*)src, dst, (ispc::etc_enc_settings*)settings);
|
||||
} else {
|
||||
ispc::CompressBlocksETC1_ispc((ispc::rgba_surface*)src, dst, (ispc::etc_enc_settings*)settings);
|
||||
}
|
||||
}
|
||||
|
||||
int ISPCIsa()
|
||||
{
|
||||
if (isAmd) {
|
||||
return ispc::ISPCIsa_ispc_sse4();
|
||||
} else {
|
||||
return ispc::ISPCIsa_ispc();
|
||||
}
|
||||
}
|
30
Source/ispc_texcomp/ispc_texcomp.def
Normal file
30
Source/ispc_texcomp/ispc_texcomp.def
Normal file
|
@ -0,0 +1,30 @@
|
|||
LIBRARY ispc_texcomp
|
||||
EXPORTS
|
||||
CompressBlocksBC1
|
||||
CompressBlocksBC3
|
||||
CompressBlocksBC4
|
||||
CompressBlocksBC5
|
||||
CompressBlocksBC6H
|
||||
CompressBlocksBC7
|
||||
CompressBlocksETC1
|
||||
CompressBlocksASTC
|
||||
GetProfile_ultrafast
|
||||
GetProfile_veryfast
|
||||
GetProfile_fast
|
||||
GetProfile_basic
|
||||
GetProfile_slow
|
||||
GetProfile_alpha_ultrafast
|
||||
GetProfile_alpha_veryfast
|
||||
GetProfile_alpha_fast
|
||||
GetProfile_alpha_basic
|
||||
GetProfile_alpha_slow
|
||||
GetProfile_bc6h_veryfast
|
||||
GetProfile_bc6h_fast
|
||||
GetProfile_bc6h_basic
|
||||
GetProfile_bc6h_slow
|
||||
GetProfile_bc6h_veryslow
|
||||
GetProfile_etc_slow
|
||||
GetProfile_astc_fast
|
||||
GetProfile_astc_alpha_fast
|
||||
GetProfile_astc_alpha_slow
|
||||
ReplicateBorders
|
128
Source/ispc_texcomp/ispc_texcomp.h
Normal file
128
Source/ispc_texcomp/ispc_texcomp.h
Normal file
|
@ -0,0 +1,128 @@
|
|||
////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2016-2019, Intel Corporation
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to
|
||||
// deal in the Software without restriction, including without limitation the
|
||||
// rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||
// sell copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in
|
||||
// all copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||
// IN THE SOFTWARE.
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
struct rgba_surface
|
||||
{
|
||||
uint8_t* ptr;
|
||||
int32_t width;
|
||||
int32_t height;
|
||||
int32_t stride; // in bytes
|
||||
};
|
||||
|
||||
struct bc7_enc_settings
|
||||
{
|
||||
bool mode_selection[4];
|
||||
int refineIterations[8];
|
||||
|
||||
bool skip_mode2;
|
||||
int fastSkipTreshold_mode1;
|
||||
int fastSkipTreshold_mode3;
|
||||
int fastSkipTreshold_mode7;
|
||||
|
||||
int mode45_channel0;
|
||||
int refineIterations_channel;
|
||||
|
||||
int channels;
|
||||
};
|
||||
|
||||
struct bc6h_enc_settings
|
||||
{
|
||||
bool slow_mode;
|
||||
bool fast_mode;
|
||||
int refineIterations_1p;
|
||||
int refineIterations_2p;
|
||||
int fastSkipTreshold;
|
||||
};
|
||||
|
||||
struct etc_enc_settings
|
||||
{
|
||||
int fastSkipTreshold;
|
||||
};
|
||||
|
||||
struct astc_enc_settings
|
||||
{
|
||||
int block_width;
|
||||
int block_height;
|
||||
int channels;
|
||||
|
||||
int fastSkipTreshold;
|
||||
int refineIterations;
|
||||
};
|
||||
|
||||
// profiles for RGB data (alpha channel will be ignored)
|
||||
extern "C" void GetProfile_ultrafast(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_veryfast(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_fast(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_basic(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_slow(bc7_enc_settings* settings);
|
||||
|
||||
// profiles for RGBA inputs
|
||||
extern "C" void GetProfile_alpha_ultrafast(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_alpha_veryfast(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_alpha_fast(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_alpha_basic(bc7_enc_settings* settings);
|
||||
extern "C" void GetProfile_alpha_slow(bc7_enc_settings* settings);
|
||||
|
||||
// profiles for BC6H (RGB HDR)
|
||||
extern "C" void GetProfile_bc6h_veryfast(bc6h_enc_settings* settings);
|
||||
extern "C" void GetProfile_bc6h_fast(bc6h_enc_settings* settings);
|
||||
extern "C" void GetProfile_bc6h_basic(bc6h_enc_settings* settings);
|
||||
extern "C" void GetProfile_bc6h_slow(bc6h_enc_settings* settings);
|
||||
extern "C" void GetProfile_bc6h_veryslow(bc6h_enc_settings* settings);
|
||||
|
||||
// profiles for ETC
|
||||
extern "C" void GetProfile_etc_slow(etc_enc_settings* settings);
|
||||
|
||||
// profiles for ASTC
|
||||
extern "C" void GetProfile_astc_fast(astc_enc_settings* settings, int block_width, int block_height);
|
||||
extern "C" void GetProfile_astc_alpha_fast(astc_enc_settings* settings, int block_width, int block_height);
|
||||
extern "C" void GetProfile_astc_alpha_slow(astc_enc_settings* settings, int block_width, int block_height);
|
||||
|
||||
// helper function to replicate border pixels for the desired block sizes (bpp = 32 or 64)
|
||||
extern "C" void ReplicateBorders(rgba_surface* dst_slice, const rgba_surface* src_tex, int x, int y, int bpp);
|
||||
|
||||
/*
|
||||
Notes:
|
||||
- input width and height need to be a multiple of block size
|
||||
- LDR input is 32 bit/pixel (sRGB), HDR is 64 bit/pixel (half float)
|
||||
- for BC4 input is 8bit/pixel (R8), for BC5 input is 16bit/pixel (RG8)
|
||||
- dst buffer must be allocated with enough space for the compressed texture:
|
||||
- 8 bytes/block for BC1/BC4/ETC1,
|
||||
- 16 bytes/block for BC3/BC5/BC6H/BC7/ASTC
|
||||
- the blocks are stored in raster scan order (natural CPU texture layout)
|
||||
- use the GetProfile_* functions to select various speed/quality tradeoffs
|
||||
- the RGB profiles are slightly faster as they ignore the alpha channel
|
||||
*/
|
||||
|
||||
extern "C" void CompressBlocksBC1(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC3(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC4(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC5(const rgba_surface* src, uint8_t* dst);
|
||||
extern "C" void CompressBlocksBC6H(const rgba_surface* src, uint8_t* dst, bc6h_enc_settings* settings);
|
||||
extern "C" void CompressBlocksBC7(const rgba_surface* src, uint8_t* dst, bc7_enc_settings* settings);
|
||||
extern "C" void CompressBlocksETC1(const rgba_surface* src, uint8_t* dst, etc_enc_settings* settings);
|
||||
extern "C" void CompressBlocksASTC(const rgba_surface* src, uint8_t* dst, astc_enc_settings* settings);
|
||||
|
||||
extern "C" void ISPCInit();
|
||||
extern "C" int ISPCIsa();
|
177
Source/ispc_texcomp/ispc_texcomp.vcxproj
Normal file
177
Source/ispc_texcomp/ispc_texcomp.vcxproj
Normal file
|
@ -0,0 +1,177 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{9B44F7B9-A9AF-45A4-8695-96792A18B052}</ProjectGuid>
|
||||
<RootNamespace>ispc_texcomp</RootNamespace>
|
||||
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>true</UseDebugLibraries>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
<UseDebugLibraries>false</UseDebugLibraries>
|
||||
<WholeProgramOptimization>true</WholeProgramOptimization>
|
||||
<CharacterSet>MultiByte</CharacterSet>
|
||||
<PlatformToolset>v142</PlatformToolset>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<ImportGroup Label="ExtensionSettings">
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="PropertySheets">
|
||||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ExecutablePath>$(SolutionDir);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ExecutablePath>$(SolutionDir);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ExecutablePath>$(SolutionDir);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ExecutablePath>$(SolutionDir);$(ExecutablePath)</ExecutablePath>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<SubSystem>Windows</SubSystem>
|
||||
<ModuleDefinitionFile>ispc_texcomp.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>Disabled</Optimization>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<ModuleDefinitionFile>ispc_texcomp.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>ispc_texcomp.def</ModuleDefinitionFile>
|
||||
<ImageHasSafeExceptionHandlers>false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
|
||||
<ClCompile>
|
||||
<WarningLevel>Level3</WarningLevel>
|
||||
<Optimization>MaxSpeed</Optimization>
|
||||
<FunctionLevelLinking>true</FunctionLevelLinking>
|
||||
<IntrinsicFunctions>true</IntrinsicFunctions>
|
||||
</ClCompile>
|
||||
<Link>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<ModuleDefinitionFile>ispc_texcomp.def</ModuleDefinitionFile>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ispc_texcomp.cpp" />
|
||||
<ClCompile Include="ispc_texcomp_astc.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ispc_texcomp.h" />
|
||||
<ClInclude Include="kernel_astc_ispc.h" />
|
||||
<ClInclude Include="kernel_astc_ispc_avx.h" />
|
||||
<ClInclude Include="kernel_astc_ispc_avx2.h" />
|
||||
<ClInclude Include="kernel_astc_ispc_sse2.h" />
|
||||
<ClInclude Include="kernel_astc_ispc_sse4.h" />
|
||||
<ClInclude Include="kernel_ispc.h" />
|
||||
<ClInclude Include="kernel_ispc_avx.h" />
|
||||
<ClInclude Include="kernel_ispc_avx2.h" />
|
||||
<ClInclude Include="kernel_ispc_sse2.h" />
|
||||
<ClInclude Include="kernel_ispc_sse4.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="kernel.ispc">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --arch=x86 --target=sse2,sse4,avx,avx2 --opt=fast-math</Command>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --target=sse2,sse4,avx,avx2 --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)%(Filename).obj;$(TargetDir)%(Filename)_sse2.obj;$(TargetDir)%(Filename)_sse4.obj;$(TargetDir)%(Filename)_avx.obj;$(TargetDir)%(Filename)_avx2.obj;</Outputs>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)%(Filename).obj;$(TargetDir)%(Filename)_sse2.obj;$(TargetDir)%(Filename)_sse4.obj;$(TargetDir)%(Filename)_avx.obj;$(TargetDir)%(Filename)_avx2.obj;</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --arch=x86 --target=sse2,sse4,avx,avx2 --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)%(Filename).obj;$(TargetDir)%(Filename)_sse2.obj;$(TargetDir)%(Filename)_sse4.obj;$(TargetDir)%(Filename)_avx.obj;$(TargetDir)%(Filename)_avx2.obj;</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --target=sse2,sse4,avx,avx2 --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)%(Filename).obj;$(TargetDir)%(Filename)_sse2.obj;$(TargetDir)%(Filename)_sse4.obj;$(TargetDir)%(Filename)_avx.obj;$(TargetDir)%(Filename)_avx2.obj;</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="kernel_astc.ispc">
|
||||
<FileType>Document</FileType>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|x64'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --target=sse2,sse4,avx,avx2 --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|x64'">$(TargetDir)%(Filename).obj;$(TargetDir)%(Filename)_sse2.obj;$(TargetDir)%(Filename)_sse4.obj;$(TargetDir)%(Filename)_avx.obj;$(TargetDir)%(Filename)_avx2.obj;</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --target=avx --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">$(TargetDir)%(Filename).obj;</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --arch=x86 --target=sse2,sse4,avx,avx2 --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(TargetDir)%(Filename).obj;$(TargetDir)%(Filename)_sse2.obj;$(TargetDir)%(Filename)_sse4.obj;$(TargetDir)%(Filename)_avx.obj;$(TargetDir)%(Filename)_avx2.obj;</Outputs>
|
||||
<Command Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">"$(ProjectDir)..\ISPC\win\ispc.exe" -O2 "%(Filename).ispc" -o "$(TargetDir)%(Filename).obj" -h "$(ProjectDir)%(Filename)_ispc.h" --arch=x86 --target=avx --opt=fast-math</Command>
|
||||
<Outputs Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(TargetDir)%(Filename).obj;</Outputs>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<ImportGroup Label="ExtensionTargets">
|
||||
</ImportGroup>
|
||||
</Project>
|
62
Source/ispc_texcomp/ispc_texcomp.vcxproj.filters
Normal file
62
Source/ispc_texcomp/ispc_texcomp.vcxproj.filters
Normal file
|
@ -0,0 +1,62 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
</Filter>
|
||||
<Filter Include="Generated Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="ispc_texcomp.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="ispc_texcomp_astc.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<CustomBuild Include="kernel.ispc">
|
||||
<Filter>Source Files</Filter>
|
||||
</CustomBuild>
|
||||
<CustomBuild Include="kernel_astc.ispc">
|
||||
<Filter>Source Files</Filter>
|
||||
</CustomBuild>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ispc_texcomp.h">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_astc_ispc_sse2.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_astc_ispc_sse4.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_ispc.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_ispc_avx.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_ispc_avx2.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_ispc_sse2.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_ispc_sse4.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_astc_ispc.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_astc_ispc_avx.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="kernel_astc_ispc_avx2.h">
|
||||
<Filter>Generated Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
</Project>
|
564
Source/ispc_texcomp/ispc_texcomp_astc.cpp
Normal file
564
Source/ispc_texcomp/ispc_texcomp_astc.cpp
Normal file
|
@ -0,0 +1,564 @@
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// Copyright (c) 2016, Intel Corporation
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation
|
||||
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
|
||||
// permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
// The above copyright notice and this permission notice shall be included in all copies or substantial portions of
|
||||
// the Software.
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO
|
||||
// THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
||||
// TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#include "ispc_texcomp.h"
|
||||
#include "kernel_astc_ispc.h"
|
||||
#include <cassert>
|
||||
#include <cstring>
|
||||
#include <algorithm>
|
||||
#include <vector>
|
||||
#include <limits>
|
||||
|
||||
void GetProfile_astc_fast(astc_enc_settings* settings, int block_width, int block_height)
|
||||
{
|
||||
settings->block_width = block_width;
|
||||
settings->block_height = block_height;
|
||||
settings->channels = 3;
|
||||
|
||||
settings->fastSkipTreshold = 5;
|
||||
settings->refineIterations = 2;
|
||||
}
|
||||
|
||||
void GetProfile_astc_alpha_fast(astc_enc_settings* settings, int block_width, int block_height)
|
||||
{
|
||||
settings->block_width = block_width;
|
||||
settings->block_height = block_height;
|
||||
settings->channels = 4;
|
||||
|
||||
settings->fastSkipTreshold = 5;
|
||||
settings->refineIterations = 2;
|
||||
}
|
||||
|
||||
void GetProfile_astc_alpha_slow(astc_enc_settings* settings, int block_width, int block_height)
|
||||
{
|
||||
settings->block_width = block_width;
|
||||
settings->block_height = block_height;
|
||||
settings->channels = 4;
|
||||
|
||||
settings->fastSkipTreshold = 64;
|
||||
settings->refineIterations = 2;
|
||||
}
|
||||
|
||||
struct astc_block
|
||||
{
|
||||
int width;
|
||||
int height;
|
||||
uint8_t dual_plane;
|
||||
int weight_range;
|
||||
uint8_t weights[64];
|
||||
int color_component_selector;
|
||||
|
||||
int partitions;
|
||||
int partition_id;
|
||||
int color_endpoint_pairs;
|
||||
int channels;
|
||||
int color_endpoint_modes[4];
|
||||
int endpoint_range;
|
||||
uint8_t endpoints[18];
|
||||
};
|
||||
|
||||
bool can_store(int value, int bits)
|
||||
{
|
||||
if (value < 0) return false;
|
||||
if (value >= 1 << bits) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int pack_block_mode(astc_block* block)
|
||||
{
|
||||
int block_mode = 0;
|
||||
|
||||
int D = block->dual_plane;
|
||||
int H = block->weight_range >= 6;
|
||||
int DH = D * 2 + H;
|
||||
int R = block->weight_range + 2 - ((H > 0) ? 6 : 0);
|
||||
R = R / 2 + R % 2 * 4;
|
||||
|
||||
if (can_store(block->width - 4, 2) && can_store(block->height - 2, 2))
|
||||
{
|
||||
int B = block->width - 4;
|
||||
int A = block->height - 2;
|
||||
|
||||
block_mode = (DH << 9) | (B << 7) | (A << 5) | ((R & 4) << 2) | (R & 3);
|
||||
}
|
||||
|
||||
if (can_store(block->width - 8, 2) && can_store(block->height - 2, 2))
|
||||
{
|
||||
int B = block->width - 8;
|
||||
int A = block->height - 2;
|
||||
|
||||
block_mode = (DH << 9) | (B << 7) | (A << 5) | ((R & 4) << 2) | 4 | (R & 3);
|
||||
}
|
||||
|
||||
if (can_store(block->width - 2, 2) && can_store(block->height - 8, 2))
|
||||
{
|
||||
int A = block->width - 2;
|
||||
int B = block->height - 8;
|
||||
|
||||
block_mode = (DH << 9) | (B << 7) | (A << 5) | ((R & 4) << 2) | 8 | (R & 3);
|
||||
}
|
||||
|
||||
if (can_store(block->width - 2, 2) && can_store(block->height - 6, 1))
|
||||
{
|
||||
int A = block->width - 2;
|
||||
int B = block->height - 6;
|
||||
|
||||
block_mode = (DH << 9) | (B << 7) | (A << 5) | ((R & 4) << 2) | 12 | (R & 3);
|
||||
}
|
||||
|
||||
if (can_store(block->width - 2, 1) && can_store(block->height - 2, 2))
|
||||
{
|
||||
int B = block->width;
|
||||
int A = block->height - 2;
|
||||
|
||||
block_mode = (DH << 9) | (B << 7) | (A << 5) | ((R & 4) << 2) | 12 | (R & 3);
|
||||
}
|
||||
|
||||
if (DH == 0 && can_store(block->width - 6, 2) && can_store(block->height - 6, 2))
|
||||
{
|
||||
int A = block->width - 6;
|
||||
int B = block->height - 6;
|
||||
|
||||
block_mode = (B << 9) | 256 | (A << 5) | (R << 2);
|
||||
}
|
||||
|
||||
return block_mode;
|
||||
}
|
||||
|
||||
int range_table[][3] =
|
||||
{
|
||||
//2^ 3^ 5^
|
||||
{ 1, 0, 0 }, // 0..1
|
||||
{ 0, 1, 0 }, // 0..2
|
||||
{ 2, 0, 0 }, // 0..3
|
||||
|
||||
{ 0, 0, 1 }, // 0..4
|
||||
{ 1, 1, 0 }, // 0..5
|
||||
{ 3, 0, 0 }, // 0..7
|
||||
|
||||
{ 1, 0, 1 }, // 0..9
|
||||
{ 2, 1, 0 }, // 0..11
|
||||
{ 4, 0, 0 }, // 0..15
|
||||
|
||||
{ 2, 0, 1 }, // 0..19
|
||||
{ 3, 1, 0 }, // 0..23
|
||||
{ 5, 0, 0 }, // 0..31
|
||||
|
||||
{ 3, 0, 1 }, // 0..39
|
||||
{ 4, 1, 0 }, // 0..47
|
||||
{ 6, 0, 0 }, // 0..63
|
||||
|
||||
{ 4, 0, 1 }, // 0..79
|
||||
{ 5, 1, 0 }, // 0..95
|
||||
{ 7, 0, 0 }, // 0..127
|
||||
|
||||
{ 5, 0, 1 }, // 0..159
|
||||
{ 6, 1, 0 }, // 0..191
|
||||
{ 8, 0, 0 }, // 0..255
|
||||
};
|
||||
|
||||
int get_levels(int range)
|
||||
{
|
||||
return (1 + 2 * range_table[range][1] + 4 * range_table[range][2]) << range_table[range][0];
|
||||
}
|
||||
|
||||
int sequence_bits(int count, int range)
|
||||
{
|
||||
int bits = count * range_table[range][0];
|
||||
bits += (count * range_table[range][1] * 8 + 4) / 5;
|
||||
bits += (count * range_table[range][2] * 7 + 2) / 3;
|
||||
return bits;
|
||||
}
|
||||
|
||||
void set_bits(uint32_t data[4], int* pos, int bits, uint32_t value)
|
||||
{
|
||||
assert(bits <= 25);
|
||||
uint32_t word = *(uint32_t*)(((uint8_t*)data) + *pos / 8);
|
||||
|
||||
uint32_t mask = (1 << bits) - 1;
|
||||
word |= value << (*pos % 8);
|
||||
|
||||
*(uint32_t*)(((uint8_t*)data) + *pos / 8) = word;
|
||||
*pos += bits;
|
||||
}
|
||||
|
||||
uint32_t get_field(uint32_t input, int a, int b)
|
||||
{
|
||||
assert(a >= b);
|
||||
return (input >> b) & ((1 << (a - b + 1)) - 1);
|
||||
}
|
||||
|
||||
uint32_t get_bit(uint32_t input, int a)
|
||||
{
|
||||
return get_field(input, a, a);
|
||||
}
|
||||
|
||||
void pack_five_trits(uint32_t data[4], int sequence[5], int* pos, int n)
|
||||
{
|
||||
int t[5];
|
||||
int m[5];
|
||||
|
||||
for (int i = 0; i < 5; i++)
|
||||
{
|
||||
t[i] = sequence[i] >> n;
|
||||
m[i] = sequence[i] - (t[i] << n);
|
||||
}
|
||||
|
||||
int C;
|
||||
|
||||
if (t[1] == 2 && t[2] == 2)
|
||||
{
|
||||
C = 3 * 4 + t[0];
|
||||
}
|
||||
else if (t[2] == 2)
|
||||
{
|
||||
C = t[1] * 16 + t[0] * 4 + 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
C = t[2] * 16 + t[1] * 4 + t[0];
|
||||
}
|
||||
|
||||
int T;
|
||||
|
||||
if (t[3] == 2 && t[4] == 2)
|
||||
{
|
||||
T = get_field(C, 4, 2) * 32 + 7 * 4 + get_field(C, 1, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
T = get_field(C, 4, 0);
|
||||
if (t[4] == 2)
|
||||
{
|
||||
T += t[3] * 128 + 3 * 32;
|
||||
}
|
||||
else
|
||||
{
|
||||
T += t[4] * 128 + t[3] * 32;
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pack1 = 0;
|
||||
pack1 |= m[0];
|
||||
pack1 |= get_field(T, 1, 0) << n;
|
||||
pack1 |= m[1] << (2 + n);
|
||||
|
||||
uint32_t pack2 = 0;
|
||||
pack2 |= get_field(T, 3, 2);
|
||||
pack2 |= m[2] << 2;
|
||||
pack2 |= get_field(T, 4, 4) << (2 + n);
|
||||
pack2 |= m[3] << (3 + n);
|
||||
pack2 |= get_field(T, 6, 5) << (3 + n * 2);
|
||||
pack2 |= m[4] << (5 + n * 2);
|
||||
pack2 |= get_field(T, 7, 7) << (5 + n * 3);
|
||||
|
||||
set_bits(data, pos, 2 + n * 2, pack1);
|
||||
set_bits(data, pos, 6 + n * 3, pack2);
|
||||
}
|
||||
|
||||
void pack_three_quint(uint32_t data[4], int sequence[3], int* pos, int n)
|
||||
{
|
||||
int q[3];
|
||||
int m[3];
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
q[i] = sequence[i] >> n;
|
||||
m[i] = sequence[i] - (q[i] << n);
|
||||
}
|
||||
|
||||
int Q;
|
||||
|
||||
if (q[0] == 4 && q[1] == 4)
|
||||
{
|
||||
Q = get_field(q[2], 1, 0) * 8 + 3 * 2 + get_bit(q[2], 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
int C;
|
||||
if (q[1] == 4)
|
||||
{
|
||||
C = (q[0] << 3) + 5;
|
||||
}
|
||||
else
|
||||
{
|
||||
C = (q[1] << 3) + q[0];
|
||||
}
|
||||
|
||||
if (q[2] == 4)
|
||||
{
|
||||
Q = get_field(~C, 2, 1) * 32 + get_field(C, 4, 3) * 8 + 3 * 2 + get_bit(C, 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
Q = q[2] * 32 + get_field(C, 4, 0);
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t pack = 0;
|
||||
pack |= m[0];
|
||||
pack |= get_field(Q, 2, 0) << n;
|
||||
pack |= m[1] << (3 + n);
|
||||
pack |= get_field(Q, 4, 3) << (3 + n * 2);
|
||||
pack |= m[2] << (5 + n * 2);
|
||||
pack |= get_field(Q, 6, 5) << (5 + n * 3);
|
||||
|
||||
set_bits(data, pos, 7 + n * 3, pack);
|
||||
}
|
||||
|
||||
void pack_integer_sequence(uint32_t output_data[4], uint8_t sequence[], int pos, int count, int range)
|
||||
{
|
||||
int n = range_table[range][0];
|
||||
int bits = sequence_bits(count, range);
|
||||
int pos0 = pos;
|
||||
|
||||
uint32_t data[5] = { 0 };
|
||||
if (range_table[range][1] == 1)
|
||||
{
|
||||
for (int j = 0; j < (count + 4) / 5; j++)
|
||||
{
|
||||
int temp[5] = { 0 };
|
||||
for (int i = 0; i < std::min(count - j * 5, 5); i++) temp[i] = sequence[j * 5 + i];
|
||||
pack_five_trits(data, temp, &pos, n);
|
||||
}
|
||||
}
|
||||
else if (range_table[range][2] == 1)
|
||||
{
|
||||
for (int j = 0; j < (count + 2) / 3; j++)
|
||||
{
|
||||
int temp[3] = { 0 };
|
||||
for (int i = 0; i < std::min(count - j * 3, 3); i++) temp[i] = sequence[j * 3 + i];
|
||||
pack_three_quint(data, temp, &pos, n);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < count; i++)
|
||||
{
|
||||
set_bits(data, &pos, n, sequence[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (pos0 + bits < 96) data[3] = 0;
|
||||
if (pos0 + bits < 64) data[2] = 0;
|
||||
if (pos0 + bits < 32) data[1] = 0;
|
||||
data[(pos0 + bits) / 32] &= (1 << ((pos0 + bits) % 32)) - 1;
|
||||
|
||||
for (int k = 0; k < 4; k++) output_data[k] |= data[k];
|
||||
}
|
||||
|
||||
uint32_t reverse_bits_32(uint32_t input)
|
||||
{
|
||||
uint32_t t = input;
|
||||
t = (t << 16) | (t >> 16);
|
||||
t = ((t & 0x00FF00FF) << 8) | ((t & 0xFF00FF00) >> 8);
|
||||
t = ((t & 0x0F0F0F0F) << 4) | ((t & 0xF0F0F0F0) >> 4);
|
||||
t = ((t & 0x33333333) << 2) | ((t & 0xCCCCCCCC) >> 2);
|
||||
t = ((t & 0x55555555) << 1) | ((t & 0xAAAAAAAA) >> 1);
|
||||
|
||||
return t;
|
||||
}
|
||||
|
||||
void pack_block(uint32_t data[4], astc_block* block)
|
||||
{
|
||||
memset(data, 0, 16);
|
||||
|
||||
int pos = 0;
|
||||
set_bits(data, &pos, 11, pack_block_mode(block));
|
||||
|
||||
int num_weights = block->width * block->height * (block->dual_plane ? 2 : 1);
|
||||
int weight_bits = sequence_bits(num_weights, block->weight_range);
|
||||
int extra_bits = 0;
|
||||
|
||||
assert(num_weights <= 64);
|
||||
assert(24 <= weight_bits && weight_bits <= 96);
|
||||
|
||||
set_bits(data, &pos, 2, block->partitions - 1);
|
||||
if (block->partitions > 1)
|
||||
{
|
||||
set_bits(data, &pos, 10, block->partition_id);
|
||||
|
||||
int min_cem = 16;
|
||||
int max_cem = 0;
|
||||
for (int j = 0; j < block->partitions; j++)
|
||||
{
|
||||
min_cem = std::min(min_cem, block->color_endpoint_modes[j]);
|
||||
max_cem = std::max(max_cem, block->color_endpoint_modes[j]);
|
||||
}
|
||||
assert(max_cem / 4 <= min_cem / 4 + 1);
|
||||
|
||||
int CEM = block->color_endpoint_modes[0] << 2;
|
||||
if (max_cem != min_cem)
|
||||
{
|
||||
CEM = std::min(3, min_cem / 4 + 1);
|
||||
for (int j = 0; j < block->partitions; j++)
|
||||
{
|
||||
int c = block->color_endpoint_modes[j] / 4 - ((CEM & 3) - 1);
|
||||
int m = block->color_endpoint_modes[j] % 4;
|
||||
assert(c == 0 || c == 1);
|
||||
CEM |= c << (2 + j);
|
||||
CEM |= m << (2 + block->partitions + 2 * j);
|
||||
}
|
||||
extra_bits = 3 * block->partitions - 4;
|
||||
int pos2 = 128 - weight_bits - extra_bits;
|
||||
set_bits(data, &pos2, extra_bits, CEM >> 6);
|
||||
}
|
||||
|
||||
set_bits(data, &pos, 6, CEM & 63);
|
||||
}
|
||||
else
|
||||
{
|
||||
set_bits(data, &pos, 4, block->color_endpoint_modes[0]);
|
||||
}
|
||||
|
||||
if (block->dual_plane)
|
||||
{
|
||||
assert(block->partitions < 4);
|
||||
extra_bits += 2;
|
||||
int pos2 = 128 - weight_bits - extra_bits;
|
||||
set_bits(data, &pos2, 2, block->color_component_selector);
|
||||
}
|
||||
|
||||
int config_bits = pos + extra_bits;
|
||||
int remaining_bits = 128 - config_bits - weight_bits;
|
||||
|
||||
int num_cem_pairs = 0;
|
||||
for (int j = 0; j < block->partitions; j++) num_cem_pairs += 1 + block->color_endpoint_modes[j] / 4;
|
||||
|
||||
assert(num_cem_pairs <= 9);
|
||||
|
||||
int endpoint_range = -1;
|
||||
for (int range = 20; range>0; range--)
|
||||
{
|
||||
int bits = sequence_bits(2 * num_cem_pairs, range);
|
||||
if (bits <= remaining_bits)
|
||||
{
|
||||
endpoint_range = range;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
assert(endpoint_range >= 4);
|
||||
assert(block->endpoint_range == endpoint_range);
|
||||
|
||||
pack_integer_sequence(data, block->endpoints, pos, 2 * num_cem_pairs, endpoint_range);
|
||||
|
||||
uint32_t rdata[4] = { 0, 0, 0, 0 };
|
||||
pack_integer_sequence(rdata, block->weights, 0, num_weights, block->weight_range);
|
||||
|
||||
for (int i = 0; i < 4; i++) data[i] |= reverse_bits_32(rdata[3 - i]);
|
||||
}
|
||||
|
||||
void atsc_rank(const rgba_surface* src, int xx, int yy, uint32_t* mode_buffer, astc_enc_settings* settings)
|
||||
{
|
||||
ispc::astc_rank_ispc((ispc::rgba_surface*)src, xx, yy, mode_buffer, (ispc::astc_enc_settings*)settings);
|
||||
}
|
||||
|
||||
extern "C" void pack_block_c(uint32_t data[4], ispc::astc_block* block)
|
||||
{
|
||||
assert(sizeof(ispc::astc_block) == sizeof(astc_block));
|
||||
pack_block(data, (astc_block*)block);
|
||||
}
|
||||
|
||||
void setup_list_context(ispc::astc_enc_context* ctx, uint32_t packed_mode)
|
||||
{
|
||||
ctx->width = 2 + get_field(packed_mode, 15, 13); // 2..8 <= 2^3
|
||||
ctx->height = 2 + get_field(packed_mode, 18, 16); // 2..8 <= 2^3
|
||||
ctx->dual_plane = get_field(packed_mode, 19, 19); // 0 or 1
|
||||
ctx->partitions = 1;
|
||||
|
||||
int color_endpoint_modes0 = get_field(packed_mode, 7, 6) * 2 + 6; // 6, 8, 10 or 12
|
||||
ctx->color_endpoint_pairs = 1 + (color_endpoint_modes0 / 4);
|
||||
|
||||
ctx->channels = (color_endpoint_modes0 > 8) ? 4 : 3;
|
||||
}
|
||||
|
||||
void astc_encode(const rgba_surface* src, float* block_scores, uint8_t* dst, uint64_t* list, astc_enc_settings* settings)
|
||||
{
|
||||
ispc::astc_enc_context list_context;
|
||||
setup_list_context(&list_context, uint32_t(list[1] & 0xFFFFFFFF));
|
||||
|
||||
assert(sizeof(ispc::rgba_surface) == sizeof(rgba_surface));
|
||||
assert(sizeof(ispc::astc_enc_settings) == sizeof(astc_enc_settings));
|
||||
ispc::astc_encode_ispc((ispc::rgba_surface*)src, block_scores, dst, list, &list_context, (ispc::astc_enc_settings*)settings);
|
||||
}
|
||||
|
||||
void CompressBlocksASTC(const rgba_surface* src, uint8_t* dst, astc_enc_settings* settings)
|
||||
{
|
||||
assert(src->height % settings->block_height == 0);
|
||||
assert(src->width % settings->block_width == 0);
|
||||
|
||||
assert(settings->block_height <= 8);
|
||||
assert(settings->block_width <= 8);
|
||||
|
||||
int tex_width = src->width / settings->block_width;
|
||||
int programCount = ispc::get_programCount();
|
||||
|
||||
std::vector<float> block_scores(tex_width * src->height / settings->block_height);
|
||||
|
||||
for (int yy = 0; yy < src->height / settings->block_height; yy++)
|
||||
for (int xx = 0; xx < tex_width; xx++)
|
||||
{
|
||||
block_scores[yy * tex_width + xx] = std::numeric_limits<float>::infinity();
|
||||
}
|
||||
|
||||
int mode_list_size = 3334;
|
||||
int list_size = programCount;
|
||||
std::vector<uint64_t> mode_lists(list_size * mode_list_size);
|
||||
std::vector<uint32_t> mode_buffer(programCount * settings->fastSkipTreshold);
|
||||
|
||||
for (int yy = 0; yy < src->height / settings->block_height; yy++)
|
||||
for (int _x = 0; _x < (tex_width + programCount - 1) / programCount; _x++)
|
||||
{
|
||||
int xx = _x * programCount;
|
||||
atsc_rank(src, xx, yy, mode_buffer.data(), settings);
|
||||
|
||||
for (int i = 0; i < settings->fastSkipTreshold; i++)
|
||||
for (int k = 0; k < programCount; k++)
|
||||
{
|
||||
if (xx + k >= tex_width) continue;
|
||||
|
||||
uint32_t offset = (yy << 16) + (xx + k);
|
||||
uint32_t mode = mode_buffer[programCount * i + k];
|
||||
int mode_bin = mode >> 20;
|
||||
uint64_t* mode_list = &mode_lists[list_size * mode_bin];
|
||||
|
||||
if (*mode_list < programCount - 1)
|
||||
{
|
||||
int index = int(mode_list[0] + 1);
|
||||
mode_list[0] = index;
|
||||
|
||||
mode_list[index] = (uint64_t(offset) << 32) + mode;
|
||||
}
|
||||
else
|
||||
{
|
||||
mode_list[0] = (uint64_t(offset) << 32) + mode;
|
||||
|
||||
astc_encode(src, block_scores.data(), dst, mode_list, settings);
|
||||
memset(mode_list, 0, list_size * sizeof(uint64_t));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int mode_bin = 0; mode_bin < mode_list_size; mode_bin++)
|
||||
{
|
||||
uint64_t* mode_list = &mode_lists[list_size * mode_bin];
|
||||
if (mode_list[0] == 0) continue;
|
||||
mode_list[0] = 0;
|
||||
|
||||
astc_encode(src, block_scores.data(), dst, mode_list, settings);
|
||||
memset(mode_list, 0, list_size * sizeof(uint64_t));
|
||||
}
|
||||
}
|
3798
Source/ispc_texcomp/kernel.ispc
Normal file
3798
Source/ispc_texcomp/kernel.ispc
Normal file
File diff suppressed because it is too large
Load diff
2272
Source/ispc_texcomp/kernel_astc.ispc
Normal file
2272
Source/ispc_texcomp/kernel_astc.ispc
Normal file
File diff suppressed because it is too large
Load diff
26
Source/meson.build
Normal file
26
Source/meson.build
Normal file
|
@ -0,0 +1,26 @@
|
|||
sources = files([
|
||||
'createdfd.cpp',
|
||||
'HalfFloat.cpp',
|
||||
'Main.cpp',
|
||||
'stb_image_resize.cpp',
|
||||
'stb_image.cpp',
|
||||
'vk2dfd.cpp'
|
||||
])
|
||||
|
||||
incdirs = include_directories([
|
||||
])
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
ispc_kernel = custom_target('ipsc_kernel', input: ['ispc_texcomp/kernel.ispc'], output: ['kernel_ispc.o', 'kernel_ispc_avx2.o', 'kernel_ispc_sse4.o', 'kernel_ispc.h'], command: ['ispc', '-O3', '--arch=x86_64', '--target=sse4,avx2', '--opt=fast-math', '--pic', '@INPUT@', '-h', '@OUTDIR@/kernel_ispc.h', '-o', '@OUTPUT0@'])
|
||||
|
||||
ispc_sources = [
|
||||
ispc_kernel,
|
||||
'ispc_texcomp/ispc_texcomp.cpp',
|
||||
'ispc_texcomp/ispc_texcomp.h'
|
||||
]
|
||||
|
||||
ispc_texcomp = static_library('ispc_texcomp', ispc_sources)
|
||||
|
||||
executable('TextureTaffy', sources, dependencies: dependencies, include_directories: incdirs, install: true, install_dir: '', install_tag: 'exe', link_with: ispc_texcomp)
|
2
Source/stb_image.cpp
Normal file
2
Source/stb_image.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define STB_IMAGE_IMPLEMENTATION
|
||||
#include "stb_image.h"
|
7987
Source/stb_image.h
Normal file
7987
Source/stb_image.h
Normal file
File diff suppressed because it is too large
Load diff
2
Source/stb_image_resize.cpp
Normal file
2
Source/stb_image_resize.cpp
Normal file
|
@ -0,0 +1,2 @@
|
|||
#define STB_IMAGE_RESIZE_IMPLEMENTATION
|
||||
#include "stb_image_resize.h"
|
2634
Source/stb_image_resize.h
Normal file
2634
Source/stb_image_resize.h
Normal file
File diff suppressed because it is too large
Load diff
33
Source/vk2dfd.cpp
Normal file
33
Source/vk2dfd.cpp
Normal file
|
@ -0,0 +1,33 @@
|
|||
/* -*- tab-width: 4; -*- */
|
||||
/* vi: set sw=2 ts=4 expandtab: */
|
||||
|
||||
/* Copyright 2019-2020 Mark Callow
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @~English
|
||||
* @brief Create a DFD for a VkFormat.
|
||||
*/
|
||||
|
||||
#include "dfd.h"
|
||||
|
||||
/**
|
||||
* @~English
|
||||
* @brief Create a DFD matching a VkFormat.
|
||||
*
|
||||
* @param[in] format VkFormat for which to create a DFD.
|
||||
*
|
||||
* @return pointer to the created DFD or 0 if format not supported or
|
||||
* unrecognized. Caller is responsible for freeing the created
|
||||
* DFD.
|
||||
*/
|
||||
uint32_t * vk2dfd(enum VkFormat format)
|
||||
{
|
||||
switch (format) {
|
||||
#include "vk2dfd.inl"
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
|
294
Source/vk2dfd.inl
Normal file
294
Source/vk2dfd.inl
Normal file
|
@ -0,0 +1,294 @@
|
|||
/* Copyright 2019-2020 The Khronos Group Inc. */
|
||||
/* SPDX-License-Identifier: Apache-2.0 */
|
||||
|
||||
/***************************** Do not edit. *****************************
|
||||
Automatically generated by makevk2dfd.pl.
|
||||
*************************************************************************/
|
||||
|
||||
/* Vulkan combined depth & stencil formats are not included here
|
||||
* because they do not exist outside a Vulkan device.
|
||||
*/
|
||||
case VK_FORMAT_R4G4_UNORM_PACK8: {
|
||||
int channels[] = {1,0}; int bits[] = {4,4};
|
||||
return createDFDPacked(0, 2, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_R4G4B4A4_UNORM_PACK16: {
|
||||
int channels[] = {3,2,1,0}; int bits[] = {4,4,4,4};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_B4G4R4A4_UNORM_PACK16: {
|
||||
int channels[] = {3,0,1,2}; int bits[] = {4,4,4,4};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_R5G6B5_UNORM_PACK16: {
|
||||
int channels[] = {2,1,0}; int bits[] = {5,6,5};
|
||||
return createDFDPacked(0, 3, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_B5G6R5_UNORM_PACK16: {
|
||||
int channels[] = {0,1,2}; int bits[] = {5,6,5};
|
||||
return createDFDPacked(0, 3, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_R5G5B5A1_UNORM_PACK16: {
|
||||
int channels[] = {3,2,1,0}; int bits[] = {1,5,5,5};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_B5G5R5A1_UNORM_PACK16: {
|
||||
int channels[] = {3,0,1,2}; int bits[] = {1,5,5,5};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_A1R5G5B5_UNORM_PACK16: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {5,5,5,1};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_R8_UNORM: return createDFDUnpacked(0, 1, 1, 0, s_UNORM);
|
||||
case VK_FORMAT_R8_SNORM: return createDFDUnpacked(0, 1, 1, 0, s_SNORM);
|
||||
case VK_FORMAT_R8_USCALED: return createDFDUnpacked(0, 1, 1, 0, s_USCALED);
|
||||
case VK_FORMAT_R8_SSCALED: return createDFDUnpacked(0, 1, 1, 0, s_SSCALED);
|
||||
case VK_FORMAT_R8_UINT: return createDFDUnpacked(0, 1, 1, 0, s_UINT);
|
||||
case VK_FORMAT_R8_SINT: return createDFDUnpacked(0, 1, 1, 0, s_SINT);
|
||||
case VK_FORMAT_R8_SRGB: return createDFDUnpacked(0, 1, 1, 0, s_SRGB);
|
||||
case VK_FORMAT_R8G8_UNORM: return createDFDUnpacked(0, 2, 1, 0, s_UNORM);
|
||||
case VK_FORMAT_R8G8_SNORM: return createDFDUnpacked(0, 2, 1, 0, s_SNORM);
|
||||
case VK_FORMAT_R8G8_USCALED: return createDFDUnpacked(0, 2, 1, 0, s_USCALED);
|
||||
case VK_FORMAT_R8G8_SSCALED: return createDFDUnpacked(0, 2, 1, 0, s_SSCALED);
|
||||
case VK_FORMAT_R8G8_UINT: return createDFDUnpacked(0, 2, 1, 0, s_UINT);
|
||||
case VK_FORMAT_R8G8_SINT: return createDFDUnpacked(0, 2, 1, 0, s_SINT);
|
||||
case VK_FORMAT_R8G8_SRGB: return createDFDUnpacked(0, 2, 1, 0, s_SRGB);
|
||||
case VK_FORMAT_R8G8B8_UNORM: return createDFDUnpacked(0, 3, 1, 0, s_UNORM);
|
||||
case VK_FORMAT_R8G8B8_SNORM: return createDFDUnpacked(0, 3, 1, 0, s_SNORM);
|
||||
case VK_FORMAT_R8G8B8_USCALED: return createDFDUnpacked(0, 3, 1, 0, s_USCALED);
|
||||
case VK_FORMAT_R8G8B8_SSCALED: return createDFDUnpacked(0, 3, 1, 0, s_SSCALED);
|
||||
case VK_FORMAT_R8G8B8_UINT: return createDFDUnpacked(0, 3, 1, 0, s_UINT);
|
||||
case VK_FORMAT_R8G8B8_SINT: return createDFDUnpacked(0, 3, 1, 0, s_SINT);
|
||||
case VK_FORMAT_R8G8B8_SRGB: return createDFDUnpacked(0, 3, 1, 0, s_SRGB);
|
||||
case VK_FORMAT_B8G8R8_UNORM: return createDFDUnpacked(0, 3, 1, 1, s_UNORM);
|
||||
case VK_FORMAT_B8G8R8_SNORM: return createDFDUnpacked(0, 3, 1, 1, s_SNORM);
|
||||
case VK_FORMAT_B8G8R8_USCALED: return createDFDUnpacked(0, 3, 1, 1, s_USCALED);
|
||||
case VK_FORMAT_B8G8R8_SSCALED: return createDFDUnpacked(0, 3, 1, 1, s_SSCALED);
|
||||
case VK_FORMAT_B8G8R8_UINT: return createDFDUnpacked(0, 3, 1, 1, s_UINT);
|
||||
case VK_FORMAT_B8G8R8_SINT: return createDFDUnpacked(0, 3, 1, 1, s_SINT);
|
||||
case VK_FORMAT_B8G8R8_SRGB: return createDFDUnpacked(0, 3, 1, 1, s_SRGB);
|
||||
case VK_FORMAT_R8G8B8A8_UNORM: return createDFDUnpacked(0, 4, 1, 0, s_UNORM);
|
||||
case VK_FORMAT_R8G8B8A8_SNORM: return createDFDUnpacked(0, 4, 1, 0, s_SNORM);
|
||||
case VK_FORMAT_R8G8B8A8_USCALED: return createDFDUnpacked(0, 4, 1, 0, s_USCALED);
|
||||
case VK_FORMAT_R8G8B8A8_SSCALED: return createDFDUnpacked(0, 4, 1, 0, s_SSCALED);
|
||||
case VK_FORMAT_R8G8B8A8_UINT: return createDFDUnpacked(0, 4, 1, 0, s_UINT);
|
||||
case VK_FORMAT_R8G8B8A8_SINT: return createDFDUnpacked(0, 4, 1, 0, s_SINT);
|
||||
case VK_FORMAT_R8G8B8A8_SRGB: return createDFDUnpacked(0, 4, 1, 0, s_SRGB);
|
||||
case VK_FORMAT_B8G8R8A8_UNORM: return createDFDUnpacked(0, 4, 1, 1, s_UNORM);
|
||||
case VK_FORMAT_B8G8R8A8_SNORM: return createDFDUnpacked(0, 4, 1, 1, s_SNORM);
|
||||
case VK_FORMAT_B8G8R8A8_USCALED: return createDFDUnpacked(0, 4, 1, 1, s_USCALED);
|
||||
case VK_FORMAT_B8G8R8A8_SSCALED: return createDFDUnpacked(0, 4, 1, 1, s_SSCALED);
|
||||
case VK_FORMAT_B8G8R8A8_UINT: return createDFDUnpacked(0, 4, 1, 1, s_UINT);
|
||||
case VK_FORMAT_B8G8R8A8_SINT: return createDFDUnpacked(0, 4, 1, 1, s_SINT);
|
||||
case VK_FORMAT_B8G8R8A8_SRGB: return createDFDUnpacked(0, 4, 1, 1, s_SRGB);
|
||||
case VK_FORMAT_A8B8G8R8_UNORM_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_A8B8G8R8_SNORM_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SNORM);
|
||||
}
|
||||
case VK_FORMAT_A8B8G8R8_USCALED_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_USCALED);
|
||||
}
|
||||
case VK_FORMAT_A8B8G8R8_SSCALED_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SSCALED);
|
||||
}
|
||||
case VK_FORMAT_A8B8G8R8_UINT_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UINT);
|
||||
}
|
||||
case VK_FORMAT_A8B8G8R8_SINT_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SINT);
|
||||
}
|
||||
case VK_FORMAT_A8B8G8R8_SRGB_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {8,8,8,8};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SRGB);
|
||||
}
|
||||
case VK_FORMAT_A2R10G10B10_UNORM_PACK32: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_A2R10G10B10_SNORM_PACK32: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SNORM);
|
||||
}
|
||||
case VK_FORMAT_A2R10G10B10_USCALED_PACK32: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_USCALED);
|
||||
}
|
||||
case VK_FORMAT_A2R10G10B10_SSCALED_PACK32: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SSCALED);
|
||||
}
|
||||
case VK_FORMAT_A2R10G10B10_UINT_PACK32: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UINT);
|
||||
}
|
||||
case VK_FORMAT_A2R10G10B10_SINT_PACK32: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SINT);
|
||||
}
|
||||
case VK_FORMAT_A2B10G10R10_UNORM_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_A2B10G10R10_SNORM_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SNORM);
|
||||
}
|
||||
case VK_FORMAT_A2B10G10R10_USCALED_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_USCALED);
|
||||
}
|
||||
case VK_FORMAT_A2B10G10R10_SSCALED_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SSCALED);
|
||||
}
|
||||
case VK_FORMAT_A2B10G10R10_UINT_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UINT);
|
||||
}
|
||||
case VK_FORMAT_A2B10G10R10_SINT_PACK32: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {10,10,10,2};
|
||||
return createDFDPacked(0, 4, bits, channels, s_SINT);
|
||||
}
|
||||
case VK_FORMAT_R16_UNORM: return createDFDUnpacked(0, 1, 2, 0, s_UNORM);
|
||||
case VK_FORMAT_R16_SNORM: return createDFDUnpacked(0, 1, 2, 0, s_SNORM);
|
||||
case VK_FORMAT_R16_USCALED: return createDFDUnpacked(0, 1, 2, 0, s_USCALED);
|
||||
case VK_FORMAT_R16_SSCALED: return createDFDUnpacked(0, 1, 2, 0, s_SSCALED);
|
||||
case VK_FORMAT_R16_UINT: return createDFDUnpacked(0, 1, 2, 0, s_UINT);
|
||||
case VK_FORMAT_R16_SINT: return createDFDUnpacked(0, 1, 2, 0, s_SINT);
|
||||
case VK_FORMAT_R16_SFLOAT: return createDFDUnpacked(0, 1, 2, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R16G16_UNORM: return createDFDUnpacked(0, 2, 2, 0, s_UNORM);
|
||||
case VK_FORMAT_R16G16_SNORM: return createDFDUnpacked(0, 2, 2, 0, s_SNORM);
|
||||
case VK_FORMAT_R16G16_USCALED: return createDFDUnpacked(0, 2, 2, 0, s_USCALED);
|
||||
case VK_FORMAT_R16G16_SSCALED: return createDFDUnpacked(0, 2, 2, 0, s_SSCALED);
|
||||
case VK_FORMAT_R16G16_UINT: return createDFDUnpacked(0, 2, 2, 0, s_UINT);
|
||||
case VK_FORMAT_R16G16_SINT: return createDFDUnpacked(0, 2, 2, 0, s_SINT);
|
||||
case VK_FORMAT_R16G16_SFLOAT: return createDFDUnpacked(0, 2, 2, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R16G16B16_UNORM: return createDFDUnpacked(0, 3, 2, 0, s_UNORM);
|
||||
case VK_FORMAT_R16G16B16_SNORM: return createDFDUnpacked(0, 3, 2, 0, s_SNORM);
|
||||
case VK_FORMAT_R16G16B16_USCALED: return createDFDUnpacked(0, 3, 2, 0, s_USCALED);
|
||||
case VK_FORMAT_R16G16B16_SSCALED: return createDFDUnpacked(0, 3, 2, 0, s_SSCALED);
|
||||
case VK_FORMAT_R16G16B16_UINT: return createDFDUnpacked(0, 3, 2, 0, s_UINT);
|
||||
case VK_FORMAT_R16G16B16_SINT: return createDFDUnpacked(0, 3, 2, 0, s_SINT);
|
||||
case VK_FORMAT_R16G16B16_SFLOAT: return createDFDUnpacked(0, 3, 2, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R16G16B16A16_UNORM: return createDFDUnpacked(0, 4, 2, 0, s_UNORM);
|
||||
case VK_FORMAT_R16G16B16A16_SNORM: return createDFDUnpacked(0, 4, 2, 0, s_SNORM);
|
||||
case VK_FORMAT_R16G16B16A16_USCALED: return createDFDUnpacked(0, 4, 2, 0, s_USCALED);
|
||||
case VK_FORMAT_R16G16B16A16_SSCALED: return createDFDUnpacked(0, 4, 2, 0, s_SSCALED);
|
||||
case VK_FORMAT_R16G16B16A16_UINT: return createDFDUnpacked(0, 4, 2, 0, s_UINT);
|
||||
case VK_FORMAT_R16G16B16A16_SINT: return createDFDUnpacked(0, 4, 2, 0, s_SINT);
|
||||
case VK_FORMAT_R16G16B16A16_SFLOAT: return createDFDUnpacked(0, 4, 2, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R32_UINT: return createDFDUnpacked(0, 1, 4, 0, s_UINT);
|
||||
case VK_FORMAT_R32_SINT: return createDFDUnpacked(0, 1, 4, 0, s_SINT);
|
||||
case VK_FORMAT_R32_SFLOAT: return createDFDUnpacked(0, 1, 4, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R32G32_UINT: return createDFDUnpacked(0, 2, 4, 0, s_UINT);
|
||||
case VK_FORMAT_R32G32_SINT: return createDFDUnpacked(0, 2, 4, 0, s_SINT);
|
||||
case VK_FORMAT_R32G32_SFLOAT: return createDFDUnpacked(0, 2, 4, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R32G32B32_UINT: return createDFDUnpacked(0, 3, 4, 0, s_UINT);
|
||||
case VK_FORMAT_R32G32B32_SINT: return createDFDUnpacked(0, 3, 4, 0, s_SINT);
|
||||
case VK_FORMAT_R32G32B32_SFLOAT: return createDFDUnpacked(0, 3, 4, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R32G32B32A32_UINT: return createDFDUnpacked(0, 4, 4, 0, s_UINT);
|
||||
case VK_FORMAT_R32G32B32A32_SINT: return createDFDUnpacked(0, 4, 4, 0, s_SINT);
|
||||
case VK_FORMAT_R32G32B32A32_SFLOAT: return createDFDUnpacked(0, 4, 4, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R64_UINT: return createDFDUnpacked(0, 1, 8, 0, s_UINT);
|
||||
case VK_FORMAT_R64_SINT: return createDFDUnpacked(0, 1, 8, 0, s_SINT);
|
||||
case VK_FORMAT_R64_SFLOAT: return createDFDUnpacked(0, 1, 8, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R64G64_UINT: return createDFDUnpacked(0, 2, 8, 0, s_UINT);
|
||||
case VK_FORMAT_R64G64_SINT: return createDFDUnpacked(0, 2, 8, 0, s_SINT);
|
||||
case VK_FORMAT_R64G64_SFLOAT: return createDFDUnpacked(0, 2, 8, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R64G64B64_UINT: return createDFDUnpacked(0, 3, 8, 0, s_UINT);
|
||||
case VK_FORMAT_R64G64B64_SINT: return createDFDUnpacked(0, 3, 8, 0, s_SINT);
|
||||
case VK_FORMAT_R64G64B64_SFLOAT: return createDFDUnpacked(0, 3, 8, 0, s_SFLOAT);
|
||||
case VK_FORMAT_R64G64B64A64_UINT: return createDFDUnpacked(0, 4, 8, 0, s_UINT);
|
||||
case VK_FORMAT_R64G64B64A64_SINT: return createDFDUnpacked(0, 4, 8, 0, s_SINT);
|
||||
case VK_FORMAT_R64G64B64A64_SFLOAT: return createDFDUnpacked(0, 4, 8, 0, s_SFLOAT);
|
||||
case VK_FORMAT_B10G11R11_UFLOAT_PACK32: {
|
||||
int channels[] = {0,1,2}; int bits[] = {11,11,10};
|
||||
return createDFDPacked(0, 3, bits, channels, s_UFLOAT);
|
||||
}
|
||||
case VK_FORMAT_E5B9G9R9_UFLOAT_PACK32: {
|
||||
int bits[] = {0}; int channels[] = {0};
|
||||
return createDFDPacked(0, 6, bits, channels, s_UFLOAT);
|
||||
}
|
||||
case VK_FORMAT_D16_UNORM: return createDFDDepthStencil(16,0,2);
|
||||
case VK_FORMAT_X8_D24_UNORM_PACK32: return createDFDDepthStencil(24,0,4);
|
||||
case VK_FORMAT_D32_SFLOAT: return createDFDDepthStencil(32,0,4);
|
||||
case VK_FORMAT_S8_UINT: return createDFDDepthStencil(0,8,1);
|
||||
case VK_FORMAT_BC1_RGB_UNORM_BLOCK: return createDFDCompressed(c_BC1_RGB, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC1_RGB_SRGB_BLOCK: return createDFDCompressed(c_BC1_RGB, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_BC1_RGBA_UNORM_BLOCK: return createDFDCompressed(c_BC1_RGBA, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC1_RGBA_SRGB_BLOCK: return createDFDCompressed(c_BC1_RGBA, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_BC2_UNORM_BLOCK: return createDFDCompressed(c_BC2, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC2_SRGB_BLOCK: return createDFDCompressed(c_BC2, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_BC3_UNORM_BLOCK: return createDFDCompressed(c_BC3, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC3_SRGB_BLOCK: return createDFDCompressed(c_BC3, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_BC4_UNORM_BLOCK: return createDFDCompressed(c_BC4, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC4_SNORM_BLOCK: return createDFDCompressed(c_BC4, 4, 4, 1, s_SNORM);
|
||||
case VK_FORMAT_BC5_UNORM_BLOCK: return createDFDCompressed(c_BC5, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC5_SNORM_BLOCK: return createDFDCompressed(c_BC5, 4, 4, 1, s_SNORM);
|
||||
case VK_FORMAT_BC6H_UFLOAT_BLOCK: return createDFDCompressed(c_BC6H, 4, 4, 1, s_UFLOAT);
|
||||
case VK_FORMAT_BC6H_SFLOAT_BLOCK: return createDFDCompressed(c_BC6H, 4, 4, 1, s_SFLOAT);
|
||||
case VK_FORMAT_BC7_UNORM_BLOCK: return createDFDCompressed(c_BC7, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_BC7_SRGB_BLOCK: return createDFDCompressed(c_BC7, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A1, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A1, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A8, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK: return createDFDCompressed(c_ETC2_R8G8B8A8, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_EAC_R11_UNORM_BLOCK: return createDFDCompressed(c_EAC_R11, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_EAC_R11_SNORM_BLOCK: return createDFDCompressed(c_EAC_R11, 4, 4, 1, s_SNORM);
|
||||
case VK_FORMAT_EAC_R11G11_UNORM_BLOCK: return createDFDCompressed(c_EAC_R11G11, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_EAC_R11G11_SNORM_BLOCK: return createDFDCompressed(c_EAC_R11G11, 4, 4, 1, s_SNORM);
|
||||
case VK_FORMAT_ASTC_4x4_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_4x4_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_5x4_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 5, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_5x4_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 5, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_5x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 5, 5, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_5x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 5, 5, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_6x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 6, 5, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_6x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 6, 5, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_6x6_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 6, 6, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_6x6_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 6, 6, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_8x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 8, 5, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_8x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 8, 5, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_8x6_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 8, 6, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_8x6_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 8, 6, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_8x8_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 8, 8, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_8x8_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 8, 8, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_10x5_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 5, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_10x5_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 5, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_10x6_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 6, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_10x6_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 6, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_10x8_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 8, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_10x8_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 8, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_10x10_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 10, 10, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_10x10_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 10, 10, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_12x10_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 10, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_12x10_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 10, 1, s_SRGB);
|
||||
case VK_FORMAT_ASTC_12x12_UNORM_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_UNORM);
|
||||
case VK_FORMAT_ASTC_12x12_SRGB_BLOCK: return createDFDCompressed(c_ASTC, 12, 12, 1, s_SRGB);
|
||||
case VK_FORMAT_PVRTC1_2BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 8, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_PVRTC1_4BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_PVRTC2_2BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 8, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_PVRTC2_4BPP_UNORM_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 4, 4, 1, s_UNORM);
|
||||
case VK_FORMAT_PVRTC1_2BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 8, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_PVRTC1_4BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_PVRTC2_2BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 8, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_PVRTC2_4BPP_SRGB_BLOCK_IMG: return createDFDCompressed(c_PVRTC2, 4, 4, 1, s_SRGB);
|
||||
case VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT: {
|
||||
int channels[] = {2,1,0,3}; int bits[] = {4,4,4,4};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
||||
case VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT: {
|
||||
int channels[] = {0,1,2,3}; int bits[] = {4,4,4,4};
|
||||
return createDFDPacked(0, 4, bits, channels, s_UNORM);
|
||||
}
|
0
build/.keep
Normal file
0
build/.keep
Normal file
3
meson.build
Normal file
3
meson.build
Normal file
|
@ -0,0 +1,3 @@
|
|||
project('TextureTaffy', 'cpp')
|
||||
|
||||
subdir('Source')
|
Loading…
Reference in a new issue