From 208c33f09c6e2ea3810cf89e84aac86bf2496b37 Mon Sep 17 00:00:00 2001 From: NeoBrainX Date: Sat, 19 Jun 2010 18:14:05 +0000 Subject: [PATCH] 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 --- .../Plugin_VideoDX11/Src/D3DTexture.cpp | 132 ++---------------- .../Plugins/Plugin_VideoDX11/Src/D3DTexture.h | 2 +- .../Plugins/Plugin_VideoDX11/Src/GfxState.cpp | 6 +- .../Plugin_VideoDX11/Src/TextureCache.cpp | 70 ++++------ 4 files changed, 45 insertions(+), 165 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp index 89f07da40f..1ad71a802c 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.cpp @@ -22,135 +22,27 @@ namespace D3D { -// buffers for storing the data for DEFAULT textures -u8* texbuf = NULL; -unsigned int texbufsize = 0; - -// TODO: Remove this class and properly clean up texbuf! -struct TexbufDeleter +void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage) { - ~TexbufDeleter() + if (usage == D3D11_USAGE_DYNAMIC) { - 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) + D3D::context->Map(pTexture, level, D3D11_MAP_WRITE_DISCARD, 0, &map); + if (4 * pitch == map.RowPitch) { - SAFE_DELETE_ARRAY(texbuf); - texbuf = new u8[4*width*height]; - texbufsize = 4*width*height; + memcpy(map.pData, buffer, map.RowPitch * 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 + { + 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 - { - 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) - { - // TODO: UpdateSubresource might be faster than mapping - D3D::context->Unmap(pTexture, 0); - } - else if (usage == D3D11_USAGE_DEFAULT) { 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); } } diff --git a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h index 51468ab532..977d399d11 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h +++ b/Source/Plugins/Plugin_VideoDX11/Src/D3DTexture.h @@ -22,7 +22,7 @@ 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 diff --git a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp index fb020b5f7f..275f123fa7 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/GfxState.cpp @@ -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::PushDepthState(const ID3D11DepthStencilState* state) { depthstates.push(AutoDepthStencilState(state));} void StateManager::PushRasterizerState(const ID3D11RasterizerState* state) { raststates.push(AutoRasterizerState(state));} -void StateManager::PopBlendState() { blendstates.pop(); } -void StateManager::PopDepthState() { depthstates.pop(); } -void StateManager::PopRasterizerState() { raststates.pop(); } +void StateManager::PopBlendState() { if(!blendstates.empty()) blendstates.pop(); } +void StateManager::PopDepthState() { if(!depthstates.empty()) depthstates.pop(); } +void StateManager::PopRasterizerState() { if(!raststates.empty()) raststates.pop(); } void StateManager::Apply() { diff --git a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp index e8c030063b..b8464a93e9 100644 --- a/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX11/Src/TextureCache.cpp @@ -268,63 +268,51 @@ TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, u TCacheEntry& entry = textures[texID]; PC_TexFormat pcfmt = PC_TEX_FMT_NONE; - if (pcfmt == PC_TEX_FMT_NONE) - 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; + pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt, true); entry.oldpixel = ((u32*)ptr)[0]; if (g_ActiveConfig.bSafeTextureCache) entry.hash = hash_value; 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))); - entry.isNonPow2 = false; unsigned int TexLevels = (isPow2 && UseNativeMips && maxlevel) ? GetPow2(max(width, height)) : ((isPow2)? 0 : 1); if (TexLevels > (maxlevel + 1) && maxlevel) TexLevels = maxlevel + 1; - entry.MipLevels = maxlevel; + D3D11_USAGE usage = (TexLevels == 1) ? D3D11_USAGE_DYNAMIC : D3D11_USAGE_DEFAULT; + if (!skip_texture_create) { // TODO: A little more verbosity in the debug names would be quite helpful.. - if (usage == D3D11_USAGE_DYNAMIC) - { - 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; - HRESULT hr; + D3D11_CPU_ACCESS_FLAG cpu_access = (TexLevels == 1) ? D3D11_CPU_ACCESS_WRITE : (D3D11_CPU_ACCESS_FLAG)0; + ID3D11Texture2D* pTexture = NULL; + 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); - hr = D3D::device->CreateTexture2D(&texdesc, NULL, &pTexture); - if (FAILED(hr)) - { - PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__); - return NULL; - } - entry.texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE); - CHECK(entry.texture!=NULL, "Create dynamic texture of the TextureCache"); - D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetTex(), "a (static) texture of the TextureCache"); - D3D::SetDebugObjectName((ID3D11DeviceChild*)entry.texture->GetSRV(), "shader resource view of a (static) texture of the TextureCache"); - pTexture->Release(); - } - if (entry.texture == NULL) PanicAlert("Failed to create texture at %s %d\n", __FILE__, __LINE__); - D3D::ReplaceTexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, d3d_fmt, pcfmt, 0, 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, (TexLevels==1)?&data:NULL, &pTexture); + CHECK(hr==S_OK, "Create texture of the TextureCache"); + entry.texture = new D3DTexture2D(pTexture, D3D11_BIND_SHADER_RESOURCE); + CHECK(entry.texture!=NULL, "Create 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 texture of the TextureCache"); + pTexture->Release(); + + if (TexLevels != 1) D3D::ReplaceRGBATexture2D(entry.texture->GetTex(), temp, width, height, expandedWidth, 0, usage); } 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) { 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; expandedWidth = (currentWidth + bsw) & (~bsw); expandedHeight = (currentHeight + bsh) & (~bsh); - PC_TexFormat texfmtbuf = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt); - D3D::ReplaceTexture2D(entry.texture->GetTex(), (BYTE*)temp, currentWidth, currentHeight, expandedWidth, d3d_fmt, texfmtbuf, level, usage); + TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt, true); + D3D::ReplaceRGBATexture2D(entry.texture->GetTex(), temp, currentWidth, currentHeight, expandedWidth, level, usage); u32 size = (max(mipWidth, bsw) * max(mipHeight, bsh) * bsdepth) >> 1; ptr += size; mipWidth >>= 1;