D3D various: "Safe texture cache" option, texture replace instead of destroy/create when possible, a commented out "optimization" that didn't speed things up (use DrawPrimitive instead of DrawIndexedPrimitive when possible), reduce code duplication in Flush(), don't periodically clean out the shader caches since it's not really beneficial - shaders are cheap to keep. some code cleanup.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4302 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
parent
dae1a68bfc
commit
7a8f6bdd6d
|
@ -31,6 +31,8 @@ void IndexGenerator::Start(unsigned short *startptr)
|
|||
ptr = startptr;
|
||||
index = 0;
|
||||
numPrims = 0;
|
||||
adds = 0;
|
||||
onlyLists = true;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddList(int numVerts)
|
||||
|
@ -45,6 +47,7 @@ void IndexGenerator::AddList(int numVerts)
|
|||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
adds++;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddStrip(int numVerts)
|
||||
|
@ -61,6 +64,8 @@ void IndexGenerator::AddStrip(int numVerts)
|
|||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
adds++;
|
||||
onlyLists = false;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineList(int numVerts)
|
||||
|
@ -74,6 +79,7 @@ void IndexGenerator::AddLineList(int numVerts)
|
|||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
adds++;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineStrip(int numVerts)
|
||||
|
@ -87,9 +93,10 @@ void IndexGenerator::AddLineStrip(int numVerts)
|
|||
}
|
||||
index += numVerts;
|
||||
numPrims += numLines;
|
||||
adds++;
|
||||
onlyLists = false;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddFan(int numVerts)
|
||||
{
|
||||
int numTris = numVerts - 2;
|
||||
|
@ -102,6 +109,8 @@ void IndexGenerator::AddFan(int numVerts)
|
|||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
adds++;
|
||||
onlyLists = false;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddQuads(int numVerts)
|
||||
|
@ -119,10 +128,13 @@ void IndexGenerator::AddQuads(int numVerts)
|
|||
}
|
||||
index += numVerts;
|
||||
numPrims += numTris;
|
||||
adds++;
|
||||
onlyLists = false;
|
||||
}
|
||||
|
||||
|
||||
void IndexGenerator::AddPointList(int numVerts)
|
||||
void IndexGenerator::AddPoints(int numVerts)
|
||||
{
|
||||
index += numVerts;
|
||||
}
|
||||
numPrims += numVerts;
|
||||
adds++;
|
||||
}
|
||||
|
|
|
@ -28,16 +28,20 @@ public:
|
|||
void AddList(int numVerts);
|
||||
void AddStrip(int numVerts);
|
||||
void AddLineList(int numVerts);
|
||||
void AddPointList(int numVerts); //dummy for counting vertices
|
||||
void AddLineStrip(int numVerts);
|
||||
void AddFan(int numVerts);
|
||||
void AddQuads(int numVerts);
|
||||
void AddPoints(int numVerts);
|
||||
int GetNumPrims() {return numPrims;} //returns numprimitives
|
||||
int GetNumVerts() {return index;} //returns numprimitives
|
||||
int GetNumAdds() {return adds;}
|
||||
bool GetOnlyLists() {return onlyLists;}
|
||||
private:
|
||||
unsigned short *ptr;
|
||||
int numPrims;
|
||||
int index;
|
||||
int adds;
|
||||
bool onlyLists;
|
||||
};
|
||||
|
||||
#endif // _INDEXGENERATOR_H
|
|
@ -57,6 +57,7 @@ char *Statistics::ToString(char *ptr)
|
|||
p+=sprintf(p,"dlists alive: %i\n",stats.numDListsAlive);
|
||||
p+=sprintf(p,"primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
|
||||
p+=sprintf(p,"draw calls: %i\n",stats.thisFrame.numDrawCalls);
|
||||
p+=sprintf(p,"indexed draw calls: %i\n",stats.thisFrame.numIndexedDrawCalls);
|
||||
p+=sprintf(p,"buffer splits: %i\n",stats.thisFrame.numBufferSplits);
|
||||
p+=sprintf(p,"primitives: %i\n",stats.thisFrame.numPrims);
|
||||
p+=sprintf(p,"primitives (DL): %i\n",stats.thisFrame.numDLPrims);
|
||||
|
|
|
@ -67,6 +67,7 @@ struct Statistics
|
|||
|
||||
int numPrimitiveJoins;
|
||||
int numDrawCalls;
|
||||
int numIndexedDrawCalls;
|
||||
int numBufferSplits;
|
||||
|
||||
int numDListsCalled;
|
||||
|
|
|
@ -142,6 +142,12 @@ struct TargetRectangle : public MathUtil::Rectangle<int>
|
|||
|
||||
#define LOG_VTX()
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ERASE_THROUGH_ITERATOR(container, iterator) iterator = container.erase(iterator)
|
||||
#else
|
||||
#define ERASE_THROUGH_ITERATOR(container, iterator) container.erase(iterator++)
|
||||
#endif
|
||||
|
||||
bool IsD3D();
|
||||
|
||||
#endif // _VIDEOCOMMON_H
|
||||
|
|
|
@ -129,6 +129,13 @@ void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int w
|
|||
D3DLOCKED_RECT Lock;
|
||||
pTexture->LockRect(level, &Lock, NULL, 0);
|
||||
u32* pIn = pBuffer;
|
||||
|
||||
bool bExpand = false;
|
||||
|
||||
if (fmt == D3DFMT_A8P8) {
|
||||
fmt = D3DFMT_A8L8;
|
||||
bExpand = true;
|
||||
}
|
||||
switch(fmt)
|
||||
{
|
||||
case D3DFMT_A8R8G8B8:
|
||||
|
@ -141,8 +148,59 @@ void ReplaceTexture2D(LPDIRECT3DTEXTURE9 pTexture, const u8* buffer, const int w
|
|||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_L8:
|
||||
case D3DFMT_A8:
|
||||
case D3DFMT_A4L4:
|
||||
{
|
||||
const u8 *pIn = buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_R5G6B5:
|
||||
{
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_A8L8:
|
||||
{
|
||||
if (bExpand) { // I8
|
||||
const u8 *pIn = buffer;
|
||||
// TODO(XK): Find a better way that does not involve either unpacking
|
||||
// or downsampling (i.e. A4L4)
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u8* pBits = ((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
for(int i = 0; i < width * 2; i += 2) {
|
||||
pBits[i] = pIn[i / 2];
|
||||
pBits[i + 1] = pIn[i / 2];
|
||||
}
|
||||
pIn += pitch;
|
||||
}
|
||||
} else { // IA8
|
||||
const u16 *pIn = (u16*)buffer;
|
||||
|
||||
for (int y = 0; y < height; y++)
|
||||
{
|
||||
u16* pBits = (u16*)((u8*)Lock.pBits + (y * Lock.Pitch));
|
||||
memcpy(pBits, pIn, width * 2);
|
||||
pIn += pitch;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case D3DFMT_DXT1:
|
||||
memcpy(Lock.pBits,buffer,(width/4)*(height/4)*8);
|
||||
memcpy(Lock.pBits, buffer, (width/4) * (height/4) * 8);
|
||||
break;
|
||||
}
|
||||
pTexture->UnlockRect(level);
|
||||
|
|
|
@ -92,6 +92,7 @@ struct TabDirect3D : public W32Util::Tab
|
|||
CheckDlgButton(hDlg, IDC_ASPECT_16_9, g_Config.bKeepAR169 ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_ASPECT_4_3, g_Config.bKeepAR43 ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_WIDESCREEN_HACK, g_Config.bWidescreenHack ? TRUE : FALSE);
|
||||
CheckDlgButton(hDlg, IDC_SAFE_TEXTURE_CACHE, g_Config.bSafeTextureCache ? TRUE : FALSE);
|
||||
}
|
||||
|
||||
void Command(HWND hDlg,WPARAM wParam)
|
||||
|
@ -114,6 +115,9 @@ struct TabDirect3D : public W32Util::Tab
|
|||
case IDC_WIREFRAME:
|
||||
g_Config.bWireFrame = Button_GetCheck(GetDlgItem(hDlg,IDC_WIREFRAME)) ? true : false;
|
||||
break;
|
||||
case IDC_SAFE_TEXTURE_CACHE:
|
||||
g_Config.bSafeTextureCache = Button_GetCheck(GetDlgItem(hDlg, IDC_SAFE_TEXTURE_CACHE));
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
@ -151,6 +151,7 @@ bool PixelShaderCache::SetShader(bool dstAlpha)
|
|||
|
||||
void PixelShaderCache::Cleanup()
|
||||
{
|
||||
/*
|
||||
PSCache::iterator iter;
|
||||
iter = PixelShaders.begin();
|
||||
while (iter != PixelShaders.end())
|
||||
|
@ -167,6 +168,7 @@ void PixelShaderCache::Cleanup()
|
|||
}
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)PixelShaders.size());
|
||||
*/
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
|
|
|
@ -49,7 +49,7 @@ void TextureCache::TCacheEntry::Destroy(bool shutdown)
|
|||
if (texture)
|
||||
texture->Release();
|
||||
texture = 0;
|
||||
if (!isRenderTarget && !shutdown)
|
||||
if (!isRenderTarget && !shutdown && !g_ActiveConfig.bSafeTextureCache)
|
||||
{
|
||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr);
|
||||
if (ptr && *ptr == hash)
|
||||
|
@ -103,88 +103,78 @@ void TextureCache::Cleanup()
|
|||
}
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntry *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 tex_format, int tlutaddr, int tlutfmt)
|
||||
{
|
||||
if (address == 0)
|
||||
return NULL;
|
||||
|
||||
u8 *ptr = g_VideoInitialize.pGetMemoryPointer(address);
|
||||
int bsw = TexDecoder_GetBlockWidthInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int bsh = TexDecoder_GetBlockHeightInTexels(tex_format) - 1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width + bsw) & (~bsw);
|
||||
int expandedHeight = (height + bsh) & (~bsh);
|
||||
|
||||
int palSize = TexDecoder_GetPaletteSize(format);
|
||||
u32 palhash = 0xc0debabe;
|
||||
if (palSize)
|
||||
u32 hash_value;
|
||||
u32 texID = address;
|
||||
u32 texHash;
|
||||
|
||||
if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bDumpTextures)
|
||||
{
|
||||
// TODO: Share this code with the GL plugin.
|
||||
if (palSize > 32)
|
||||
palSize = 32; //let's not do excessive amount of checking
|
||||
u8 *pal = g_VideoInitialize.pGetMemoryPointer(tlutaddr);
|
||||
if (pal != 0)
|
||||
texHash = TexDecoder_GetSafeTextureHash(ptr, expandedWidth, expandedHeight, tex_format, 0);
|
||||
if (g_ActiveConfig.bSafeTextureCache)
|
||||
hash_value = texHash;
|
||||
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
|
||||
{
|
||||
for (int i = 0; i < palSize; i++)
|
||||
{
|
||||
palhash = _rotl(palhash,13);
|
||||
palhash ^= pal[i];
|
||||
palhash += 31;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
u32 tex_hash = 0;
|
||||
u32 texID = address;
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures || g_ActiveConfig.bSafeTextureCache)
|
||||
{
|
||||
tex_hash = hash_value;
|
||||
if ((format == GX_TF_C4) || (format == GX_TF_C8) || (format == GX_TF_C14X2))
|
||||
{
|
||||
u32 tlutHash = TexDecoder_GetTlutHash(&texMem[tlutaddr], (format == GX_TF_C4) ? 32 : 128);
|
||||
tex_hash ^= tlutHash;
|
||||
// WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
|
||||
// tlut size can be up to 32768B (GX_TF_C14X2) but Safer == Slower.
|
||||
// This trick (to change the texID depending on the TLUT addr) is a trick to get around
|
||||
// an issue with metroid prime's fonts, where it has multiple sets of fonts on top of
|
||||
// each other stored in a single texture, and uses the palette to make different characters
|
||||
// visible or invisible. Thus, unless we want to recreate the textures for every drawn character,
|
||||
// we must make sure that texture with different tluts get different IDs.
|
||||
u32 tlutHash = TexDecoder_GetTlutHash(&texMem[tlutaddr], (tex_format == GX_TF_C4) ? 32 : 128);
|
||||
texHash ^= tlutHash;
|
||||
if (g_ActiveConfig.bSafeTextureCache)
|
||||
texID ^= tlutHash;
|
||||
}
|
||||
}
|
||||
|
||||
bool skip_texture_create = false;
|
||||
TexCache::iterator iter = textures.find(texID);
|
||||
|
||||
if (iter != textures.end())
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if (!g_ActiveConfig.bSafeTextureCache)
|
||||
hash_value = ((u32 *)ptr)[0];
|
||||
|
||||
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash)))
|
||||
{
|
||||
entry.frameCount = frameCount;
|
||||
if (lastTexture[stage] == entry.texture)
|
||||
{
|
||||
return &entry;
|
||||
}
|
||||
lastTexture[stage] = entry.texture;
|
||||
D3D::SetTexture(stage, entry.texture);
|
||||
return &entry;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* if (width == iter->second.w && height==entry.h && format==entry.fmt)
|
||||
// Let's reload the new texture data into the same texture,
|
||||
// instead of destroying it and having to create a new one.
|
||||
// Might speed up movie playback very, very slightly.
|
||||
|
||||
if (width == entry.w && height==entry.h && tex_format == entry.fmt)
|
||||
{
|
||||
LPDIRECT3DTEXTURE9 tex = entry.texture;
|
||||
int bs = TexDecoder_GetBlockWidthInTexels(format)-1; //TexelSizeInNibbles(format)*width*height/16;
|
||||
int expandedWidth = (width+bs) & (~bs);
|
||||
D3DFORMAT dfmt = TexDecoder_Decode(temp,ptr,expandedWidth,height,format, tlutaddr, tlutfmt);
|
||||
D3D::ReplaceTexture2D(tex,temp,width,height,expandedWidth,dfmt);
|
||||
D3D::dev->SetTexture(stage,tex);
|
||||
return;
|
||||
skip_texture_create = true;
|
||||
}
|
||||
else
|
||||
{*/
|
||||
{
|
||||
entry.Destroy(false);
|
||||
textures.erase(iter);
|
||||
//}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
PC_TexFormat pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, format, tlutaddr, tlutfmt);
|
||||
PC_TexFormat pcfmt = TexDecoder_Decode(temp, ptr, expandedWidth, height, tex_format, tlutaddr, tlutfmt);
|
||||
|
||||
D3DFORMAT d3d_fmt;
|
||||
switch (pcfmt) {
|
||||
case PC_TEX_FMT_BGRA32:
|
||||
|
@ -213,23 +203,32 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
//Make an entry in the table
|
||||
TCacheEntry& entry = textures[texID];
|
||||
|
||||
entry.hash = hash_value;
|
||||
//entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||
entry.paletteHash = palhash;
|
||||
entry.oldpixel = ((u32 *)ptr)[0];
|
||||
//((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
||||
if (g_ActiveConfig.bSafeTextureCache)
|
||||
entry.hash = hash_value;
|
||||
else
|
||||
{
|
||||
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||
((u32 *)ptr)[0] = entry.hash;
|
||||
}
|
||||
|
||||
entry.addr = address;
|
||||
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format);
|
||||
entry.isRenderTarget = false;
|
||||
entry.isNonPow2 = ((width & (width - 1)) || (height & (height - 1)));
|
||||
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
||||
if (!skip_texture_create) {
|
||||
entry.texture = D3D::CreateTexture2D((BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
||||
} else {
|
||||
D3D::ReplaceTexture2D(entry.texture, (BYTE*)temp, width, height, expandedWidth, d3d_fmt);
|
||||
}
|
||||
entry.frameCount = frameCount;
|
||||
entry.w = width;
|
||||
entry.h = height;
|
||||
entry.fmt = format;
|
||||
entry.fmt = tex_format;
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures)
|
||||
{ // dump texture to file
|
||||
{
|
||||
// dump texture to file
|
||||
char szTemp[MAX_PATH];
|
||||
char szDir[MAX_PATH];
|
||||
const char* uniqueId = globals->unique_id;
|
||||
|
@ -242,7 +241,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
|
||||
bCheckedDumpDir = true;
|
||||
}
|
||||
sprintf(szTemp, "%s/%s_%08x_%i.png", szDir, uniqueId, tex_hash, format);
|
||||
sprintf(szTemp, "%s/%s_%08x_%i.png", szDir, uniqueId, texHash, tex_format);
|
||||
//sprintf(szTemp, "%s\\txt_%04i_%i.png", g_Config.texDumpPath.c_str(), counter++, format); <-- Old method
|
||||
if (!File::Exists(szTemp))
|
||||
D3DXSaveTextureToFileA(szTemp,D3DXIFF_BMP,entry.texture,0);
|
||||
|
@ -254,8 +253,6 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
|
|||
//Set the texture!
|
||||
D3D::SetTexture(stage, entry.texture);
|
||||
|
||||
lastTexture[stage] = entry.texture;
|
||||
|
||||
DEBUGGER_PAUSE_LOG_AT(NEXT_NEW_TEXTURE,true,{printf("A new texture (%d x %d) is loaded", width, height);});
|
||||
return &entry;
|
||||
}
|
||||
|
|
|
@ -56,9 +56,18 @@ enum Collection
|
|||
C_POINTS,
|
||||
};
|
||||
|
||||
const D3DPRIMITIVETYPE pts[3] =
|
||||
{
|
||||
D3DPT_POINTLIST, //DUMMY
|
||||
D3DPT_TRIANGLELIST,
|
||||
D3DPT_LINELIST,
|
||||
};
|
||||
|
||||
static IndexGenerator indexGen;
|
||||
static Collection collection;
|
||||
|
||||
int lastPrimitive;
|
||||
|
||||
static u8 *fakeVBuffer; // format undefined - NativeVertexFormat takes care of the declaration.
|
||||
static u16 *fakeIBuffer; // These are just straightforward 16-bit indices.
|
||||
|
||||
|
@ -67,16 +76,29 @@ static u16 *fakeIBuffer; // These are just straightforward 16-bit indices.
|
|||
|
||||
const Collection collectionTypeLUT[8] =
|
||||
{
|
||||
C_TRIANGLES,//quads
|
||||
C_NOTHING, //nothing
|
||||
C_TRIANGLES,//triangles
|
||||
C_TRIANGLES,//strip
|
||||
C_TRIANGLES,//fan
|
||||
C_LINES, //lines
|
||||
C_LINES, //linestrip
|
||||
C_POINTS //guess :P
|
||||
C_TRIANGLES, //quads
|
||||
C_NOTHING, //nothing
|
||||
C_TRIANGLES, //triangles
|
||||
C_TRIANGLES, //strip
|
||||
C_TRIANGLES, //fan
|
||||
C_LINES, //lines
|
||||
C_LINES, //linestrip
|
||||
C_POINTS //guess :P
|
||||
};
|
||||
|
||||
const D3DPRIMITIVETYPE gxPrimToD3DPrim[8] = {
|
||||
(D3DPRIMITIVETYPE)0, // not supported
|
||||
(D3DPRIMITIVETYPE)0, // nothing
|
||||
|
||||
D3DPT_TRIANGLELIST,
|
||||
D3DPT_TRIANGLESTRIP,
|
||||
D3DPT_TRIANGLEFAN,
|
||||
|
||||
D3DPT_LINELIST,
|
||||
D3DPT_LINESTRIP,
|
||||
};
|
||||
|
||||
|
||||
void CreateDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
|
@ -116,7 +138,7 @@ void AddIndices(int _primitive, int _numVertices)
|
|||
case GX_DRAW_TRIANGLE_FAN: indexGen.AddFan(_numVertices); return;
|
||||
case GX_DRAW_LINE_STRIP: indexGen.AddLineStrip(_numVertices); return;
|
||||
case GX_DRAW_LINES: indexGen.AddLineList(_numVertices); return;
|
||||
case GX_DRAW_POINTS: indexGen.AddPointList(_numVertices); return;
|
||||
case GX_DRAW_POINTS: indexGen.AddPoints(_numVertices); return;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -129,7 +151,8 @@ void AddVertices(int _primitive, int _numVertices)
|
|||
{
|
||||
if (_numVertices <= 0) //This check is pretty stupid...
|
||||
return;
|
||||
|
||||
lastPrimitive = _primitive;
|
||||
|
||||
Collection type = collectionTypeLUT[_primitive];
|
||||
if (type == C_NOTHING)
|
||||
return;
|
||||
|
@ -166,12 +189,55 @@ void AddVertices(int _primitive, int _numVertices)
|
|||
}
|
||||
}
|
||||
|
||||
const D3DPRIMITIVETYPE pts[3] =
|
||||
inline void Draw(int numVertices, int stride)
|
||||
{
|
||||
D3DPT_POINTLIST, //DUMMY
|
||||
D3DPT_TRIANGLELIST,
|
||||
D3DPT_LINELIST,
|
||||
};
|
||||
if (collection != C_POINTS)
|
||||
{
|
||||
int numPrimitives = indexGen.GetNumPrims();
|
||||
/* For some reason, this makes things slower!
|
||||
if ((indexGen.GetNumAdds() == 1 || indexGen.GetOnlyLists()) && lastPrimitive != GX_DRAW_QUADS && gxPrimToD3DPrim[lastPrimitive])
|
||||
{
|
||||
if (FAILED(D3D::dev->DrawPrimitiveUP(
|
||||
gxPrimToD3DPrim[lastPrimitive],
|
||||
numPrimitives,
|
||||
fakeVBuffer,
|
||||
stride))) {
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
File::WriteStringToFile(true, error_shaders, "bad_shader_combo.txt");
|
||||
PanicAlert("DrawPrimitiveUP failed. Shaders written to bad_shader_combo.txt.");
|
||||
#endif
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
} else*/ {
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
pts[(int)collection],
|
||||
0, numVertices, numPrimitives,
|
||||
fakeIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
fakeVBuffer,
|
||||
stride))) {
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
File::WriteStringToFile(true, error_shaders, "bad_shader_combo.txt");
|
||||
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to bad_shader_combo.txt.");
|
||||
#endif
|
||||
}
|
||||
INCSTAT(stats.thisFrame.numIndexedDrawCalls);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::dev->SetIndices(0);
|
||||
D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST, numVertices, fakeVBuffer, stride);
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void Flush()
|
||||
{
|
||||
|
@ -219,73 +285,26 @@ void Flush()
|
|||
VertexShaderManager::SetConstants();
|
||||
PixelShaderManager::SetConstants();
|
||||
|
||||
if (!PixelShaderCache::SetShader(false))
|
||||
goto shader_fail;
|
||||
if (!VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
|
||||
goto shader_fail;
|
||||
if (!PixelShaderCache::SetShader(false))
|
||||
goto shader_fail;
|
||||
|
||||
int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
if (collection != C_POINTS)
|
||||
{
|
||||
int numPrimitives = indexGen.GetNumPrims();
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
pts[(int)collection],
|
||||
0, numVertices, numPrimitives,
|
||||
fakeIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
fakeVBuffer,
|
||||
stride))) {
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
File::WriteStringToFile(true, error_shaders, "bad_shader_combo.txt");
|
||||
PanicAlert("DrawIndexedPrimitiveUP failed. Shaders written to bad_shader_combo.txt.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::dev->SetIndices(0);
|
||||
D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST, numVertices, fakeVBuffer, stride);
|
||||
}
|
||||
|
||||
Draw(numVertices, stride);
|
||||
|
||||
if (bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
|
||||
{
|
||||
DWORD write = 0;
|
||||
if (!PixelShaderCache::SetShader(true))
|
||||
goto shader_fail;
|
||||
|
||||
// update alpha only
|
||||
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, D3DCOLORWRITEENABLE_ALPHA);
|
||||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, false);
|
||||
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
if (collection != C_POINTS)
|
||||
{
|
||||
int numPrimitives = indexGen.GetNumPrims();
|
||||
if (FAILED(D3D::dev->DrawIndexedPrimitiveUP(
|
||||
pts[(int)collection],
|
||||
0, numVertices, numPrimitives,
|
||||
fakeIBuffer,
|
||||
D3DFMT_INDEX16,
|
||||
fakeVBuffer,
|
||||
stride))) {
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
std::string error_shaders;
|
||||
error_shaders.append(VertexShaderCache::GetCurrentShaderCode());
|
||||
error_shaders.append(PixelShaderCache::GetCurrentShaderCode());
|
||||
File::WriteStringToFile(true, error_shaders, "bad_shader_combo.txt");
|
||||
PanicAlert("DrawIndexedPrimitiveUP failed (dstalpha). Shaders written to bad_shader_combo.txt.");
|
||||
#endif
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
D3D::dev->SetIndices(0);
|
||||
D3D::dev->DrawPrimitiveUP(D3DPT_POINTLIST, numVertices, fakeVBuffer, stride);
|
||||
}
|
||||
Draw(numVertices, stride);
|
||||
|
||||
if (bpmem.blendmode.alphaupdate)
|
||||
write = D3DCOLORWRITEENABLE_ALPHA;
|
||||
|
@ -295,11 +314,7 @@ void Flush()
|
|||
D3D::SetRenderState(D3DRS_ALPHABLENDENABLE, true);
|
||||
|
||||
D3D::SetRenderState(D3DRS_COLORWRITEENABLE, write);
|
||||
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
}
|
||||
|
||||
INCSTAT(stats.thisFrame.numDrawCalls);
|
||||
}
|
||||
shader_fail:
|
||||
collection = C_NOTHING;
|
||||
|
|
|
@ -203,6 +203,7 @@ bool VertexShaderCache::SetShader(u32 components)
|
|||
|
||||
void VertexShaderCache::Cleanup()
|
||||
{
|
||||
/*
|
||||
for (VSCache::iterator iter = vshaders.begin(); iter != vshaders.end();)
|
||||
{
|
||||
VSCacheEntry &entry = iter->second;
|
||||
|
@ -216,7 +217,8 @@ void VertexShaderCache::Cleanup()
|
|||
++iter;
|
||||
}
|
||||
}
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());
|
||||
SETSTAT(stats.numVertexShadersAlive, (int)vshaders.size());*/
|
||||
|
||||
}
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
|
|
|
@ -1224,6 +1224,8 @@
|
|||
#define IDC_WIDESCREEN_HACK 1036
|
||||
#define IDC_DUMPFRAMES 1037
|
||||
#define psh14 0x040d
|
||||
#define IDC_ASPECT_16_10 1037
|
||||
#define IDC_SAFE_TEXTURE_CACHE 1037
|
||||
#define psh15 0x040e
|
||||
#define psh16 0x040f
|
||||
#define _WIN32_WINDOWS 0x0410
|
||||
|
@ -1532,8 +1534,8 @@
|
|||
#define SPVERSION_MASK 0x0000FF00
|
||||
#define HTERROR -2
|
||||
#define IDC_STATIC -1
|
||||
#define PWR_FAIL -1
|
||||
#define UNICODE_NOCHAR 0xFFFF
|
||||
#define PWR_FAIL -1
|
||||
#define HTTRANSPARENT -1
|
||||
|
||||
// Next default values for new objects
|
||||
|
|
|
@ -2,15 +2,6 @@
|
|||
//
|
||||
#include "resource.h"
|
||||
#include <windows.h>
|
||||
|
||||
#define APSTUDIO_READONLY_SYMBOLS
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
//
|
||||
// Generated from the TEXTINCLUDE 2 resource.
|
||||
//
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#undef APSTUDIO_READONLY_SYMBOLS
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
// English (U.S.) resources
|
||||
|
||||
|
@ -36,7 +27,7 @@ BEGIN
|
|||
LTEXT "Will not work correctly on older GPU:s.",IDC_STATIC,7,47,170,8
|
||||
END
|
||||
|
||||
IDD_SETTINGS DIALOGEX 0, 0, 231, 174
|
||||
IDD_SETTINGS DIALOGEX 0, 0, 231, 194
|
||||
STYLE DS_SETFONT | DS_FIXEDSYS | WS_CHILD | WS_SYSMENU
|
||||
FONT 8, "MS Shell Dlg", 0, 0, 0x0
|
||||
BEGIN
|
||||
|
@ -57,6 +48,7 @@ BEGIN
|
|||
CONTROL "4:3",IDC_ASPECT_4_3,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,66,59,11
|
||||
CONTROL "16:9",IDC_ASPECT_16_9,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,80,49,11
|
||||
CONTROL "&Widescreen Hack",IDC_WIDESCREEN_HACK,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,128,81,73,10
|
||||
CONTROL "&Safe Texture Cache",IDC_SAFE_TEXTURE_CACHE,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,68,172,85,11
|
||||
END
|
||||
|
||||
IDD_DEBUGGER DIALOGEX 0, 0, 234, 254
|
||||
|
@ -128,7 +120,7 @@ BEGIN
|
|||
VERTGUIDE, 81
|
||||
VERTGUIDE, 87
|
||||
TOPMARGIN, 7
|
||||
BOTTOMMARGIN, 167
|
||||
BOTTOMMARGIN, 187
|
||||
END
|
||||
|
||||
IDD_DEBUGGER, DIALOG
|
||||
|
@ -198,7 +190,7 @@ END
|
|||
// Generated from the TEXTINCLUDE 3 resource.
|
||||
//
|
||||
|
||||
À
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////
|
||||
#endif // not APSTUDIO_INVOKED
|
||||
|
||||
|
|
|
@ -222,6 +222,7 @@ FRAGMENTSHADER* PixelShaderCache::GetShader(bool dstAlphaEnable)
|
|||
|
||||
void PixelShaderCache::ProgressiveCleanup()
|
||||
{
|
||||
/*
|
||||
PSCache::iterator iter = pshaders.begin();
|
||||
while (iter != pshaders.end()) {
|
||||
PSCacheEntry &entry = iter->second;
|
||||
|
@ -237,6 +238,7 @@ void PixelShaderCache::ProgressiveCleanup()
|
|||
iter++;
|
||||
}
|
||||
SETSTAT(stats.numPixelShadersAlive, (int)pshaders.size());
|
||||
*/
|
||||
}
|
||||
|
||||
bool PixelShaderCache::CompilePixelShader(FRAGMENTSHADER& ps, const char* pstrprogram)
|
||||
|
|
|
@ -148,7 +148,7 @@ void TextureMngr::TCacheEntry::Destroy(bool shutdown)
|
|||
return;
|
||||
glDeleteTextures(1, &texture);
|
||||
if (!isRenderTarget && !shutdown && !g_ActiveConfig.bSafeTextureCache) {
|
||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr + hashoffset * 4);
|
||||
u32 *ptr = (u32*)g_VideoInitialize.pGetMemoryPointer(addr);
|
||||
if (ptr && *ptr == hash)
|
||||
*ptr = oldpixel;
|
||||
}
|
||||
|
@ -183,12 +183,6 @@ void TextureMngr::Shutdown()
|
|||
temp = NULL;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
#define ERASE_THROUGH_ITERATOR(container, iterator) iterator = container.erase(iterator)
|
||||
#else
|
||||
#define ERASE_THROUGH_ITERATOR(container, iterator) container.erase(iterator++)
|
||||
#endif
|
||||
|
||||
void TextureMngr::ProgressiveCleanup()
|
||||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
|
@ -210,7 +204,8 @@ void TextureMngr::ProgressiveCleanup()
|
|||
}
|
||||
}
|
||||
|
||||
void TextureMngr::InvalidateRange(u32 start_address, u32 size) {
|
||||
void TextureMngr::InvalidateRange(u32 start_address, u32 size)
|
||||
{
|
||||
TexCache::iterator iter = textures.begin();
|
||||
while (iter != textures.end())
|
||||
{
|
||||
|
@ -291,11 +286,12 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
|
|||
bool skip_texture_create = false;
|
||||
TexCache::iterator iter = textures.find(texID);
|
||||
|
||||
if (iter != textures.end()) {
|
||||
if (iter != textures.end())
|
||||
{
|
||||
TCacheEntry &entry = iter->second;
|
||||
|
||||
if (!g_ActiveConfig.bSafeTextureCache)
|
||||
hash_value = ((u32 *)ptr)[entry.hashoffset];
|
||||
hash_value = ((u32 *)ptr)[0];
|
||||
|
||||
if (entry.isRenderTarget || ((address == entry.addr) && (hash_value == entry.hash)))
|
||||
{
|
||||
|
@ -355,20 +351,15 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
|
|||
if (dfmt == PC_TEX_FMT_NONE)
|
||||
dfmt = TexDecoder_Decode(temp, ptr, expandedWidth, expandedHeight, tex_format, tlutaddr, tlutfmt);
|
||||
|
||||
entry.hashoffset = 0;
|
||||
//entry.paletteHash = hashseed;
|
||||
entry.oldpixel = ((u32 *)ptr)[entry.hashoffset];
|
||||
entry.oldpixel = ((u32 *)ptr)[0];
|
||||
|
||||
if (g_ActiveConfig.bSafeTextureCache)
|
||||
entry.hash = hash_value;
|
||||
else
|
||||
{
|
||||
entry.hash = (u32)(((double)rand() / RAND_MAX) * 0xFFFFFFFF);
|
||||
((u32 *)ptr)[entry.hashoffset] = entry.hash;
|
||||
((u32 *)ptr)[0] = entry.hash;
|
||||
}
|
||||
//DebugLog("%c addr: %08x | fmt: %i | e.hash: %08x | w:%04i h:%04i", g_ActiveConfig.bSafeTextureCache ? 'S' : 'U'
|
||||
// , address, tex_format, entry.hash, width, height);
|
||||
|
||||
|
||||
entry.addr = address;
|
||||
entry.size_in_bytes = TexDecoder_GetTextureSizeInBytes(width, height, tex_format);
|
||||
|
@ -511,7 +502,6 @@ void TextureMngr::CopyRenderTargetToTexture(u32 address, bool bFromZBuffer, bool
|
|||
|
||||
TCacheEntry& entry = textures[address];
|
||||
entry.hash = 0;
|
||||
entry.hashoffset = 0;
|
||||
entry.frameCount = frameCount;
|
||||
|
||||
int w = (abs(source_rect.GetWidth()) >> bScaleByHalf);
|
||||
|
|
|
@ -36,7 +36,6 @@ public:
|
|||
u32 size_in_bytes;
|
||||
u32 hash;
|
||||
u32 paletteHash;
|
||||
u32 hashoffset;
|
||||
u32 oldpixel; // used for simple cleanup
|
||||
TexMode0 mode; // current filter and clamp modes that texture is set to
|
||||
|
||||
|
|
|
@ -182,6 +182,7 @@ VERTEXSHADER* VertexShaderCache::GetShader(u32 components)
|
|||
|
||||
void VertexShaderCache::ProgressiveCleanup()
|
||||
{
|
||||
/*
|
||||
VSCache::iterator iter = vshaders.begin();
|
||||
while (iter != vshaders.end()) {
|
||||
VSCacheEntry &entry = iter->second;
|
||||
|
@ -199,6 +200,7 @@ void VertexShaderCache::ProgressiveCleanup()
|
|||
}
|
||||
|
||||
SETSTAT(stats.numVertexShadersAlive, vshaders.size());
|
||||
*/
|
||||
}
|
||||
|
||||
bool VertexShaderCache::CompileVertexShader(VERTEXSHADER& vs, const char* pstrprogram)
|
||||
|
|
Loading…
Reference in New Issue