This commit is contained in:
Chuck Walbourn 2016-09-08 19:09:46 -07:00
Родитель 53e66ba1e9
Коммит 51bc3d5b16
28 изменённых файлов: 13052 добавлений и 12638 удалений

Просмотреть файл

@ -165,21 +165,11 @@ namespace
}
// open the file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName,
GENERIC_READ,
FILE_SHARE_READ,
OPEN_EXISTING,
nullptr ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName,
GENERIC_READ,
FILE_SHARE_READ,
nullptr,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
nullptr ) ) );
#endif
if ( !hFile )
{

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -17,8 +17,7 @@
#include "BC.h"
namespace DirectX
{
using namespace DirectX;
//------------------------------------------------------------------------------------
// Constants
@ -26,338 +25,361 @@ namespace DirectX
// Because these are used in SAL annotations, they need to remain macros rather than const values
#define BLOCK_LEN 4
// length of each block in texel
// length of each block in texel
#define BLOCK_SIZE (BLOCK_LEN * BLOCK_LEN)
// total texels in a 4x4 block.
// total texels in a 4x4 block.
//------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
namespace
{
//------------------------------------------------------------------------------------
// Structures
//-------------------------------------------------------------------------------------
#pragma warning(push)
#pragma warning(disable : 4201)
// BC4U/BC5U
struct BC4_UNORM
{
float R(size_t uOffset) const
// BC4U/BC5U
struct BC4_UNORM
{
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
}
float DecodeFromIndex(size_t uIndex) const
{
if (uIndex == 0)
return red_0 / 255.0f;
if (uIndex == 1)
return red_1 / 255.0f;
float fred_0 = red_0 / 255.0f;
float fred_1 = red_1 / 255.0f;
if (red_0 > red_1)
float R(size_t uOffset) const
{
uIndex -= 1;
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
}
else
float DecodeFromIndex(size_t uIndex) const
{
if (uIndex == 6)
return 0.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
if (uIndex == 0)
return red_0 / 255.0f;
if (uIndex == 1)
return red_1 / 255.0f;
float fred_0 = red_0 / 255.0f;
float fred_1 = red_1 / 255.0f;
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
if (uIndex == 6)
return 0.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
}
}
}
size_t GetIndex(size_t uOffset) const
{
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
data |= ((uint64_t) uIndex << (3*uOffset + 16));
}
union
{
struct
size_t GetIndex(size_t uOffset) const
{
uint8_t red_0;
uint8_t red_1;
uint8_t indices[6];
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
}
union
{
struct
{
uint8_t red_0;
uint8_t red_1;
uint8_t indices[6];
};
uint64_t data;
};
uint64_t data;
};
};
// BC4S/BC5S
struct BC4_SNORM
{
float R(size_t uOffset) const
// BC4S/BC5S
struct BC4_SNORM
{
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
}
float DecodeFromIndex(size_t uIndex) const
{
int8_t sred_0 = (red_0 == -128)? -127 : red_0;
int8_t sred_1 = (red_1 == -128)? -127 : red_1;
if (uIndex == 0)
return sred_0 / 127.0f;
if (uIndex == 1)
return sred_1 / 127.0f;
float fred_0 = sred_0 / 127.0f;
float fred_1 = sred_1 / 127.0f;
if (red_0 > red_1)
float R(size_t uOffset) const
{
uIndex -= 1;
return (fred_0 * (7-uIndex) + fred_1 * uIndex) / 7.0f;
size_t uIndex = GetIndex(uOffset);
return DecodeFromIndex(uIndex);
}
else
float DecodeFromIndex(size_t uIndex) const
{
if (uIndex == 6)
return -1.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5-uIndex) + fred_1 * uIndex) / 5.0f;
int8_t sred_0 = (red_0 == -128) ? -127 : red_0;
int8_t sred_1 = (red_1 == -128) ? -127 : red_1;
if (uIndex == 0)
return sred_0 / 127.0f;
if (uIndex == 1)
return sred_1 / 127.0f;
float fred_0 = sred_0 / 127.0f;
float fred_1 = sred_1 / 127.0f;
if (red_0 > red_1)
{
uIndex -= 1;
return (fred_0 * (7 - uIndex) + fred_1 * uIndex) / 7.0f;
}
else
{
if (uIndex == 6)
return -1.0f;
if (uIndex == 7)
return 1.0f;
uIndex -= 1;
return (fred_0 * (5 - uIndex) + fred_1 * uIndex) / 5.0f;
}
}
}
size_t GetIndex(size_t uOffset) const
{
return (size_t) ((data >> (3*uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t) 0x07 << (3*uOffset + 16));
data |= ((uint64_t) uIndex << (3*uOffset + 16));
}
union
{
struct
size_t GetIndex(size_t uOffset) const
{
int8_t red_0;
int8_t red_1;
uint8_t indices[6];
return (size_t)((data >> (3 * uOffset + 16)) & 0x07);
}
void SetIndex(size_t uOffset, size_t uIndex)
{
data &= ~((uint64_t)0x07 << (3 * uOffset + 16));
data |= ((uint64_t)uIndex << (3 * uOffset + 16));
}
union
{
struct
{
int8_t red_0;
int8_t red_1;
uint8_t indices[6];
};
uint64_t data;
};
uint64_t data;
};
};
#pragma warning(pop)
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
//-------------------------------------------------------------------------------------
static void inline FloatToSNorm( _In_ float fVal, _Out_ int8_t *piSNorm )
{
const uint32_t dwMostNeg = ( 1 << ( 8 * sizeof( int8_t ) - 1 ) );
//-------------------------------------------------------------------------------------
// Convert a floating point value to an 8-bit SNORM
//-------------------------------------------------------------------------------------
void inline FloatToSNorm(_In_ float fVal, _Out_ int8_t *piSNorm)
{
const uint32_t dwMostNeg = (1 << (8 * sizeof(int8_t) - 1));
if( _isnan( fVal ) )
fVal = 0;
else
if( fVal > 1 )
fVal = 1; // Clamp to 1
if (_isnan(fVal))
fVal = 0;
else
if( fVal < -1 )
fVal = -1; // Clamp to -1
if (fVal > 1)
fVal = 1; // Clamp to 1
else
if (fVal < -1)
fVal = -1; // Clamp to -1
fVal = fVal * (int8_t) ( dwMostNeg - 1 );
fVal = fVal * (int8_t)(dwMostNeg - 1);
if( fVal >= 0 )
fVal += .5f;
else
fVal -= .5f;
if (fVal >= 0)
fVal += .5f;
else
fVal -= .5f;
*piSNorm = (int8_t) (fVal);
}
//------------------------------------------------------------------------------
static void FindEndPointsBC4U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
int8_t iStart, iEnd;
size_t i;
MIN_NORM = 0.0f;
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i]<fBlockMin)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i]>fBlockMax)
{
fBlockMax = theTexelsU[i];
}
*piSNorm = (int8_t)(fVal);
}
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
// Using Optimize
float fStart, fEnd;
if (!bUsing4BlockCodec)
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
iStart = (uint8_t) (fStart * 255.0f);
iEnd = (uint8_t) (fEnd * 255.0f);
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
//------------------------------------------------------------------------------
void FindEndPointsBC4U(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_Out_ uint8_t &endpointU_0,
_Out_ uint8_t &endpointU_1)
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
int8_t iStart, iEnd;
size_t i;
iStart = (uint8_t) (fStart * 255.0f);
iEnd = (uint8_t) (fEnd * 255.0f);
MIN_NORM = 0.0f;
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
static void FindEndPointsBC4S(_In_reads_(BLOCK_SIZE) const float theTexelsU[], _Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
int8_t iStart, iEnd;
size_t i;
MIN_NORM = -1.0f;
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i]<fBlockMin)
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i]>fBlockMax)
{
fBlockMax = theTexelsU[i];
}
}
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = ( MIN_NORM == fBlockMin || MAX_NORM == fBlockMax );
// Using Optimize
float fStart, fEnd;
if (!bUsing4BlockCodec)
{
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 8);
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 6);
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
//------------------------------------------------------------------------------
static inline void FindEndPointsBC5U( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0, _Out_ uint8_t &endpointU_1, _Out_ uint8_t &endpointV_0, _Out_ uint8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4U( theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4U( theTexelsV, endpointV_0, endpointV_1);
}
static inline void FindEndPointsBC5S( _In_reads_(BLOCK_SIZE) const float theTexelsU[], _In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0, _Out_ int8_t &endpointU_1, _Out_ int8_t &endpointV_0, _Out_ int8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4S( theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4S( theTexelsV, endpointV_0, endpointV_1);
}
//------------------------------------------------------------------------------
static void FindClosestUNORM(_Inout_ BC4_UNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
{
rGradient[i] = pBC->DecodeFromIndex(i);
}
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
if (theTexelsU[i] < fBlockMin)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i] > fBlockMax)
{
fBlockMax = theTexelsU[i];
}
}
pBC->SetIndex(i, uBestIndex);
}
}
static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
{
rGradient[i] = pBC->DecodeFromIndex(i);
}
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
// Using Optimize
float fStart, fEnd;
if (!bUsing4BlockCodec)
{
float fCurrentDelta = fabsf(rGradient[uIndex]-theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 8);
iStart = (uint8_t)(fStart * 255.0f);
iEnd = (uint8_t)(fEnd * 255.0f);
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
OptimizeAlpha<false>(&fStart, &fEnd, theTexelsU, 6);
iStart = (uint8_t)(fStart * 255.0f);
iEnd = (uint8_t)(fEnd * 255.0f);
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
void FindEndPointsBC4S(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_Out_ int8_t &endpointU_0,
_Out_ int8_t &endpointU_1)
{
// The boundary of codec for signed/unsigned format
float MIN_NORM;
float MAX_NORM = 1.0f;
int8_t iStart, iEnd;
size_t i;
MIN_NORM = -1.0f;
// Find max/min of input texels
float fBlockMax = theTexelsU[0];
float fBlockMin = theTexelsU[0];
for (i = 0; i < BLOCK_SIZE; ++i)
{
if (theTexelsU[i] < fBlockMin)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
fBlockMin = theTexelsU[i];
}
else if (theTexelsU[i] > fBlockMax)
{
fBlockMax = theTexelsU[i];
}
}
pBC->SetIndex(i, uBestIndex);
// If there are boundary values in input texels, Should use 4 block-codec to guarantee
// the exact code of the boundary values.
bool bUsing4BlockCodec = (MIN_NORM == fBlockMin || MAX_NORM == fBlockMax);
// Using Optimize
float fStart, fEnd;
if (!bUsing4BlockCodec)
{
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 8);
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
endpointU_0 = iEnd;
endpointU_1 = iStart;
}
else
{
OptimizeAlpha<true>(&fStart, &fEnd, theTexelsU, 6);
FloatToSNorm(fStart, &iStart);
FloatToSNorm(fEnd, &iEnd);
endpointU_1 = iEnd;
endpointU_0 = iStart;
}
}
//------------------------------------------------------------------------------
inline void FindEndPointsBC5U(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ uint8_t &endpointU_0,
_Out_ uint8_t &endpointU_1,
_Out_ uint8_t &endpointV_0,
_Out_ uint8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4U(theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4U(theTexelsV, endpointV_0, endpointV_1);
}
inline void FindEndPointsBC5S(
_In_reads_(BLOCK_SIZE) const float theTexelsU[],
_In_reads_(BLOCK_SIZE) const float theTexelsV[],
_Out_ int8_t &endpointU_0,
_Out_ int8_t &endpointU_1,
_Out_ int8_t &endpointV_0,
_Out_ int8_t &endpointV_1)
{
//Encoding the U and V channel by BC4 codec separately.
FindEndPointsBC4S(theTexelsU, endpointU_0, endpointU_1);
FindEndPointsBC4S(theTexelsV, endpointV_0, endpointV_1);
}
//------------------------------------------------------------------------------
void FindClosestUNORM(
_Inout_ BC4_UNORM* pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
{
rGradient[i] = pBC->DecodeFromIndex(i);
}
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
}
}
pBC->SetIndex(i, uBestIndex);
}
}
void FindClosestSNORM(
_Inout_ BC4_SNORM* pBC,
_In_reads_(NUM_PIXELS_PER_BLOCK) const float theTexelsU[])
{
float rGradient[8];
int i;
for (i = 0; i < 8; ++i)
{
rGradient[i] = pBC->DecodeFromIndex(i);
}
for (i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
size_t uBestIndex = 0;
float fBestDelta = 100000;
for (size_t uIndex = 0; uIndex < 8; uIndex++)
{
float fCurrentDelta = fabsf(rGradient[uIndex] - theTexelsU[i]);
if (fCurrentDelta < fBestDelta)
{
uBestIndex = uIndex;
fBestDelta = fCurrentDelta;
}
}
pBC->SetIndex(i, uBestIndex);
}
}
}
@ -370,42 +392,42 @@ static void FindClosestSNORM(_Inout_ BC4_SNORM* pBC, _In_reads_(NUM_PIXELS_PER_B
// BC4 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC4U( XMVECTOR *pColor, const uint8_t *pBC )
void DirectX::D3DXDecodeBC4U(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
auto pBC4 = reinterpret_cast<const BC4_UNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
}
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC4S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
auto pBC4 = reinterpret_cast<const BC4_SNORM*>(pBC);
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet( pBC4->R(i), 0, 0, 1.0f);
}
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBC4->R(i), 0, 0, 1.0f);
}
}
_Use_decl_annotations_
void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC4U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_UNORM*>(pBC);
@ -413,7 +435,7 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
theTexelsU[i] = XMVectorGetX( pColor[i] );
theTexelsU[i] = XMVectorGetX(pColor[i]);
}
FindEndPointsBC4U(theTexelsU, pBC4->red_0, pBC4->red_1);
@ -421,12 +443,12 @@ void D3DXEncodeBC4U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
}
_Use_decl_annotations_
void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC4S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM));
auto pBC4 = reinterpret_cast<BC4_SNORM*>(pBC);
@ -434,7 +456,7 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
theTexelsU[i] = XMVectorGetX( pColor[i] );
theTexelsU[i] = XMVectorGetX(pColor[i]);
}
FindEndPointsBC4S(theTexelsU, pBC4->red_0, pBC4->red_1);
@ -446,55 +468,55 @@ void D3DXEncodeBC4S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
// BC5 Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC5U(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
auto pBCR = reinterpret_cast<const BC4_UNORM*>(pBC);
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
auto pBCG = reinterpret_cast<const BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
}
_Use_decl_annotations_
void D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
void DirectX::D3DXDecodeBC5S(XMVECTOR *pColor, const uint8_t *pBC)
{
assert( pColor && pBC );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pColor && pBC);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
auto pBCR = reinterpret_cast<const BC4_SNORM*>(pBC);
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
auto pBCG = reinterpret_cast<const BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
#pragma prefast(suppress:22103, "writing blocks in two halves confuses tool")
pColor[i] = XMVectorSet(pBCR->R(i), pBCG->R(i), 0, 1.0f);
}
}
}
_Use_decl_annotations_
void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC5U(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_UNORM) == 8, "BC4_UNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM)*2);
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
auto pBCR = reinterpret_cast<BC4_UNORM*>(pBC);
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC+sizeof(BC4_UNORM));
auto pBCG = reinterpret_cast<BC4_UNORM*>(pBC + sizeof(BC4_UNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
{
XMFLOAT4A clr;
XMStoreFloat4A( &clr, pColor[i] );
XMStoreFloat4A(&clr, pColor[i]);
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
@ -512,23 +534,23 @@ void D3DXEncodeBC5U( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
}
_Use_decl_annotations_
void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
void DirectX::D3DXEncodeBC5S(uint8_t *pBC, const XMVECTOR *pColor, DWORD flags)
{
UNREFERENCED_PARAMETER( flags );
UNREFERENCED_PARAMETER(flags);
assert( pBC && pColor );
static_assert( sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes" );
assert(pBC && pColor);
static_assert(sizeof(BC4_SNORM) == 8, "BC4_SNORM should be 8 bytes");
memset(pBC, 0, sizeof(BC4_UNORM)*2);
memset(pBC, 0, sizeof(BC4_UNORM) * 2);
auto pBCR = reinterpret_cast<BC4_SNORM*>(pBC);
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC+sizeof(BC4_SNORM));
auto pBCG = reinterpret_cast<BC4_SNORM*>(pBC + sizeof(BC4_SNORM));
float theTexelsU[NUM_PIXELS_PER_BLOCK];
float theTexelsV[NUM_PIXELS_PER_BLOCK];
for (size_t i = 0; i < NUM_PIXELS_PER_BLOCK; ++i)
{
XMFLOAT4A clr;
XMStoreFloat4A( &clr, pColor[i] );
XMStoreFloat4A(&clr, pColor[i]);
theTexelsU[i] = clr.x;
theTexelsV[i] = clr.y;
}
@ -543,6 +565,4 @@ void D3DXEncodeBC5S( uint8_t *pBC, const XMVECTOR *pColor, DWORD flags )
FindClosestSNORM(pBCR, theTexelsU);
FindClosestSNORM(pBCG, theTexelsV);
}
} // namespace
}

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -19,6 +19,7 @@
#pragma comment(lib,"dxguid.lib")
#endif
using namespace DirectX;
using Microsoft::WRL::ComPtr;
namespace
@ -82,9 +83,6 @@ namespace
}
};
namespace DirectX
{
GPUCompressBC::GPUCompressBC() :
m_bcformat(DXGI_FORMAT_UNKNOWN),
m_srcformat(DXGI_FORMAT_UNKNOWN),
@ -97,79 +95,79 @@ GPUCompressBC::GPUCompressBC() :
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
HRESULT GPUCompressBC::Initialize(ID3D11Device* pDevice)
{
if ( !pDevice )
if (!pDevice)
return E_INVALIDARG;
// Check for DirectCompute support
D3D_FEATURE_LEVEL fl = pDevice->GetFeatureLevel();
if ( fl < D3D_FEATURE_LEVEL_10_0 )
if (fl < D3D_FEATURE_LEVEL_10_0)
{
// DirectCompute not supported on Feature Level 9.x hardware
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
if ( fl < D3D_FEATURE_LEVEL_11_0 )
if (fl < D3D_FEATURE_LEVEL_11_0)
{
// DirectCompute support on Feature Level 10.x hardware is optional, and this function needs it
D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS hwopts;
HRESULT hr = pDevice->CheckFeatureSupport( D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts) );
if ( FAILED(hr) )
HRESULT hr = pDevice->CheckFeatureSupport(D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS, &hwopts, sizeof(hwopts));
if (FAILED(hr))
{
memset( &hwopts, 0, sizeof(hwopts) );
memset(&hwopts, 0, sizeof(hwopts));
}
if ( !hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x )
if (!hwopts.ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x)
{
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
}
// Save a device reference and obtain immediate context
m_device = pDevice;
pDevice->GetImmediateContext( m_context.ReleaseAndGetAddressOf() );
assert( m_context );
pDevice->GetImmediateContext(m_context.ReleaseAndGetAddressOf());
assert(m_context);
//--- Create compute shader library: BC6H -----------------------------------------
// Modes 11-14
HRESULT hr = pDevice->CreateComputeShader( BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateComputeShader(BC6HEncode_TryModeG10CS, sizeof(BC6HEncode_TryModeG10CS), nullptr, m_BC6H_tryModeG10CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Modes 1-10
hr = pDevice->CreateComputeShader( BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC6HEncode_TryModeLE10CS, sizeof(BC6HEncode_TryModeLE10CS), nullptr, m_BC6H_tryModeLE10CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Encode
hr = pDevice->CreateComputeShader( BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC6HEncode_EncodeBlockCS, sizeof(BC6HEncode_EncodeBlockCS), nullptr, m_BC6H_encodeBlockCS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
//--- Create compute shader library: BC7 ------------------------------------------
// Modes 4, 5, 6
hr = pDevice->CreateComputeShader( BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_TryMode456CS, sizeof(BC7Encode_TryMode456CS), nullptr, m_BC7_tryMode456CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Modes 1, 3, 7
hr = pDevice->CreateComputeShader( BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_TryMode137CS, sizeof(BC7Encode_TryMode137CS), nullptr, m_BC7_tryMode137CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Modes 0, 2
hr = pDevice->CreateComputeShader( BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_TryMode02CS, sizeof(BC7Encode_TryMode02CS), nullptr, m_BC7_tryMode02CS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
// Encode
hr = pDevice->CreateComputeShader( BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateComputeShader(BC7Encode_EncodeBlockCS, sizeof(BC7Encode_EncodeBlockCS), nullptr, m_BC7_encodeBlockCS.ReleaseAndGetAddressOf());
if (FAILED(hr))
return hr;
return S_OK;
@ -178,12 +176,12 @@ HRESULT GPUCompressBC::Initialize( ID3D11Device* pDevice )
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets )
HRESULT GPUCompressBC::Prepare(size_t width, size_t height, DXGI_FORMAT format, float alphaWeight, bool skip3subsets)
{
if ( !width || !height || alphaWeight < 0.f )
if (!width || !height || alphaWeight < 0.f)
return E_INVALIDARG;
if ( (width > UINT32_MAX) || (height > UINT32_MAX) )
if ((width > UINT32_MAX) || (height > UINT32_MAX))
return E_INVALIDARG;
m_width = width;
@ -193,20 +191,20 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
m_skip3Subsets = skip3subsets;
size_t xblocks = std::max<size_t>( 1, (width + 3) >> 2 );
size_t yblocks = std::max<size_t>( 1, (height + 3) >> 2 );
size_t xblocks = std::max<size_t>(1, (width + 3) >> 2);
size_t yblocks = std::max<size_t>(1, (height + 3) >> 2);
size_t num_blocks = xblocks * yblocks;
switch( format )
switch (format)
{
// BC6H GPU compressor takes RGBAF32 as input
// BC6H GPU compressor takes RGBAF32 as input
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
case DXGI_FORMAT_BC6H_SF16:
m_srcformat = DXGI_FORMAT_R32G32B32A32_FLOAT;
break;
// BC7 GPU compressor takes RGBA32 as input
// BC7 GPU compressor takes RGBA32 as input
case DXGI_FORMAT_BC7_TYPELESS:
case DXGI_FORMAT_BC7_UNORM:
m_srcformat = DXGI_FORMAT_R8G8B8A8_UNORM;
@ -218,39 +216,39 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
default:
m_bcformat = m_srcformat = DXGI_FORMAT_UNKNOWN;
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
m_bcformat = format;
auto pDevice = m_device.Get();
if ( !pDevice )
if (!pDevice)
return E_POINTER;
// Create structured buffers
size_t bufferSize = num_blocks * sizeof( BufferBC6HBC7 );
size_t bufferSize = num_blocks * sizeof(BufferBC6HBC7);
{
D3D11_BUFFER_DESC desc = {};
desc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE;
desc.Usage = D3D11_USAGE_DEFAULT;
desc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED;
desc.StructureByteStride = sizeof( BufferBC6HBC7 );
desc.ByteWidth = static_cast<UINT>( bufferSize );
desc.StructureByteStride = sizeof(BufferBC6HBC7);
desc.ByteWidth = static_cast<UINT>(bufferSize);
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_output.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_output.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateBuffer( &desc, nullptr, m_err1.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateBuffer(&desc, nullptr, m_err1.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateBuffer( &desc, nullptr, m_err2.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateBuffer(&desc, nullptr, m_err2.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -261,10 +259,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
D3D11_BUFFER_DESC desc = {};
desc.Usage = D3D11_USAGE_STAGING;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
desc.ByteWidth = static_cast<UINT>( bufferSize );
desc.ByteWidth = static_cast<UINT>(bufferSize);
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_outputCPU.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -276,10 +274,10 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
desc.BindFlags = D3D11_BIND_CONSTANT_BUFFER;
desc.Usage = D3D11_USAGE_DYNAMIC;
desc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
desc.ByteWidth = sizeof( ConstantsBC6HBC7 );
desc.ByteWidth = sizeof(ConstantsBC6HBC7);
HRESULT hr = pDevice->CreateBuffer( &desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateBuffer(&desc, nullptr, m_constBuffer.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -288,17 +286,17 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
// Create shader resource views
{
D3D11_SHADER_RESOURCE_VIEW_DESC desc = {};
desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
desc.Buffer.NumElements = static_cast<UINT>(num_blocks);
desc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
HRESULT hr = pDevice->CreateShaderResourceView( m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateShaderResourceView(m_err1.Get(), &desc, m_err1SRV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateShaderResourceView( m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateShaderResourceView(m_err2.Get(), &desc, m_err2SRV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -307,62 +305,62 @@ HRESULT GPUCompressBC::Prepare( size_t width, size_t height, DXGI_FORMAT format,
// Create unordered access views
{
D3D11_UNORDERED_ACCESS_VIEW_DESC desc = {};
desc.Buffer.NumElements = static_cast<UINT>( num_blocks );
desc.Buffer.NumElements = static_cast<UINT>(num_blocks);
desc.ViewDimension = D3D11_UAV_DIMENSION_BUFFER;
HRESULT hr = pDevice->CreateUnorderedAccessView( m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateUnorderedAccessView(m_output.Get(), &desc, m_outputUAV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateUnorderedAccessView( m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateUnorderedAccessView(m_err1.Get(), &desc, m_err1UAV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
hr = pDevice->CreateUnorderedAccessView( m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf() );
if ( FAILED(hr) )
hr = pDevice->CreateUnorderedAccessView(m_err2.Get(), &desc, m_err2UAV.ReleaseAndGetAddressOf());
if (FAILED(hr))
{
return hr;
}
}
return S_OK;
}
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
HRESULT GPUCompressBC::Compress(const Image& srcImage, const Image& destImage)
{
if ( !srcImage.pixels || !destImage.pixels )
if (!srcImage.pixels || !destImage.pixels)
return E_INVALIDARG;
if ( srcImage.width != destImage.width
|| srcImage.height != destImage.height
|| srcImage.width != m_width
|| srcImage.height != m_height
|| srcImage.format != m_srcformat
|| destImage.format != m_bcformat )
if (srcImage.width != destImage.width
|| srcImage.height != destImage.height
|| srcImage.width != m_width
|| srcImage.height != m_height
|| srcImage.format != m_srcformat
|| destImage.format != m_bcformat)
{
return E_UNEXPECTED;
}
//--- Create input texture --------------------------------------------------------
auto pDevice = m_device.Get();
if ( !pDevice )
if (!pDevice)
return E_POINTER;
// We need to avoid the hardware doing additional colorspace conversion
DXGI_FORMAT inputFormat = ( m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB ) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
DXGI_FORMAT inputFormat = (m_srcformat == DXGI_FORMAT_R8G8B8A8_UNORM_SRGB) ? DXGI_FORMAT_R8G8B8A8_UNORM : m_srcformat;
ComPtr<ID3D11Texture2D> sourceTex;
{
D3D11_TEXTURE2D_DESC desc = {};
desc.Width = static_cast<UINT>( srcImage.width );
desc.Height = static_cast<UINT>( srcImage.height );
desc.Width = static_cast<UINT>(srcImage.width);
desc.Height = static_cast<UINT>(srcImage.height);
desc.MipLevels = 1;
desc.ArraySize = 1;
desc.Format = inputFormat;
@ -372,11 +370,11 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
D3D11_SUBRESOURCE_DATA initData;
initData.pSysMem = srcImage.pixels;
initData.SysMemPitch = static_cast<DWORD>( srcImage.rowPitch );
initData.SysMemSlicePitch = static_cast<DWORD>( srcImage.slicePitch );
initData.SysMemPitch = static_cast<DWORD>(srcImage.rowPitch);
initData.SysMemSlicePitch = static_cast<DWORD>(srcImage.slicePitch);
HRESULT hr = pDevice->CreateTexture2D( &desc, &initData, sourceTex.GetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateTexture2D(&desc, &initData, sourceTex.GetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -389,8 +387,8 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
desc.Format = inputFormat;
desc.ViewDimension = D3D11_SRV_DIMENSION_TEXTURE2D;
HRESULT hr = pDevice->CreateShaderResourceView( sourceTex.Get(), &desc, sourceSRV.GetAddressOf() );
if ( FAILED(hr) )
HRESULT hr = pDevice->CreateShaderResourceView(sourceTex.Get(), &desc, sourceSRV.GetAddressOf());
if (FAILED(hr))
{
return hr;
}
@ -398,7 +396,7 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
//--- Compress using DirectCompute ------------------------------------------------
bool isbc7 = false;
switch( m_bcformat )
switch (m_bcformat)
{
case DXGI_FORMAT_BC6H_TYPELESS:
case DXGI_FORMAT_BC6H_UF16:
@ -418,47 +416,47 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
const UINT MAX_BLOCK_BATCH = 64;
auto pContext = m_context.Get();
if ( !pContext )
if (!pContext)
return E_UNEXPECTED;
size_t xblocks = std::max<size_t>( 1, (m_width + 3) >> 2 );
size_t yblocks = std::max<size_t>( 1, (m_height + 3) >> 2 );
size_t xblocks = std::max<size_t>(1, (m_width + 3) >> 2);
size_t yblocks = std::max<size_t>(1, (m_height + 3) >> 2);
UINT num_total_blocks = static_cast<UINT>( xblocks * yblocks );
UINT num_total_blocks = static_cast<UINT>(xblocks * yblocks);
UINT num_blocks = num_total_blocks;
int start_block_id = 0;
while (num_blocks > 0)
{
UINT n = std::min<UINT>( num_blocks, MAX_BLOCK_BATCH );
UINT n = std::min<UINT>(num_blocks, MAX_BLOCK_BATCH);
UINT uThreadGroupCount = n;
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
return hr;
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = 0;
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
param.alpha_weight = m_alphaWeight;
memcpy( mapped.pData, &param, sizeof( param ) );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap( m_constBuffer.Get(), 0 );
pContext->Unmap(m_constBuffer.Get(), 0);
}
if ( isbc7 )
if (isbc7)
{
//--- BC7 -----------------------------------------------------------------
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
RunComputeShader( pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
RunComputeShader(pContext, m_BC7_tryMode456CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
for ( UINT i = 0; i < 3; ++i )
for (UINT i = 0; i < 3; ++i)
{
static const UINT modes[] = { 1, 3, 7 };
@ -467,141 +465,139 @@ HRESULT GPUCompressBC::Compress( const Image& srcImage, const Image& destImage )
// Mode 7: err1 -> err2
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
{
ResetContext( pContext );
ResetContext(pContext);
return hr;
}
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = modes[i];
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
param.alpha_weight = m_alphaWeight;
memcpy( mapped.pData, &param, sizeof( param ) );
pContext->Unmap( m_constBuffer.Get(), 0 );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap(m_constBuffer.Get(), 0);
}
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
RunComputeShader( pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount );
}
RunComputeShader(pContext, m_BC7_tryMode137CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), uThreadGroupCount);
}
if ( !m_skip3Subsets )
if (!m_skip3Subsets)
{
// 3 subset modes tend to be used rarely and add significant compression time
for ( UINT i = 0; i < 2; ++i )
for (UINT i = 0; i < 2; ++i)
{
static const UINT modes[] = { 0, 2 };
// Mode 0: err2 -> err1
// Mode 2: err1 -> err2
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
{
ResetContext( pContext );
ResetContext(pContext);
return hr;
}
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = modes[i];
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
param.alpha_weight = m_alphaWeight;
memcpy( mapped.pData, &param, sizeof( param ) );
pContext->Unmap( m_constBuffer.Get(), 0 );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap(m_constBuffer.Get(), 0);
}
pSRVs[1] = (i & 1) ? m_err1SRV.Get() : m_err2SRV.Get();
RunComputeShader( pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount );
RunComputeShader(pContext, m_BC7_tryMode02CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err2UAV.Get() : m_err1UAV.Get(), uThreadGroupCount);
}
}
pSRVs[1] = m_err2SRV.Get();
RunComputeShader( pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
RunComputeShader(pContext, m_BC7_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
}
else
{
//--- BC6H ----------------------------------------------------------------
ID3D11ShaderResourceView* pSRVs[] = { sourceSRV.Get(), nullptr };
RunComputeShader( pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>( (uThreadGroupCount + 3) / 4, 1) );
RunComputeShader(pContext, m_BC6H_tryModeG10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_err1UAV.Get(), std::max<UINT>((uThreadGroupCount + 3) / 4, 1));
for ( UINT i = 0; i < 10; ++i )
for (UINT i = 0; i < 10; ++i)
{
{
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped );
if ( FAILED(hr) )
HRESULT hr = pContext->Map(m_constBuffer.Get(), 0, D3D11_MAP_WRITE_DISCARD, 0, &mapped);
if (FAILED(hr))
{
ResetContext( pContext );
ResetContext(pContext);
return hr;
}
ConstantsBC6HBC7 param;
param.tex_width = static_cast<UINT>( srcImage.width );
param.num_block_x = static_cast<UINT>( xblocks );
param.tex_width = static_cast<UINT>(srcImage.width);
param.num_block_x = static_cast<UINT>(xblocks);
param.format = m_bcformat;
param.mode_id = i;
param.start_block_id = start_block_id;
param.num_total_blocks = num_total_blocks;
memcpy( mapped.pData, &param, sizeof( param ) );
pContext->Unmap( m_constBuffer.Get(), 0 );
memcpy(mapped.pData, &param, sizeof(param));
pContext->Unmap(m_constBuffer.Get(), 0);
}
pSRVs[1] = (i & 1) ? m_err2SRV.Get() : m_err1SRV.Get();
RunComputeShader( pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
}
RunComputeShader(pContext, m_BC6H_tryModeLE10CS.Get(), pSRVs, 2, m_constBuffer.Get(),
(i & 1) ? m_err1UAV.Get() : m_err2UAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
}
pSRVs[1] = m_err1SRV.Get();
RunComputeShader( pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>( (uThreadGroupCount + 1) / 2, 1) );
RunComputeShader(pContext, m_BC6H_encodeBlockCS.Get(), pSRVs, 2, m_constBuffer.Get(),
m_outputUAV.Get(), std::max<UINT>((uThreadGroupCount + 1) / 2, 1));
}
start_block_id += n;
num_blocks -= n;
}
ResetContext( pContext );
ResetContext(pContext);
//--- Copy output texture back to CPU ---------------------------------------------
pContext->CopyResource( m_outputCPU.Get(), m_output.Get() );
pContext->CopyResource(m_outputCPU.Get(), m_output.Get());
D3D11_MAPPED_SUBRESOURCE mapped;
HRESULT hr = pContext->Map( m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped );
if ( SUCCEEDED(hr) )
HRESULT hr = pContext->Map(m_outputCPU.Get(), 0, D3D11_MAP_READ, 0, &mapped);
if (SUCCEEDED(hr))
{
const uint8_t *pSrc = reinterpret_cast<const uint8_t *>( mapped.pData );
const uint8_t *pSrc = reinterpret_cast<const uint8_t *>(mapped.pData);
uint8_t *pDest = destImage.pixels;
size_t pitch = xblocks * sizeof( BufferBC6HBC7 );
size_t pitch = xblocks * sizeof(BufferBC6HBC7);
size_t rows = std::max<size_t>( 1, ( destImage.height + 3 ) >> 2 );
size_t rows = std::max<size_t>(1, (destImage.height + 3) >> 2);
for( size_t h = 0; h < rows; ++h )
for (size_t h = 0; h < rows; ++h)
{
memcpy( pDest, pSrc, destImage.rowPitch );
memcpy(pDest, pSrc, destImage.rowPitch);
pSrc += pitch;
pDest += destImage.rowPitch;
}
pContext->Unmap( m_outputCPU.Get(), 0 );
pContext->Unmap(m_outputCPU.Get(), 0);
}
return hr;
}
}; // namespace
}

Просмотреть файл

@ -33,7 +33,7 @@
#include <ocidl.h>
#define DIRECTX_TEX_VERSION 134
#define DIRECTX_TEX_VERSION 140
struct IWICImagingFactory;
struct IWICMetadataQueryReader;
@ -204,21 +204,21 @@ namespace DirectX
// Filtering mode to use for any required image resizing (only needed when loading arrays of differently sized images; defaults to Fant)
};
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
HRESULT __cdecl GetMetadataFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ LPCWSTR szFile,
HRESULT __cdecl GetMetadataFromTGAFile( _In_z_ const wchar_t* szFile,
_Out_ TexMetadata& metadata );
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_ TexMetadata& metadata,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl GetMetadataFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_ TexMetadata& metadata,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
@ -238,13 +238,16 @@ namespace DirectX
{
public:
ScratchImage()
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) {}
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) {}
ScratchImage(ScratchImage&& moveFrom)
: _nimages(0), _size(0), _image(nullptr), _memory(nullptr) { *this = std::move(moveFrom); }
: m_nimages(0), m_size(0), m_image(nullptr), m_memory(nullptr) { *this = std::move(moveFrom); }
~ScratchImage() { Release(); }
ScratchImage& __cdecl operator= (ScratchImage&& moveFrom);
ScratchImage(const ScratchImage&) = delete;
ScratchImage& operator=(const ScratchImage&) = delete;
HRESULT __cdecl Initialize( _In_ const TexMetadata& mdata, _In_ DWORD flags = CP_FLAGS_NONE );
HRESULT __cdecl Initialize1D( _In_ DXGI_FORMAT fmt, _In_ size_t length, _In_ size_t arraySize, _In_ size_t mipLevels, _In_ DWORD flags = CP_FLAGS_NONE );
@ -261,27 +264,23 @@ namespace DirectX
bool __cdecl OverrideFormat( _In_ DXGI_FORMAT f );
const TexMetadata& __cdecl GetMetadata() const { return _metadata; }
const TexMetadata& __cdecl GetMetadata() const { return m_metadata; }
const Image* __cdecl GetImage(_In_ size_t mip, _In_ size_t item, _In_ size_t slice) const;
const Image* __cdecl GetImages() const { return _image; }
size_t __cdecl GetImageCount() const { return _nimages; }
const Image* __cdecl GetImages() const { return m_image; }
size_t __cdecl GetImageCount() const { return m_nimages; }
uint8_t* __cdecl GetPixels() const { return _memory; }
size_t __cdecl GetPixelsSize() const { return _size; }
uint8_t* __cdecl GetPixels() const { return m_memory; }
size_t __cdecl GetPixelsSize() const { return m_size; }
bool __cdecl IsAlphaAllOpaque() const;
private:
size_t _nimages;
size_t _size;
TexMetadata _metadata;
Image* _image;
uint8_t* _memory;
// Hide copy constructor and assignment operator
ScratchImage( const ScratchImage& );
ScratchImage& operator=( const ScratchImage& );
size_t m_nimages;
size_t m_size;
TexMetadata m_metadata;
Image* m_image;
uint8_t* m_memory;
};
//---------------------------------------------------------------------------------
@ -289,35 +288,34 @@ namespace DirectX
class Blob
{
public:
Blob() : _buffer(nullptr), _size(0) {}
Blob(Blob&& moveFrom) : _buffer(nullptr), _size(0) { *this = std::move(moveFrom); }
Blob() : m_buffer(nullptr), m_size(0) {}
Blob(Blob&& moveFrom) : m_buffer(nullptr), m_size(0) { *this = std::move(moveFrom); }
~Blob() { Release(); }
Blob& __cdecl operator= (Blob&& moveFrom);
Blob(const Blob&) = delete;
Blob& operator=(const Blob&) = delete;
HRESULT __cdecl Initialize( _In_ size_t size );
void __cdecl Release();
void *__cdecl GetBufferPointer() const { return _buffer; }
size_t __cdecl GetBufferSize() const { return _size; }
void *__cdecl GetBufferPointer() const { return m_buffer; }
size_t __cdecl GetBufferSize() const { return m_size; }
private:
void* _buffer;
size_t _size;
// Hide copy constructor and assignment operator
Blob( const Blob& );
Blob& operator=( const Blob& );
void* m_buffer;
size_t m_size;
};
//---------------------------------------------------------------------------------
// Image I/O
// DDS operations
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl LoadFromDDSMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromDDSFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl LoadFromDDSFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToDDSMemory( _In_ const Image& image, _In_ DWORD flags,
@ -325,23 +323,23 @@ namespace DirectX
HRESULT __cdecl SaveToDDSMemory( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags,
_Out_ Blob& blob );
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToDDSFile( _In_ const Image& image, _In_ DWORD flags, _In_z_ const wchar_t* szFile );
HRESULT __cdecl SaveToDDSFile( _In_reads_(nimages) const Image* images, _In_ size_t nimages, _In_ const TexMetadata& metadata, _In_ DWORD flags, _In_z_ const wchar_t* szFile );
// TGA operations
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size,
HRESULT __cdecl LoadFromTGAMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl LoadFromTGAFile( _In_z_ LPCWSTR szFile,
HRESULT __cdecl LoadFromTGAFile( _In_z_ const wchar_t* szFile,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image );
HRESULT __cdecl SaveToTGAMemory( _In_ const Image& image, _Out_ Blob& blob );
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ LPCWSTR szFile );
HRESULT __cdecl SaveToTGAFile( _In_ const Image& image, _In_z_ const wchar_t* szFile );
// WIC operations
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DWORD flags,
HRESULT __cdecl LoadFromWICMemory( _In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
HRESULT __cdecl LoadFromWICFile( _In_z_ LPCWSTR szFile, _In_ DWORD flags,
HRESULT __cdecl LoadFromWICFile( _In_z_ const wchar_t* szFile, _In_ DWORD flags,
_Out_opt_ TexMetadata* metadata, _Out_ ScratchImage& image,
_In_opt_ std::function<void __cdecl(IWICMetadataQueryReader*)> getMQR = nullptr);
@ -353,10 +351,10 @@ namespace DirectX
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICFile( _In_ const Image& image, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
HRESULT __cdecl SaveToWICFile( _In_count_(nimages) const Image* images, _In_ size_t nimages, _In_ DWORD flags, _In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_z_ const wchar_t* szFile, _In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void __cdecl(IPropertyBag2*)> setCustomProps = nullptr );
//---------------------------------------------------------------------------------

Просмотреть файл

@ -113,7 +113,7 @@ inline HRESULT __cdecl SaveToDDSMemory(const Image& image, DWORD flags, Blob& bl
}
_Use_decl_annotations_
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, LPCWSTR szFile)
inline HRESULT __cdecl SaveToDDSFile(const Image& image, DWORD flags, const wchar_t* szFile)
{
TexMetadata mdata = {};
mdata.width = image.width;

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -17,178 +17,190 @@
#include "bcdirectcompute.h"
namespace DirectX
using namespace DirectX;
namespace
{
inline static DWORD _GetSRGBFlags( _In_ DWORD compress )
{
static_assert( TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*" );
return ( compress & TEX_COMPRESS_SRGB );
}
//-------------------------------------------------------------------------------------
// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
//-------------------------------------------------------------------------------------
static HRESULT _ConvertToRGBA32( _In_ const Image& srcImage, _In_ ScratchImage& image, bool srgb, _In_ DWORD filter )
{
if ( !srcImage.pixels )
return E_POINTER;
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
HRESULT hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
inline DWORD GetSRGBFlags(_In_ DWORD compress)
{
image.Release();
return E_POINTER;
static_assert(TEX_COMPRESS_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_COMPRESS_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_COMPRESS_SRGB == TEX_FILTER_SRGB, "TEX_COMPRESS_SRGB* should match TEX_FILTER_SRGB*");
return (compress & TEX_COMPRESS_SRGB);
}
uint8_t* pDest = img->pixels;
if ( !pDest )
//-------------------------------------------------------------------------------------
// Converts to R8G8B8A8_UNORM or R8G8B8A8_UNORM_SRGB doing any conversion logic needed
//-------------------------------------------------------------------------------------
HRESULT ConvertToRGBA32(
const Image& srcImage,
ScratchImage& image,
bool srgb,
DWORD filter)
{
image.Release();
return E_POINTER;
}
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( ( sizeof(XMVECTOR) * srcImage.width ), 16 ) ) );
if ( !scanline )
{
image.Release();
return E_OUTOFMEMORY;
}
const uint8_t *pSrc = srcImage.pixels;
for( size_t h = 0; h < srcImage.height; ++h )
{
if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
{
image.Release();
return E_FAIL;
}
_ConvertScanline( scanline.get(), srcImage.width, format, srcImage.format, filter );
if ( !_StoreScanline( pDest, img->rowPitch, format, scanline.get(), srcImage.width ) )
{
image.Release();
return E_FAIL;
}
pSrc += srcImage.rowPitch;
pDest += img->rowPitch;
}
return S_OK;
}
//-------------------------------------------------------------------------------------
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
//-------------------------------------------------------------------------------------
static HRESULT _ConvertToRGBAF32( const Image& srcImage, ScratchImage& image, _In_ DWORD filter )
{
if ( !srcImage.pixels )
return E_POINTER;
HRESULT hr = image.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
{
image.Release();
return E_POINTER;
}
uint8_t* pDest = img->pixels;
if ( !pDest )
{
image.Release();
return E_POINTER;
}
const uint8_t *pSrc = srcImage.pixels;
for( size_t h = 0; h < srcImage.height; ++h )
{
if ( !_LoadScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
{
image.Release();
return E_FAIL;
}
_ConvertScanline( reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter );
pSrc += srcImage.rowPitch;
pDest += img->rowPitch;
}
return S_OK;
}
//-------------------------------------------------------------------------------------
// Compress using GPU, converting to the proper input format for the shader if needed
//-------------------------------------------------------------------------------------
inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image& srcImage, _In_ const Image& destImage, _In_ DWORD compress )
{
if ( !gpubc )
return E_POINTER;
assert( srcImage.pixels && destImage.pixels );
DXGI_FORMAT format = gpubc->GetSourceFormat();
if ( srcImage.format == format )
{
// Input is already in our required source format
return gpubc->Compress( srcImage, destImage );
}
else
{
// Convert format and then use as the source image
ScratchImage image;
HRESULT hr;
DWORD srgb = _GetSRGBFlags( compress );
switch( format )
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
hr = _ConvertToRGBA32( srcImage, image, false, srgb );
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
hr = _ConvertToRGBA32( srcImage, image, true, srgb );
break;
case DXGI_FORMAT_R32G32B32A32_FLOAT:
hr = _ConvertToRGBAF32( srcImage, image, srgb );
break;
default:
hr = E_UNEXPECTED;
break;
}
if ( FAILED(hr) )
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
if (!srcImage.pixels)
return E_POINTER;
return gpubc->Compress( *img, destImage );
}
}
DXGI_FORMAT format = srgb ? DXGI_FORMAT_R8G8B8A8_UNORM_SRGB : DXGI_FORMAT_R8G8B8A8_UNORM;
HRESULT hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
uint8_t* pDest = img->pixels;
if (!pDest)
{
image.Release();
return E_POINTER;
}
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR) * srcImage.width), 16)));
if (!scanline)
{
image.Release();
return E_OUTOFMEMORY;
}
const uint8_t *pSrc = srcImage.pixels;
for (size_t h = 0; h < srcImage.height; ++h)
{
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
{
image.Release();
return E_FAIL;
}
_ConvertScanline(scanline.get(), srcImage.width, format, srcImage.format, filter);
if (!_StoreScanline(pDest, img->rowPitch, format, scanline.get(), srcImage.width))
{
image.Release();
return E_FAIL;
}
pSrc += srcImage.rowPitch;
pDest += img->rowPitch;
}
return S_OK;
}
//-------------------------------------------------------------------------------------
// Converts to DXGI_FORMAT_R32G32B32A32_FLOAT doing any conversion logic needed
//-------------------------------------------------------------------------------------
HRESULT ConvertToRGBAF32(
const Image& srcImage,
ScratchImage& image,
DWORD filter)
{
if (!srcImage.pixels)
return E_POINTER;
HRESULT hr = image.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
uint8_t* pDest = img->pixels;
if (!pDest)
{
image.Release();
return E_POINTER;
}
const uint8_t *pSrc = srcImage.pixels;
for (size_t h = 0; h < srcImage.height; ++h)
{
if (!_LoadScanline(reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
{
image.Release();
return E_FAIL;
}
_ConvertScanline(reinterpret_cast<XMVECTOR*>(pDest), srcImage.width, DXGI_FORMAT_R32G32B32A32_FLOAT, srcImage.format, filter);
pSrc += srcImage.rowPitch;
pDest += img->rowPitch;
}
return S_OK;
}
//-------------------------------------------------------------------------------------
// Compress using GPU, converting to the proper input format for the shader if needed
//-------------------------------------------------------------------------------------
inline HRESULT GPUCompress(
_In_ GPUCompressBC* gpubc,
const Image& srcImage,
const Image& destImage,
DWORD compress)
{
if (!gpubc)
return E_POINTER;
assert(srcImage.pixels && destImage.pixels);
DXGI_FORMAT format = gpubc->GetSourceFormat();
if (srcImage.format == format)
{
// Input is already in our required source format
return gpubc->Compress(srcImage, destImage);
}
else
{
// Convert format and then use as the source image
ScratchImage image;
HRESULT hr;
DWORD srgb = GetSRGBFlags(compress);
switch (format)
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
hr = ConvertToRGBA32(srcImage, image, false, srgb);
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
hr = ConvertToRGBA32(srcImage, image, true, srgb);
break;
case DXGI_FORMAT_R32G32B32A32_FLOAT:
hr = ConvertToRGBAF32(srcImage, image, srgb);
break;
default:
hr = E_UNEXPECTED;
break;
}
if (FAILED(hr))
return hr;
const Image *img = image.GetImage(0, 0, 0);
if (!img)
return E_POINTER;
return gpubc->Compress(*img, destImage);
}
}
};
//=====================================================================================
// Entry-points
@ -198,205 +210,216 @@ inline static HRESULT _GPUCompress( _In_ GPUCompressBC* gpubc, _In_ const Image&
// Compression
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT Compress( ID3D11Device* pDevice, const Image& srcImage, DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& image )
HRESULT DirectX::Compress(
ID3D11Device* pDevice,
const Image& srcImage,
DXGI_FORMAT format,
DWORD compress,
float alphaWeight,
ScratchImage& image)
{
if ( !pDevice || IsCompressed(srcImage.format) || !IsCompressed(format) )
if (!pDevice || IsCompressed(srcImage.format) || !IsCompressed(format))
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format)
|| IsTypeless(srcImage.format) || IsPlanar(srcImage.format) || IsPalettized(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Setup GPU compressor
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
if ( !gpubc )
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
if (!gpubc)
return E_OUTOFMEMORY;
HRESULT hr = gpubc->Initialize( pDevice );
if ( FAILED(hr) )
HRESULT hr = gpubc->Initialize(pDevice);
if (FAILED(hr))
return hr;
hr = gpubc->Prepare( srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
if ( FAILED(hr) )
hr = gpubc->Prepare(srcImage.width, srcImage.height, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
if (FAILED(hr))
return hr;
// Create workspace for result
hr = image.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
hr = image.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = image.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = image.GetImage(0, 0, 0);
if (!img)
{
image.Release();
return E_POINTER;
}
hr = _GPUCompress( gpubc.get(), srcImage, *img, compress );
if ( FAILED(hr) )
hr = GPUCompress(gpubc.get(), srcImage, *img, compress);
if (FAILED(hr))
image.Release();
return hr;
}
_Use_decl_annotations_
HRESULT Compress( ID3D11Device* pDevice, const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DXGI_FORMAT format, DWORD compress, float alphaWeight, ScratchImage& cImages )
HRESULT DirectX::Compress(
ID3D11Device* pDevice,
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DXGI_FORMAT format,
DWORD compress,
float alphaWeight,
ScratchImage& cImages)
{
if ( !pDevice || !srcImages || !nimages )
if (!pDevice || !srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed(metadata.format) || !IsCompressed(format) )
if (IsCompressed(metadata.format) || !IsCompressed(format))
return E_INVALIDARG;
if ( IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsTypeless(format)
|| IsTypeless(metadata.format) || IsPlanar(metadata.format) || IsPalettized(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
cImages.Release();
// Setup GPU compressor
std::unique_ptr<GPUCompressBC> gpubc( new (std::nothrow) GPUCompressBC );
if ( !gpubc )
std::unique_ptr<GPUCompressBC> gpubc(new (std::nothrow) GPUCompressBC);
if (!gpubc)
return E_OUTOFMEMORY;
HRESULT hr = gpubc->Initialize( pDevice );
if ( FAILED(hr) )
HRESULT hr = gpubc->Initialize(pDevice);
if (FAILED(hr))
return hr;
// Create workspace for result
TexMetadata mdata2 = metadata;
mdata2.format = format;
hr = cImages.Initialize( mdata2 );
if ( FAILED(hr) )
hr = cImages.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != cImages.GetImageCount() )
if (nimages != cImages.GetImageCount())
{
cImages.Release();
return E_FAIL;
}
const Image* dest = cImages.GetImages();
if ( !dest )
if (!dest)
{
cImages.Release();
return E_POINTER;
}
// Process images (ordered by size)
switch( metadata.dimension )
switch (metadata.dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
{
size_t w = metadata.width;
size_t h = metadata.height;
{
size_t w = metadata.width;
size_t h = metadata.height;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
if (FAILED(hr))
{
hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
if ( FAILED(hr) )
cImages.Release();
return hr;
}
for (size_t item = 0; item < metadata.arraySize; ++item)
{
size_t index = metadata.ComputeIndex(level, item, 0);
if (index >= nimages)
{
cImages.Release();
return E_FAIL;
}
assert(dest[index].format == format);
const Image& src = srcImages[index];
if (src.width != dest[index].width || src.height != dest[index].height)
{
cImages.Release();
return E_FAIL;
}
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
if (FAILED(hr))
{
cImages.Release();
return hr;
}
for( size_t item = 0; item < metadata.arraySize; ++item )
{
size_t index = metadata.ComputeIndex( level, item, 0 );
if ( index >= nimages )
{
cImages.Release();
return E_FAIL;
}
assert( dest[ index ].format == format );
const Image& src = srcImages[ index ];
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
{
cImages.Release();
return E_FAIL;
}
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
if ( FAILED(hr) )
{
cImages.Release();
return hr;
}
}
if ( h > 1 )
h >>= 1;
if ( w > 1 )
w >>= 1;
}
if (h > 1)
h >>= 1;
if (w > 1)
w >>= 1;
}
break;
}
break;
case TEX_DIMENSION_TEXTURE3D:
{
size_t w = metadata.width;
size_t h = metadata.height;
size_t d = metadata.depth;
{
size_t w = metadata.width;
size_t h = metadata.height;
size_t d = metadata.depth;
for( size_t level=0; level < metadata.mipLevels; ++level )
for (size_t level = 0; level < metadata.mipLevels; ++level)
{
hr = gpubc->Prepare(w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS));
if (FAILED(hr))
{
hr = gpubc->Prepare( w, h, format, alphaWeight, !(compress & TEX_COMPRESS_BC7_USE_3SUBSETS) );
if ( FAILED(hr) )
cImages.Release();
return hr;
}
for (size_t slice = 0; slice < d; ++slice)
{
size_t index = metadata.ComputeIndex(level, 0, slice);
if (index >= nimages)
{
cImages.Release();
return E_FAIL;
}
assert(dest[index].format == format);
const Image& src = srcImages[index];
if (src.width != dest[index].width || src.height != dest[index].height)
{
cImages.Release();
return E_FAIL;
}
hr = GPUCompress(gpubc.get(), src, dest[index], compress);
if (FAILED(hr))
{
cImages.Release();
return hr;
}
for( size_t slice=0; slice < d; ++slice )
{
size_t index = metadata.ComputeIndex( level, 0, slice );
if ( index >= nimages )
{
cImages.Release();
return E_FAIL;
}
assert( dest[ index ].format == format );
const Image& src = srcImages[ index ];
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
{
cImages.Release();
return E_FAIL;
}
hr = _GPUCompress( gpubc.get(), src, dest[ index ], compress );
if ( FAILED(hr) )
{
cImages.Release();
return hr;
}
}
if ( h > 1 )
h >>= 1;
if ( w > 1 )
w >>= 1;
if ( d > 1 )
d >>= 1;
}
if (h > 1)
h >>= 1;
if (w > 1)
w >>= 1;
if (d > 1)
d >>= 1;
}
break;
}
break;
default:
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
return S_OK;
}
}; // namespace

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -15,110 +15,117 @@
#include "directxtexp.h"
using namespace DirectX;
using Microsoft::WRL::ComPtr;
namespace DirectX
namespace
{
//-------------------------------------------------------------------------------------
// Do flip/rotate operation using WIC
//-------------------------------------------------------------------------------------
static HRESULT _PerformFlipRotateUsingWIC( _In_ const Image& srcImage, _In_ DWORD flags,
_In_ const WICPixelFormatGUID& pfGUID, _In_ const Image& destImage )
{
if ( !srcImage.pixels || !destImage.pixels )
return E_POINTER;
assert( srcImage.format == destImage.format );
bool iswic2 = false;
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
if ( !pWIC )
return E_NOINTERFACE;
ComPtr<IWICBitmap> source;
HRESULT hr = pWIC->CreateBitmapFromMemory( static_cast<UINT>( srcImage.width ), static_cast<UINT>( srcImage.height ), pfGUID,
static_cast<UINT>( srcImage.rowPitch ), static_cast<UINT>( srcImage.slicePitch ),
srcImage.pixels, source.GetAddressOf() );
if ( FAILED(hr) )
return hr;
ComPtr<IWICBitmapFlipRotator> FR;
hr = pWIC->CreateBitmapFlipRotator( FR.GetAddressOf() );
if ( FAILED(hr) )
return hr;
hr = FR->Initialize( source.Get(), static_cast<WICBitmapTransformOptions>( flags ) );
if ( FAILED(hr) )
return hr;
WICPixelFormatGUID pfFR;
hr = FR->GetPixelFormat( &pfFR );
if ( FAILED(hr) )
return hr;
if ( memcmp( &pfFR, &pfGUID, sizeof(GUID) ) != 0 )
//-------------------------------------------------------------------------------------
// Do flip/rotate operation using WIC
//-------------------------------------------------------------------------------------
HRESULT PerformFlipRotateUsingWIC(
const Image& srcImage,
DWORD flags,
const WICPixelFormatGUID& pfGUID,
const Image& destImage)
{
// Flip/rotate should return the same format as the source...
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (!srcImage.pixels || !destImage.pixels)
return E_POINTER;
assert(srcImage.format == destImage.format);
bool iswic2 = false;
IWICImagingFactory* pWIC = GetWICFactory(iswic2);
if (!pWIC)
return E_NOINTERFACE;
ComPtr<IWICBitmap> source;
HRESULT hr = pWIC->CreateBitmapFromMemory(static_cast<UINT>(srcImage.width), static_cast<UINT>(srcImage.height), pfGUID,
static_cast<UINT>(srcImage.rowPitch), static_cast<UINT>(srcImage.slicePitch),
srcImage.pixels, source.GetAddressOf());
if (FAILED(hr))
return hr;
ComPtr<IWICBitmapFlipRotator> FR;
hr = pWIC->CreateBitmapFlipRotator(FR.GetAddressOf());
if (FAILED(hr))
return hr;
hr = FR->Initialize(source.Get(), static_cast<WICBitmapTransformOptions>(flags));
if (FAILED(hr))
return hr;
WICPixelFormatGUID pfFR;
hr = FR->GetPixelFormat(&pfFR);
if (FAILED(hr))
return hr;
if (memcmp(&pfFR, &pfGUID, sizeof(GUID)) != 0)
{
// Flip/rotate should return the same format as the source...
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
UINT nwidth, nheight;
hr = FR->GetSize(&nwidth, &nheight);
if (FAILED(hr))
return hr;
if (destImage.width != nwidth || destImage.height != nheight)
return E_FAIL;
hr = FR->CopyPixels(0, static_cast<UINT>(destImage.rowPitch), static_cast<UINT>(destImage.slicePitch), destImage.pixels);
if (FAILED(hr))
return hr;
return S_OK;
}
UINT nwidth, nheight;
hr = FR->GetSize( &nwidth, &nheight );
if ( FAILED(hr) )
return hr;
if ( destImage.width != nwidth || destImage.height != nheight )
return E_FAIL;
//-------------------------------------------------------------------------------------
// Do conversion, flip/rotate using WIC, conversion cycle
//-------------------------------------------------------------------------------------
HRESULT PerformFlipRotateViaF32(
const Image& srcImage,
DWORD flags,
const Image& destImage)
{
if (!srcImage.pixels || !destImage.pixels)
return E_POINTER;
hr = FR->CopyPixels( 0, static_cast<UINT>( destImage.rowPitch ), static_cast<UINT>( destImage.slicePitch ), destImage.pixels );
if ( FAILED(hr) )
return hr;
assert(srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT);
assert(srcImage.format == destImage.format);
return S_OK;
}
ScratchImage temp;
HRESULT hr = _ConvertToR32G32B32A32(srcImage, temp);
if (FAILED(hr))
return hr;
const Image *tsrc = temp.GetImage(0, 0, 0);
if (!tsrc)
return E_POINTER;
//-------------------------------------------------------------------------------------
// Do conversion, flip/rotate using WIC, conversion cycle
//-------------------------------------------------------------------------------------
static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
{
if ( !srcImage.pixels || !destImage.pixels )
return E_POINTER;
ScratchImage rtemp;
hr = rtemp.Initialize2D(DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1);
if (FAILED(hr))
return hr;
assert( srcImage.format != DXGI_FORMAT_R32G32B32A32_FLOAT );
assert( srcImage.format == destImage.format );
const Image *tdest = rtemp.GetImage(0, 0, 0);
if (!tdest)
return E_POINTER;
ScratchImage temp;
HRESULT hr = _ConvertToR32G32B32A32( srcImage, temp );
if ( FAILED(hr) )
return hr;
hr = PerformFlipRotateUsingWIC(*tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest);
if (FAILED(hr))
return hr;
const Image *tsrc = temp.GetImage( 0, 0, 0 );
if ( !tsrc )
return E_POINTER;
temp.Release();
ScratchImage rtemp;
hr = rtemp.Initialize2D( DXGI_FORMAT_R32G32B32A32_FLOAT, destImage.width, destImage.height, 1, 1 );
if ( FAILED(hr) )
return hr;
hr = _ConvertFromR32G32B32A32(*tdest, destImage);
if (FAILED(hr))
return hr;
const Image *tdest = rtemp.GetImage( 0, 0, 0 );
if ( !tdest )
return E_POINTER;
hr = _PerformFlipRotateUsingWIC( *tsrc, flags, GUID_WICPixelFormat128bppRGBAFloat, *tdest );
if ( FAILED(hr) )
return hr;
temp.Release();
hr = _ConvertFromR32G32B32A32( *tdest, destImage );
if ( FAILED(hr) )
return hr;
return S_OK;
return S_OK;
}
}
@ -130,32 +137,35 @@ static HRESULT _PerformFlipRotateViaF32( _In_ const Image& srcImage, _In_ DWORD
// Flip/rotate image
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
HRESULT DirectX::FlipRotate(
const Image& srcImage,
DWORD flags,
ScratchImage& image)
{
if ( !srcImage.pixels )
if (!srcImage.pixels)
return E_POINTER;
if ( !flags )
if (!flags)
return E_INVALIDARG;
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
return E_INVALIDARG;
if ( IsCompressed( srcImage.format ) )
if (IsCompressed(srcImage.format))
{
// We don't support flip/rotate operations on compressed images
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
static_assert(TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC");
static_assert(TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC");
static_assert(TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC");
static_assert(TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC");
static_assert(TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC");
static_assert(TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC");
// Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270))
{
case 0:
case TEX_FR_ROTATE90:
@ -170,33 +180,33 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
size_t nwidth = srcImage.width;
size_t nheight = srcImage.height;
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
{
nwidth = srcImage.height;
nheight = srcImage.width;
}
HRESULT hr = image.Initialize2D( srcImage.format, nwidth, nheight, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(srcImage.format, nwidth, nheight, 1, 1);
if (FAILED(hr))
return hr;
const Image *rimage = image.GetImage( 0, 0, 0 );
if ( !rimage )
const Image *rimage = image.GetImage(0, 0, 0);
if (!rimage)
return E_POINTER;
WICPixelFormatGUID pfGUID;
if ( _DXGIToWIC( srcImage.format, pfGUID ) )
if (_DXGIToWIC(srcImage.format, pfGUID))
{
// Case 1: Source format is supported by Windows Imaging Component
hr = _PerformFlipRotateUsingWIC( srcImage, flags, pfGUID, *rimage );
hr = PerformFlipRotateUsingWIC(srcImage, flags, pfGUID, *rimage);
}
else
{
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
hr = _PerformFlipRotateViaF32( srcImage, flags, *rimage );
hr = PerformFlipRotateViaF32(srcImage, flags, *rimage);
}
if ( FAILED(hr) )
if (FAILED(hr))
{
image.Release();
return hr;
@ -210,27 +220,31 @@ HRESULT FlipRotate( const Image& srcImage, DWORD flags, ScratchImage& image )
// Flip/rotate image (complex)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD flags, ScratchImage& result )
HRESULT DirectX::FlipRotate(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DWORD flags,
ScratchImage& result)
{
if ( !srcImages || !nimages )
if (!srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed( metadata.format ) )
if (IsCompressed(metadata.format))
{
// We don't support flip/rotate operations on compressed images
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
static_assert( TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC" );
static_assert( TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC" );
static_assert( TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC" );
static_assert( TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC" );
static_assert( TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC" );
static_assert( TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC" );
static_assert(TEX_FR_ROTATE0 == WICBitmapTransformRotate0, "TEX_FR_ROTATE0 no longer matches WIC");
static_assert(TEX_FR_ROTATE90 == WICBitmapTransformRotate90, "TEX_FR_ROTATE90 no longer matches WIC");
static_assert(TEX_FR_ROTATE180 == WICBitmapTransformRotate180, "TEX_FR_ROTATE180 no longer matches WIC");
static_assert(TEX_FR_ROTATE270 == WICBitmapTransformRotate270, "TEX_FR_ROTATE270 no longer matches WIC");
static_assert(TEX_FR_FLIP_HORIZONTAL == WICBitmapTransformFlipHorizontal, "TEX_FR_FLIP_HORIZONTAL no longer matches WIC");
static_assert(TEX_FR_FLIP_VERTICAL == WICBitmapTransformFlipVertical, "TEX_FR_FLIP_VERTICAL no longer matches WIC");
// Only supports 90, 180, 270, or no rotation flags... not a combination of rotation flags
switch ( flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE180|TEX_FR_ROTATE270) )
switch (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE180 | TEX_FR_ROTATE270))
{
case 0:
case TEX_FR_ROTATE90:
@ -245,51 +259,51 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
TexMetadata mdata2 = metadata;
bool flipwh = false;
if (flags & (TEX_FR_ROTATE90|TEX_FR_ROTATE270))
if (flags & (TEX_FR_ROTATE90 | TEX_FR_ROTATE270))
{
flipwh = true;
mdata2.width = metadata.height;
mdata2.height = metadata.width;
}
HRESULT hr = result.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = result.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != result.GetImageCount() )
if (nimages != result.GetImageCount())
{
result.Release();
return E_FAIL;
}
const Image* dest = result.GetImages();
if ( !dest )
if (!dest)
{
result.Release();
return E_POINTER;
}
WICPixelFormatGUID pfGUID;
bool wicpf = _DXGIToWIC( metadata.format, pfGUID );
bool wicpf = _DXGIToWIC(metadata.format, pfGUID);
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
const Image& src = srcImages[ index ];
if ( src.format != metadata.format )
const Image& src = srcImages[index];
if (src.format != metadata.format)
{
result.Release();
return E_FAIL;
}
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
return E_FAIL;
const Image& dst = dest[ index ];
assert( dst.format == metadata.format );
const Image& dst = dest[index];
assert(dst.format == metadata.format);
if ( flipwh )
if (flipwh)
{
if ( src.width != dst.height || src.height != dst.width )
if (src.width != dst.height || src.height != dst.width)
{
result.Release();
return E_FAIL;
@ -297,7 +311,7 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
}
else
{
if ( src.width != dst.width || src.height != dst.height )
if (src.width != dst.width || src.height != dst.height)
{
result.Release();
return E_FAIL;
@ -307,15 +321,15 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
if (wicpf)
{
// Case 1: Source format is supported by Windows Imaging Component
hr = _PerformFlipRotateUsingWIC( src, flags, pfGUID, dst );
hr = PerformFlipRotateUsingWIC(src, flags, pfGUID, dst);
}
else
{
// Case 2: Source format is not supported by WIC, so we have to convert, flip/rotate, and convert back
hr = _PerformFlipRotateViaF32( src, flags, dst );
hr = PerformFlipRotateViaF32(src, flags, dst);
}
if ( FAILED(hr) )
if (FAILED(hr))
{
result.Release();
return hr;
@ -324,5 +338,3 @@ HRESULT FlipRotate( const Image* srcImages, size_t nimages, const TexMetadata& m
return S_OK;
}
}; // namespace

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -15,152 +15,158 @@
#include "directxtexp.h"
namespace DirectX
using namespace DirectX;
namespace
{
static const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
const XMVECTORF32 g_Gamma22 = { 2.2f, 2.2f, 2.2f, 1.f };
//-------------------------------------------------------------------------------------
static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
_Out_ float& mse, _Out_writes_opt_(4) float* mseV,
_In_ DWORD flags )
{
if ( !image1.pixels || !image2.pixels )
return E_POINTER;
assert( image1.width == image2.width && image1.height == image2.height );
assert( !IsCompressed( image1.format ) && !IsCompressed( image2.format ) );
const size_t width = image1.width;
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width)*2, 16 ) ) );
if ( !scanline )
return E_OUTOFMEMORY;
// Flags implied from image formats
switch( image1.format )
//-------------------------------------------------------------------------------------
HRESULT ComputeMSE_(
const Image& image1,
const Image& image2,
float& mse,
_Out_writes_opt_(4) float* mseV,
DWORD flags)
{
case DXGI_FORMAT_B8G8R8X8_UNORM:
flags |= CMSE_IGNORE_ALPHA;
break;
if (!image1.pixels || !image2.pixels)
return E_POINTER;
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
flags |= CMSE_IMAGE1_SRGB | CMSE_IGNORE_ALPHA;
break;
assert(image1.width == image2.width && image1.height == image2.height);
assert(!IsCompressed(image1.format) && !IsCompressed(image2.format));
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_BC7_UNORM_SRGB:
flags |= CMSE_IMAGE1_SRGB;
break;
}
const size_t width = image1.width;
switch( image2.format )
{
case DXGI_FORMAT_B8G8R8X8_UNORM:
flags |= CMSE_IGNORE_ALPHA;
break;
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width) * 2, 16)));
if (!scanline)
return E_OUTOFMEMORY;
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
flags |= CMSE_IMAGE2_SRGB | CMSE_IGNORE_ALPHA;
break;
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_BC7_UNORM_SRGB:
flags |= CMSE_IMAGE2_SRGB;
break;
}
const uint8_t *pSrc1 = image1.pixels;
const size_t rowPitch1 = image1.rowPitch;
const uint8_t *pSrc2 = image2.pixels;
const size_t rowPitch2 = image2.rowPitch;
XMVECTOR acc = g_XMZero;
static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
for( size_t h = 0; h < image1.height; ++h )
{
XMVECTOR* ptr1 = scanline.get();
if ( !_LoadScanline( ptr1, width, pSrc1, rowPitch1, image1.format ) )
return E_FAIL;
XMVECTOR* ptr2 = scanline.get() + width;
if ( !_LoadScanline( ptr2, width, pSrc2, rowPitch2, image2.format ) )
return E_FAIL;
for( size_t i = 0; i < width; ++i )
// Flags implied from image formats
switch (image1.format)
{
XMVECTOR v1 = *(ptr1++);
if ( flags & CMSE_IMAGE1_SRGB )
{
v1 = XMVectorPow( v1, g_Gamma22 );
}
if ( flags & CMSE_IMAGE1_X2_BIAS )
{
v1 = XMVectorMultiplyAdd( v1, two, g_XMNegativeOne );
}
case DXGI_FORMAT_B8G8R8X8_UNORM:
flags |= CMSE_IGNORE_ALPHA;
break;
XMVECTOR v2 = *(ptr2++);
if ( flags & CMSE_IMAGE2_SRGB )
{
v2 = XMVectorPow( v2, g_Gamma22 );
}
if ( flags & CMSE_IMAGE2_X2_BIAS )
{
v1 = XMVectorMultiplyAdd( v2, two, g_XMNegativeOne );
}
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
flags |= CMSE_IMAGE1_SRGB | CMSE_IGNORE_ALPHA;
break;
// sum[ (I1 - I2)^2 ]
XMVECTOR v = XMVectorSubtract( v1, v2 );
if ( flags & CMSE_IGNORE_RED )
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskX );
}
if ( flags & CMSE_IGNORE_GREEN )
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskY );
}
if ( flags & CMSE_IGNORE_BLUE )
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskZ );
}
if ( flags & CMSE_IGNORE_ALPHA )
{
v = XMVectorSelect( v, g_XMZero, g_XMMaskW );
}
acc = XMVectorMultiplyAdd( v, v, acc );
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_BC7_UNORM_SRGB:
flags |= CMSE_IMAGE1_SRGB;
break;
}
pSrc1 += rowPitch1;
pSrc2 += rowPitch2;
}
switch (image2.format)
{
case DXGI_FORMAT_B8G8R8X8_UNORM:
flags |= CMSE_IGNORE_ALPHA;
break;
// MSE = sum[ (I1 - I2)^2 ] / w*h
XMVECTOR d = XMVectorReplicate( float(image1.width * image1.height) );
XMVECTOR v = XMVectorDivide( acc, d );
if ( mseV )
{
XMStoreFloat4( reinterpret_cast<XMFLOAT4*>( mseV ), v );
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
}
else
{
XMFLOAT4 _mseV;
XMStoreFloat4( &_mseV, v );
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
}
case DXGI_FORMAT_B8G8R8X8_UNORM_SRGB:
flags |= CMSE_IMAGE2_SRGB | CMSE_IGNORE_ALPHA;
break;
return S_OK;
}
case DXGI_FORMAT_R8G8B8A8_UNORM_SRGB:
case DXGI_FORMAT_BC1_UNORM_SRGB:
case DXGI_FORMAT_BC2_UNORM_SRGB:
case DXGI_FORMAT_BC3_UNORM_SRGB:
case DXGI_FORMAT_B8G8R8A8_UNORM_SRGB:
case DXGI_FORMAT_BC7_UNORM_SRGB:
flags |= CMSE_IMAGE2_SRGB;
break;
}
const uint8_t *pSrc1 = image1.pixels;
const size_t rowPitch1 = image1.rowPitch;
const uint8_t *pSrc2 = image2.pixels;
const size_t rowPitch2 = image2.rowPitch;
XMVECTOR acc = g_XMZero;
static XMVECTORF32 two = { 2.0f, 2.0f, 2.0f, 2.0f };
for (size_t h = 0; h < image1.height; ++h)
{
XMVECTOR* ptr1 = scanline.get();
if (!_LoadScanline(ptr1, width, pSrc1, rowPitch1, image1.format))
return E_FAIL;
XMVECTOR* ptr2 = scanline.get() + width;
if (!_LoadScanline(ptr2, width, pSrc2, rowPitch2, image2.format))
return E_FAIL;
for (size_t i = 0; i < width; ++i)
{
XMVECTOR v1 = *(ptr1++);
if (flags & CMSE_IMAGE1_SRGB)
{
v1 = XMVectorPow(v1, g_Gamma22);
}
if (flags & CMSE_IMAGE1_X2_BIAS)
{
v1 = XMVectorMultiplyAdd(v1, two, g_XMNegativeOne);
}
XMVECTOR v2 = *(ptr2++);
if (flags & CMSE_IMAGE2_SRGB)
{
v2 = XMVectorPow(v2, g_Gamma22);
}
if (flags & CMSE_IMAGE2_X2_BIAS)
{
v1 = XMVectorMultiplyAdd(v2, two, g_XMNegativeOne);
}
// sum[ (I1 - I2)^2 ]
XMVECTOR v = XMVectorSubtract(v1, v2);
if (flags & CMSE_IGNORE_RED)
{
v = XMVectorSelect(v, g_XMZero, g_XMMaskX);
}
if (flags & CMSE_IGNORE_GREEN)
{
v = XMVectorSelect(v, g_XMZero, g_XMMaskY);
}
if (flags & CMSE_IGNORE_BLUE)
{
v = XMVectorSelect(v, g_XMZero, g_XMMaskZ);
}
if (flags & CMSE_IGNORE_ALPHA)
{
v = XMVectorSelect(v, g_XMZero, g_XMMaskW);
}
acc = XMVectorMultiplyAdd(v, v, acc);
}
pSrc1 += rowPitch1;
pSrc2 += rowPitch2;
}
// MSE = sum[ (I1 - I2)^2 ] / w*h
XMVECTOR d = XMVectorReplicate(float(image1.width * image1.height));
XMVECTOR v = XMVectorDivide(acc, d);
if (mseV)
{
XMStoreFloat4(reinterpret_cast<XMFLOAT4*>(mseV), v);
mse = mseV[0] + mseV[1] + mseV[2] + mseV[3];
}
else
{
XMFLOAT4 _mseV;
XMStoreFloat4(&_mseV, v);
mse = _mseV.x + _mseV.y + _mseV.z + _mseV.w;
}
return S_OK;
}
};
//=====================================================================================
@ -171,57 +177,63 @@ static HRESULT _ComputeMSE( _In_ const Image& image1, _In_ const Image& image2,
// Copies a rectangle from one image into another
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image& dstImage, DWORD filter, size_t xOffset, size_t yOffset )
HRESULT DirectX::CopyRectangle(
const Image& srcImage,
const Rect& srcRect,
const Image& dstImage,
DWORD filter,
size_t xOffset,
size_t yOffset)
{
if ( !srcImage.pixels || !dstImage.pixels )
if (!srcImage.pixels || !dstImage.pixels)
return E_POINTER;
if ( IsCompressed( srcImage.format ) || IsCompressed( dstImage.format )
|| IsPlanar( srcImage.format ) || IsPlanar( dstImage.format )
|| IsPalettized( srcImage.format ) || IsPalettized( dstImage.format ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsCompressed(srcImage.format) || IsCompressed(dstImage.format)
|| IsPlanar(srcImage.format) || IsPlanar(dstImage.format)
|| IsPalettized(srcImage.format) || IsPalettized(dstImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Validate rectangle/offset
if ( !srcRect.w || !srcRect.h || ( (srcRect.x + srcRect.w) > srcImage.width ) || ( (srcRect.y + srcRect.h) > srcImage.height ) )
if (!srcRect.w || !srcRect.h || ((srcRect.x + srcRect.w) > srcImage.width) || ((srcRect.y + srcRect.h) > srcImage.height))
{
return E_INVALIDARG;
}
if ( ( (xOffset + srcRect.w) > dstImage.width ) || ( (yOffset + srcRect.h) > dstImage.height ) )
if (((xOffset + srcRect.w) > dstImage.width) || ((yOffset + srcRect.h) > dstImage.height))
{
return E_INVALIDARG;
}
// Compute source bytes-per-pixel
size_t sbpp = BitsPerPixel( srcImage.format );
if ( !sbpp )
size_t sbpp = BitsPerPixel(srcImage.format);
if (!sbpp)
return E_FAIL;
if ( sbpp < 8 )
if (sbpp < 8)
{
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
const uint8_t* pEndSrc = srcImage.pixels + srcImage.rowPitch*srcImage.height;
const uint8_t* pEndDest = dstImage.pixels + dstImage.rowPitch*dstImage.height;
// Round to bytes
sbpp = ( sbpp + 7 ) / 8;
sbpp = (sbpp + 7) / 8;
const uint8_t* pSrc = srcImage.pixels + (srcRect.y * srcImage.rowPitch) + (srcRect.x * sbpp);
if ( srcImage.format == dstImage.format )
if (srcImage.format == dstImage.format)
{
// Direct copy case (avoid intermediate conversions)
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * sbpp);
const size_t copyW = srcRect.w * sbpp;
for( size_t h=0; h < srcRect.h; ++h )
for (size_t h = 0; h < srcRect.h; ++h)
{
if ( ( (pSrc+copyW) > pEndSrc ) || (pDest > pEndDest) )
if (((pSrc + copyW) > pEndSrc) || (pDest > pEndDest))
return E_FAIL;
memcpy_s( pDest, pEndDest - pDest, pSrc, copyW );
memcpy_s(pDest, pEndDest - pDest, pSrc, copyW);
pSrc += srcImage.rowPitch;
pDest += dstImage.rowPitch;
@ -231,39 +243,39 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
}
// Compute destination bytes-per-pixel (not the same format as source)
size_t dbpp = BitsPerPixel( dstImage.format );
if ( !dbpp )
size_t dbpp = BitsPerPixel(dstImage.format);
if (!dbpp)
return E_FAIL;
if ( dbpp < 8 )
if (dbpp < 8)
{
// We don't support monochrome (DXGI_FORMAT_R1_UNORM)
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
// Round to bytes
dbpp = ( dbpp + 7 ) / 8;
dbpp = (dbpp + 7) / 8;
uint8_t* pDest = dstImage.pixels + (yOffset * dstImage.rowPitch) + (xOffset * dbpp);
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcRect.w), 16 ) ) );
if ( !scanline )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcRect.w), 16)));
if (!scanline)
return E_OUTOFMEMORY;
const size_t copyS = srcRect.w * sbpp;
const size_t copyD = srcRect.w * dbpp;
for( size_t h=0; h < srcRect.h; ++h )
for (size_t h = 0; h < srcRect.h; ++h)
{
if ( ( (pSrc+copyS) > pEndSrc) || ((pDest+copyD) > pEndDest) )
if (((pSrc + copyS) > pEndSrc) || ((pDest + copyD) > pEndDest))
return E_FAIL;
if ( !_LoadScanline( scanline.get(), srcRect.w, pSrc, copyS, srcImage.format ) )
if (!_LoadScanline(scanline.get(), srcRect.w, pSrc, copyS, srcImage.format))
return E_FAIL;
_ConvertScanline( scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter );
_ConvertScanline(scanline.get(), srcRect.w, dstImage.format, srcImage.format, filter);
if ( !_StoreScanline( pDest, copyD, dstImage.format, scanline.get(), srcRect.w ) )
if (!_StoreScanline(pDest, copyD, dstImage.format, scanline.get(), srcRect.w))
return E_FAIL;
pSrc += srcImage.rowPitch;
@ -278,77 +290,80 @@ HRESULT CopyRectangle( const Image& srcImage, const Rect& srcRect, const Image&
// Computes the Mean-Squared-Error (MSE) between two images
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT ComputeMSE( const Image& image1, const Image& image2, float& mse, float* mseV, DWORD flags )
HRESULT DirectX::ComputeMSE(
const Image& image1,
const Image& image2,
float& mse,
float* mseV,
DWORD flags)
{
if ( !image1.pixels || !image2.pixels )
if (!image1.pixels || !image2.pixels)
return E_POINTER;
if ( image1.width != image2.width || image1.height != image2.height )
if (image1.width != image2.width || image1.height != image2.height)
return E_INVALIDARG;
if ( IsPlanar( image1.format ) || IsPlanar( image2.format )
|| IsPalettized( image1.format ) || IsPalettized( image2.format ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsPlanar(image1.format) || IsPlanar(image2.format)
|| IsPalettized(image1.format) || IsPalettized(image2.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( IsCompressed(image1.format) )
if (IsCompressed(image1.format))
{
if ( IsCompressed(image2.format) )
if (IsCompressed(image2.format))
{
// Case 1: both images are compressed, expand to RGBA32F
ScratchImage temp1;
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1 );
if ( FAILED(hr) )
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp1);
if (FAILED(hr))
return hr;
ScratchImage temp2;
hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2 );
if ( FAILED(hr) )
hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp2);
if (FAILED(hr))
return hr;
const Image* img1 = temp1.GetImage(0,0,0);
const Image* img2 = temp2.GetImage(0,0,0);
if ( !img1 || !img2 )
const Image* img1 = temp1.GetImage(0, 0, 0);
const Image* img2 = temp2.GetImage(0, 0, 0);
if (!img1 || !img2)
return E_POINTER;
return _ComputeMSE( *img1, *img2, mse, mseV, flags );
return ComputeMSE_(*img1, *img2, mse, mseV, flags);
}
else
{
// Case 2: image1 is compressed, expand to RGBA32F
ScratchImage temp;
HRESULT hr = Decompress( image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
if ( FAILED(hr) )
HRESULT hr = Decompress(image1, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
if (FAILED(hr))
return hr;
const Image* img = temp.GetImage(0,0,0);
if ( !img )
const Image* img = temp.GetImage(0, 0, 0);
if (!img)
return E_POINTER;
return _ComputeMSE( *img, image2, mse, mseV, flags );
return ComputeMSE_(*img, image2, mse, mseV, flags);
}
}
else
{
if ( IsCompressed(image2.format) )
if (IsCompressed(image2.format))
{
// Case 3: image2 is compressed, expand to RGBA32F
ScratchImage temp;
HRESULT hr = Decompress( image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp );
if ( FAILED(hr) )
HRESULT hr = Decompress(image2, DXGI_FORMAT_R32G32B32A32_FLOAT, temp);
if (FAILED(hr))
return hr;
const Image* img = temp.GetImage(0,0,0);
if ( !img )
const Image* img = temp.GetImage(0, 0, 0);
if (!img)
return E_POINTER;
return _ComputeMSE( image1, *img, mse, mseV, flags );
return ComputeMSE_(image1, *img, mse, mseV, flags);
}
else
{
// Case 4: neither image is compressed
return _ComputeMSE( image1, image2, mse, mseV, flags );
return ComputeMSE_(image1, image2, mse, mseV, flags);
}
}
}
}; // namespace

Просмотреть файл

@ -15,232 +15,238 @@
#include "directxtexp.h"
namespace DirectX
using namespace DirectX;
namespace
{
#pragma prefast(suppress : 25000, "FXMVECTOR is 16 bytes")
static inline float _EvaluateColor( _In_ FXMVECTOR val, _In_ DWORD flags )
{
XMFLOAT4A f;
static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.f };
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
inline float EvaluateColor(_In_ FXMVECTOR val, _In_ DWORD flags)
{
case 0:
case CNMAP_CHANNEL_RED: return XMVectorGetX( val );
case CNMAP_CHANNEL_GREEN: return XMVectorGetY( val );
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ( val );
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW( val );
XMFLOAT4A f;
case CNMAP_CHANNEL_LUMINANCE:
static XMVECTORF32 lScale = { 0.2125f, 0.7154f, 0.0721f, 1.f };
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
switch (flags & 0xf)
{
XMVECTOR v = XMVectorMultiply( val, lScale );
XMStoreFloat4A( &f, v );
case 0:
case CNMAP_CHANNEL_RED: return XMVectorGetX(val);
case CNMAP_CHANNEL_GREEN: return XMVectorGetY(val);
case CNMAP_CHANNEL_BLUE: return XMVectorGetZ(val);
case CNMAP_CHANNEL_ALPHA: return XMVectorGetW(val);
case CNMAP_CHANNEL_LUMINANCE:
{
XMVECTOR v = XMVectorMultiply(val, lScale);
XMStoreFloat4A(&f, v);
return f.x + f.y + f.z;
}
break;
default:
assert(false);
return 0.f;
}
}
static void _EvaluateRow( _In_reads_(width) const XMVECTOR* pSource, _Out_writes_(width+2) float* pDest,
_In_ size_t width, _In_ DWORD flags )
{
assert( pSource && pDest );
assert( width > 0 );
for( size_t x = 0; x < width; ++x )
{
pDest[x+1] = _EvaluateColor( pSource[x], flags );
default:
assert(false);
return 0.f;
}
}
if ( flags & CNMAP_MIRROR_U )
void EvaluateRow(
_In_reads_(width) const XMVECTOR* pSource,
_Out_writes_(width + 2) float* pDest,
size_t width,
DWORD flags)
{
// Mirror in U
pDest[0] = _EvaluateColor( pSource[0], flags );
pDest[width+1] = _EvaluateColor( pSource[width-1], flags );
}
else
{
// Wrap in U
pDest[0] = _EvaluateColor( pSource[width-1], flags );
pDest[width+1] = _EvaluateColor( pSource[0], flags );
}
}
assert(pSource && pDest);
assert(width > 0);
static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
_In_ DXGI_FORMAT format, _In_ const Image& normalMap )
{
if ( !srcImage.pixels || !normalMap.pixels )
return E_INVALIDARG;
const DWORD convFlags = _GetConvertFlags( format );
if ( !convFlags )
return E_FAIL;
if ( !( convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT) ) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
const size_t width = srcImage.width;
const size_t height = srcImage.height;
if ( width != normalMap.width || height != normalMap.height )
return E_FAIL;
// Allocate temporary space (4 scanlines and 3 evaluated rows)
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*width*4), 16 ) ) );
if ( !scanline )
return E_OUTOFMEMORY;
ScopedAlignedArrayFloat buffer( reinterpret_cast<float*>( _aligned_malloc( ( ( sizeof(float) * ( width + 2 ) ) * 3 ), 16 ) ) );
if ( !buffer )
return E_OUTOFMEMORY;
uint8_t* pDest = normalMap.pixels;
if ( !pDest )
return E_POINTER;
XMVECTOR* row0 = scanline.get();
XMVECTOR* row1 = row0 + width;
XMVECTOR* row2 = row1 + width;
XMVECTOR* target = row2 + width;
float* val0 = buffer.get();
float* val1 = val0 + width + 2;
float* val2 = val1 + width + 2;
const size_t rowPitch = srcImage.rowPitch;
const uint8_t* pSrc = srcImage.pixels;
// Read first scanline row into 'row1'
if ( !_LoadScanline( row1, width, pSrc, rowPitch, srcImage.format ) )
return E_FAIL;
// Setup 'row0'
if ( flags & CNMAP_MIRROR_V )
{
// Mirror first row
memcpy_s( row0, rowPitch, row1, rowPitch );
}
else
{
// Read last row (Wrap V)
if ( !_LoadScanline( row0, width, pSrc + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
return E_FAIL;
}
// Evaluate the initial rows
_EvaluateRow( row0, val0, width, flags );
_EvaluateRow( row1, val1, width, flags );
pSrc += rowPitch;
for( size_t y = 0; y < height; ++y )
{
// Load next scanline of source image
if ( y < (height-1) )
for (size_t x = 0; x < width; ++x)
{
if ( !_LoadScanline( row2, width, pSrc, rowPitch, srcImage.format ) )
return E_FAIL;
pDest[x + 1] = EvaluateColor(pSource[x], flags);
}
if (flags & CNMAP_MIRROR_U)
{
// Mirror in U
pDest[0] = EvaluateColor(pSource[0], flags);
pDest[width + 1] = EvaluateColor(pSource[width - 1], flags);
}
else
{
if ( flags & CNMAP_MIRROR_V )
// Wrap in U
pDest[0] = EvaluateColor(pSource[width - 1], flags);
pDest[width + 1] = EvaluateColor(pSource[0], flags);
}
}
HRESULT ComputeNMap(_In_ const Image& srcImage, _In_ DWORD flags, _In_ float amplitude,
_In_ DXGI_FORMAT format, _In_ const Image& normalMap)
{
if (!srcImage.pixels || !normalMap.pixels)
return E_INVALIDARG;
const DWORD convFlags = _GetConvertFlags(format);
if (!convFlags)
return E_FAIL;
if (!(convFlags & (CONVF_UNORM | CONVF_SNORM | CONVF_FLOAT)))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
const size_t width = srcImage.width;
const size_t height = srcImage.height;
if (width != normalMap.width || height != normalMap.height)
return E_FAIL;
// Allocate temporary space (4 scanlines and 3 evaluated rows)
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*width * 4), 16)));
if (!scanline)
return E_OUTOFMEMORY;
ScopedAlignedArrayFloat buffer(reinterpret_cast<float*>(_aligned_malloc(((sizeof(float) * (width + 2)) * 3), 16)));
if (!buffer)
return E_OUTOFMEMORY;
uint8_t* pDest = normalMap.pixels;
if (!pDest)
return E_POINTER;
XMVECTOR* row0 = scanline.get();
XMVECTOR* row1 = row0 + width;
XMVECTOR* row2 = row1 + width;
XMVECTOR* target = row2 + width;
float* val0 = buffer.get();
float* val1 = val0 + width + 2;
float* val2 = val1 + width + 2;
const size_t rowPitch = srcImage.rowPitch;
const uint8_t* pSrc = srcImage.pixels;
// Read first scanline row into 'row1'
if (!_LoadScanline(row1, width, pSrc, rowPitch, srcImage.format))
return E_FAIL;
// Setup 'row0'
if (flags & CNMAP_MIRROR_V)
{
// Mirror first row
memcpy_s(row0, rowPitch, row1, rowPitch);
}
else
{
// Read last row (Wrap V)
if (!_LoadScanline(row0, width, pSrc + (rowPitch * (height - 1)), rowPitch, srcImage.format))
return E_FAIL;
}
// Evaluate the initial rows
EvaluateRow(row0, val0, width, flags);
EvaluateRow(row1, val1, width, flags);
pSrc += rowPitch;
for (size_t y = 0; y < height; ++y)
{
// Load next scanline of source image
if (y < (height - 1))
{
// Use last row of source image
if ( !_LoadScanline( row2, width, srcImage.pixels + (rowPitch * (height-1)), rowPitch, srcImage.format ) )
if (!_LoadScanline(row2, width, pSrc, rowPitch, srcImage.format))
return E_FAIL;
}
else
{
// Use first row of source image (Wrap V)
if ( !_LoadScanline( row2, width, srcImage.pixels, rowPitch, srcImage.format ) )
return E_FAIL;
}
}
// Evaluate row
_EvaluateRow( row2, val2, width, flags );
// Generate target scanline
XMVECTOR *dptr = target;
for( size_t x = 0; x < width; ++x )
{
// Compute normal via central differencing
float totDelta = ( val0[x] - val0[x+2] ) + ( val1[x] - val1[x+2] ) + ( val2[x] - val2[x+2] );
float deltaZX = totDelta * amplitude / 6.f;
totDelta = ( val0[x] - val2[x] ) + ( val0[x+1] - val2[x+1] ) + ( val0[x+2] - val2[x+2] );
float deltaZY = totDelta * amplitude / 6.f;
XMVECTOR vx = XMVectorSetZ( g_XMNegIdentityR0, deltaZX ); // (-1.0f, 0.0f, deltaZX)
XMVECTOR vy = XMVectorSetZ( g_XMNegIdentityR1, deltaZY ); // (0.0f, -1.0f, deltaZY)
XMVECTOR normal = XMVector3Normalize( XMVector3Cross( vx, vy ) );
// Compute alpha (1.0 or an occlusion term)
float alpha = 1.f;
if ( flags & CNMAP_COMPUTE_OCCLUSION )
{
float delta = 0.f;
float c = val1[x+1];
float t = val0[x] - c; if ( t > 0.f ) delta += t;
t = val0[x+1] - c; if ( t > 0.f ) delta += t;
t = val0[x+2] - c; if ( t > 0.f ) delta += t;
t = val1[x] - c; if ( t > 0.f ) delta += t;
// Skip current pixel
t = val1[x+2] - c; if ( t > 0.f ) delta += t;
t = val2[x] - c; if ( t > 0.f ) delta += t;
t = val2[x+1] - c; if ( t > 0.f ) delta += t;
t = val2[x+2] - c; if ( t > 0.f ) delta += t;
// Average delta (divide by 8, scale by amplitude factor)
delta *= 0.125f * amplitude;
if ( delta > 0.f )
if (flags & CNMAP_MIRROR_V)
{
// If < 0, then no occlusion
float r = sqrtf( 1.f + delta*delta );
alpha = (r - delta) / r;
// Use last row of source image
if (!_LoadScanline(row2, width, srcImage.pixels + (rowPitch * (height - 1)), rowPitch, srcImage.format))
return E_FAIL;
}
else
{
// Use first row of source image (Wrap V)
if (!_LoadScanline(row2, width, srcImage.pixels, rowPitch, srcImage.format))
return E_FAIL;
}
}
// Encode based on target format
if ( convFlags & CONVF_UNORM )
// Evaluate row
EvaluateRow(row2, val2, width, flags);
// Generate target scanline
XMVECTOR *dptr = target;
for (size_t x = 0; x < width; ++x)
{
// 0.5f*normal + 0.5f -or- invert sign case: -0.5f*normal + 0.5f
XMVECTOR n1 = XMVectorMultiplyAdd( (flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf );
*dptr++ = XMVectorSetW( n1, alpha );
}
else if ( flags & CNMAP_INVERT_SIGN )
{
*dptr++ = XMVectorSetW( XMVectorNegate( normal ), alpha );
}
else
{
*dptr++ = XMVectorSetW( normal, alpha );
// Compute normal via central differencing
float totDelta = (val0[x] - val0[x + 2]) + (val1[x] - val1[x + 2]) + (val2[x] - val2[x + 2]);
float deltaZX = totDelta * amplitude / 6.f;
totDelta = (val0[x] - val2[x]) + (val0[x + 1] - val2[x + 1]) + (val0[x + 2] - val2[x + 2]);
float deltaZY = totDelta * amplitude / 6.f;
XMVECTOR vx = XMVectorSetZ(g_XMNegIdentityR0, deltaZX); // (-1.0f, 0.0f, deltaZX)
XMVECTOR vy = XMVectorSetZ(g_XMNegIdentityR1, deltaZY); // (0.0f, -1.0f, deltaZY)
XMVECTOR normal = XMVector3Normalize(XMVector3Cross(vx, vy));
// Compute alpha (1.0 or an occlusion term)
float alpha = 1.f;
if (flags & CNMAP_COMPUTE_OCCLUSION)
{
float delta = 0.f;
float c = val1[x + 1];
float t = val0[x] - c; if (t > 0.f) delta += t;
t = val0[x + 1] - c; if (t > 0.f) delta += t;
t = val0[x + 2] - c; if (t > 0.f) delta += t;
t = val1[x] - c; if (t > 0.f) delta += t;
// Skip current pixel
t = val1[x + 2] - c; if (t > 0.f) delta += t;
t = val2[x] - c; if (t > 0.f) delta += t;
t = val2[x + 1] - c; if (t > 0.f) delta += t;
t = val2[x + 2] - c; if (t > 0.f) delta += t;
// Average delta (divide by 8, scale by amplitude factor)
delta *= 0.125f * amplitude;
if (delta > 0.f)
{
// If < 0, then no occlusion
float r = sqrtf(1.f + delta*delta);
alpha = (r - delta) / r;
}
}
// Encode based on target format
if (convFlags & CONVF_UNORM)
{
// 0.5f*normal + 0.5f -or- invert sign case: -0.5f*normal + 0.5f
XMVECTOR n1 = XMVectorMultiplyAdd((flags & CNMAP_INVERT_SIGN) ? g_XMNegativeOneHalf : g_XMOneHalf, normal, g_XMOneHalf);
*dptr++ = XMVectorSetW(n1, alpha);
}
else if (flags & CNMAP_INVERT_SIGN)
{
*dptr++ = XMVectorSetW(XMVectorNegate(normal), alpha);
}
else
{
*dptr++ = XMVectorSetW(normal, alpha);
}
}
if (!_StoreScanline(pDest, normalMap.rowPitch, format, target, width))
return E_FAIL;
// Cycle buffers
float* temp = val0;
val0 = val1;
val1 = val2;
val2 = temp;
pSrc += rowPitch;
pDest += normalMap.rowPitch;
}
if ( !_StoreScanline( pDest, normalMap.rowPitch, format, target, width ) )
return E_FAIL;
// Cycle buffers
float* temp = val0;
val0 = val1;
val1 = val2;
val2 = temp;
pSrc += rowPitch;
pDest += normalMap.rowPitch;
return S_OK;
}
return S_OK;
}
@ -252,14 +258,18 @@ static HRESULT _ComputeNMap( _In_ const Image& srcImage, _In_ DWORD flags, _In_
// Generates a normal map from a height-map
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
DXGI_FORMAT format, ScratchImage& normalMap )
HRESULT DirectX::ComputeNormalMap(
const Image& srcImage,
DWORD flags,
float amplitude,
DXGI_FORMAT format,
ScratchImage& normalMap)
{
if ( !srcImage.pixels || !IsValid(format) )
if (!srcImage.pixels || !IsValid(format))
return E_INVALIDARG;
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
switch (flags & 0xf)
{
case 0:
case CNMAP_CHANNEL_RED:
@ -273,28 +283,28 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
return E_INVALIDARG;
}
if ( IsCompressed(format) || IsCompressed(srcImage.format)
|| IsTypeless(format) || IsTypeless(srcImage.format)
|| IsPlanar(format) || IsPlanar(srcImage.format)
|| IsPalettized(format) || IsPalettized(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsCompressed(format) || IsCompressed(srcImage.format)
|| IsTypeless(format) || IsTypeless(srcImage.format)
|| IsPlanar(format) || IsPlanar(srcImage.format)
|| IsPalettized(format) || IsPalettized(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
// Setup target image
normalMap.Release();
HRESULT hr = normalMap.Initialize2D( format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = normalMap.Initialize2D(format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *img = normalMap.GetImage( 0, 0, 0 );
if ( !img )
const Image *img = normalMap.GetImage(0, 0, 0);
if (!img)
{
normalMap.Release();
return E_POINTER;
}
hr = _ComputeNMap( srcImage, flags, amplitude, format, *img );
if ( FAILED(hr) )
hr = ComputeNMap(srcImage, flags, amplitude, format, *img);
if (FAILED(hr))
{
normalMap.Release();
return hr;
@ -304,20 +314,26 @@ HRESULT ComputeNormalMap( const Image& srcImage, DWORD flags, float amplitude,
}
_Use_decl_annotations_
HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetadata& metadata,
DWORD flags, float amplitude, DXGI_FORMAT format, ScratchImage& normalMaps )
HRESULT DirectX::ComputeNormalMap(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DWORD flags,
float amplitude,
DXGI_FORMAT format,
ScratchImage& normalMaps)
{
if ( !srcImages || !nimages || !IsValid(format) )
if (!srcImages || !nimages || !IsValid(format))
return E_INVALIDARG;
if ( IsCompressed(format) || IsCompressed(metadata.format)
|| IsTypeless(format) || IsTypeless(metadata.format)
|| IsPlanar(format) || IsPlanar(metadata.format)
|| IsPalettized(format) || IsPalettized(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsCompressed(format) || IsCompressed(metadata.format)
|| IsTypeless(format) || IsTypeless(metadata.format)
|| IsPlanar(format) || IsPlanar(metadata.format)
|| IsPalettized(format) || IsPalettized(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
static_assert( CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask" );
switch( flags & 0xf )
static_assert(CNMAP_CHANNEL_RED == 0x1, "CNMAP_CHANNEL_ flag values don't match mask");
switch (flags & 0xf)
{
case 0:
case CNMAP_CHANNEL_RED:
@ -335,42 +351,42 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
TexMetadata mdata2 = metadata;
mdata2.format = format;
HRESULT hr = normalMaps.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = normalMaps.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != normalMaps.GetImageCount() )
if (nimages != normalMaps.GetImageCount())
{
normalMaps.Release();
return E_FAIL;
}
const Image* dest = normalMaps.GetImages();
if ( !dest )
if (!dest)
{
normalMaps.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
assert( dest[ index ].format == format );
assert(dest[index].format == format);
const Image& src = srcImages[ index ];
if ( IsCompressed( src.format ) || IsTypeless( src.format ) )
const Image& src = srcImages[index];
if (IsCompressed(src.format) || IsTypeless(src.format))
{
normalMaps.Release();
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
}
if ( src.width != dest[ index ].width || src.height != dest[ index ].height )
if (src.width != dest[index].width || src.height != dest[index].height)
{
normalMaps.Release();
return E_FAIL;
}
hr = _ComputeNMap( src, flags, amplitude, format, dest[ index ] );
if ( FAILED(hr) )
hr = ComputeNMap(src, flags, amplitude, format, dest[index]);
if (FAILED(hr))
{
normalMaps.Release();
return hr;
@ -379,5 +395,3 @@ HRESULT ComputeNormalMap( const Image* srcImages, size_t nimages, const TexMetad
return S_OK;
}
}; // namespace

Просмотреть файл

@ -175,40 +175,40 @@ namespace DirectX
void __cdecl _CopyScanline( _When_(pDestination == pSource, _Inout_updates_bytes_(outSize))
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
LPVOID pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
void* pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT format, _In_ DWORD flags );
void __cdecl _SwizzleScanline( _When_(pDestination == pSource, _In_)
_When_(pDestination != pSource, _Out_writes_bytes_(outSize))
LPVOID pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
void* pDestination, _In_ size_t outSize,
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT format, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) LPVOID pDestination, _In_ size_t outSize,
bool __cdecl _ExpandScanline( _Out_writes_bytes_(outSize) void* pDestination, _In_ size_t outSize,
_In_ DXGI_FORMAT outFormat,
_In_reads_bytes_(inSize) LPCVOID pSource, _In_ size_t inSize,
_In_reads_bytes_(inSize) const void* pSource, _In_ size_t inSize,
_In_ DXGI_FORMAT inFormat, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _LoadScanline( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format );
_Success_(return != false)
bool __cdecl _LoadScanlineLinear( _Out_writes_(count) XMVECTOR* pDestination, _In_ size_t count,
_In_reads_bytes_(size) LPCVOID pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
_In_reads_bytes_(size) const void* pSource, _In_ size_t size, _In_ DXGI_FORMAT format, _In_ DWORD flags );
_Success_(return != false)
bool __cdecl _StoreScanline( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
bool __cdecl _StoreScanline( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_In_reads_(count) const XMVECTOR* pSource, _In_ size_t count, _In_ float threshold = 0 );
_Success_(return != false)
bool __cdecl _StoreScanlineLinear( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
bool __cdecl _StoreScanlineLinear( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ DWORD flags, _In_ float threshold = 0 );
_Success_(return != false)
bool __cdecl _StoreScanlineDither( LPVOID pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
bool __cdecl _StoreScanlineDither( void* pDestination, _In_ size_t size, _In_ DXGI_FORMAT format,
_Inout_updates_all_(count) XMVECTOR* pSource, _In_ size_t count, _In_ float threshold, size_t y, size_t z,
_Inout_updates_all_opt_(count+2) XMVECTOR* pDiffusionErrors );
@ -225,6 +225,6 @@ namespace DirectX
//---------------------------------------------------------------------------------
// DDS helper functions
HRESULT __cdecl _EncodeDDSHeader( _In_ const TexMetadata& metadata, DWORD flags,
_Out_writes_bytes_to_opt_(maxsize, required) LPVOID pDestination, _In_ size_t maxsize, _Out_ size_t& required );
_Out_writes_bytes_to_opt_(maxsize, required) void* pDestination, _In_ size_t maxsize, _Out_ size_t& required );
}; // namespace

Просмотреть файл

@ -15,88 +15,91 @@
#include "directxtexp.h"
namespace DirectX
using namespace DirectX;
namespace
{
static HRESULT _PremultiplyAlpha( _In_ const Image& srcImage, _In_ const Image& destImage )
{
assert( srcImage.width == destImage.width );
assert( srcImage.height == destImage.height );
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
if ( !scanline )
return E_OUTOFMEMORY;
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if ( !pSrc || !pDest )
return E_POINTER;
for( size_t h = 0; h < srcImage.height; ++h )
HRESULT PremultiplyAlpha_(const Image& srcImage, const Image& destImage)
{
if ( !_LoadScanline( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format ) )
return E_FAIL;
assert(srcImage.width == destImage.width);
assert(srcImage.height == destImage.height);
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < srcImage.width; ++w )
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
if (!scanline)
return E_OUTOFMEMORY;
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if (!pSrc || !pDest)
return E_POINTER;
for (size_t h = 0; h < srcImage.height; ++h)
{
XMVECTOR v = *ptr;
XMVECTOR alpha = XMVectorSplatW( *ptr );
alpha = XMVectorMultiply( v, alpha );
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
if (!_LoadScanline(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format))
return E_FAIL;
XMVECTOR* ptr = scanline.get();
for (size_t w = 0; w < srcImage.width; ++w)
{
XMVECTOR v = *ptr;
XMVECTOR alpha = XMVectorSplatW(*ptr);
alpha = XMVectorMultiply(v, alpha);
*(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110);
}
if (!_StoreScanline(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width))
return E_FAIL;
pSrc += srcImage.rowPitch;
pDest += destImage.rowPitch;
}
if ( !_StoreScanline( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width ) )
return E_FAIL;
pSrc += srcImage.rowPitch;
pDest += destImage.rowPitch;
return S_OK;
}
return S_OK;
}
static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD flags, _In_ const Image& destImage )
{
assert( srcImage.width == destImage.width );
assert( srcImage.height == destImage.height );
static_assert( TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
static_assert( TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*" );
flags &= TEX_PMALPHA_SRGB;
ScopedAlignedArrayXMVECTOR scanline( reinterpret_cast<XMVECTOR*>( _aligned_malloc( (sizeof(XMVECTOR)*srcImage.width), 16 ) ) );
if ( !scanline )
return E_OUTOFMEMORY;
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if ( !pSrc || !pDest )
return E_POINTER;
for( size_t h = 0; h < srcImage.height; ++h )
HRESULT PremultiplyAlphaLinear(const Image& srcImage, DWORD flags, const Image& destImage)
{
if ( !_LoadScanlineLinear( scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags ) )
return E_FAIL;
assert(srcImage.width == destImage.width);
assert(srcImage.height == destImage.height);
XMVECTOR* ptr = scanline.get();
for( size_t w = 0; w < srcImage.width; ++w )
static_assert(TEX_PMALPHA_SRGB_IN == TEX_FILTER_SRGB_IN, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_PMALPHA_SRGB_OUT == TEX_FILTER_SRGB_OUT, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
static_assert(TEX_PMALPHA_SRGB == TEX_FILTER_SRGB, "TEX_PMALHPA_SRGB* should match TEX_FILTER_SRGB*");
flags &= TEX_PMALPHA_SRGB;
ScopedAlignedArrayXMVECTOR scanline(reinterpret_cast<XMVECTOR*>(_aligned_malloc((sizeof(XMVECTOR)*srcImage.width), 16)));
if (!scanline)
return E_OUTOFMEMORY;
const uint8_t *pSrc = srcImage.pixels;
uint8_t *pDest = destImage.pixels;
if (!pSrc || !pDest)
return E_POINTER;
for (size_t h = 0; h < srcImage.height; ++h)
{
XMVECTOR v = *ptr;
XMVECTOR alpha = XMVectorSplatW( *ptr );
alpha = XMVectorMultiply( v, alpha );
*(ptr++) = XMVectorSelect( v, alpha, g_XMSelect1110 );
if (!_LoadScanlineLinear(scanline.get(), srcImage.width, pSrc, srcImage.rowPitch, srcImage.format, flags))
return E_FAIL;
XMVECTOR* ptr = scanline.get();
for (size_t w = 0; w < srcImage.width; ++w)
{
XMVECTOR v = *ptr;
XMVECTOR alpha = XMVectorSplatW(*ptr);
alpha = XMVectorMultiply(v, alpha);
*(ptr++) = XMVectorSelect(v, alpha, g_XMSelect1110);
}
if (!_StoreScanlineLinear(pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags))
return E_FAIL;
pSrc += srcImage.rowPitch;
pDest += destImage.rowPitch;
}
if ( !_StoreScanlineLinear( pDest, destImage.rowPitch, destImage.format, scanline.get(), srcImage.width, flags ) )
return E_FAIL;
pSrc += srcImage.rowPitch;
pDest += destImage.rowPitch;
return S_OK;
}
return S_OK;
}
@ -108,34 +111,37 @@ static HRESULT _PremultiplyAlphaLinear( _In_ const Image& srcImage, _In_ DWORD f
// Converts to a premultiplied alpha version of the texture
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& image )
HRESULT DirectX::PremultiplyAlpha(
const Image& srcImage,
DWORD flags,
ScratchImage& image)
{
if ( !srcImage.pixels )
if (!srcImage.pixels)
return E_POINTER;
if ( IsCompressed(srcImage.format)
|| IsPlanar(srcImage.format)
|| IsPalettized(srcImage.format)
|| IsTypeless(srcImage.format)
|| !HasAlpha(srcImage.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsCompressed(srcImage.format)
|| IsPlanar(srcImage.format)
|| IsPalettized(srcImage.format)
|| IsTypeless(srcImage.format)
|| !HasAlpha(srcImage.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( (srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX) )
if ((srcImage.width > UINT32_MAX) || (srcImage.height > UINT32_MAX))
return E_INVALIDARG;
HRESULT hr = image.Initialize2D( srcImage.format, srcImage.width, srcImage.height, 1, 1 );
if ( FAILED(hr) )
HRESULT hr = image.Initialize2D(srcImage.format, srcImage.width, srcImage.height, 1, 1);
if (FAILED(hr))
return hr;
const Image *rimage = image.GetImage( 0, 0, 0 );
if ( !rimage )
const Image *rimage = image.GetImage(0, 0, 0);
if (!rimage)
{
image.Release();
return E_POINTER;
}
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( srcImage, *rimage ) : _PremultiplyAlphaLinear( srcImage, flags, *rimage );
if ( FAILED(hr) )
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(srcImage, *rimage) : PremultiplyAlphaLinear(srcImage, flags, *rimage);
if (FAILED(hr))
{
image.Release();
return hr;
@ -149,22 +155,27 @@ HRESULT PremultiplyAlpha( const Image& srcImage, DWORD flags, ScratchImage& imag
// Converts to a premultiplied alpha version of the texture (complex)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetadata& metadata, DWORD flags, ScratchImage& result )
HRESULT DirectX::PremultiplyAlpha(
const Image* srcImages,
size_t nimages,
const TexMetadata& metadata,
DWORD flags,
ScratchImage& result)
{
if ( !srcImages || !nimages )
if (!srcImages || !nimages)
return E_INVALIDARG;
if ( IsCompressed(metadata.format)
|| IsPlanar(metadata.format)
|| IsPalettized(metadata.format)
|| IsTypeless(metadata.format)
|| !HasAlpha(metadata.format) )
return HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED );
if (IsCompressed(metadata.format)
|| IsPlanar(metadata.format)
|| IsPalettized(metadata.format)
|| IsTypeless(metadata.format)
|| !HasAlpha(metadata.format))
return HRESULT_FROM_WIN32(ERROR_NOT_SUPPORTED);
if ( (metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX) )
if ((metadata.width > UINT32_MAX) || (metadata.height > UINT32_MAX))
return E_INVALIDARG;
if ( metadata.IsPMAlpha() )
if (metadata.IsPMAlpha())
{
// Already premultiplied
return E_FAIL;
@ -172,46 +183,46 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
TexMetadata mdata2 = metadata;
mdata2.SetAlphaMode(TEX_ALPHA_MODE_PREMULTIPLIED);
HRESULT hr = result.Initialize( mdata2 );
if ( FAILED(hr) )
HRESULT hr = result.Initialize(mdata2);
if (FAILED(hr))
return hr;
if ( nimages != result.GetImageCount() )
if (nimages != result.GetImageCount())
{
result.Release();
return E_FAIL;
}
const Image* dest = result.GetImages();
if ( !dest )
if (!dest)
{
result.Release();
return E_POINTER;
}
for( size_t index=0; index < nimages; ++index )
for (size_t index = 0; index < nimages; ++index)
{
const Image& src = srcImages[ index ];
if ( src.format != metadata.format )
const Image& src = srcImages[index];
if (src.format != metadata.format)
{
result.Release();
return E_FAIL;
}
if ( (src.width > UINT32_MAX) || (src.height > UINT32_MAX) )
if ((src.width > UINT32_MAX) || (src.height > UINT32_MAX))
return E_FAIL;
const Image& dst = dest[ index ];
assert( dst.format == metadata.format );
const Image& dst = dest[index];
assert(dst.format == metadata.format);
if ( src.width != dst.width || src.height != dst.height )
if (src.width != dst.width || src.height != dst.height)
{
result.Release();
return E_FAIL;
}
hr = ( flags & TEX_PMALPHA_IGNORE_SRGB ) ? _PremultiplyAlpha( src, dst ) : _PremultiplyAlphaLinear( src, flags, dst );
if ( FAILED(hr) )
hr = (flags & TEX_PMALPHA_IGNORE_SRGB) ? PremultiplyAlpha_(src, dst) : PremultiplyAlphaLinear(src, flags, dst);
if (FAILED(hr))
{
result.Release();
return hr;
@ -220,5 +231,3 @@ HRESULT PremultiplyAlpha( const Image* srcImages, size_t nimages, const TexMetad
return S_OK;
}
}; // namespace

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -15,8 +15,6 @@
#include "directxtexp.h"
using Microsoft::WRL::ComPtr;
#if defined(_XBOX_ONE) && defined(_TITLE)
static_assert(XBOX_DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT == DXGI_FORMAT_R10G10B10_7E3_A2_FLOAT, "Xbox One XDK mismatch detected");
static_assert(XBOX_DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT == DXGI_FORMAT_R10G10B10_6E4_A2_FLOAT, "Xbox One XDK mismatch detected");
@ -33,68 +31,70 @@ static_assert(WIN10_DXGI_FORMAT_V208 == DXGI_FORMAT_V208, "Windows SDK mismatch
static_assert(WIN10_DXGI_FORMAT_V408 == DXGI_FORMAT_V408, "Windows SDK mismatch detected");
#endif
using namespace DirectX;
using Microsoft::WRL::ComPtr;
//-------------------------------------------------------------------------------------
// WIC Pixel Format Translation Data
//-------------------------------------------------------------------------------------
struct WICTranslate
namespace
{
GUID wic;
DXGI_FORMAT format;
bool srgb;
};
//-------------------------------------------------------------------------------------
// WIC Pixel Format Translation Data
//-------------------------------------------------------------------------------------
struct WICTranslate
{
GUID wic;
DXGI_FORMAT format;
bool srgb;
};
static const WICTranslate g_WICFormats[] =
{
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
const WICTranslate g_WICFormats[] =
{
{ GUID_WICPixelFormat128bppRGBAFloat, DXGI_FORMAT_R32G32B32A32_FLOAT, false },
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true },
{ GUID_WICPixelFormat64bppRGBAHalf, DXGI_FORMAT_R16G16B16A16_FLOAT, false },
{ GUID_WICPixelFormat64bppRGBA, DXGI_FORMAT_R16G16B16A16_UNORM, true },
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true },
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1
{ GUID_WICPixelFormat32bppRGBA, DXGI_FORMAT_R8G8B8A8_UNORM, true },
{ GUID_WICPixelFormat32bppBGRA, DXGI_FORMAT_B8G8R8A8_UNORM, true }, // DXGI 1.1
{ GUID_WICPixelFormat32bppBGR, DXGI_FORMAT_B8G8R8X8_UNORM, true }, // DXGI 1.1
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true },
{ GUID_WICPixelFormat32bppRGBA1010102XR, DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM, true }, // DXGI 1.1
{ GUID_WICPixelFormat32bppRGBA1010102, DXGI_FORMAT_R10G10B10A2_UNORM, true },
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true },
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true },
{ GUID_WICPixelFormat16bppBGRA5551, DXGI_FORMAT_B5G5R5A1_UNORM, true },
{ GUID_WICPixelFormat16bppBGR565, DXGI_FORMAT_B5G6R5_UNORM, true },
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false },
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false },
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true },
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true },
{ GUID_WICPixelFormat32bppGrayFloat, DXGI_FORMAT_R32_FLOAT, false },
{ GUID_WICPixelFormat16bppGrayHalf, DXGI_FORMAT_R16_FLOAT, false },
{ GUID_WICPixelFormat16bppGray, DXGI_FORMAT_R16_UNORM, true },
{ GUID_WICPixelFormat8bppGray, DXGI_FORMAT_R8_UNORM, true },
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false },
{ GUID_WICPixelFormat8bppAlpha, DXGI_FORMAT_A8_UNORM, false },
{ GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
};
{ GUID_WICPixelFormatBlackWhite, DXGI_FORMAT_R1_UNORM, false },
};
static bool g_WIC2 = false;
static IWICImagingFactory* g_Factory = nullptr;
bool g_WIC2 = false;
IWICImagingFactory* g_Factory = nullptr;
}
namespace DirectX
{
//=====================================================================================
// WIC Utilities
//=====================================================================================
_Use_decl_annotations_
DXGI_FORMAT _WICToDXGI( const GUID& guid )
DXGI_FORMAT DirectX::_WICToDXGI(const GUID& guid)
{
for( size_t i=0; i < _countof(g_WICFormats); ++i )
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
{
if ( memcmp( &g_WICFormats[i].wic, &guid, sizeof(GUID) ) == 0 )
if (memcmp(&g_WICFormats[i].wic, &guid, sizeof(GUID)) == 0)
return g_WICFormats[i].format;
}
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
if ( g_WIC2 )
if (g_WIC2)
{
if ( memcmp( &GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID) ) == 0 )
if (memcmp(&GUID_WICPixelFormat96bppRGBFloat, &guid, sizeof(GUID)) == 0)
return DXGI_FORMAT_R32G32B32_FLOAT;
}
#endif
@ -103,7 +103,7 @@ DXGI_FORMAT _WICToDXGI( const GUID& guid )
}
_Use_decl_annotations_
bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
bool DirectX::_DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
{
switch( format )
{
@ -163,28 +163,28 @@ bool _DXGIToWIC( DXGI_FORMAT format, GUID& guid, bool ignoreRGBvsBGR )
return false;
}
DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetGUID )
DWORD DirectX::_CheckWICColorSpace(_In_ const GUID& sourceGUID, _In_ const GUID& targetGUID)
{
DWORD srgb = 0;
for( size_t i=0; i < _countof(g_WICFormats); ++i )
for (size_t i = 0; i < _countof(g_WICFormats); ++i)
{
if ( memcmp( &g_WICFormats[i].wic, &sourceGUID, sizeof(GUID) ) == 0 )
if (memcmp(&g_WICFormats[i].wic, &sourceGUID, sizeof(GUID)) == 0)
{
if ( g_WICFormats[i].srgb )
if (g_WICFormats[i].srgb)
srgb |= TEX_FILTER_SRGB_IN;
}
if ( memcmp( &g_WICFormats[i].wic, &targetGUID, sizeof(GUID) ) == 0 )
if (memcmp(&g_WICFormats[i].wic, &targetGUID, sizeof(GUID)) == 0)
{
if ( g_WICFormats[i].srgb )
if (g_WICFormats[i].srgb)
srgb |= TEX_FILTER_SRGB_OUT;
}
}
if ( (srgb & (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT) )
if ((srgb & (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT)) == (TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT))
{
srgb &= ~(TEX_FILTER_SRGB_IN|TEX_FILTER_SRGB_OUT);
srgb &= ~(TEX_FILTER_SRGB_IN | TEX_FILTER_SRGB_OUT);
}
return srgb;
@ -195,9 +195,9 @@ DWORD _CheckWICColorSpace( _In_ const GUID& sourceGUID, _In_ const GUID& targetG
// Public helper function to get common WIC codec GUIDs
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
REFGUID GetWICCodec( WICCodecs codec )
REFGUID DirectX::GetWICCodec(WICCodecs codec)
{
switch( codec )
switch (codec)
{
case WIC_CODEC_BMP:
return GUID_ContainerFormatBmp;
@ -229,9 +229,9 @@ REFGUID GetWICCodec( WICCodecs codec )
//-------------------------------------------------------------------------------------
// Singleton function for WIC factory
//-------------------------------------------------------------------------------------
IWICImagingFactory* GetWICFactory( bool& iswic2 )
IWICImagingFactory* DirectX::GetWICFactory(bool& iswic2)
{
if ( g_Factory )
if (g_Factory)
{
iswic2 = g_WIC2;
return g_Factory;
@ -240,47 +240,47 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
static INIT_ONCE s_initOnce = INIT_ONCE_STATIC_INIT;
InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
[](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
factory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory2,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory2),
factory
);
if (SUCCEEDED(hr))
{
// WIC2 is available on Windows 10, Windows 8.x, and Windows 7 SP1 with KB 2670838 installed
g_WIC2 = true;
return TRUE;
}
else
{
g_WIC2 = false;
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
factory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
g_WIC2 = false;
return SUCCEEDED( CoCreateInstance(
CLSID_WICImagingFactory,
hr = CoCreateInstance(
CLSID_WICImagingFactory1,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
factory) ) ? TRUE : FALSE;
#endif
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory) );
factory
);
return SUCCEEDED(hr) ? TRUE : FALSE;
}
#else
g_WIC2 = false;
return SUCCEEDED(CoCreateInstance(
CLSID_WICImagingFactory,
nullptr,
CLSCTX_INPROC_SERVER,
__uuidof(IWICImagingFactory),
factory)) ? TRUE : FALSE;
#endif
}, nullptr, reinterpret_cast<LPVOID*>(&g_Factory));
iswic2 = g_WIC2;
return g_Factory;
@ -290,7 +290,7 @@ IWICImagingFactory* GetWICFactory( bool& iswic2 )
//-------------------------------------------------------------------------------------
// Optional initializer for WIC factory
//-------------------------------------------------------------------------------------
void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
void DirectX::SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
{
if (pWIC == g_Factory)
return;
@ -311,7 +311,7 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
g_WIC2 = iswic2;
std::swap(pWIC, g_Factory);
if ( pWIC )
if (pWIC)
pWIC->Release();
}
@ -323,9 +323,9 @@ void SetWICFactory(_In_opt_ IWICImagingFactory* pWIC)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsPacked(DXGI_FORMAT fmt)
bool DirectX::IsPacked(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R8G8_B8G8_UNORM:
case DXGI_FORMAT_G8R8_G8B8_UNORM:
@ -342,9 +342,9 @@ bool IsPacked(DXGI_FORMAT fmt)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsVideo(DXGI_FORMAT fmt)
bool DirectX::IsVideo(DXGI_FORMAT fmt)
{
switch ( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_AYUV:
case DXGI_FORMAT_Y410:
@ -379,9 +379,9 @@ bool IsVideo(DXGI_FORMAT fmt)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsPlanar(DXGI_FORMAT fmt)
bool DirectX::IsPlanar(DXGI_FORMAT fmt)
{
switch ( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_NV12: // 4:2:0 8-bit
case DXGI_FORMAT_P010: // 4:2:0 10-bit
@ -403,15 +403,14 @@ bool IsPlanar(DXGI_FORMAT fmt)
default:
return false;
}
}
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsDepthStencil(DXGI_FORMAT fmt)
bool DirectX::IsDepthStencil(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_D32_FLOAT_S8X24_UINT:
case DXGI_FORMAT_R32_FLOAT_X8X24_TYPELESS:
@ -434,9 +433,9 @@ bool IsDepthStencil(DXGI_FORMAT fmt)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
bool DirectX::IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32_TYPELESS:
@ -478,9 +477,9 @@ bool IsTypeless(DXGI_FORMAT fmt, bool partialTypeless)
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
bool HasAlpha(DXGI_FORMAT fmt)
bool DirectX::HasAlpha(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -541,9 +540,9 @@ bool HasAlpha(DXGI_FORMAT fmt)
// Returns bits-per-pixel for a given DXGI format, or 0 on failure
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t BitsPerPixel( DXGI_FORMAT fmt )
size_t DirectX::BitsPerPixel(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -703,9 +702,9 @@ size_t BitsPerPixel( DXGI_FORMAT fmt )
// For mixed formats, it returns the largest color-depth in the format
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t BitsPerColor( DXGI_FORMAT fmt )
size_t DirectX::BitsPerColor(DXGI_FORMAT fmt)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
case DXGI_FORMAT_R32G32B32A32_FLOAT:
@ -869,10 +868,10 @@ size_t BitsPerColor( DXGI_FORMAT fmt )
// based on DXGI format, width, and height
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
size_t& rowPitch, size_t& slicePitch, DWORD flags )
void DirectX::ComputePitch(DXGI_FORMAT fmt, size_t width, size_t height,
size_t& rowPitch, size_t& slicePitch, DWORD flags)
{
switch( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
@ -882,8 +881,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
case DXGI_FORMAT_BC4_SNORM:
assert(IsCompressed(fmt));
{
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
rowPitch = nbw * 8;
slicePitch = rowPitch * nbh;
@ -907,8 +906,8 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
case DXGI_FORMAT_BC7_UNORM_SRGB:
assert(IsCompressed(fmt));
{
size_t nbw = std::max<size_t>( 1, (width + 3) / 4 );
size_t nbh = std::max<size_t>( 1, (height + 3) / 4 );
size_t nbw = std::max<size_t>(1, (width + 3) / 4);
size_t nbh = std::max<size_t>(1, (height + 3) / 4);
rowPitch = nbw * 16;
slicePitch = rowPitch * nbh;
@ -919,22 +918,22 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
case DXGI_FORMAT_G8R8_G8B8_UNORM:
case DXGI_FORMAT_YUY2:
assert(IsPacked(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 4;
rowPitch = ((width + 1) >> 1) * 4;
slicePitch = rowPitch * height;
break;
case DXGI_FORMAT_Y210:
case DXGI_FORMAT_Y216:
assert(IsPacked(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 8;
rowPitch = ((width + 1) >> 1) * 8;
slicePitch = rowPitch * height;
break;
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_420_OPAQUE:
assert(IsPlanar(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
rowPitch = ((width + 1) >> 1) * 2;
slicePitch = rowPitch * (height + ((height + 1) >> 1));
break;
case DXGI_FORMAT_P010:
@ -943,84 +942,84 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
assert(IsPlanar(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 4;
slicePitch = rowPitch * ( height + ( ( height + 1 ) >> 1 ) );
rowPitch = ((width + 1) >> 1) * 4;
slicePitch = rowPitch * (height + ((height + 1) >> 1));
break;
case DXGI_FORMAT_NV11:
assert(IsPlanar(fmt));
rowPitch = ( ( width + 3 ) >> 2 ) * 4;
rowPitch = ((width + 3) >> 2) * 4;
slicePitch = rowPitch * height * 2;
break;
case WIN10_DXGI_FORMAT_P208:
assert(IsPlanar(fmt));
rowPitch = ( ( width + 1 ) >> 1 ) * 2;
rowPitch = ((width + 1) >> 1) * 2;
slicePitch = rowPitch * height * 2;
break;
case WIN10_DXGI_FORMAT_V208:
assert(IsPlanar(fmt));
rowPitch = width;
slicePitch = rowPitch * ( height + ( ( ( height + 1 ) >> 1 ) * 2 ) );
slicePitch = rowPitch * (height + (((height + 1) >> 1) * 2));
break;
case WIN10_DXGI_FORMAT_V408:
assert(IsPlanar(fmt));
rowPitch = width;
slicePitch = rowPitch * ( height + ( ( height >> 1 ) * 4 ) );
slicePitch = rowPitch * (height + ((height >> 1) * 4));
break;
default:
assert( IsValid(fmt) );
assert( !IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt) );
assert(IsValid(fmt));
assert(!IsCompressed(fmt) && !IsPacked(fmt) && !IsPlanar(fmt));
{
size_t bpp;
if ( flags & CP_FLAGS_24BPP )
if (flags & CP_FLAGS_24BPP)
bpp = 24;
else if ( flags & CP_FLAGS_16BPP )
else if (flags & CP_FLAGS_16BPP)
bpp = 16;
else if ( flags & CP_FLAGS_8BPP )
else if (flags & CP_FLAGS_8BPP)
bpp = 8;
else
bpp = BitsPerPixel( fmt );
bpp = BitsPerPixel(fmt);
if ( flags & ( CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K ) )
if (flags & (CP_FLAGS_LEGACY_DWORD | CP_FLAGS_PARAGRAPH | CP_FLAGS_YMM | CP_FLAGS_ZMM | CP_FLAGS_PAGE4K))
{
if ( flags & CP_FLAGS_PAGE4K )
if (flags & CP_FLAGS_PAGE4K)
{
rowPitch = ( ( width * bpp + 32767 ) / 32768 ) * 4096;
rowPitch = ((width * bpp + 32767) / 32768) * 4096;
slicePitch = rowPitch * height;
}
else if ( flags & CP_FLAGS_ZMM )
else if (flags & CP_FLAGS_ZMM)
{
rowPitch = ( ( width * bpp + 511 ) / 512 ) * 64;
rowPitch = ((width * bpp + 511) / 512) * 64;
slicePitch = rowPitch * height;
}
else if ( flags & CP_FLAGS_YMM )
else if (flags & CP_FLAGS_YMM)
{
rowPitch = ( ( width * bpp + 255 ) / 256) * 32;
rowPitch = ((width * bpp + 255) / 256) * 32;
slicePitch = rowPitch * height;
}
else if ( flags & CP_FLAGS_PARAGRAPH )
else if (flags & CP_FLAGS_PARAGRAPH)
{
rowPitch = ( ( width * bpp + 127 ) / 128 ) * 16;
rowPitch = ((width * bpp + 127) / 128) * 16;
slicePitch = rowPitch * height;
}
else // DWORD alignment
{
// Special computation for some incorrectly created DDS files based on
// legacy DirectDraw assumptions about pitch alignment
rowPitch = ( ( width * bpp + 31 ) / 32 ) * sizeof(uint32_t);
rowPitch = ((width * bpp + 31) / 32) * sizeof(uint32_t);
slicePitch = rowPitch * height;
}
}
else
{
// Default byte alignment
rowPitch = ( width * bpp + 7 ) / 8;
rowPitch = (width * bpp + 7) / 8;
slicePitch = rowPitch * height;
}
}
@ -1031,9 +1030,9 @@ void ComputePitch( DXGI_FORMAT fmt, size_t width, size_t height,
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
size_t DirectX::ComputeScanlines(DXGI_FORMAT fmt, size_t height)
{
switch ( static_cast<int>(fmt) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_BC1_TYPELESS:
case DXGI_FORMAT_BC1_UNORM:
@ -1057,7 +1056,7 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
case DXGI_FORMAT_BC7_UNORM:
case DXGI_FORMAT_BC7_UNORM_SRGB:
assert(IsCompressed(fmt));
return std::max<size_t>( 1, (height + 3) / 4 );
return std::max<size_t>(1, (height + 3) / 4);
case DXGI_FORMAT_NV11:
case WIN10_DXGI_FORMAT_P208:
@ -1066,11 +1065,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
case WIN10_DXGI_FORMAT_V208:
assert(IsPlanar(fmt));
return height + ( ( (height + 1) >> 1 ) * 2 );
return height + (((height + 1) >> 1) * 2);
case WIN10_DXGI_FORMAT_V408:
assert(IsPlanar(fmt));
return height + ( (height >> 1) * 4 );
return height + ((height >> 1) * 4);
case DXGI_FORMAT_NV12:
case DXGI_FORMAT_P010:
@ -1080,11 +1079,11 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
case XBOX_DXGI_FORMAT_R16_UNORM_X8_TYPELESS:
case XBOX_DXGI_FORMAT_X16_TYPELESS_G8_UINT:
assert(IsPlanar(fmt));
return height + ( ( height + 1 ) >> 1 );
return height + ((height + 1) >> 1);
default:
assert( IsValid(fmt) );
assert( !IsCompressed(fmt) && !IsPlanar(fmt) );
assert(IsValid(fmt));
assert(!IsCompressed(fmt) && !IsPlanar(fmt));
return height;
}
}
@ -1094,9 +1093,9 @@ size_t ComputeScanlines(DXGI_FORMAT fmt, size_t height)
// Converts to an SRGB equivalent type if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeSRGB(DXGI_FORMAT fmt)
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R8G8B8A8_UNORM:
return DXGI_FORMAT_R8G8B8A8_UNORM_SRGB;
@ -1129,9 +1128,9 @@ DXGI_FORMAT MakeSRGB( DXGI_FORMAT fmt )
// Converts to a format to an equivalent TYPELESS format if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeTypeless(DXGI_FORMAT fmt)
{
switch( static_cast<int>( fmt ) )
switch (static_cast<int>(fmt))
{
case DXGI_FORMAT_R32G32B32A32_FLOAT:
case DXGI_FORMAT_R32G32B32A32_UINT:
@ -1249,9 +1248,9 @@ DXGI_FORMAT MakeTypeless( DXGI_FORMAT fmt )
// Converts to a TYPELESS format to an equivalent UNORM format if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeTypelessUNORM(DXGI_FORMAT fmt)
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R16G16B16A16_TYPELESS:
return DXGI_FORMAT_R16G16B16A16_UNORM;
@ -1308,9 +1307,9 @@ DXGI_FORMAT MakeTypelessUNORM( DXGI_FORMAT fmt )
// Converts to a TYPELESS format to an equivalent FLOAT format if available
//-------------------------------------------------------------------------------------
_Use_decl_annotations_
DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
DXGI_FORMAT DirectX::MakeTypelessFLOAT(DXGI_FORMAT fmt)
{
switch( fmt )
switch (fmt)
{
case DXGI_FORMAT_R32G32B32A32_TYPELESS:
return DXGI_FORMAT_R32G32B32A32_FLOAT;
@ -1344,25 +1343,25 @@ DXGI_FORMAT MakeTypelessFLOAT( DXGI_FORMAT fmt )
//=====================================================================================
_Use_decl_annotations_
size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
size_t TexMetadata::ComputeIndex(size_t mip, size_t item, size_t slice) const
{
if ( mip >= mipLevels )
if (mip >= mipLevels)
return size_t(-1);
switch( dimension )
switch (dimension)
{
case TEX_DIMENSION_TEXTURE1D:
case TEX_DIMENSION_TEXTURE2D:
if ( slice > 0 )
if (slice > 0)
return size_t(-1);
if ( item >= arraySize )
if (item >= arraySize)
return size_t(-1);
return (item*( mipLevels ) + mip);
return (item*(mipLevels)+mip);
case TEX_DIMENSION_TEXTURE3D:
if ( item > 0 )
if (item > 0)
{
// No support for arrays of volumes
return size_t(-1);
@ -1372,14 +1371,14 @@ size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
size_t index = 0;
size_t d = depth;
for( size_t level = 0; level < mip; ++level )
for (size_t level = 0; level < mip; ++level)
{
index += d;
if ( d > 1 )
if (d > 1)
d >>= 1;
}
if ( slice >= d )
if (slice >= d)
return size_t(-1);
index += slice;
@ -1400,48 +1399,46 @@ size_t TexMetadata::ComputeIndex( size_t mip, size_t item, size_t slice ) const
Blob& Blob::operator= (Blob&& moveFrom)
{
if ( this != &moveFrom )
if (this != &moveFrom)
{
Release();
_buffer = moveFrom._buffer;
_size = moveFrom._size;
m_buffer = moveFrom.m_buffer;
m_size = moveFrom.m_size;
moveFrom._buffer = nullptr;
moveFrom._size = 0;
moveFrom.m_buffer = nullptr;
moveFrom.m_size = 0;
}
return *this;
}
void Blob::Release()
{
if ( _buffer )
if (m_buffer)
{
_aligned_free( _buffer );
_buffer = nullptr;
_aligned_free(m_buffer);
m_buffer = nullptr;
}
_size = 0;
m_size = 0;
}
_Use_decl_annotations_
HRESULT Blob::Initialize( size_t size )
HRESULT Blob::Initialize(size_t size)
{
if ( !size )
if (!size)
return E_INVALIDARG;
Release();
_buffer = _aligned_malloc( size, 16 );
if ( !_buffer )
m_buffer = _aligned_malloc(size, 16);
if (!m_buffer)
{
Release();
return E_OUTOFMEMORY;
}
_size = size;
m_size = size;
return S_OK;
}
}; // namespace

Разница между файлами не показана из-за своего большого размера Загрузить разницу

Просмотреть файл

@ -63,36 +63,36 @@ struct LinearFilter
float weight1;
};
inline void _CreateLinearFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf )
inline void _CreateLinearFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Out_writes_(dest) LinearFilter* lf)
{
assert( source > 0 );
assert( dest > 0 );
assert( lf != 0 );
assert(source > 0);
assert(dest > 0);
assert(lf != 0);
float scale = float(source) / float(dest);
// Mirror is the same case as clamp for linear
for( size_t u = 0; u < dest; ++u )
for (size_t u = 0; u < dest; ++u)
{
float srcB = ( float(u) + 0.5f ) * scale + 0.5f;
float srcB = (float(u) + 0.5f) * scale + 0.5f;
ptrdiff_t isrcB = ptrdiff_t(srcB);
ptrdiff_t isrcA = isrcB - 1;
if ( isrcA < 0 )
if (isrcA < 0)
{
isrcA = ( wrap ) ? ( source - 1) : 0;
isrcA = (wrap) ? (source - 1) : 0;
}
if ( size_t(isrcB) >= source )
if (size_t(isrcB) >= source)
{
isrcB = ( wrap ) ? 0 : ( source - 1);
isrcB = (wrap) ? 0 : (source - 1);
}
float weight = 1.0f + float(isrcB) - srcB;
auto& entry = lf[ u ];
auto& entry = lf[u];
entry.u0 = size_t(isrcA);
entry.weight0 = weight;
@ -120,34 +120,34 @@ XMGLOBALCONST XMVECTORF32 g_cubicThird = { 1.f/3.f, 1.f/3.f, 1.f/3.f, 1.f/3.f };
XMGLOBALCONST XMVECTORF32 g_cubicSixth = { 1.f/6.f, 1.f/6.f, 1.f/6.f, 1.f/6.f };
XMGLOBALCONST XMVECTORF32 g_cubicHalf = { 1.f/2.f, 1.f/2.f, 1.f/2.f, 1.f/2.f };
inline ptrdiff_t bounduvw( ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror )
inline ptrdiff_t bounduvw(ptrdiff_t u, ptrdiff_t maxu, bool wrap, bool mirror)
{
if ( wrap )
if (wrap)
{
if ( u < 0 )
if (u < 0)
{
u = maxu + u + 1;
}
else if ( u > maxu )
else if (u > maxu)
{
u = u - maxu - 1;
}
}
else if ( mirror )
else if (mirror)
{
if ( u < 0 )
if (u < 0)
{
u = ( -u ) - 1;
u = (-u) - 1;
}
else if ( u > maxu )
else if (u > maxu)
{
u = maxu - (u - maxu - 1);
}
}
// Handles clamp, but also a safety factor for degenerate images for wrap/mirror
u = std::min<ptrdiff_t>( u, maxu );
u = std::max<ptrdiff_t>( u, 0 );
u = std::min<ptrdiff_t>(u, maxu);
u = std::max<ptrdiff_t>(u, 0);
return u;
}
@ -161,24 +161,24 @@ struct CubicFilter
float x;
};
inline void _CreateCubicFilter( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf )
inline void _CreateCubicFilter(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _In_ bool mirror, _Out_writes_(dest) CubicFilter* cf)
{
assert( source > 0 );
assert( dest > 0 );
assert( cf != 0 );
assert(source > 0);
assert(dest > 0);
assert(cf != 0);
float scale = float(source) / float(dest);
for( size_t u = 0; u < dest; ++u )
for (size_t u = 0; u < dest; ++u)
{
float srcB = ( float(u) + 0.5f ) * scale - 0.5f;
float srcB = (float(u) + 0.5f) * scale - 0.5f;
ptrdiff_t isrcB = bounduvw( ptrdiff_t(srcB), source - 1, wrap, mirror );
ptrdiff_t isrcA = bounduvw( isrcB - 1, source - 1, wrap, mirror );
ptrdiff_t isrcC = bounduvw( isrcB + 1, source - 1, wrap, mirror );
ptrdiff_t isrcD = bounduvw( isrcB + 2, source - 1, wrap, mirror );
ptrdiff_t isrcB = bounduvw(ptrdiff_t(srcB), source - 1, wrap, mirror);
ptrdiff_t isrcA = bounduvw(isrcB - 1, source - 1, wrap, mirror);
ptrdiff_t isrcC = bounduvw(isrcB + 1, source - 1, wrap, mirror);
ptrdiff_t isrcD = bounduvw(isrcB + 2, source - 1, wrap, mirror);
auto& entry = cf[ u ];
auto& entry = cf[u];
entry.u0 = size_t(isrcA);
entry.u1 = size_t(isrcB);
entry.u2 = size_t(isrcC);
@ -246,10 +246,10 @@ namespace TriangleFilter
static const float TF_EPSILON = 0.00001f;
inline HRESULT _Create( _In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf )
inline HRESULT _Create(_In_ size_t source, _In_ size_t dest, _In_ bool wrap, _Inout_ std::unique_ptr<Filter>& tf)
{
assert( source > 0 );
assert( dest > 0 );
assert(source > 0);
assert(dest > 0);
float scale = float(dest) / float(source);
float scaleInv = 0.5f / scale;
@ -258,109 +258,109 @@ namespace TriangleFilter
size_t totalSize = TF_FILTER_SIZE + TF_FROM_SIZE + TF_TO_SIZE;
float repeat = (wrap) ? 1.f : 0.f;
for( size_t u = 0; u < source; ++u )
for (size_t u = 0; u < source; ++u)
{
float src = float(u) - 0.5f;
float destMin = src * scale;
float destMax = destMin + scale;
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t( destMax - destMin + repeat + 1.f ) * TF_TO_SIZE * 2;
totalSize += TF_FROM_SIZE + TF_TO_SIZE + size_t(destMax - destMin + repeat + 1.f) * TF_TO_SIZE * 2;
}
uint8_t* pFilter = nullptr;
if ( tf )
if (tf)
{
// See if existing filter memory block is large enough to reuse
if ( tf->totalSize >= totalSize )
if (tf->totalSize >= totalSize)
{
pFilter = reinterpret_cast<uint8_t*>( tf.get() );
pFilter = reinterpret_cast<uint8_t*>(tf.get());
}
else
{
// Need to reallocate filter memory block
tf.reset( nullptr );
tf.reset(nullptr);
}
}
if ( !tf )
if (!tf)
{
// Allocate filter memory block
pFilter = new (std::nothrow) uint8_t[ totalSize ];
if ( !pFilter )
pFilter = new (std::nothrow) uint8_t[totalSize];
if (!pFilter)
return E_OUTOFMEMORY;
tf.reset( reinterpret_cast<Filter*>( pFilter ) );
tf.reset(reinterpret_cast<Filter*>(pFilter));
tf->totalSize = totalSize;
}
assert( pFilter != 0 );
assert(pFilter != 0);
// Filter setup
size_t sizeInBytes = TF_FILTER_SIZE;
size_t accumU = 0;
float accumWeight = 0.f;
for( size_t u = 0; u < source; ++u )
for (size_t u = 0; u < source; ++u)
{
// Setup from entry
size_t sizeFrom = sizeInBytes;
auto pFrom = reinterpret_cast<FilterFrom*>( pFilter + sizeInBytes );
auto pFrom = reinterpret_cast<FilterFrom*>(pFilter + sizeInBytes);
sizeInBytes += TF_FROM_SIZE;
if ( sizeInBytes > totalSize )
if (sizeInBytes > totalSize)
return E_FAIL;
size_t toCount = 0;
// Perform two passes to capture the influences from both sides
for( size_t j = 0; j < 2; ++j )
for (size_t j = 0; j < 2; ++j)
{
float src = float( u + j ) - 0.5f;
float src = float(u + j) - 0.5f;
float destMin = src * scale;
float destMax = destMin + scale;
if ( !wrap )
if (!wrap)
{
// Clamp
if ( destMin < 0.f )
if (destMin < 0.f)
destMin = 0.f;
if ( destMax > float(dest) )
if (destMax > float(dest))
destMax = float(dest);
}
for( auto k = static_cast<ptrdiff_t>( floorf( destMin ) ); float(k) < destMax; ++k )
for (auto k = static_cast<ptrdiff_t>(floorf(destMin)); float(k) < destMax; ++k)
{
float d0 = float(k);
float d1 = d0 + 1.f;
size_t u0;
if ( k < 0 )
if (k < 0)
{
// Handle wrap
u0 = size_t( k + ptrdiff_t(dest) );
u0 = size_t(k + ptrdiff_t(dest));
}
else if ( k >= ptrdiff_t(dest) )
else if (k >= ptrdiff_t(dest))
{
// Handle wrap
u0 = size_t( k - ptrdiff_t(dest) );
u0 = size_t(k - ptrdiff_t(dest));
}
else
{
u0 = size_t( k );
u0 = size_t(k);
}
// Save previous accumulated weight (if any)
if ( u0 != accumU )
if (u0 != accumU)
{
if ( accumWeight > TF_EPSILON )
if (accumWeight > TF_EPSILON)
{
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
auto pTo = reinterpret_cast<FilterTo*>(pFilter + sizeInBytes);
sizeInBytes += TF_TO_SIZE;
++toCount;
if ( sizeInBytes > totalSize )
if (sizeInBytes > totalSize)
return E_FAIL;
pTo->u = accumU;
@ -372,33 +372,33 @@ namespace TriangleFilter
}
// Clip destination
if ( d0 < destMin )
if (d0 < destMin)
d0 = destMin;
if ( d1 > destMax )
if (d1 > destMax)
d1 = destMax;
// Calculate average weight over destination pixel
float weight;
if ( !wrap && src < 0.f )
if (!wrap && src < 0.f)
weight = 1.f;
else if ( !wrap && ( ( src + 1.f ) >= float(source) ) )
else if (!wrap && ((src + 1.f) >= float(source)))
weight = 0.f;
else
weight = (d0 + d1) * scaleInv - src;
accumWeight += (d1 - d0) * ( j ? (1.f - weight) : weight );
accumWeight += (d1 - d0) * (j ? (1.f - weight) : weight);
}
}
// Store accumulated weight
if ( accumWeight > TF_EPSILON )
if (accumWeight > TF_EPSILON)
{
auto pTo = reinterpret_cast<FilterTo*>( pFilter + sizeInBytes );
auto pTo = reinterpret_cast<FilterTo*>(pFilter + sizeInBytes);
sizeInBytes += TF_TO_SIZE;
++toCount;
if ( sizeInBytes > totalSize )
if (sizeInBytes > totalSize)
return E_FAIL;
pTo->u = accumU;
@ -417,6 +417,6 @@ namespace TriangleFilter
return S_OK;
}
}; // namespace
}; // namespace TriangleFilter
}; // namespace
}; // namespace DirectX

Просмотреть файл

@ -229,7 +229,7 @@ namespace
class auto_delete_file_wic
{
public:
auto_delete_file_wic(ComPtr<IWICStream>& hFile, LPCWSTR szFile) : m_handle(hFile), m_filename(szFile) {}
auto_delete_file_wic(ComPtr<IWICStream>& hFile, const wchar_t* szFile) : m_handle(hFile), m_filename(szFile) {}
~auto_delete_file_wic()
{
if (m_filename)
@ -242,7 +242,7 @@ namespace
void clear() { m_filename = 0; }
private:
LPCWSTR m_filename;
const wchar_t* m_filename;
ComPtr<IWICStream>& m_handle;
auto_delete_file_wic(const auto_delete_file_wic&) = delete;
@ -705,7 +705,7 @@ namespace
IWICImagingFactory* factory = nullptr;
InitOnceExecuteOnce(&s_initOnce,
[](PINIT_ONCE, PVOID, PVOID *factory) -> BOOL
[](PINIT_ONCE, PVOID, LPVOID *factory) -> BOOL
{
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8) || defined(_WIN7_PLATFORM_UPDATE)
HRESULT hr = CoCreateInstance(
@ -751,7 +751,7 @@ namespace
//--------------------------------------------------------------------------------------
HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_z_ LPCWSTR fileName )
_In_z_ const wchar_t* fileName )
{
if ( !fileName )
return E_INVALIDARG;
@ -764,9 +764,9 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
// Create file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, 0 ) ) );
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE | DELETE, 0, CREATE_ALWAYS, nullptr ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE | DELETE, 0, nullptr, CREATE_ALWAYS, 0, nullptr ) ) );
#endif
if ( !hFile )
return HRESULT_FROM_WIN32( GetLastError() );
@ -912,7 +912,7 @@ HRESULT DirectX::SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
HRESULT DirectX::SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR fileName,
_In_z_ const wchar_t* fileName,
_In_opt_ const GUID* targetFormat,
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps )
{

Просмотреть файл

@ -32,12 +32,12 @@ namespace DirectX
{
HRESULT SaveDDSTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_z_ LPCWSTR fileName );
_In_z_ const wchar_t* fileName );
HRESULT SaveWICTextureToFile( _In_ ID3D11DeviceContext* pContext,
_In_ ID3D11Resource* pSource,
_In_ REFGUID guidContainerFormat,
_In_z_ LPCWSTR fileName,
_In_z_ const wchar_t* fileName,
_In_opt_ const GUID* targetFormat = nullptr,
_In_opt_ std::function<void(IPropertyBag2*)> setCustomProps = nullptr );
}

Просмотреть файл

@ -839,11 +839,7 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
return hr;
// Create file
#if (_WIN32_WINNT >= _WIN32_WINNT_WIN8)
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, 0 ) ) );
#else
ScopedHandle hFile( safe_handle( CreateFileW( fileName, GENERIC_WRITE, 0, 0, CREATE_ALWAYS, 0, 0 ) ) );
#endif
ScopedHandle hFile( safe_handle( CreateFile2( fileName, GENERIC_WRITE, 0, CREATE_ALWAYS, nullptr ) ) );
if ( !hFile )
return HRESULT_FROM_WIN32( GetLastError() );
@ -972,13 +968,13 @@ HRESULT DirectX::SaveDDSTextureToFile( ID3D12CommandQueue* pCommandQ,
// Write header & pixels
DWORD bytesWritten;
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, 0 ) )
if ( !WriteFile( hFile.get(), fileHeader, static_cast<DWORD>( headerSize ), &bytesWritten, nullptr ) )
return HRESULT_FROM_WIN32( GetLastError() );
if ( bytesWritten != headerSize )
return E_FAIL;
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, 0 ) )
if ( !WriteFile( hFile.get(), pixels.get(), static_cast<DWORD>( slicePitch ), &bytesWritten, nullptr ) )
return HRESULT_FROM_WIN32( GetLastError() );
if ( bytesWritten != slicePitch )

Просмотреть файл

@ -34,90 +34,98 @@
namespace DirectX
{
// Standard version
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromMemory(
_In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
// Standard version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemory( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromMemory(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
HRESULT CreateWICTextureFromFile(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView,
_In_ size_t maxsize = 0
);
// Extended version
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromMemoryEx(
_In_ ID3D11Device* d3dDevice,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_In_ size_t maxsize,
D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
_In_z_ const wchar_t* szFileName,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
// Extended version with optional auto-gen mipmap support
HRESULT CreateWICTextureFromMemoryEx( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromMemoryEx(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_reads_bytes_(wicDataSize) const uint8_t* wicData,
_In_ size_t wicDataSize,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromFileEx( _In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
HRESULT CreateWICTextureFromFileEx(
_In_ ID3D11Device* d3dDevice,
_In_opt_ ID3D11DeviceContext* d3dContext,
_In_z_ const wchar_t* szFileName,
_In_ size_t maxsize,
_In_ D3D11_USAGE usage,
_In_ unsigned int bindFlags,
_In_ unsigned int cpuAccessFlags,
_In_ unsigned int miscFlags,
_In_ bool forceSRGB,
_Out_opt_ ID3D11Resource** texture,
_Out_opt_ ID3D11ShaderResourceView** textureView
);
}