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:
parent
7455361ed2
commit
7419475959
|
@ -726,23 +726,3 @@ void BPWritten(int addr, int changes, int newval)
|
||||||
break;
|
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();
|
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||||
hello += "\n\n";
|
hello += "\n\n";
|
||||||
hello += code;
|
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;
|
vShader = 0;
|
||||||
}
|
}
|
||||||
else if (SUCCEEDED(hr))
|
else if (SUCCEEDED(hr))
|
||||||
|
@ -86,7 +86,7 @@ LPDIRECT3DPIXELSHADER9 CompilePixelShader(const char *code, int len, bool assemb
|
||||||
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
std::string hello = (char*)errorBuffer->GetBufferPointer();
|
||||||
hello += "\n\n";
|
hello += "\n\n";
|
||||||
hello += code;
|
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;
|
pShader = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|
|
@ -99,8 +99,8 @@ void PixelShaderCache::SetShader()
|
||||||
|
|
||||||
INCSTAT(stats.numPixelShadersCreated);
|
INCSTAT(stats.numPixelShadersCreated);
|
||||||
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
||||||
} else
|
} else;
|
||||||
PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
//PanicAlert("Failed to compile Pixel Shader:\n\n%s", code);
|
||||||
}
|
}
|
||||||
|
|
||||||
LPDIRECT3DPIXELSHADER9 PixelShaderCache::CompileCgShader(const char *pstrprogram)
|
LPDIRECT3DPIXELSHADER9 PixelShaderCache::CompileCgShader(const char *pstrprogram)
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
#include "Statistics.h"
|
#include "Statistics.h"
|
||||||
|
#include "MemoryUtil.h"
|
||||||
|
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
#include "D3DTexture.h"
|
#include "D3DTexture.h"
|
||||||
|
@ -37,6 +38,7 @@ TextureCache::TexCache TextureCache::textures;
|
||||||
extern int frameCount;
|
extern int frameCount;
|
||||||
|
|
||||||
#define TEMP_SIZE (1024*1024*4)
|
#define TEMP_SIZE (1024*1024*4)
|
||||||
|
#define TEXTURE_KILL_THRESHOLD 200
|
||||||
|
|
||||||
void TextureCache::TCacheEntry::Destroy(bool shutdown)
|
void TextureCache::TCacheEntry::Destroy(bool shutdown)
|
||||||
{
|
{
|
||||||
|
@ -45,35 +47,30 @@ void TextureCache::TCacheEntry::Destroy(bool shutdown)
|
||||||
texture = 0;
|
texture = 0;
|
||||||
if (!isRenderTarget && !shutdown) {
|
if (!isRenderTarget && !shutdown) {
|
||||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4);
|
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset*4);
|
||||||
if (*ptr == hash)
|
if (ptr && *ptr == hash)
|
||||||
*ptr = oldpixel;
|
*ptr = oldpixel;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::Init()
|
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);
|
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::Invalidate(bool shutdown)
|
void TextureCache::Invalidate(bool shutdown)
|
||||||
{
|
{
|
||||||
TexCache::iterator iter = textures.begin();
|
for (TexCache::iterator iter = textures.begin(); iter != textures.end(); iter++)
|
||||||
for (; iter != textures.end(); iter++)
|
|
||||||
iter->second.Destroy(shutdown);
|
iter->second.Destroy(shutdown);
|
||||||
textures.clear();
|
textures.clear();
|
||||||
TexDecoder_SetTexFmtOverlayOptions(g_Config.bTexFmtOverlayEnable, g_Config.bTexFmtOverlayCenter);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::Shutdown()
|
void TextureCache::Shutdown()
|
||||||
{
|
{
|
||||||
Invalidate(true);
|
Invalidate(true);
|
||||||
|
|
||||||
if (temp != NULL)
|
FreeMemoryPages(temp, TEMP_SIZE);
|
||||||
{
|
temp = NULL;
|
||||||
VirtualFree(temp, 0, MEM_RELEASE);
|
|
||||||
temp = NULL;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void TextureCache::Cleanup()
|
void TextureCache::Cleanup()
|
||||||
|
@ -82,7 +79,7 @@ void TextureCache::Cleanup()
|
||||||
|
|
||||||
while(iter != textures.end())
|
while(iter != textures.end())
|
||||||
{
|
{
|
||||||
if (frameCount>20+iter->second.frameCount)
|
if (frameCount> TEXTURE_KILL_THRESHOLD + iter->second.frameCount)
|
||||||
{
|
{
|
||||||
if (!iter->second.isRenderTarget)
|
if (!iter->second.isRenderTarget)
|
||||||
{
|
{
|
||||||
|
@ -91,7 +88,9 @@ void TextureCache::Cleanup()
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
iter++;
|
// Used to be just iter++
|
||||||
|
iter->second.Destroy(false);
|
||||||
|
iter = textures.erase(iter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
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)
|
if (address == 0)
|
||||||
return;
|
return NULL;
|
||||||
TexCache::iterator iter = textures.find(address);
|
TexCache::iterator iter = textures.find(address);
|
||||||
|
|
||||||
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(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};
|
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())
|
if (iter != textures.end())
|
||||||
{
|
{
|
||||||
TCacheEntry &entry = iter->second;
|
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;
|
entry.frameCount = frameCount;
|
||||||
if (lastTexture[stage] == iter->second.texture)
|
if (lastTexture[stage] == entry.texture)
|
||||||
{
|
{
|
||||||
return;
|
return &entry;
|
||||||
}
|
}
|
||||||
lastTexture[stage] = iter->second.texture;
|
lastTexture[stage] = entry.texture;
|
||||||
|
|
||||||
// D3D::dev->SetTexture(stage,iter->second.texture);
|
// D3D::dev->SetTexture(stage,iter->second.texture);
|
||||||
Renderer::SetTexture( stage, iter->second.texture );
|
Renderer::SetTexture( stage, entry.texture );
|
||||||
|
|
||||||
return;
|
return &entry;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TCacheEntry &entry = iter->second;
|
|
||||||
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
|
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
|
||||||
{
|
{
|
||||||
LPDIRECT3DTEXTURE9 tex = entry.texture;
|
LPDIRECT3DTEXTURE9 tex = entry.texture;
|
||||||
|
@ -162,14 +164,12 @@ void TextureCache::Load(int stage, u32 address, int width, int height, int forma
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{*/
|
{*/
|
||||||
iter->second.Destroy(false);
|
entry.Destroy(false);
|
||||||
textures.erase(iter);
|
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);
|
PC_TexFormat pcfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||||
D3DFORMAT d3d_fmt;
|
D3DFORMAT d3d_fmt;
|
||||||
switch (pcfmt) {
|
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
|
//Make an entry in the table
|
||||||
TCacheEntry entry;
|
TCacheEntry& entry = textures[address];
|
||||||
|
|
||||||
entry.hashoffset = 0;
|
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.paletteHash = palhash;
|
||||||
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
|
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
|
||||||
((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
//((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
||||||
|
|
||||||
entry.addr = address;
|
entry.addr = address;
|
||||||
entry.isRenderTarget=false;
|
entry.isRenderTarget = false;
|
||||||
entry.isNonPow2 = ((width&(width-1)) || (height&(height-1)));
|
entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1)));
|
||||||
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
||||||
entry.frameCount = frameCount;
|
entry.frameCount = frameCount;
|
||||||
entry.w=width;
|
entry.w = width;
|
||||||
entry.h=height;
|
entry.h = height;
|
||||||
entry.fmt=format;
|
entry.fmt = format;
|
||||||
textures[address] = entry;
|
entry.mode = bpmem.tex[stage > 3].texMode0[stage & 3];
|
||||||
|
|
||||||
if (g_Config.bDumpTextures)
|
if (g_Config.bDumpTextures)
|
||||||
{ // dump texture to file
|
{ // 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 );
|
Renderer::SetTexture( stage, entry.texture );
|
||||||
|
|
||||||
lastTexture[stage] = entry.texture;
|
lastTexture[stage] = entry.texture;
|
||||||
|
|
||||||
|
return &entry;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -22,9 +22,11 @@
|
||||||
#include <map>
|
#include <map>
|
||||||
|
|
||||||
#include "D3DBase.h"
|
#include "D3DBase.h"
|
||||||
|
#include "BPMemory.h"
|
||||||
|
|
||||||
class TextureCache
|
class TextureCache
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
struct TCacheEntry
|
struct TCacheEntry
|
||||||
{
|
{
|
||||||
LPDIRECT3DTEXTURE9 texture;
|
LPDIRECT3DTEXTURE9 texture;
|
||||||
|
@ -37,6 +39,7 @@ class TextureCache
|
||||||
bool isNonPow2;
|
bool isNonPow2;
|
||||||
int frameCount;
|
int frameCount;
|
||||||
int w,h,fmt;
|
int w,h,fmt;
|
||||||
|
TexMode0 mode; // current filter and clamp modes that texture is set to
|
||||||
TCacheEntry()
|
TCacheEntry()
|
||||||
{
|
{
|
||||||
texture=0;
|
texture=0;
|
||||||
|
@ -46,6 +49,7 @@ class TextureCache
|
||||||
void Destroy(bool shutdown);
|
void Destroy(bool shutdown);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
typedef std::map<u32,TCacheEntry> TexCache;
|
typedef std::map<u32,TCacheEntry> TexCache;
|
||||||
|
|
||||||
|
@ -57,7 +61,7 @@ public:
|
||||||
static void Cleanup();
|
static void Cleanup();
|
||||||
static void Shutdown();
|
static void Shutdown();
|
||||||
static void Invalidate(bool 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);
|
static void CopyEFBToRenderTarget(u32 address, RECT *source);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@
|
||||||
#include "Utils.h"
|
#include "Utils.h"
|
||||||
#include "NativeVertexFormat.h"
|
#include "NativeVertexFormat.h"
|
||||||
#include "NativeVertexWriter.h"
|
#include "NativeVertexWriter.h"
|
||||||
|
#include "TextureCache.h"
|
||||||
|
|
||||||
#include "BPStructs.h"
|
#include "BPStructs.h"
|
||||||
#include "XFStructs.h"
|
#include "XFStructs.h"
|
||||||
|
@ -181,7 +182,54 @@ void Flush()
|
||||||
DVSTARTPROFILE();
|
DVSTARTPROFILE();
|
||||||
if (collection != C_NOTHING)
|
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();
|
int numVertices = indexGen.GetNumVerts();
|
||||||
if (numVertices)
|
if (numVertices)
|
||||||
{
|
{
|
||||||
|
|
|
@ -101,7 +101,7 @@ void VertexShaderCache::SetShader(u32 components)
|
||||||
INCSTAT(stats.numVertexShadersCreated);
|
INCSTAT(stats.numVertexShadersCreated);
|
||||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||||
} else {
|
} 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);
|
D3D::dev->SetFVF(NULL);
|
||||||
|
|
Loading…
Reference in New Issue