1
0
mirror of https://github.com/microsoft/DirectXTex synced 2024-11-21 12:00:06 +00:00

General code cleanuP

This commit is contained in:
Chuck Walbourn 2016-09-08 19:09:46 -07:00
parent 53e66ba1e9
commit 51bc3d5b16
28 changed files with 13052 additions and 12638 deletions

View File

@ -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 )
{

File diff suppressed because it is too large Load Diff

View File

@ -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
}

File diff suppressed because it is too large Load Diff

View File

@ -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
}

View File

@ -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 );
//---------------------------------------------------------------------------------

View File

@ -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;

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -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

File diff suppressed because it is too large Load Diff

View File

@ -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

View File

@ -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 )
{

View File

@ -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 );
}

View File

@ -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 )

View File

@ -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
);
}