16 #if defined(_MSC_VER) && (_MSC_VER > 1000)
21 #include <directxmath.h>
22 #include <directxpackedvector.h>
35 #define SIGN_EXTEND(x,nb) ((((x)&(1<<((nb)-1)))?((~0)<<(nb)):0)|(x))
38 #define NUM_PIXELS_PER_BLOCK 16
39 #define BC6H_MAX_REGIONS 2
40 #define BC6H_MAX_INDICES 16
41 #define BC7_MAX_REGIONS 3
42 #define BC7_MAX_INDICES 16
87 default:
assert(
false);
return r;
99 default:
assert(
false);
return r;
107 const int* aWeights =
nullptr;
110 case 2: aWeights =
g_aWeights2;
assert( wc < 4 ); _Analysis_assume_( wc < 4 );
break;
111 case 3: aWeights =
g_aWeights3;
assert( wc < 8 ); _Analysis_assume_( wc < 8 );
break;
112 case 4: aWeights =
g_aWeights4;
assert( wc < 16 ); _Analysis_assume_( wc < 16 );
break;
113 default:
assert(
false); out.r = out.g = out.b = 0;
return;
122 const int* aWeights =
nullptr;
125 case 2: aWeights =
g_aWeights2;
assert( wa < 4 ); _Analysis_assume_( wa < 4 );
break;
126 case 3: aWeights =
g_aWeights3;
assert( wa < 8 ); _Analysis_assume_( wa < 8 );
break;
127 case 4: aWeights =
g_aWeights4;
assert( wa < 16 ); _Analysis_assume_( wa < 16 );
break;
128 default:
assert(
false); out.a = 0;
return;
133 static void Interpolate(_In_
const LDRColorA& c0, _In_
const LDRColorA& c1, _In_
size_t wc, _In_
size_t wa, _In_ _In_range_(2, 4)
size_t wcprec, _In_ _In_range_(2, 4)
size_t waprec, _Out_
LDRColorA& out)
140 static_assert(
sizeof(LDRColorA) == 4,
"Unexpected packing");
149 HDRColorA(
float _r,
float _g,
float _b,
float _a) :
r(_r),
g(_g),
b(_b),
a(_a) {}
153 r = float(c.
r) * (1.0f/255.0f);
154 g = float(c.
g) * (1.0f/255.0f);
155 b = float(c.
b) * (1.0f/255.0f);
156 a = float(c.
a) * (1.0f/255.0f);
177 float fInv = 1.0f / f;
183 return r * c.r +
g * c.g +
b * c.b +
a * c.a;
216 float fInv = 1.0f / f;
235 r = std::min<float>(fMax, std::max<float>(fMin,
r));
236 g = std::min<float>(fMax, std::max<float>(fMin,
g));
237 b = std::min<float>(fMax, std::max<float>(fMin,
b));
238 a = std::min<float>(fMax, std::max<float>(fMin,
a));
252 tmp = tmp.
Clamp(0.0f, 1.0f) * 255.0f;
274 pOut->
r = pC1->r + s * (pC2->r - pC1->r);
275 pOut->g = pC1->g + s * (pC2->g - pC1->g);
276 pOut->b = pC1->b + s * (pC2->b - pC1->b);
277 pOut->a = pC1->a + s * (pC2->a - pC1->a);
348 _Analysis_assume_(i <
sizeof(
INTColor) /
sizeof(
int));
349 return ((
int*)
this)[i];
354 PackedVector::XMHALF4 aF16;
356 XMVECTOR v = XMLoadFloat4( (
const XMFLOAT4*)& c );
357 XMStoreHalf4( &aF16, v );
359 r = F16ToINT(aF16.x, bSigned);
360 g = F16ToINT(aF16.y, bSigned);
361 b = F16ToINT(aF16.z, bSigned);
366 r = std::min<int>(iMax, std::max<int>(iMin,
r));
367 g = std::min<int>(iMax, std::max<int>(iMin,
g));
368 b = std::min<int>(iMax, std::max<int>(iMin,
b));
382 aF16[0] = INT2F16(
r, bSigned);
383 aF16[1] = INT2F16(
g, bSigned);
384 aF16[2] = INT2F16(
b, bSigned);
388 static int F16ToINT(_In_
const PackedVector::HALF& f, _In_
bool bSigned)
390 uint16_t input = *((
const uint16_t*) &f);
398 out = s ? -out : out;
402 if(input & F16S_MASK) out = 0;
408 static PackedVector::HALF INT2F16(_In_
int input, _In_
bool bSigned)
410 PackedVector::HALF h;
420 out = uint16_t(s | input);
425 out = (uint16_t) input;
428 *((uint16_t*) &h) = out;
433 static_assert(
sizeof(INTColor) == 16,
"Unexpected packing");
441 template<
size_t SizeInBytes >
448 _Analysis_assume_(uStartBit < 128);
449 size_t uIndex = uStartBit >> 3;
450 uint8_t ret = (m_uBits[uIndex] >> (uStartBit - (uIndex << 3))) & 0x01;
457 if(uNumBits == 0)
return 0;
458 assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
459 _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
461 size_t uIndex = uStartBit >> 3;
462 size_t uBase = uStartBit - (uIndex << 3);
463 if(uBase + uNumBits > 8)
465 size_t uFirstIndexBits = 8 - uBase;
466 size_t uNextIndexBits = uNumBits - uFirstIndexBits;
467 ret = (m_uBits[uIndex] >> uBase) | ((m_uBits[uIndex+1] & ((1 << uNextIndexBits) - 1)) << uFirstIndexBits);
471 ret = (m_uBits[uIndex] >> uBase) & ((1 << uNumBits) - 1);
473 assert(ret < (1 << uNumBits));
474 uStartBit += uNumBits;
480 assert(uStartBit < 128 && uValue < 2);
481 _Analysis_assume_(uStartBit < 128 && uValue < 2);
482 size_t uIndex = uStartBit >> 3;
483 size_t uBase = uStartBit - (uIndex << 3);
484 m_uBits[uIndex] &= ~(1 << uBase);
485 m_uBits[uIndex] |= uValue << uBase;
489 void SetBits(_Inout_
size_t& uStartBit, _In_
size_t uNumBits, _In_
uint8_t uValue)
493 assert(uStartBit + uNumBits <= 128 && uNumBits <= 8);
494 _Analysis_assume_(uStartBit + uNumBits <= 128 && uNumBits <= 8);
495 assert(uValue < (1 << uNumBits));
496 size_t uIndex = uStartBit >> 3;
497 size_t uBase = uStartBit - (uIndex << 3);
498 if(uBase + uNumBits > 8)
500 size_t uFirstIndexBits = 8 - uBase;
501 size_t uNextIndexBits = uNumBits - uFirstIndexBits;
502 m_uBits[uIndex] &= ~(((1 << uFirstIndexBits) - 1) << uBase);
503 m_uBits[uIndex] |= uValue << uBase;
504 m_uBits[uIndex+1] &= ~((1 << uNextIndexBits) - 1);
505 m_uBits[uIndex+1] |= uValue >> uFirstIndexBits;
509 m_uBits[uIndex] &= ~(((1 << uNumBits) - 1) << uBase);
510 m_uBits[uIndex] |= uValue << uBase;
512 uStartBit += uNumBits;
516 uint8_t m_uBits[ SizeInBytes ];
527 #pragma warning(push)
528 #pragma warning(disable : 4480)
549 struct ModeDescriptor
564 #pragma warning(push)
565 #pragma warning(disable : 4512)
576 EncodeParams(
const HDRColorA*
const aOriginal,
bool bSignedFormat) :
577 aHDRPixels(aOriginal), fBestErr(FLT_MAX), bSigned(bSignedFormat)
581 aIPixels[i].Set(aOriginal[i], bSigned);
587 static int Quantize(_In_
int iValue, _In_
int prec, _In_
bool bSigned);
588 static int Unquantize(_In_
int comp, _In_
uint8_t uBitsPerComp, _In_
bool bSigned);
589 static int FinishUnquantize(_In_
int comp, _In_
bool bSigned);
593 void GeneratePaletteQuantized(_In_
const EncodeParams* pEP, _In_
const INTEndPntPair& endPts,
595 float MapColorsQuantized(_In_
const EncodeParams* pEP,
_In_reads_(np)
const INTColor aColors[], _In_
size_t np, _In_
const INTEndPntPair &endPts)
const;
598 void OptimizeOne(_In_
const EncodeParams* pEP,
_In_reads_(np)
const INTColor aColors[], _In_
size_t np, _In_
float aOrgErr,
611 void Refine(_Inout_ EncodeParams* pEP);
614 float MapColors(_In_
const EncodeParams* pEP, _In_
size_t uRegion, _In_
size_t np,
_In_reads_(np)
const size_t* auIndex)
const;
615 float RoughMSE(_Inout_ EncodeParams* pEP)
const;
618 const static ModeDescriptor ms_aDesc[][82];
619 const static ModeInfo ms_aInfo[];
620 const static int ms_aModeToInfo[];
644 #pragma warning(push)
645 #pragma warning(disable : 4512)
653 EncodeParams(
const HDRColorA*
const aOriginal) : aHDRPixels(aOriginal) {}
659 assert(0 < uPrec && uPrec <= 8);
660 uint8_t rnd = (
uint8_t) std::min<uint16_t>(255, uint16_t(comp) + (1 << (7 - uPrec)));
661 return rnd >> (8 - uPrec);
667 q.
r = Quantize(c.r, RGBAPrec.r);
668 q.
g = Quantize(c.g, RGBAPrec.g);
669 q.
b = Quantize(c.b, RGBAPrec.b);
671 q.
a = Quantize(c.a, RGBAPrec.a);
679 assert(0 < uPrec && uPrec <= 8);
680 comp = comp << (8 - uPrec);
681 return comp | (comp >> uPrec);
687 q.
r = Unquantize(c.r, RGBAPrec.r);
688 q.
g = Unquantize(c.g, RGBAPrec.g);
689 q.
b = Unquantize(c.b, RGBAPrec.b);
690 q.
a = RGBAPrec.a > 0 ? Unquantize(c.a, RGBAPrec.a) : 255;
694 void GeneratePaletteQuantized(_In_
const EncodeParams* pEP, _In_
size_t uIndexMode, _In_
const LDREndPntPair& endpts,
696 float PerturbOne(_In_
const EncodeParams* pEP,
_In_reads_(np)
const LDRColorA colors[], _In_
size_t np, _In_
size_t uIndexMode,
699 void Exhaustive(_In_
const EncodeParams* pEP,
_In_reads_(np)
const LDRColorA aColors[], _In_
size_t np, _In_
size_t uIndexMode,
700 _In_
size_t ch, _Inout_
float& fOrgErr, _Inout_
LDREndPntPair& optEndPt)
const;
701 void OptimizeOne(_In_
const EncodeParams* pEP,
_In_reads_(np)
const LDRColorA colors[], _In_
size_t np, _In_
size_t uIndexMode,
703 void OptimizeEndPoints(_In_
const EncodeParams* pEP, _In_
size_t uShape, _In_
size_t uIndexMode,
707 void AssignIndices(_In_
const EncodeParams* pEP, _In_
size_t uShape, _In_
size_t uIndexMode,
711 void EmitBlock(_In_
const EncodeParams* pEP, _In_
size_t uShape, _In_
size_t uRotation, _In_
size_t uIndexMode,
715 float Refine(_In_
const EncodeParams* pEP, _In_
size_t uShape, _In_
size_t uRotation, _In_
size_t uIndexMode);
717 float MapColors(_In_
const EncodeParams* pEP,
_In_reads_(np)
const LDRColorA aColors[], _In_
size_t np, _In_
size_t uIndexMode,
719 static float RoughMSE(_Inout_ EncodeParams* pEP, _In_
size_t uShape, _In_
size_t uIndexMode);
722 const static ModeInfo ms_aInfo[];
726 #pragma warning(push)
727 #pragma warning(disable : 4127)
728 template <
bool bRange>
void OptimizeAlpha(
float *pX,
float *pY,
const float *pPoints,
size_t cSteps)
730 static const float pC6[] = { 5.0f/5.0f, 4.0f/5.0f, 3.0f/5.0f, 2.0f/5.0f, 1.0f/5.0f, 0.0f/5.0f };
731 static const float pD6[] = { 0.0f/5.0f, 1.0f/5.0f, 2.0f/5.0f, 3.0f/5.0f, 4.0f/5.0f, 5.0f/5.0f };
732 static const float pC8[] = { 7.0f/7.0f, 6.0f/7.0f, 5.0f/7.0f, 4.0f/7.0f, 3.0f/7.0f, 2.0f/7.0f, 1.0f/7.0f, 0.0f/7.0f };
733 static const float pD8[] = { 0.0f/7.0f, 1.0f/7.0f, 2.0f/7.0f, 3.0f/7.0f, 4.0f/7.0f, 5.0f/7.0f, 6.0f/7.0f, 7.0f/7.0f };
735 const float *pC = (6 == cSteps) ? pC6 : pC8;
736 const float *pD = (6 == cSteps) ? pD6 : pD8;
738 float MAX_VALUE = 1.0f;
750 float fX = MAX_VALUE;
751 float fY = MIN_VALUE;
757 if(pPoints[iPoint] < fX)
758 fX = pPoints[iPoint];
760 if(pPoints[iPoint] > fY)
761 fY = pPoints[iPoint];
768 if(pPoints[iPoint] < fX && pPoints[iPoint] > MIN_VALUE)
769 fX = pPoints[iPoint];
771 if(pPoints[iPoint] > fY && pPoints[iPoint] < MAX_VALUE)
772 fY = pPoints[iPoint];
782 float fSteps = (float) (cSteps - 1);
784 for(
size_t iIteration = 0; iIteration < 8; iIteration++)
788 if((fY - fX) < (1.0f / 256.0f))
791 fScale = fSteps / (fY - fX);
796 for(
size_t iStep = 0; iStep < cSteps; iStep++)
797 pSteps[iStep] = pC[iStep] * fX + pD[iStep] * fY;
801 pSteps[6] = MIN_VALUE;
802 pSteps[7] = MAX_VALUE;
813 float fDot = (pPoints[iPoint] - fX) * fScale;
818 iStep = ((6 == cSteps) && (pPoints[iPoint] <= fX * 0.5f)) ? 6 : 0;
819 else if(fDot >= fSteps)
820 iStep = ((6 == cSteps) && (pPoints[iPoint] >= (fY + 1.0f) * 0.5f)) ? 7 : (cSteps - 1);
822 iStep =
static_cast<int32_t
>(fDot + 0.5f);
829 float fDiff = pSteps[iStep] - pPoints[iPoint];
831 dX += pC[iStep] * fDiff;
832 d2X += pC[iStep] * pC[iStep];
834 dY += pD[iStep] * fDiff;
835 d2Y += pD[iStep] * pD[iStep];
848 float f = fX; fX = fY; fY = f;
851 if((dX * dX < (1.0f / 64.0f)) && (dY * dY < (1.0f / 64.0f)))
855 *pX = (fX < MIN_VALUE) ? MIN_VALUE : (fX > MAX_VALUE) ? MAX_VALUE : fX;
856 *pY = (fY < MIN_VALUE) ? MIN_VALUE : (fY > MAX_VALUE) ? MAX_VALUE : fY;
_Use_decl_annotations_ void D3DXEncodeBC3(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
INTColor & operator-=(_In_ const INTColor &c)
HDRColorA operator+(_In_ const HDRColorA &c) const
const size_t BC7_NUM_CHANNELS
LDRColorA(uint8_t _r, uint8_t _g, uint8_t _b, uint8_t _a)
void D3DXEncodeBC5U(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
const uint8_t & operator[](_In_range_(0, 3) size_t uElement) const
void D3DXDecodeBC6HS(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
INTColor & Clamp(_In_ int iMin, _In_ int iMax)
#define NUM_PIXELS_PER_BLOCK
void(* BC_DECODE)(XMVECTOR *pColor, const uint8_t *pBC)
INTColor operator-(_In_ const INTColor &c) const
INTColor & operator&=(_In_ const INTColor &c)
_In_ size_t _In_ DXGI_FORMAT _In_ size_t _In_ DXGI_FORMAT _In_ DWORD flags
INTColor & SignExtend(_In_ const LDRColorA &Prec)
_Use_decl_annotations_ void D3DXDecodeBC3(XMVECTOR *pColor, const uint8_t *pBC)
size_t _In_ DXGI_FORMAT size_t _In_ TEXP_LEGACY_FORMAT _In_ DWORD flags assert(pDestination &&outSize > 0)
void D3DXEncodeBC4U(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
HDRColorA & operator/=(_In_ float f)
const size_t BC6H_MAX_SHAPES
const int32_t BC67_WEIGHT_MAX
HDRColorA(const HDRColorA &c)
void D3DXEncodeBC4S(_Out_writes_(8) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC4S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC)
void ToF16(_Out_writes_(3) PackedVector::HALF aF16[3], _In_ bool bSigned) const
HDRColorA & operator*=(_In_ float f)
void D3DXEncodeBC6HU(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC4U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(8) const uint8_t *pBC)
uint8_t GetBits(_Inout_ size_t &uStartBit, _In_ size_t uNumBits) const
void D3DXDecodeBC6HU(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
static void InterpolateRGB(_In_ const LDRColorA &c0, _In_ const LDRColorA &c1, _In_ size_t wc, _In_ _In_range_(2, 4) size_t wcprec, _Out_ LDRColorA &out)
INTColor(int nr, int ng, int nb)
static void Interpolate(_In_ const LDRColorA &c0, _In_ const LDRColorA &c1, _In_ size_t wc, _In_ size_t wa, _In_ _In_range_(2, 4) size_t wcprec, _In_ _In_range_(2, 4) size_t waprec, _Out_ LDRColorA &out)
HDRColorA(float _r, float _g, float _b, float _a)
void Decode(_In_ bool bSigned, _Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA *pOut) const
#define SIGN_EXTEND(x, nb)
const size_t BC6H_NUM_CHANNELS
const int32_t BC67_WEIGHT_ROUND
static void InterpolateA(_In_ const LDRColorA &c0, _In_ const LDRColorA &c1, _In_ size_t wa, _In_range_(2, 4) _In_ size_t waprec, _Out_ LDRColorA &out)
void D3DXDecodeBC7(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
void D3DXEncodeBC6HS(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
void D3DXDecodeBC5U(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
_In_ size_t _In_ DXGI_FORMAT _Inout_updates_all_(count) XMVECTOR *pSource
HDRColorA * HDRColorALerp(_Out_ HDRColorA *pOut, _In_ const HDRColorA *pC1, _In_ const HDRColorA *pC2, _In_ float s)
HDRColorA & operator+=(_In_ const HDRColorA &c)
_In_ size_t _In_ const TexMetadata _In_ DWORD _Out_writes_(nImages) Image *images
HDRColorA(const LDRColorA &c)
void Encode(_In_ bool bSigned, _In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *const pIn)
INTColor(const INTColor &c)
HDRColorA & operator=(_In_ const LDRColorA &c)
const size_t BC7_MAX_SHAPES
int & operator[](_In_ uint8_t i)
_Use_decl_annotations_ void D3DXEncodeBC1(uint8_t *pBC, const XMVECTOR *pColor, float alphaRef, DWORD flags)
void Set(_In_ const HDRColorA &c, _In_ bool bSigned)
_In_ size_t _In_ DXGI_FORMAT _In_reads_(count) const XMVECTOR *pSource
INTColor & operator+=(_In_ const INTColor &c)
LDRColorA ToLDRColorA() const
HDRColorA operator-(_In_ const HDRColorA &c) const
void Encode(_In_reads_(NUM_PIXELS_PER_BLOCK) const HDRColorA *const pIn)
void SetBit(_Inout_ size_t &uStartBit, _In_ uint8_t uValue)
const uint16_t F16EM_MASK
void OptimizeAlpha(float *pX, float *pY, const float *pPoints, size_t cSteps)
HDRColorA & Clamp(_In_ float fMin, _In_ float fMax)
uint8_t GetBit(_Inout_ size_t &uStartBit) const
void SetBits(_Inout_ size_t &uStartBit, _In_ size_t uNumBits, _In_ uint8_t uValue)
HDRColorA operator*(_In_ float f) const
void D3DXDecodeBC5S(_Out_writes_(NUM_PIXELS_PER_BLOCK) XMVECTOR *pColor, _In_reads_(16) const uint8_t *pBC)
LDRColorA operator=(_In_ const HDRColorA &c)
HDRColorA & operator-=(_In_ const HDRColorA &c)
const uint32_t BC67_WEIGHT_SHIFT
void(* BC_ENCODE)(uint8_t *pDXT, const XMVECTOR *pColor, DWORD flags)
_Use_decl_annotations_ void D3DXEncodeBC2(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
void D3DXEncodeBC5S(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
HDRColorA operator/(_In_ float f) const
const int g_aWeights4[16]
_Use_decl_annotations_ void D3DXDecodeBC1(XMVECTOR *pColor, const uint8_t *pBC)
void Decode(_Out_writes_(NUM_PIXELS_PER_BLOCK) HDRColorA *pOut) const
void D3DXEncodeBC7(_Out_writes_(16) uint8_t *pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const XMVECTOR *pColor, _In_ DWORD flags)
_Use_decl_annotations_ void D3DXDecodeBC2(XMVECTOR *pColor, const uint8_t *pBC)