Merge pull request #9345 from hrydgard/d3d11-16bit-textures

D3D11: Expand 16-bit textures to 32-bit if Win8+-only texture formats are not supported
This commit is contained in:
Henrik Rydgård 2017-02-22 18:28:44 +01:00 committed by GitHub
commit 364b7e26bf
20 changed files with 217 additions and 123 deletions

View File

@ -49,6 +49,31 @@
#define TEXCACHE_MIN_PRESSURE 16 * 1024 * 1024 // Total in VRAM
#define TEXCACHE_SECOND_MIN_PRESSURE 4 * 1024 * 1024
// Just for reference
// PSP Color formats:
// 565: BBBBBGGGGGGRRRRR
// 5551: ABBBBBGGGGGRRRRR
// 4444: AAAABBBBGGGGRRRR
// 8888: AAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR (Bytes in memory: RGBA)
// D3D11/9 Color formats:
// DXGI_FORMAT_B4G4R4A4/D3DFMT_A4R4G4B4: AAAARRRRGGGGBBBB
// DXGI_FORMAT_B5G5R5A1/D3DFMT_A1R5G6B5: ARRRRRGGGGGBBBBB
// DXGI_FORMAT_B5G6R6/D3DFMT_R5G6B5: RRRRRGGGGGGBBBBB
// DXGI_FORMAT_B8G8R8A8: AAAAAAAARRRRRRRRGGGGGGGGBBBBBBBB (Bytes in memory: BGRA)
// These are Data::Format:: A4R4G4B4_PACK16, A1R5G6B5_PACK16, R5G6B5_PACK16, B8G8R8A8.
// So these are good matches, just with R/B swapped.
// OpenGL ES color formats:
// GL_UNSIGNED_SHORT_4444: BBBBGGGGRRRRAAAA (4-bit rotation)
// GL_UNSIGNED_SHORT_565: BBBBBGGGGGGRRRRR (match)
// GL_UNSIGNED_SHORT_1555: BBBBBGGGGGRRRRRA (1-bit rotation)
// GL_UNSIGNED_BYTE/RGBA: AAAAAAAABBBBBBBBGGGGGGGGRRRRRRRR (match)
// These are Data::Format:: B4G4R4A4_PACK16, B5G6R6_PACK16, B5G5R5A1_PACK16, R8G8B8A8
// Vulkan color formats:
// TODO
TextureCacheCommon::TextureCacheCommon(Draw::DrawContext *draw)
: draw_(draw),
clearCacheNextFrame_(false),
@ -105,7 +130,7 @@ void TextureCacheCommon::GetSamplingParams(int &minFilt, int &magFilt, bool &sCl
sClamp = gstate.isTexCoordClampedS();
tClamp = gstate.isTexCoordClampedT();
bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001 || (gstate.texlevel & 0xFFFFFF) == 0x100001 ; // Fix texlevel at 0
bool noMip = (gstate.texlevel & 0xFFFFFF) == 0x000001 || (gstate.texlevel & 0xFFFFFF) == 0x100001; // Fix texlevel at 0
if (IsFakeMipmapChange())
noMip = gstate.getTexLevelMode() == GE_TEXLEVEL_MODE_CONST;
@ -974,7 +999,7 @@ static void ReverseColors(void *dstBuf, const void *srcBuf, GETextureFormat fmt,
}
}
void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA) {
void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32bit) {
bool swizzled = gstate.isTextureSwizzled();
if ((texaddr & 0x00600000) != 0 && Memory::IsVRAMAddress(texaddr)) {
// This means it's in a mirror, possibly a swizzled mirror. Let's report.
@ -1008,7 +1033,7 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
case GE_CMODE_16BIT_ABGR4444:
{
const u16 *clut = GetCurrentClut<u16>() + clutSharingOffset;
if (clutAlphaLinear_ && mipmapShareClut) {
if (clutAlphaLinear_ && mipmapShareClut && !expandTo32bit) {
// Here, reverseColors means the CLUT is already reversed.
if (reverseColors) {
for (int y = 0; y < h; ++y) {
@ -1020,8 +1045,26 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
}
}
} else {
for (int y = 0; y < h; ++y) {
DeIndexTexture4((u16 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, clut);
if (expandTo32bit && !reverseColors) {
// We simply expand the CLUT to 32-bit, then we deindex as usual. Probably the fastest way.
switch (clutformat) {
case GE_CMODE_16BIT_ABGR4444:
ConvertRGBA4444ToRGBA8888(expandClut_, clut, 16);
break;
case GE_CMODE_16BIT_ABGR5551:
ConvertRGBA5551ToRGBA8888(expandClut_, clut, 16);
break;
case GE_CMODE_16BIT_BGR5650:
ConvertRGBA565ToRGBA8888(expandClut_, clut, 16);
break;
}
for (int y = 0; y < h; ++y) {
DeIndexTexture4((u32 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, expandClut_);
}
} else {
for (int y = 0; y < h; ++y) {
DeIndexTexture4((u16 *)(out + outPitch * y), texptr + (bufw * y) / 2, w, clut);
}
}
}
}
@ -1044,15 +1087,15 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
break;
case GE_TFMT_CLUT8:
ReadIndexedTex(out, outPitch, level, texptr, 1, bufw);
ReadIndexedTex(out, outPitch, level, texptr, 1, bufw, expandTo32bit);
break;
case GE_TFMT_CLUT16:
ReadIndexedTex(out, outPitch, level, texptr, 2, bufw);
ReadIndexedTex(out, outPitch, level, texptr, 2, bufw, expandTo32bit);
break;
case GE_TFMT_CLUT32:
ReadIndexedTex(out, outPitch, level, texptr, 4, bufw);
ReadIndexedTex(out, outPitch, level, texptr, 4, bufw, expandTo32bit);
break;
case GE_TFMT_4444:
@ -1064,6 +1107,20 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
for (int y = 0; y < h; ++y) {
ReverseColors(out + outPitch * y, texptr + bufw * sizeof(u16) * y, format, w, useBGRA);
}
} else if (expandTo32bit) {
for (int y = 0; y < h; ++y) {
switch (format) {
case GE_CMODE_16BIT_ABGR4444:
ConvertRGBA4444ToRGBA8888((u32 *)(out + outPitch * y), (const u16 *)texptr + bufw * y, w);
break;
case GE_CMODE_16BIT_ABGR5551:
ConvertRGBA5551ToRGBA8888((u32 *)(out + outPitch * y), (const u16 *)texptr + bufw * y, w);
break;
case GE_CMODE_16BIT_BGR5650:
ConvertRGBA565ToRGBA8888((u32 *)(out + outPitch * y), (const u16 *)texptr + bufw * y, w);
break;
}
}
} else {
for (int y = 0; y < h; ++y) {
memcpy(out + outPitch * y, texptr + bufw * sizeof(u16) * y, w * sizeof(u16));
@ -1084,6 +1141,20 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
for (int y = 0; y < h; ++y) {
ReverseColors(out + outPitch * y, unswizzled + bufw * sizeof(u16) * y, format, w, useBGRA);
}
} else if (expandTo32bit) {
for (int y = 0; y < h; ++y) {
switch (format) {
case GE_CMODE_16BIT_ABGR4444:
ConvertRGBA4444ToRGBA8888((u32 *)(out + outPitch * y), (const u16 *)unswizzled + bufw * y, w);
break;
case GE_CMODE_16BIT_ABGR5551:
ConvertRGBA5551ToRGBA8888((u32 *)(out + outPitch * y), (const u16 *)unswizzled + bufw * y, w);
break;
case GE_CMODE_16BIT_BGR5650:
ConvertRGBA565ToRGBA8888((u32 *)(out + outPitch * y), (const u16 *)unswizzled + bufw * y, w);
break;
}
}
} else {
for (int y = 0; y < h; ++y) {
memcpy(out + outPitch * y, unswizzled + bufw * sizeof(u16) * y, w * sizeof(u16));
@ -1198,7 +1269,7 @@ void TextureCacheCommon::DecodeTextureLevel(u8 *out, int outPitch, GETextureForm
}
}
void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw) {
void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool expandTo32Bit) {
int w = gstate.getTextureWidth(level);
int h = gstate.getTextureHeight(level);
@ -1208,28 +1279,48 @@ void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const
texptr = (u8 *)tmpTexBuf32_.data();
}
switch (gstate.getClutPaletteFormat()) {
int palFormat = gstate.getClutPaletteFormat();
const u16 *clut16 = (const u16 *)clutBuf_;
const u32 *clut32 = (const u32 *)clutBuf_;
if (expandTo32Bit && palFormat != GE_CMODE_32BIT_ABGR8888) {
switch (palFormat) {
case GE_CMODE_16BIT_ABGR4444:
ConvertRGBA4444ToRGBA8888(expandClut_, clut16, 256);
break;
case GE_CMODE_16BIT_ABGR5551:
ConvertRGBA5551ToRGBA8888(expandClut_, clut16, 256);
break;
case GE_CMODE_16BIT_BGR5650:
ConvertRGBA565ToRGBA8888(expandClut_, clut16, 256);
break;
}
clut32 = expandClut_;
palFormat = GE_CMODE_32BIT_ABGR8888;
}
switch (palFormat) {
case GE_CMODE_16BIT_BGR5650:
case GE_CMODE_16BIT_ABGR5551:
case GE_CMODE_16BIT_ABGR4444:
{
const u16 *clut = GetCurrentClut<u16>();
switch (bytesPerIndex) {
case 1:
for (int y = 0; y < h; ++y) {
DeIndexTexture((u16 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut);
DeIndexTexture((u16 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut16);
}
break;
case 2:
for (int y = 0; y < h; ++y) {
DeIndexTexture((u16 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut);
DeIndexTexture((u16 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut16);
}
break;
case 4:
for (int y = 0; y < h; ++y) {
DeIndexTexture((u16 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut);
DeIndexTexture((u16 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut16);
}
break;
}
@ -1238,23 +1329,22 @@ void TextureCacheCommon::ReadIndexedTex(u8 *out, int outPitch, int level, const
case GE_CMODE_32BIT_ABGR8888:
{
const u32 *clut = GetCurrentClut<u32>();
switch (bytesPerIndex) {
case 1:
for (int y = 0; y < h; ++y) {
DeIndexTexture((u32 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut);
DeIndexTexture((u32 *)(out + outPitch * y), (const u8 *)texptr + bufw * y, w, clut32);
}
break;
case 2:
for (int y = 0; y < h; ++y) {
DeIndexTexture((u32 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut);
DeIndexTexture((u32 *)(out + outPitch * y), (const u16_le *)texptr + bufw * y, w, clut32);
}
break;
case 4:
for (int y = 0; y < h; ++y) {
DeIndexTexture((u32 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut);
DeIndexTexture((u32 *)(out + outPitch * y), (const u32_le *)texptr + bufw * y, w, clut32);
}
break;
}

View File

@ -225,9 +225,9 @@ protected:
u32 yOffset;
};
void DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA = false);
void DecodeTextureLevel(u8 *out, int outPitch, GETextureFormat format, GEPaletteFormat clutformat, uint32_t texaddr, int level, int bufw, bool reverseColors, bool useBGRA, bool expandTo32Bit);
void UnswizzleFromMem(u32 *dest, u32 destPitch, const u8 *texptr, u32 bufw, u32 height, u32 bytesPerPixel);
void ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw);
void ReadIndexedTex(u8 *out, int outPitch, int level, const u8 *texptr, int bytesPerIndex, int bufw, bool expandTo32Bit);
template <typename T>
inline const T *GetCurrentClut() {
@ -322,6 +322,8 @@ protected:
bool nextNeedsRebuild_;
bool isBgraBackend_;
u32 expandClut_[256];
};
inline bool TexCacheEntry::Matches(u16 dim2, u8 format2, u8 maxLevel2) const {

View File

@ -81,7 +81,7 @@ ID3D11ShaderResourceView *DepalShaderCacheD3D11::GetClutTexture(GEPaletteFormat
return oldtex->second->view;
}
DXGI_FORMAT dstFmt = getClutDestFormatD3D11(clutFormat);
DXGI_FORMAT dstFmt = GetClutDestFormatD3D11(clutFormat);
int texturePixels = clutFormat == GE_CMODE_32BIT_ABGR8888 ? 256 : 512;
DepalTextureD3D11 *tex = new DepalTextureD3D11();

View File

@ -512,8 +512,11 @@ void GPU_D3D11::CheckGPUFeatures() {
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
features |= GPU_SUPPORTS_ANY_COPY_IMAGE;
if (draw_->GetDataFormatSupport(Draw::DataFormat::A4B4G4R4_UNORM_PACK16) & Draw::FMT_TEXTURE) {
features |= GPU_SUPPORTS_4BIT_FORMAT;
uint32_t fmt4444 = draw_->GetDataFormatSupport(Draw::DataFormat::A4R4G4B4_UNORM_PACK16);
uint32_t fmt1555 = draw_->GetDataFormatSupport(Draw::DataFormat::A1R5G5B5_UNORM_PACK16);
uint32_t fmt565 = draw_->GetDataFormatSupport(Draw::DataFormat::R5G6B5_UNORM_PACK16);
if ((fmt4444 & Draw::FMT_TEXTURE) && (fmt565 & Draw::FMT_TEXTURE) && (fmt1555 & Draw::FMT_TEXTURE)) {
features |= GPU_SUPPORTS_16BIT_FORMATS;
}
if (draw_->GetDeviceCaps().logicOpSupported) {

View File

@ -146,21 +146,6 @@ void TextureCacheD3D11::InvalidateLastTexture(TexCacheEntry *entry) {
}
}
DXGI_FORMAT getClutDestFormatD3D11(GEPaletteFormat format) {
switch (format) {
case GE_CMODE_16BIT_ABGR4444:
return DXGI_FORMAT_B4G4R4A4_UNORM;
case GE_CMODE_16BIT_ABGR5551:
return DXGI_FORMAT_B5G5R5A1_UNORM;
case GE_CMODE_16BIT_BGR5650:
return DXGI_FORMAT_B5G6R5_UNORM;
case GE_CMODE_32BIT_ABGR8888:
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
// Should never be here !
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
void TextureCacheD3D11::UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key) {
// TODO: Make GetSamplingParams write SamplerCacheKey directly
int minFilt;
@ -427,7 +412,7 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra
const u32 bytesPerColor = clutFormat == GE_CMODE_32BIT_ABGR8888 ? sizeof(u32) : sizeof(u16);
const u32 clutTotalColors = clutMaxBytes_ / bytesPerColor;
TexCacheEntry::Status alphaStatus = CheckAlpha(clutBuf_, getClutDestFormatD3D11(clutFormat), clutTotalColors, clutTotalColors, 1);
TexCacheEntry::Status alphaStatus = CheckAlpha(clutBuf_, GetClutDestFormatD3D11(clutFormat), clutTotalColors, clutTotalColors, 1);
gstate_c.textureFullAlpha = alphaStatus == TexCacheEntry::STATUS_ALPHA_FULL;
gstate_c.textureSimpleAlpha = alphaStatus == TexCacheEntry::STATUS_ALPHA_SIMPLE;
} else {
@ -572,13 +557,32 @@ void TextureCacheD3D11::BuildTexture(TexCacheEntry *const entry, bool replaceIma
}
}
DXGI_FORMAT GetClutDestFormatD3D11(GEPaletteFormat format) {
switch (format) {
case GE_CMODE_16BIT_ABGR4444:
return DXGI_FORMAT_B4G4R4A4_UNORM;
case GE_CMODE_16BIT_ABGR5551:
return DXGI_FORMAT_B5G5R5A1_UNORM;
case GE_CMODE_16BIT_BGR5650:
return DXGI_FORMAT_B5G6R5_UNORM;
case GE_CMODE_32BIT_ABGR8888:
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
// Should never be here !
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
DXGI_FORMAT TextureCacheD3D11::GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const {
if (!gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS)) {
return DXGI_FORMAT_B8G8R8A8_UNORM;
}
switch (format) {
case GE_TFMT_CLUT4:
case GE_TFMT_CLUT8:
case GE_TFMT_CLUT16:
case GE_TFMT_CLUT32:
return getClutDestFormatD3D11(clutFormat);
return GetClutDestFormatD3D11(clutFormat);
case GE_TFMT_4444:
return DXGI_FORMAT_B4G4R4A4_UNORM;
case GE_TFMT_5551:
@ -633,7 +637,7 @@ DXGI_FORMAT ToDXGIFormat(ReplacedTextureFormat fmt) {
}
}
void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt) {
void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, DXGI_FORMAT dstFmt) {
int w = gstate.getTextureWidth(level);
int h = gstate.getTextureHeight(level);
@ -642,14 +646,13 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
// Create texture
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
int tw = w, th = h;
DXGI_FORMAT tfmt = (DXGI_FORMAT)(dstFmt);
if (replaced.GetSize(level, tw, th)) {
tfmt = ToDXGIFormat(replaced.Format(level));
dstFmt = ToDXGIFormat(replaced.Format(level));
} else {
tw *= scaleFactor;
th *= scaleFactor;
if (scaleFactor > 1) {
tfmt = DXGI_FORMAT_B8G8R8A8_UNORM;
dstFmt = DXGI_FORMAT_B8G8R8A8_UNORM;
}
}
@ -661,7 +664,7 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
desc.SampleDesc.Count = 1;
desc.Width = tw;
desc.Height = th;
desc.Format = tfmt;
desc.Format = dstFmt;
desc.MipLevels = levels;
desc.BindFlags = D3D11_BIND_SHADER_RESOURCE;
@ -708,10 +711,12 @@ void TextureCacheD3D11::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &
decPitch = mapRowPitch;
}
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false);
bool expand32 = !gstate_c.Supports(GPU_SUPPORTS_16BIT_FORMATS);
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, expand32);
if (scaleFactor > 1) {
scaler.ScaleAlways((u32 *)mapData, pixelData, dstFmt, w, h, scaleFactor);
u32 scaleFmt = (u32)dstFmt;
scaler.ScaleAlways((u32 *)mapData, pixelData, scaleFmt, w, h, scaleFactor);
pixelData = (u32 *)mapData;
// We always end up at 8888. Other parts assume this.

View File

@ -71,7 +71,7 @@ protected:
private:
void UpdateSamplingParams(TexCacheEntry &entry, SamplerCacheKey &key);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, u32 dstFmt);
void LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &replaced, int level, int maxLevel, bool replaceImages, int scaleFactor, DXGI_FORMAT dstFmt);
DXGI_FORMAT GetDestFormat(GETextureFormat format, GEPaletteFormat clutFormat) const;
TexCacheEntry::Status CheckAlpha(const u32 *pixelData, u32 dstFmt, int stride, int w, int h);
void UpdateCurrentClut(GEPaletteFormat clutFormat, u32 clutBase, bool clutIndexIsSimple) override;
@ -104,4 +104,4 @@ private:
ShaderManagerD3D11 *shaderManager_;
};
DXGI_FORMAT getClutDestFormatD3D11(GEPaletteFormat format);
DXGI_FORMAT GetClutDestFormatD3D11(GEPaletteFormat format);

View File

@ -473,11 +473,12 @@ void GPU_DX9::UpdateCmdInfo() {
void GPU_DX9::CheckGPUFeatures() {
u32 features = 0;
features |= GPU_SUPPORTS_4BIT_FORMAT;
features |= GPU_SUPPORTS_16BIT_FORMATS;
features |= GPU_SUPPORTS_BLEND_MINMAX;
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
features |= GPU_PREFER_CPU_DOWNLOAD;
features |= GPU_SUPPORTS_ACCURATE_DEPTH;
features |= GPU_SUPPORTS_16BIT_FORMATS;
D3DCAPS9 caps;
ZeroMemory(&caps, sizeof(caps));

View File

@ -654,10 +654,8 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
// Create texture
D3DPOOL pool = D3DPOOL_MANAGED;
int usage = 0;
if (pD3DdeviceEx) {
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_DYNAMIC; // TODO: Switch to using a staging texture?
}
pool = D3DPOOL_DEFAULT;
usage = D3DUSAGE_DYNAMIC; // TODO: Switch to using a staging texture?
int levels = scaleFactor == 1 ? maxLevel + 1 : 1;
int tw = w, th = h;
D3DFORMAT tfmt = (D3DFORMAT)(dstFmt);
@ -676,17 +674,24 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
else
hr = pD3Ddevice->CreateTexture(tw, th, levels, usage, tfmt, pool, &texture, NULL);
if (FAILED(hr)) {
INFO_LOG(G3D, "Failed to create D3D texture");
INFO_LOG(G3D, "Failed to create D3D texture: %dx%d", tw, th);
ReleaseTexture(&entry);
return;
}
}
D3DLOCKED_RECT rect;
HRESULT result;
uint32_t lockFlag = level == 0 ? D3DLOCK_DISCARD : 0; // Can only discard the top level
if (IsFakeMipmapChange())
texture->LockRect(0, &rect, NULL, D3DLOCK_DISCARD);
result = texture->LockRect(0, &rect, NULL, lockFlag);
else
texture->LockRect(level, &rect, NULL, D3DLOCK_DISCARD);
result = texture->LockRect(level, &rect, NULL, lockFlag);
if (FAILED(result)) {
ERROR_LOG(G3D, "Failed to lock D3D texture: %dx%d", w, h);
return;
}
gpuStats.numTexturesDecoded++;
if (replaced.GetSize(level, w, h)) {
@ -708,7 +713,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, ReplacedTexture &re
decPitch = w * bpp;
}
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false);
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, false);
if (scaleFactor > 1) {
scaler.ScaleAlways((u32 *)rect.pBits, pixelData, dstFmt, w, h, scaleFactor);

View File

@ -506,7 +506,7 @@ GPU_GLES::~GPU_GLES() {
void GPU_GLES::CheckGPUFeatures() {
u32 features = 0;
features |= GPU_SUPPORTS_4BIT_FORMAT;
features |= GPU_SUPPORTS_16BIT_FORMATS;
if (gl_extensions.ARB_blend_func_extended || gl_extensions.EXT_blend_func_extended) {
if (gl_extensions.gpuVendor == GPU_VENDOR_INTEL || !gl_extensions.VersionGEThan(3, 0, 0)) {

View File

@ -766,7 +766,7 @@ void *TextureCacheGLES::DecodeTextureLevelOld(GETextureFormat format, GEPaletteF
}
tmpTexBufRearrange_.resize(std::max(w, bufw) * h);
DecodeTextureLevel((u8 *)tmpTexBufRearrange_.data(), decPitch, format, clutformat, texaddr, level, bufw, true, UseBGRA8888());
DecodeTextureLevel((u8 *)tmpTexBufRearrange_.data(), decPitch, format, clutformat, texaddr, level, bufw, true, UseBGRA8888(), false);
return tmpTexBufRearrange_.data();
}

View File

@ -459,7 +459,7 @@ enum {
GPU_SUPPORTS_INSTANCE_RENDERING = FLAG_BIT(10),
GPU_SUPPORTS_VERTEX_TEXTURE_FETCH = FLAG_BIT(11),
GPU_SUPPORTS_TEXTURE_FLOAT = FLAG_BIT(12),
GPU_SUPPORTS_4BIT_FORMAT = FLAG_BIT(13),
GPU_SUPPORTS_16BIT_FORMATS = FLAG_BIT(13),
GPU_SUPPORTS_LARGE_VIEWPORTS = FLAG_BIT(16),
GPU_SUPPORTS_ACCURATE_DEPTH = FLAG_BIT(17),
GPU_SUPPORTS_VAO = FLAG_BIT(18),

View File

@ -463,32 +463,34 @@ GPU_Vulkan::~GPU_Vulkan() {
}
void GPU_Vulkan::CheckGPUFeatures() {
gstate_c.featureFlags = 0;
gstate_c.featureFlags |= GPU_SUPPORTS_4BIT_FORMAT;
uint32_t features = 0;
features |= GPU_SUPPORTS_16BIT_FORMATS;
if (vulkan_->GetFeaturesEnabled().wideLines) {
gstate_c.featureFlags |= GPU_SUPPORTS_WIDE_LINES;
features |= GPU_SUPPORTS_WIDE_LINES;
}
if (vulkan_->GetFeaturesEnabled().dualSrcBlend) {
gstate_c.featureFlags |= GPU_SUPPORTS_DUALSOURCE_BLEND;
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
}
if (vulkan_->GetFeaturesEnabled().logicOp) {
gstate_c.featureFlags |= GPU_SUPPORTS_LOGIC_OP;
features |= GPU_SUPPORTS_LOGIC_OP;
}
if (vulkan_->GetFeaturesEnabled().samplerAnisotropy) {
gstate_c.featureFlags |= GPU_SUPPORTS_ANISOTROPY;
features |= GPU_SUPPORTS_ANISOTROPY;
}
if (PSP_CoreParameter().compat.flags().ClearToRAM) {
gstate_c.featureFlags |= GPU_USE_CLEAR_RAM_HACK;
features |= GPU_USE_CLEAR_RAM_HACK;
}
// Mandatory features on Vulkan, which may be checked in "centralized" code
gstate_c.featureFlags |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
gstate_c.featureFlags |= GPU_SUPPORTS_FBO;
gstate_c.featureFlags |= GPU_SUPPORTS_BLEND_MINMAX;
gstate_c.featureFlags |= GPU_SUPPORTS_ANY_COPY_IMAGE;
gstate_c.featureFlags |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
gstate_c.featureFlags |= GPU_SUPPORTS_LARGE_VIEWPORTS;
features |= GPU_SUPPORTS_TEXTURE_LOD_CONTROL;
features |= GPU_SUPPORTS_FBO;
features |= GPU_SUPPORTS_BLEND_MINMAX;
features |= GPU_SUPPORTS_ANY_COPY_IMAGE;
features |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
features |= GPU_SUPPORTS_LARGE_VIEWPORTS;
features |= GPU_SUPPORTS_16BIT_FORMATS;
gstate_c.featureFlags = features;
}
void GPU_Vulkan::BeginHostFrame() {

View File

@ -745,7 +745,7 @@ void TextureCacheVulkan::LoadTextureLevel(TexCacheEntry &entry, uint8_t *writePt
decPitch = w * bpp;
}
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false);
DecodeTextureLevel((u8 *)pixelData, decPitch, tfmt, clutformat, texaddr, level, bufw, false, false, false);
gpuStats.numTexturesDecoded++;
if (scaleFactor > 1) {

View File

@ -282,8 +282,8 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
DataFormat texFormat;
// For our purposes these are equivalent, so just choose the supported one. D3D can emulate them.
if (draw_->GetDataFormatSupport(Draw::DataFormat::A4B4G4R4_UNORM_PACK16) & FMT_TEXTURE)
texFormat = Draw::DataFormat::A4B4G4R4_UNORM_PACK16;
if (draw_->GetDataFormatSupport(Draw::DataFormat::A4R4G4B4_UNORM_PACK16) & FMT_TEXTURE)
texFormat = Draw::DataFormat::A4R4G4B4_UNORM_PACK16;
else if (draw_->GetDataFormatSupport(Draw::DataFormat::B4G4R4A4_UNORM_PACK16) & FMT_TEXTURE)
texFormat = Draw::DataFormat::B4G4R4A4_UNORM_PACK16;
else
@ -294,8 +294,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
TextureDesc desc{};
uint32_t *bitmapData32 = nullptr;
uint16_t *bitmapData16 = nullptr;
if (texFormat == Draw::DataFormat::R8G8B8A8_UNORM) {
// We need a full 32-bit format :(
if (texFormat == Draw::DataFormat::R8G8B8A8_UNORM || texFormat == Draw::DataFormat::B8G8R8A8_UNORM) {
bitmapData32 = new uint32_t[entry->bmWidth * entry->bmHeight];
for (int y = 0; y < entry->bmHeight; y++) {
for (int x = 0; x < entry->bmWidth; x++) {
@ -313,7 +312,7 @@ void TextDrawer::DrawString(DrawBuffer &target, const char *str, float x, float
}
}
desc.initData.push_back((uint8_t *)bitmapData16);
} else {
} else if (texFormat == Draw::DataFormat::A4R4G4B4_UNORM_PACK16) {
bitmapData16 = new uint16_t[entry->bmWidth * entry->bmHeight];
for (int y = 0; y < entry->bmHeight; y++) {
for (int x = 0; x < entry->bmWidth; x++) {

View File

@ -13,7 +13,7 @@ size_t DataFormatSizeInBytes(DataFormat fmt) {
case DataFormat::R4G4B4A4_UNORM_PACK16: return 2;
case DataFormat::B4G4R4A4_UNORM_PACK16: return 2;
case DataFormat::A4B4G4R4_UNORM_PACK16: return 2;
case DataFormat::A4R4G4B4_UNORM_PACK16: return 2;
case DataFormat::R5G5B5A1_UNORM_PACK16: return 2;
case DataFormat::B5G5R5A1_UNORM_PACK16: return 2;
case DataFormat::R5G6B5_UNORM_PACK16: return 2;

View File

@ -192,14 +192,14 @@ enum class DataFormat : uint8_t {
R8G8B8A8_SINT,
R4G4_UNORM_PACK8,
A4B4G4R4_UNORM_PACK16, // This is the one D3D supports
B4G4R4A4_UNORM_PACK16, // Supported by Vulkan (guaranteed one), as is the below but not on all cards.
R4G4B4A4_UNORM_PACK16, // This is the one OpenGL ES supports
A4R4G4B4_UNORM_PACK16, // A4 in the UPPER bit
B4G4R4A4_UNORM_PACK16,
R4G4B4A4_UNORM_PACK16,
R5G6B5_UNORM_PACK16,
B5G6R5_UNORM_PACK16,
R5G5B5A1_UNORM_PACK16,
B5G5R5A1_UNORM_PACK16,
A1R5G5B5_UNORM_PACK16,
R5G5B5A1_UNORM_PACK16, // A1 in the LOWER bit
B5G5R5A1_UNORM_PACK16, // A1 in the LOWER bit
A1R5G5B5_UNORM_PACK16, // A1 in the UPPER bit.
R16_FLOAT,
R16G16_FLOAT,
@ -297,6 +297,7 @@ enum FormatSupport {
FMT_RENDERTARGET = 1,
FMT_TEXTURE = 2,
FMT_INPUTLAYOUT = 4,
FMT_DEPTHSTENCIL = 8,
};
enum InfoField {

View File

@ -383,7 +383,7 @@ static DXGI_FORMAT dataFormatToD3D11(DataFormat format) {
case DataFormat::R32G32_FLOAT: return DXGI_FORMAT_R32G32_FLOAT;
case DataFormat::R32G32B32_FLOAT: return DXGI_FORMAT_R32G32B32_FLOAT;
case DataFormat::R32G32B32A32_FLOAT: return DXGI_FORMAT_R32G32B32A32_FLOAT;
case DataFormat::A4B4G4R4_UNORM_PACK16: return DXGI_FORMAT_B4G4R4A4_UNORM;
case DataFormat::A4R4G4B4_UNORM_PACK16: return DXGI_FORMAT_B4G4R4A4_UNORM;
case DataFormat::A1R5G5B5_UNORM_PACK16: return DXGI_FORMAT_B5G5R5A1_UNORM;
case DataFormat::R5G6B5_UNORM_PACK16: return DXGI_FORMAT_B5G6R5_UNORM;
case DataFormat::R8G8B8A8_UNORM: return DXGI_FORMAT_R8G8B8A8_UNORM;
@ -1023,37 +1023,23 @@ void D3D11DrawContext::DrawUP(const void *vdata, int vertexCount) {
}
uint32_t D3D11DrawContext::GetDataFormatSupport(DataFormat fmt) const {
// TODO: Actually do proper checks
switch (fmt) {
case DataFormat::B8G8R8A8_UNORM:
return FMT_RENDERTARGET | FMT_TEXTURE;
// D3D11 has no support for 4-bit component formats, except this one and only on Windows 8.
case DataFormat::A4B4G4R4_UNORM_PACK16:
return b4g4r4a4Supported_ ? FMT_TEXTURE : 0;
case DataFormat::R4G4B4A4_UNORM_PACK16:
case DataFormat::B4G4R4A4_UNORM_PACK16:
DXGI_FORMAT giFmt = dataFormatToD3D11(fmt);
if (giFmt == DXGI_FORMAT_UNKNOWN)
return 0;
case DataFormat::R8G8B8A8_UNORM:
return FMT_RENDERTARGET | FMT_TEXTURE | FMT_INPUTLAYOUT;
case DataFormat::R32_FLOAT:
case DataFormat::R32G32_FLOAT:
case DataFormat::R32G32B32_FLOAT:
case DataFormat::R32G32B32A32_FLOAT:
return FMT_INPUTLAYOUT;
case DataFormat::R8_UNORM:
UINT giSupport = 0;
HRESULT result = device_->CheckFormatSupport(giFmt, &giSupport);
if (FAILED(result))
return 0;
case DataFormat::BC1_RGBA_UNORM_BLOCK:
case DataFormat::BC2_UNORM_BLOCK:
case DataFormat::BC3_UNORM_BLOCK:
return FMT_TEXTURE;
default:
return 0;
}
uint32_t support = 0;
if (giSupport & D3D11_FORMAT_SUPPORT_TEXTURE2D)
support |= FMT_TEXTURE;
if (giSupport & D3D11_FORMAT_SUPPORT_RENDER_TARGET)
support |= FMT_RENDERTARGET;
if (giSupport & D3D11_FORMAT_SUPPORT_IA_VERTEX_BUFFER)
support |= FMT_INPUTLAYOUT;
if (giSupport & D3D11_FORMAT_SUPPORT_DEPTH_STENCIL)
support |= FMT_DEPTHSTENCIL;
return support;
}
// A D3D11Framebuffer is a D3D11Framebuffer plus all the textures it owns.

View File

@ -122,7 +122,7 @@ D3DFORMAT FormatToD3DFMT(DataFormat fmt) {
case DataFormat::R8G8B8A8_UNORM: return D3DFMT_A8R8G8B8;
case DataFormat::R4G4B4A4_UNORM_PACK16: return D3DFMT_A4R4G4B4; // emulated
case DataFormat::B4G4R4A4_UNORM_PACK16: return D3DFMT_A4R4G4B4; // native
case DataFormat::A4B4G4R4_UNORM_PACK16: return D3DFMT_A4R4G4B4; // emulated
case DataFormat::A4R4G4B4_UNORM_PACK16: return D3DFMT_A4R4G4B4; // emulated
case DataFormat::R5G6B5_UNORM_PACK16: return D3DFMT_R5G6B5;
case DataFormat::A1R5G5B5_UNORM_PACK16: return D3DFMT_A1R5G5B5;
case DataFormat::D24_S8: return D3DFMT_D24S8;
@ -407,7 +407,7 @@ void D3D9Texture::SetImageData(int x, int y, int z, int width, int height, int d
((uint16_t *)dest)[j] = (color << 12) | (color >> 4);
}
break;
case DataFormat::A4B4G4R4_UNORM_PACK16:
case DataFormat::A4R4G4B4_UNORM_PACK16:
// Native
memcpy(dest, source, width * sizeof(uint16_t));
break;
@ -1162,7 +1162,7 @@ uint32_t D3D9Context::GetDataFormatSupport(DataFormat fmt) const {
return FMT_TEXTURE; // emulated support
case DataFormat::R5G6B5_UNORM_PACK16:
case DataFormat::A1R5G5B5_UNORM_PACK16:
case DataFormat::A4B4G4R4_UNORM_PACK16:
case DataFormat::A4R4G4B4_UNORM_PACK16:
return FMT_RENDERTARGET | FMT_TEXTURE; // native support
case DataFormat::R8G8B8A8_UNORM:

View File

@ -743,7 +743,7 @@ void OpenGLTexture::SetImageData(int x, int y, int z, int width, int height, int
type = GL_UNSIGNED_SHORT_4_4_4_4;
break;
#ifndef USING_GLES2
case DataFormat::A4B4G4R4_UNORM_PACK16:
case DataFormat::A4R4G4B4_UNORM_PACK16:
internalFormat = GL_RGBA;
format = GL_RGBA;
type = GL_UNSIGNED_SHORT_4_4_4_4_REV;
@ -1657,7 +1657,7 @@ uint32_t OpenGLContext::GetDataFormatSupport(DataFormat fmt) const {
return FMT_RENDERTARGET | FMT_TEXTURE;
case DataFormat::B4G4R4A4_UNORM_PACK16:
return FMT_RENDERTARGET | FMT_TEXTURE; // native support
case DataFormat::A4B4G4R4_UNORM_PACK16:
case DataFormat::A4R4G4B4_UNORM_PACK16:
#ifndef USING_GLES2
// Can support this if _REV formats are supported.
return FMT_TEXTURE;

View File

@ -1242,7 +1242,7 @@ uint32_t VKContext::GetDataFormatSupport(DataFormat fmt) const {
return FMT_RENDERTARGET | FMT_TEXTURE;
case DataFormat::R4G4B4A4_UNORM_PACK16:
return 0;
case DataFormat::A4B4G4R4_UNORM_PACK16:
case DataFormat::A4R4G4B4_UNORM_PACK16:
return 0;
case DataFormat::R8G8B8A8_UNORM: