forked from dolphin-emu/dolphin
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
This commit is contained in:
@@ -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;
|
||||
}
|
||||
}
|
||||
|
@@ -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
|
||||
|
@@ -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)
|
||||
|
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
@@ -22,9 +22,11 @@
|
||||
#include <map>
|
||||
|
||||
#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<u32,TCacheEntry> 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);
|
||||
};
|
||||
|
||||
|
@@ -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)
|
||||
{
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user