Use the new texture decoder path to speed up texture loading in DX11.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@5748 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
ccbc1feb0b
commit
208c33f09c
|
@ -22,135 +22,27 @@
|
||||||
namespace D3D
|
namespace D3D
|
||||||
{
|
{
|
||||||
|
|
||||||
// buffers for storing the data for DEFAULT textures
|
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage)
|
||||||
u8* texbuf = NULL;
|
|
||||||
unsigned int texbufsize = 0;
|
|
||||||
|
|
||||||
// TODO: Remove this class and properly clean up texbuf!
|
|
||||||
struct TexbufDeleter
|
|
||||||
{
|
{
|
||||||
~TexbufDeleter()
|
|
||||||
{
|
|
||||||
SAFE_DELETE_ARRAY(texbuf);
|
|
||||||
texbufsize = 0;
|
|
||||||
}
|
|
||||||
} texbufdeleter;
|
|
||||||
|
|
||||||
void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, DXGI_FORMAT fmt, PC_TexFormat pcfmt, unsigned int level, D3D11_USAGE usage)
|
|
||||||
{
|
|
||||||
u8* outptr;
|
|
||||||
unsigned int destPitch;
|
|
||||||
bool bExpand = false;
|
|
||||||
|
|
||||||
if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
|
|
||||||
{
|
|
||||||
if (usage == D3D11_USAGE_DYNAMIC && level != 0) PanicAlert("Dynamic textures don't support mipmaps, but given level is not 0 at %s %d\n", __FILE__, __LINE__);
|
|
||||||
D3D11_MAPPED_SUBRESOURCE map;
|
|
||||||
D3D::context->Map(pTexture, 0, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
|
||||||
outptr = (u8*)map.pData;
|
|
||||||
destPitch = map.RowPitch;
|
|
||||||
}
|
|
||||||
else if (usage == D3D11_USAGE_DEFAULT && !(pcfmt == PC_TEX_FMT_BGRA32 && fmt == DXGI_FORMAT_B8G8R8A8_UNORM))
|
|
||||||
{
|
|
||||||
if (texbufsize < 4*width*height)
|
|
||||||
{
|
|
||||||
SAFE_DELETE_ARRAY(texbuf);
|
|
||||||
texbuf = new u8[4*width*height];
|
|
||||||
texbufsize = 4*width*height;
|
|
||||||
}
|
|
||||||
outptr = texbuf;
|
|
||||||
destPitch = width * 4;
|
|
||||||
}
|
|
||||||
else if (usage == D3D11_USAGE_DEFAULT && pcfmt == PC_TEX_FMT_BGRA32 && fmt == DXGI_FORMAT_B8G8R8A8_UNORM)
|
|
||||||
{
|
|
||||||
// BGRA32 textures can be uploaded directly to VRAM in this case
|
|
||||||
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
|
|
||||||
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
PanicAlert("ReplaceTexture2D called on an immutable texture!\n");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO: Merge the conversions done here to VideoDecoder
|
|
||||||
switch (pcfmt)
|
|
||||||
{
|
|
||||||
case PC_TEX_FMT_IA8:
|
|
||||||
case PC_TEX_FMT_IA4_AS_IA8:
|
|
||||||
for (unsigned int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
u16* in = (u16*)buffer + y * pitch;
|
|
||||||
u32* pBits = (u32*)(outptr + y * destPitch);
|
|
||||||
for (unsigned int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
const u8 I = (*in & 0xFF);
|
|
||||||
const u8 A = (*in & 0xFF00) >> 8;
|
|
||||||
*pBits++ = (A << 24) | (I << 16) | (I << 8) | I;
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PC_TEX_FMT_I8:
|
|
||||||
case PC_TEX_FMT_I4_AS_I8:
|
|
||||||
for (unsigned int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
const u8* in = buffer + y * pitch;
|
|
||||||
u32* pBits = (u32*)(outptr + y * destPitch);
|
|
||||||
for(unsigned int i = 0; i < width; i++)
|
|
||||||
memset( pBits++, *in++, 4 );
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PC_TEX_FMT_BGRA32:
|
|
||||||
if (fmt == DXGI_FORMAT_B8G8R8A8_UNORM)
|
|
||||||
{
|
|
||||||
for (unsigned int y = 0; y < height; y++)
|
|
||||||
memcpy( outptr + y * destPitch, (u32*)buffer + y * pitch, destPitch );
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
for (unsigned int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
u32* in = (u32*)buffer + y * pitch;
|
|
||||||
u32* pBits = (u32*)(outptr + y * destPitch);
|
|
||||||
for (unsigned int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
*pBits++ = (*in & 0xFF00FF00) | ((*in >> 16) & 0xFF) | ((*in << 16) & 0xFF0000);
|
|
||||||
in++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case PC_TEX_FMT_RGB565:
|
|
||||||
for (unsigned int y = 0; y < height; y++)
|
|
||||||
{
|
|
||||||
u16* in = (u16*)buffer + y * pitch;
|
|
||||||
u32* pBits = (u32*)(outptr + y * destPitch);
|
|
||||||
for (unsigned int x = 0; x < width; x++)
|
|
||||||
{
|
|
||||||
// we can't simply shift here, since e.g. 11111 must map to 11111111 and not 11111000
|
|
||||||
const u16 col = *in++;
|
|
||||||
*(pBits++) = 0xFF000000 | // alpha
|
|
||||||
(( (col&0xF800) >> 11) * 255 / 31) | // red
|
|
||||||
((((col& 0x7e0) << 3) * 255 / 63) & 0xFF00) | // green
|
|
||||||
((((col& 0x1f) << 16) * 255 / 31) & 0xFF0000); // blue
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
PanicAlert("Unknown tex fmt %d\n", pcfmt);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (usage == D3D11_USAGE_DYNAMIC)
|
if (usage == D3D11_USAGE_DYNAMIC)
|
||||||
{
|
{
|
||||||
// TODO: UpdateSubresource might be faster than mapping
|
D3D11_MAPPED_SUBRESOURCE map;
|
||||||
D3D::context->Unmap(pTexture, 0);
|
D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map);
|
||||||
|
if (4 * pitch == map.RowPitch)
|
||||||
|
{
|
||||||
|
memcpy(map.pData, buffer, map.RowPitch * height);
|
||||||
}
|
}
|
||||||
else if (usage == D3D11_USAGE_DEFAULT)
|
else
|
||||||
|
{
|
||||||
|
for (unsigned int y = 0; y < height; ++y)
|
||||||
|
memcpy((u8*)map.pData + y * map.RowPitch, (u32*)buffer + y * pitch, map.RowPitch);
|
||||||
|
}
|
||||||
|
D3D::context->Unmap(pTexture, level);
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
|
D3D11_BOX dest_region = CD3D11_BOX(0, 0, 0, width, height, 1);
|
||||||
D3D::context->UpdateSubresource(pTexture, level, &dest_region, outptr, destPitch, 4*width*height);
|
D3D::context->UpdateSubresource(pTexture, level, &dest_region, buffer, 4*pitch, 4*pitch*height);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,7 +22,7 @@
|
||||||
|
|
||||||
namespace D3D
|
namespace D3D
|
||||||
{
|
{
|
||||||
void ReplaceTexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, DXGI_FORMAT fmt, PC_TexFormat pcfmt, unsigned int level, D3D11_USAGE usage);
|
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage);
|
||||||
}
|
}
|
||||||
|
|
||||||
class D3DTexture2D
|
class D3DTexture2D
|
||||||
|
|
|
@ -311,9 +311,9 @@ StateManager::StateManager() : cur_blendstate(NULL), cur_depthstate(NULL), cur_r
|
||||||
void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state));}
|
void StateManager::PushBlendState(const ID3D11BlendState* state) { blendstates.push(AutoBlendState(state));}
|
||||||
void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state));}
|
void StateManager::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state));}
|
||||||
void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state));}
|
void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state));}
|
||||||
void StateManager::PopBlendState() { blendstates.pop(); }
|
void StateManager::PopBlendState() { if(!blendstates.empty()) blendstates.pop(); }
|
||||||
void StateManager::PopDepthState() { depthstates.pop(); }
|
void StateManager::PopDepthState() { if(!depthstates.empty()) depthstates.pop(); }
|
||||||
void StateManager::PopRasterizerState() { raststates.pop(); }
|
void StateManager::PopRasterizerState() { if(!raststates.empty()) raststates.pop(); }
|
||||||
|
|
||||||
void StateManager::Apply()
|
void StateManager::Apply()
|
||||||
{
|
{
|
||||||
|
|
|
@ -268,63 +268,51 @@ TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, u
|
||||||
TCacheEntry& entry = textures[texID];
|
TCacheEntry& entry = textures[texID];
|
||||||
PC_TexFormat pcfmt = PC_TEX_FMT_NONE;
|
PC_TexFormat pcfmt = PC_TEX_FMT_NONE;
|
||||||
|
|
||||||
if (pcfmt == PC_TEX_FMT_NONE)
|
pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt, true);
|
||||||
pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
|
|
||||||
|
|
||||||
DXGI_FORMAT d3d_fmt = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
||||||
bool swap_r_b = false;
|
|
||||||
if (pcfmt == PC_TEX_FMT_BGRA32 && D3D::BGRATexturesSupported()) d3d_fmt = DXGI_FORMAT_B8G8R8A8_UNORM;
|
|
||||||
|
|
||||||
entry.oldpixel = ((u32*)ptr)[0];
|
entry.oldpixel = ((u32*)ptr)[0];
|
||||||
if (g_ActiveConfig.bSafeTextureCache) entry.hash = hash_value;
|
if (g_ActiveConfig.bSafeTextureCache) entry.hash = hash_value;
|
||||||
else entry.hash = ((u32*)ptr)[0] = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
else entry.hash = ((u32*)ptr)[0] = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||||
|
|
||||||
entry.addr = address;
|
|
||||||
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format);
|
|
||||||
entry.isRenderTarget = false;
|
|
||||||
bool isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
bool isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
||||||
entry.isNonPow2 = false;
|
|
||||||
unsigned int TexLevels = (isPow2 && UseNativeMips && maxlevel) ? GetPow2(max(width, height)) : ((isPow2)? 0 : 1);
|
unsigned int TexLevels = (isPow2 && UseNativeMips && maxlevel) ? GetPow2(max(width, height)) : ((isPow2)? 0 : 1);
|
||||||
if (TexLevels > (maxlevel + 1) && maxlevel)
|
if (TexLevels > (maxlevel + 1) && maxlevel)
|
||||||
TexLevels = maxlevel + 1;
|
TexLevels = maxlevel + 1;
|
||||||
entry.MipLevels = maxlevel;
|
|
||||||
D3D11_USAGE usage = (TexLevels == 1) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
|
D3D11_USAGE usage = (TexLevels == 1) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT;
|
||||||
|
|
||||||
if (!skip_texture_create)
|
if (!skip_texture_create)
|
||||||
{
|
{
|
||||||
// TODO: A little more verbosity in the debug names would be quite helpful..
|
// TODO: A little more verbosity in the debug names would be quite helpful..
|
||||||
if (usage == D3D11_USAGE_DYNAMIC)
|
D3D11_CPU_ACCESS_FLAG cpu_access = (TexLevels == 1) ? D3D11_CPU_ACCESS_WRITE : (D3D11_CPU_ACCESS_FLAG)0;
|
||||||
{
|
|
||||||
entry.texture = D3DTexture2D::Create(width, height, D3D11_BIND_SHADER_RESOURCE, usage, d3d_fmt, TexLevels);
|
|
||||||
CHECK(entry.texture!=NULL, "Create dynamic texture of the TextureCache");
|
|
||||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetTex(), "a (dynamic) texture of the TextureCache");
|
|
||||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetSRV(), "shader resource view of a (dynamic) texture of the TextureCache");
|
|
||||||
}
|
|
||||||
else // need to use default textures
|
|
||||||
{
|
|
||||||
ID3D11Texture2D* pTexture = NULL;
|
ID3D11Texture2D* pTexture = NULL;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
D3D11_SUBRESOURCE_DATA data;
|
||||||
|
data.pSysMem = temp;
|
||||||
|
data.SysMemPitch = 4*expandedWidth;
|
||||||
|
|
||||||
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(d3d_fmt, width, height, 1, TexLevels, D3D11_BIND_SHADER_RESOURCE, usage);
|
D3D11_TEXTURE2D_DESC texdesc = CD3D11_TEXTURE2D_DESC(DXGI_FORMAT_R8G8B8A8_UNORM, width, height, 1, TexLevels, D3D11_BIND_SHADER_RESOURCE, usage, cpu_access);
|
||||||
hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture);
|
hr = D3D::device->CreateTexture2D(&texdesc, (TexLevels==1)?&data:NULL, &pTexture);
|
||||||
if (FAILED(hr))
|
CHECK(hr==S_OK, "Create texture of the TextureCache");
|
||||||
{
|
|
||||||
PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__);
|
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
entry.texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE);
|
entry.texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE);
|
||||||
CHECK(entry.texture!=NULL, "Create dynamic texture of the TextureCache");
|
CHECK(entry.texture!=NULL, "Create texture of the TextureCache");
|
||||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetTex(), "a (static) texture of the TextureCache");
|
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetTex(), "a texture of the TextureCache");
|
||||||
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetSRV(), "shader resource view of a (static) texture of the TextureCache");
|
D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetSRV(), "shader resource view of a texture of the TextureCache");
|
||||||
pTexture->Release();
|
pTexture->Release();
|
||||||
}
|
|
||||||
if (entry.texture == NULL) PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__);
|
if (TexLevels != 1) D3D::ReplaceRGBATexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, 0, usage);
|
||||||
D3D::ReplaceTexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, d3d_fmt, pcfmt, 0, usage);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
D3D::ReplaceTexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, d3d_fmt, pcfmt, 0, usage);
|
D3D::ReplaceRGBATexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, 0, usage);
|
||||||
}
|
}
|
||||||
if (TexLevels == 0 && usage == D3D11_USAGE_DEFAULT) D3DX11FilterTexture(D3D::context, entry.texture->GetTex(), 0, D3DX11_DEFAULT);
|
entry.addr = address;
|
||||||
|
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format);
|
||||||
|
entry.isRenderTarget = false;
|
||||||
|
entry.isNonPow2 = false;
|
||||||
|
entry.MipLevels = maxlevel;
|
||||||
|
|
||||||
|
if (TexLevels == 0) D3DX11FilterTexture(D3D::context, entry.texture->GetTex(), 0, D3DX11_DEFAULT);
|
||||||
else if (TexLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
|
else if (TexLevels > 1 && pcfmt != PC_TEX_FMT_NONE)
|
||||||
{
|
{
|
||||||
unsigned int level = 1;
|
unsigned int level = 1;
|
||||||
|
@ -337,8 +325,8 @@ TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, u
|
||||||
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
||||||
expandedWidth = (currentWidth + bsw) & (~bsw);
|
expandedWidth = (currentWidth + bsw) & (~bsw);
|
||||||
expandedHeight = (currentHeight + bsh) & (~bsh);
|
expandedHeight = (currentHeight + bsh) & (~bsh);
|
||||||
PC_TexFormat texfmtbuf = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
|
TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt, true);
|
||||||
D3D::ReplaceTexture2D(entry.texture->GetTex(), (BYTE*)temp, currentWidth, currentHeight, expandedWidth, d3d_fmt, texfmtbuf, level, usage);
|
D3D::ReplaceRGBATexture2D(entry.texture->GetTex(), temp, currentWidth, currentHeight, expandedWidth, level, usage);
|
||||||
u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1;
|
u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1;
|
||||||
ptr += size;
|
ptr += size;
|
||||||
mipWidth >>= 1;
|
mipWidth >>= 1;
|
||||||
|
|
Loading…
Reference in New Issue