From 74194759593f6b24c9b364413083170251e14c87 Mon Sep 17 00:00:00 2001 From: "XTra.KrazzY" Date: Sat, 7 Mar 2009 18:05:29 +0000 Subject: [PATCH] One step closer to fixing D3D. Now textures are set properly. Still, memory leak exists for some unknown reason (we don't allocate more pages and we release every texture) git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2601 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugins/Plugin_VideoDX9/Src/BPStructs.cpp | 20 ------ .../Plugins/Plugin_VideoDX9/Src/D3DShader.cpp | 4 +- .../Plugin_VideoDX9/Src/PixelShaderCache.cpp | 4 +- .../Plugin_VideoDX9/Src/TextureCache.cpp | 72 ++++++++++--------- .../Plugin_VideoDX9/Src/TextureCache.h | 6 +- .../Plugin_VideoDX9/Src/VertexManager.cpp | 50 ++++++++++++- .../Plugin_VideoDX9/Src/VertexShaderCache.cpp | 2 +- 7 files changed, 97 insertions(+), 61 deletions(-) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp b/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp index 12132bfcf2..1db6e957c5 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/BPStructs.cpp @@ -726,23 +726,3 @@ void BPWritten(int addr, int changes, int newval) break; } } - -void ActivateTextures() -{ - for (int i = 0; i < 8; i++) - { - //TODO(ector): this should be a speedup - //if (textureChanged[i] || ASK TEXCACHE ABOUT SENTINEL VALUE) - { - FourTexUnits &tex = bpmem.tex[i>>2]; - TextureCache::Load(i, - (tex.texImage3[i&3].image_base) << 5, - tex.texImage0[i&3].width+1, - tex.texImage0[i&3].height+1, - tex.texImage0[i&3].format, - tex.texTlut[i&3].tmem_offset<<9, - tex.texTlut[i&3].tlut_format); - } - textureChanged[i] = false; - } -} diff --git a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp index 7d4ae6f7fb..b5171cab31 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/D3DShader.cpp @@ -43,7 +43,7 @@ LPDIRECT3DVERTEXSHADER9 CompileVertexShader(const char *code, int len, bool asse std::string hello = (char*)errorBuffer->GetBufferPointer(); hello += "\n\n"; hello += code; - MessageBox(0, hello.c_str(), "Error assembling vertex shader", MB_ICONERROR); + //MessageBox(0, hello.c_str(), "Error assembling vertex shader", MB_ICONERROR); vShader = 0; } else if (SUCCEEDED(hr)) @@ -86,7 +86,7 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(const char *code, int len, bool assemb std::string hello = (char*)errorBuffer->GetBufferPointer(); hello += "\n\n"; hello += code; - MessageBox(0, hello.c_str(), "Error assembling pixel shader", MB_ICONERROR); + //MessageBox(0, hello.c_str(), "Error assembling pixel shader", MB_ICONERROR); pShader = 0; } else diff --git a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp index 4fb7b82ef1..1b456c849c 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/PixelShaderCache.cpp @@ -99,8 +99,8 @@ void PixelShaderCache::SetShader() INCSTAT(stats.numPixelShadersCreated); SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size()); - } else - PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); + } else; + //PanicAlert("Failed to compile Pixel Shader:\n\n%s", code); } LPDIRECT3DPIXELSHADER9 PixelShaderCache::CompileCgShader(const char *pstrprogram) diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp index d12d4879f4..69ee1bc914 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.cpp @@ -19,6 +19,7 @@ #include "Common.h" #include "Statistics.h" +#include "MemoryUtil.h" #include "D3DBase.h" #include "D3DTexture.h" @@ -37,6 +38,7 @@ TextureCache::TexCache TextureCache::textures; extern int frameCount; #define TEMP_SIZE (1024*1024*4) +#define TEXTURE_KILL_THRESHOLD 200 void TextureCache::TCacheEntry::Destroy(bool shutdown) { @@ -45,35 +47,30 @@ void TextureCache::TCacheEntry::Destroy(bool shutdown) texture = 0; if (!isRenderTarget && !shutdown) { u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4); - if (*ptr == hash) + if (ptr && *ptr == hash) *ptr = oldpixel; } } void TextureCache::Init() { - temp = (u8*)VirtualAlloc(0,TEMP_SIZE,MEM_COMMIT,PAGE_READWRITE); + temp = (u8*)AllocateMemoryPages(TEMP_SIZE); TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); } void TextureCache::Invalidate(bool shutdown) { - TexCache::iterator iter = textures.begin(); - for (; iter != textures.end(); iter++) + for (TexCache::iterator iter = textures.begin(); iter != textures.end(); iter++) iter->second.Destroy(shutdown); textures.clear(); - TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter); } void TextureCache::Shutdown() { Invalidate(true); - if (temp != NULL) - { - VirtualFree(temp, 0, MEM_RELEASE); - temp = NULL; - } + FreeMemoryPages(temp, TEMP_SIZE); + temp = NULL; } void TextureCache::Cleanup() @@ -82,7 +79,7 @@ void TextureCache::Cleanup() while(iter != textures.end()) { - if (frameCount>20+iter->second.frameCount) + if (frameCount> TEXTURE_KILL_THRESHOLD + iter->second.frameCount) { if (!iter->second.isRenderTarget) { @@ -91,7 +88,9 @@ void TextureCache::Cleanup() } else { - iter++; + // Used to be just iter++ + iter->second.Destroy(false); + iter = textures.erase(iter); } } else @@ -101,10 +100,10 @@ void TextureCache::Cleanup() } } -void TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt) +TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt) { if (address == 0) - return; + return NULL; TexCache::iterator iter = textures.find(address); u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address); @@ -129,27 +128,30 @@ void TextureCache::Load(int stage, u32 address, int width, int height, int forma static LPDIRECT3DTEXTURE9 lastTexture[8] = {0,0,0,0,0,0,0,0}; + int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16; + int expandedWidth = (width+bs) & (~bs); + u32 hash_value = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, height, format, 0); + if (iter != textures.end()) { TCacheEntry &entry = iter->second; - if (entry.isRenderTarget || (((u32 *)ptr)[entry.hashoffset] == entry.hash && palhash == entry.paletteHash)) //stupid, improve + if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash))) { - iter->second.frameCount = frameCount; - if (lastTexture[stage] == iter->second.texture) + entry.frameCount = frameCount; + if (lastTexture[stage] == entry.texture) { - return; + return &entry; } - lastTexture[stage] = iter->second.texture; + lastTexture[stage] = entry.texture; // D3D::dev->SetTexture(stage,iter->second.texture); - Renderer::SetTexture( stage, iter->second.texture ); + Renderer::SetTexture( stage, entry.texture ); - return; + return &entry; } else { - TCacheEntry &entry = iter->second; /* if (width == iter->second.w && height==entry.h && format==entry.fmt) { LPDIRECT3DTEXTURE9 tex = entry.texture; @@ -162,14 +164,12 @@ void TextureCache::Load(int stage, u32 address, int width, int height, int forma } else {*/ - iter->second.Destroy(false); + entry.Destroy(false); textures.erase(iter); //} } } - int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16; - int expandedWidth = (width+bs) & (~bs); PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt); D3DFORMAT d3d_fmt; switch (pcfmt) { @@ -196,22 +196,24 @@ void TextureCache::Load(int stage, u32 address, int width, int height, int forma } //Make an entry in the table - TCacheEntry entry; + TCacheEntry& entry = textures[address]; + entry.hashoffset = 0; - entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); + entry.hash = hash_value; + //entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF); entry.paletteHash = palhash; entry.oldpixel = ((u32 *)ptr)[entry.hashoffset]; - ((u32 *)ptr)[entry.hashoffset] = entry.hash; + //((u32 *)ptr)[entry.hashoffset] = entry.hash; entry.addr = address; - entry.isRenderTarget=false; - entry.isNonPow2 = ((width&(width-1)) || (height&(height-1))); + entry.isRenderTarget = false; + entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1))); entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt); entry.frameCount = frameCount; - entry.w=width; - entry.h=height; - entry.fmt=format; - textures[address] = entry; + entry.w = width; + entry.h = height; + entry.fmt = format; + entry.mode = bpmem.tex[stage > 3].texMode0[stage & 3]; if (g_Config.bDumpTextures) { // dump texture to file @@ -230,6 +232,8 @@ void TextureCache::Load(int stage, u32 address, int width, int height, int forma Renderer::SetTexture( stage, entry.texture ); lastTexture[stage] = entry.texture; + + return &entry; } diff --git a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h index 199d8603b8..a2c98e2bbf 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h +++ b/Source/Plugins/Plugin_VideoDX9/Src/TextureCache.h @@ -22,9 +22,11 @@ #include #include "D3DBase.h" +#include "BPMemory.h" class TextureCache { +public: struct TCacheEntry { LPDIRECT3DTEXTURE9 texture; @@ -37,6 +39,7 @@ class TextureCache bool isNonPow2; int frameCount; int w,h,fmt; + TexMode0 mode; // current filter and clamp modes that texture is set to TCacheEntry() { texture=0; @@ -46,6 +49,7 @@ class TextureCache void Destroy(bool shutdown); }; +private: typedef std::map TexCache; @@ -57,7 +61,7 @@ public: static void Cleanup(); static void Shutdown(); static void Invalidate(bool shutdown); - static void Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt); + static TCacheEntry *Load(int stage, u32 address, int width, int height, int format, int tlutaddr, int tlutfmt); static void CopyEFBToRenderTarget(u32 address, RECT *source); }; diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp index e7be031039..6fb7691ebf 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexManager.cpp @@ -31,6 +31,7 @@ #include "Utils.h" #include "NativeVertexFormat.h" #include "NativeVertexWriter.h" +#include "TextureCache.h" #include "BPStructs.h" #include "XFStructs.h" @@ -181,7 +182,54 @@ void Flush() DVSTARTPROFILE(); if (collection != C_NOTHING) { - ActivateTextures(); + u32 usedtextures = 0; + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { + if (bpmem.tevorders[i/2].getEnable(i & 1)) + usedtextures |= 1 << bpmem.tevorders[i/2].getTexMap(i & 1); + } + + if (bpmem.genMode.numindstages > 0) { + for (u32 i = 0; i < (u32)bpmem.genMode.numtevstages + 1; ++i) { + if (bpmem.tevind[i].IsActive() && bpmem.tevind[i].bt < bpmem.genMode.numindstages) { + usedtextures |= 1 << bpmem.tevindref.getTexMap(bpmem.tevind[i].bt); + } + } + } + + u32 nonpow2tex = 0; + for (int i = 0; i < 8; i++) + { + // if (usedtextures & (1 << i)) { + { + FourTexUnits &tex = bpmem.tex[i >> 2]; + TextureCache::TCacheEntry* tentry = TextureCache::Load(i, + (tex.texImage3[i&3].image_base/* & 0x1FFFFF*/) << 5, + tex.texImage0[i&3].width+1, tex.texImage0[i&3].height+1, + tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, + tex.texTlut[i&3].tlut_format); + + if (tentry) { + // texture loaded fine, set dims for pixel shader + if (tentry->isNonPow2) { + PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, tentry->mode.wrap_s, tentry->mode.wrap_t); + nonpow2tex |= 1 << i; + if (tentry->mode.wrap_s > 0) nonpow2tex |= 1 << (8 + i); + if (tentry->mode.wrap_t > 0) nonpow2tex |= 1 << (16 + i); + } + // if texture is power of two, set to ones (since don't need scaling) + // (the above seems to have changed - we set the width and height here too. + else + { + PixelShaderManager::SetTexDims(i, tentry->w, tentry->h, 0, 0); + } + } + else + ERROR_LOG(VIDEO, "error loading texture"); + } + } + PixelShaderManager::SetTexturesUsed(nonpow2tex); + + int numVertices = indexGen.GetNumVerts(); if (numVertices) { diff --git a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp index e9aa4aff73..d9352d3eb6 100644 --- a/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp +++ b/Source/Plugins/Plugin_VideoDX9/Src/VertexShaderCache.cpp @@ -101,7 +101,7 @@ void VertexShaderCache::SetShader(u32 components) INCSTAT(stats.numVertexShadersCreated); SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size()); } else { - PanicAlert("Failed to compile Vertex Shader:\n\n%s", code); + //PanicAlert("Failed to compile Vertex Shader:\n\n%s", code); } D3D::dev->SetFVF(NULL);