sometimes to advance you have to make a step back.

use plain vertex arrays instead of VBOs to render in Opengl plugin as the nature of the data make VBOs slower. This must bring, depending on the implementation, a good speedup in opengl.
in my system now opengl and d3d9 have a difference of 1 to 5 fps depending of the game.
some cleanup and a little work pointing to future improvements in the way of rendering.
please test and check for any errors.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@6139 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
Rodolfo Osvaldo Bogado 2010-08-28 15:09:42 +00:00
parent eb40f765c2
commit 9b0357b5e2
18 changed files with 414 additions and 424 deletions

View File

@ -119,3 +119,119 @@ u32 HashEctor(const u8* ptr, int length)
return(crc); return(crc);
} }
#ifdef _M_X64
u64 GetHash64(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995;
const int r = 47;
u64 h = len * m;
u32 Step = (len/8);
const u64 * data = (const u64 *)src;
const u64 * end = data + Step;
if(samples == 0) samples = Step;
Step = Step / samples;
if(Step < 1) Step = 1;
while(data < end)
{
u64 k = data[0];
data+=Step;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const u8 * data2 = (const u8*)end;
switch(len & 7)
{
case 7: h ^= u64(data2[6]) << 48;
case 6: h ^= u64(data2[5]) << 40;
case 5: h ^= u64(data2[4]) << 32;
case 4: h ^= u64(data2[3]) << 24;
case 3: h ^= u64(data2[2]) << 16;
case 2: h ^= u64(data2[1]) << 8;
case 1: h ^= u64(data2[0]);
h *= m;
};
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
#else
u64 GetHash64(const u8 *src, int len, u32 samples)
{
const u32 m = 0x5bd1e995;
const int r = 24;
u32 h1 = len;
u32 h2 = 0;
u32 Step = (len / 4);
const u32 * data = (const u32 *)src;
const u32 * end = data + Step;
const u8 * uEnd = (const u8 *)end;
if(samples == 0) samples = Step;
Step = Step / samples;
if(Step < 2) Step = 2;
while(data < end)
{
u32 k1 = data[0];
k1 *= m;
k1 ^= k1 >> r;
k1 *= m;
h1 *= m;
h1 ^= k1;
u32 k2 = data[1];
k2 *= m;
k2 ^= k2 >> r;
k2 *= m;
h2 *= m;
h2 ^= k2;
data+=Step;
}
if((len & 7) > 3)
{
u32 k1 = *(end - 1);
k1 *= m;
k1 ^= k1 >> r;
k1 *= m;
h1 *= m;
h1 ^= k1;
len -= 4;
}
switch(len & 3)
{
case 3: h2 ^= uEnd[2] << 16;
case 2: h2 ^= uEnd[1] << 8;
case 1: h2 ^= uEnd[0];
h2 *= m;
};
h1 ^= h2 >> 18; h1 *= m;
h2 ^= h1 >> 22; h2 *= m;
h1 ^= h2 >> 17; h1 *= m;
h2 ^= h1 >> 19; h2 *= m;
u64 h = h1;
h = (h << 32) | h2;
return h;
}
#endif

View File

@ -24,5 +24,5 @@ u32 HashFletcher(const u8* data_u8, size_t length); // FAST. Length & 1 == 0.
u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower
u32 HashFNV(const u8* ptr, int length); // Another fast and decent hash u32 HashFNV(const u8* ptr, int length); // Another fast and decent hash
u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS
u64 GetHash64(const u8 *src, int len, u32 samples);
#endif // _HASH_H_ #endif // _HASH_H_

View File

@ -22,7 +22,7 @@ static const char ID[4] = {'D', 'C', 'A', 'C'};
// Update this to the current SVN revision every time you change shader generation code. // Update this to the current SVN revision every time you change shader generation code.
// We don't automatically get this from SVN_REV because that would mean regenerating the // We don't automatically get this from SVN_REV because that would mean regenerating the
// shader cache for every revision, graphics-related or not, which is simply annoying. // shader cache for every revision, graphics-related or not, which is simply annoying.
const int version = 6124; const int version = 6139;
LinearDiskCache::LinearDiskCache() LinearDiskCache::LinearDiskCache()
: file_(NULL), num_entries_(0) { : file_(NULL), num_entries_(0) {

View File

@ -22,6 +22,7 @@ namespace VertexManager
{ {
u8* s_pCurBufferPointer = NULL; u8* s_pCurBufferPointer = NULL;
u8* s_pBaseBufferPointer = NULL;
} }

View File

@ -29,6 +29,7 @@ int GetRemainingVertices(int primitive); // remaining number of vertices that ca
// TODO: move, rename. // TODO: move, rename.
extern u8* s_pCurBufferPointer; extern u8* s_pCurBufferPointer;
extern u8* s_pBaseBufferPointer;
} }

View File

@ -233,12 +233,12 @@ static void Decode()
{ {
u32 Cmd2 = DataReadU32(); u32 Cmd2 = DataReadU32();
int transfer_size = ((Cmd2 >> 16) & 15) + 1; int transfer_size = ((Cmd2 >> 16) & 15) + 1;
u32 address = Cmd2 & 0xFFFF; u32 xf_address = Cmd2 & 0xFFFF;
// TODO - speed this up. pshufb? // TODO - speed this up. pshufb?
u32 data_buffer[16]; u32 data_buffer[16];
for (int i = 0; i < transfer_size; i++) for (int i = 0; i < transfer_size; i++)
data_buffer[i] = DataReadU32(); data_buffer[i] = DataReadU32();
LoadXFReg(transfer_size, address, data_buffer); LoadXFReg(transfer_size, xf_address, data_buffer);
INCSTAT(stats.thisFrame.numXFLoads); INCSTAT(stats.thisFrame.numXFLoads);
} }
break; break;

View File

@ -48,5 +48,5 @@
void OpcodeDecoder_Init(); void OpcodeDecoder_Init();
void OpcodeDecoder_Shutdown(); void OpcodeDecoder_Shutdown();
void OpcodeDecoder_Run(bool skipped_frame); void OpcodeDecoder_Run(bool skipped_frame);
void ExecuteDisplayList(u32 address, u32 size);
#endif // _OPCODE_DECODING_H #endif // _OPCODE_DECODING_H

View File

@ -20,7 +20,6 @@
#include "CPUDetect.h" #include "CPUDetect.h"
#include "TextureDecoder.h" #include "TextureDecoder.h"
#include "OpenCL.h" #include "OpenCL.h"
#if defined(HAVE_OPENCL) && HAVE_OPENCL #if defined(HAVE_OPENCL) && HAVE_OPENCL
#include "OpenCL/OCLTextureDecoder.h" #include "OpenCL/OCLTextureDecoder.h"
@ -96,122 +95,6 @@ int TexDecoder_GetTextureSizeInBytes(int width, int height, int format)
return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 2; return (width * height * TexDecoder_GetTexelSizeInNibbles(format)) / 2;
} }
#ifdef _M_X64
u64 TexDecoder_GetHash64(const u8 *src, int len, u32 samples)
{
const u64 m = 0xc6a4a7935bd1e995;
const int r = 47;
u64 h = len * m;
u32 Step = (len/8);
const u64 * data = (const u64 *)src;
const u64 * end = data + Step;
if(samples == 0) samples = Step;
Step = Step / samples;
if(Step < 1) Step = 1;
while(data < end)
{
u64 k = data[0];
data+=Step;
k *= m;
k ^= k >> r;
k *= m;
h ^= k;
h *= m;
}
const u8 * data2 = (const u8*)end;
switch(len & 7)
{
case 7: h ^= u64(data2[6]) << 48;
case 6: h ^= u64(data2[5]) << 40;
case 5: h ^= u64(data2[4]) << 32;
case 4: h ^= u64(data2[3]) << 24;
case 3: h ^= u64(data2[2]) << 16;
case 2: h ^= u64(data2[1]) << 8;
case 1: h ^= u64(data2[0]);
h *= m;
};
h ^= h >> r;
h *= m;
h ^= h >> r;
return h;
}
#else
u64 TexDecoder_GetHash64(const u8 *src, int len, u32 samples)
{
const u32 m = 0x5bd1e995;
const int r = 24;
u32 h1 = len;
u32 h2 = 0;
u32 Step = (len / 4);
const u32 * data = (const u32 *)src;
const u32 * end = data + Step;
const u8 * uEnd = (const u8 *)end;
if(samples == 0) samples = Step;
Step = Step / samples;
if(Step < 2) Step = 2;
while(data < end)
{
u32 k1 = data[0];
k1 *= m;
k1 ^= k1 >> r;
k1 *= m;
h1 *= m;
h1 ^= k1;
u32 k2 = data[1];
k2 *= m;
k2 ^= k2 >> r;
k2 *= m;
h2 *= m;
h2 ^= k2;
data+=Step;
}
if((len & 7) > 3)
{
u32 k1 = *(end - 1);
k1 *= m;
k1 ^= k1 >> r;
k1 *= m;
h1 *= m;
h1 ^= k1;
len -= 4;
}
switch(len & 3)
{
case 3: h2 ^= uEnd[2] << 16;
case 2: h2 ^= uEnd[1] << 8;
case 1: h2 ^= uEnd[0];
h2 *= m;
};
h1 ^= h2 >> 18; h1 *= m;
h2 ^= h1 >> 22; h2 *= m;
h1 ^= h2 >> 17; h1 *= m;
h2 ^= h1 >> 19; h2 *= m;
u64 h = h1;
h = (h << 32) | h2;
return h;
}
#endif
int TexDecoder_GetBlockWidthInTexels(u32 format) int TexDecoder_GetBlockWidthInTexels(u32 format)
{ {
switch (format) switch (format)

View File

@ -17,7 +17,7 @@
#ifndef _TEXTUREDECODER_H #ifndef _TEXTUREDECODER_H
#define _TEXTUREDECODER_H #define _TEXTUREDECODER_H
#include "hash.h"
enum enum
{ {
TMEM_SIZE = 1024*1024, TMEM_SIZE = 1024*1024,
@ -86,9 +86,6 @@ enum PC_TexFormat
PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt,bool rgbaOnly = false); PC_TexFormat TexDecoder_Decode(u8 *dst, const u8 *src, int width, int height, int texformat, int tlutaddr, int tlutfmt,bool rgbaOnly = false);
PC_TexFormat GetPC_TexFormat(int texformat, int tlutfmt); PC_TexFormat GetPC_TexFormat(int texformat, int tlutfmt);
void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth, int texformat, int tlutaddr, int tlutfmt); void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth, int texformat, int tlutaddr, int tlutfmt);
u64 TexDecoder_GetHash64(const u8 *src, int len, u32 samples = 0);
void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center); void TexDecoder_SetTexFmtOverlayOptions(bool enable, bool center);
#endif #endif

View File

@ -45,10 +45,6 @@ void GetVertexShaderId(VERTEXSHADERUID *uid, u32 components)
(u32)xfregs.colChans[i].alpha.matsource) << 15; (u32)xfregs.colChans[i].alpha.matsource) << 15;
} }
// fog
uid->values[1] |= (((u32)bpmem.fog.c_proj_fsel.fsel & 3) << 30);
uid->values[2] |= (((u32)bpmem.fog.c_proj_fsel.fsel >> 2) << 30);
u32 *pcurvalue = &uid->values[3]; u32 *pcurvalue = &uid->values[3];
for (int i = 0; i < xfregs.numTexGens; ++i) { for (int i = 0; i < xfregs.numTexGens; ++i) {
TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo; TexMtxInfo tinfo = xfregs.texcoords[i].texmtxinfo;

View File

@ -207,7 +207,7 @@ TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, u
// hires textures and texture dumping not supported, yet // hires textures and texture dumping not supported, yet
if (g_ActiveConfig.bSafeTextureCache/* || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures*/) if (g_ActiveConfig.bSafeTextureCache/* || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures*/)
{ {
texHash = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); texHash = GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{ {
// WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up) // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
@ -217,7 +217,7 @@ TextureCache::TCacheEntry* TextureCache::Load(unsigned int stage, u32 address, u
// each other stored in a single texture, and uses the palette to make different characters // 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, // 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. // we must make sure that texture with different tluts get different IDs.
u64 tlutHash = TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); u64 tlutHash = GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
texHash ^= tlutHash; texHash ^= tlutHash;
if (g_ActiveConfig.bSafeTextureCache) if (g_ActiveConfig.bSafeTextureCache)
{ {

View File

@ -166,7 +166,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures) if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures)
{ {
texHash = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); texHash = GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{ {
// WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up) // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
@ -176,7 +176,7 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
// each other stored in a single texture, and uses the palette to make different characters // 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, // 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. // we must make sure that texture with different tluts get different IDs.
u64 tlutHash = TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); u64 tlutHash = GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
texHash ^= tlutHash; texHash ^= tlutHash;
if (g_ActiveConfig.bSafeTextureCache) if (g_ActiveConfig.bSafeTextureCache)
{ {
@ -200,10 +200,10 @@ TextureCache::TCacheEntry *TextureCache::Load(int stage, u32 address, int width,
{ {
if(!g_ActiveConfig.bCopyEFBToTexture) if(!g_ActiveConfig.bCopyEFBToTexture)
{ {
hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); hash_value = GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{ {
hash_value ^= TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); hash_value ^= GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
} }
} }
else else

View File

@ -450,7 +450,7 @@ u64 EncodeToRamFromTexture(u32 address,LPDIRECT3DTEXTURE9 source_texture,u32 Sou
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight,readStride, true, bScaleByHalf > 0);
TextureCache::MakeRangeDynamic(address,size_in_bytes); TextureCache::MakeRangeDynamic(address,size_in_bytes);
u64 Hashvalue = 0; u64 Hashvalue = 0;
Hashvalue = TexDecoder_GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); Hashvalue = GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
return Hashvalue; return Hashvalue;
} }

View File

@ -78,7 +78,7 @@ struct CachedDisplayList
bool uncachable; // if set, this DL will always be interpreted. This gets set if hash ever changes. bool uncachable; // if set, this DL will always be interpreted. This gets set if hash ever changes.
int pass; int pass;
u32 dl_hash; u64 dl_hash;
int check; int check;
int next_check; int next_check;
@ -128,136 +128,125 @@ bool AnalyzeAndRunDisplayList(u32 address, int size, CachedDisplayList *dl)
int num_index_xf = 0; int num_index_xf = 0;
//int num_draw_call = 0; // unused? //int num_draw_call = 0; // unused?
u8 *old_datareader = g_pVideoData; u8* old_pVideoData = g_pVideoData;
g_pVideoData = Memory_GetPtr(address); u8* startAddress = Memory_GetPtr(address);
u8 *end = g_pVideoData + size; // Avoid the crash if Memory_GetPtr failed ..
while (g_pVideoData < end) if (startAddress != 0)
{ {
// Yet another reimplementation of the DL reading... g_pVideoData = startAddress;
int cmd_byte = DataReadU8();
switch (cmd_byte) // temporarily swap dl and non-dl (small "hack" for the stats)
Statistics::SwapDL();
u8 *end = g_pVideoData + size;
while (g_pVideoData < end)
{ {
case GX_NOP: // Yet another reimplementation of the DL reading...
break; int cmd_byte = DataReadU8();
switch (cmd_byte)
case GX_LOAD_CP_REG: //0x08
{ {
// Execute case GX_NOP:
u8 sub_cmd = DataReadU8(); break;
u32 value = DataReadU32();
LoadCPReg(sub_cmd, value);
INCSTAT(stats.thisFrame.numCPLoads);
// Analyze case GX_LOAD_CP_REG: //0x08
num_cp_reg++; {
} u8 sub_cmd = DataReadU8();
break; u32 value = DataReadU32();
LoadCPReg(sub_cmd, value);
INCSTAT(stats.thisFrame.numCPLoads);
num_cp_reg++;
}
break;
case GX_LOAD_XF_REG: case GX_LOAD_XF_REG:
{ {
// Execute u32 Cmd2 = DataReadU32();
u32 Cmd2 = DataReadU32(); int transfer_size = ((Cmd2 >> 16) & 15) + 1;
int transfer_size = ((Cmd2 >> 16) & 15) + 1; u32 xf_address = Cmd2 & 0xFFFF;
u32 xf_address = Cmd2 & 0xFFFF; // TODO - speed this up. pshufb?
// TODO - speed this up. pshufb? u32 data_buffer[16];
u32 data_buffer[16]; for (int i = 0; i < transfer_size; i++)
for (int i = 0; i < transfer_size; i++) data_buffer[i] = DataReadU32();
data_buffer[i] = DataReadU32(); LoadXFReg(transfer_size, xf_address, data_buffer);
LoadXFReg(transfer_size, xf_address, data_buffer); INCSTAT(stats.thisFrame.numXFLoads);
INCSTAT(stats.thisFrame.numXFLoads); num_xf_reg++;
}
break;
// Analyze case GX_LOAD_INDX_A: //used for position matrices
num_xf_reg++; {
} LoadIndexedXF(DataReadU32(), 0xC);
break; num_index_xf++;
}
case GX_LOAD_INDX_A: //used for position matrices break;
{ case GX_LOAD_INDX_B: //used for normal matrices
u32 value = DataReadU32(); {
// Execute LoadIndexedXF(DataReadU32(), 0xD);
LoadIndexedXF(value, 0xC); num_index_xf++;
// Analyze }
num_index_xf++; break;
} case GX_LOAD_INDX_C: //used for postmatrices
break; {
case GX_LOAD_INDX_B: //used for normal matrices LoadIndexedXF(DataReadU32(), 0xE);
{ num_index_xf++;
u32 value = DataReadU32(); }
// Execute break;
LoadIndexedXF(value, 0xD); case GX_LOAD_INDX_D: //used for lights
// Analyze {
num_index_xf++; LoadIndexedXF(DataReadU32(), 0xF);
} num_index_xf++;
break; }
case GX_LOAD_INDX_C: //used for postmatrices break;
{ case GX_CMD_CALL_DL:
u32 value = DataReadU32(); {
// Execute u32 address = DataReadU32();
LoadIndexedXF(value, 0xE); u32 count = DataReadU32();
// Analyze ExecuteDisplayList(address, count);
num_index_xf++; }
} break;
break; case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
case GX_LOAD_INDX_D: //used for lights DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte);
{ break;
u32 value = DataReadU32(); case GX_CMD_INVL_VC: // Invalidate Vertex Cache
// Execute DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
LoadIndexedXF(value, 0xF); break;
// Analyze case GX_LOAD_BP_REG: //0x61
num_index_xf++; {
} u32 bp_cmd = DataReadU32();
break; LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
case GX_CMD_CALL_DL: }
PanicAlert("Seeing DL call inside DL."); break;
break;
case GX_CMD_UNKNOWN_METRICS:
// zelda 4 swords calls it and checks the metrics registers after that
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
break;
case GX_LOAD_BP_REG: //0x61
{
u32 bp_cmd = DataReadU32();
// Execute
LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
// Analyze
}
break;
// draw primitives // draw primitives
default: default:
if (cmd_byte & 0x80) if (cmd_byte & 0x80)
{ {
// load vertices (use computed vertex size from FifoCommandRunnable above) // load vertices (use computed vertex size from FifoCommandRunnable above)
u16 numVertices = DataReadU16();
// Execute VertexLoaderManager::RunVertices(
u16 numVertices = DataReadU16(); cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
VertexLoaderManager::RunVertices( numVertices);
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) }
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, else
numVertices); {
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
// Analyze break;
} }
else
{
ERROR_LOG(VIDEO, "DLCache::CompileAndRun: Illegal command %02x", cmd_byte);
break; break;
} }
break;
} }
INCSTAT(stats.numDListsCalled);
INCSTAT(stats.thisFrame.numDListsCalled);
// un-swap
Statistics::SwapDL();
} }
g_pVideoData = old_datareader; // reset to the old pointer
g_pVideoData = old_pVideoData;
return true; return true;
} }
@ -271,173 +260,175 @@ bool AnalyzeAndRunDisplayList(u32 address, int size, CachedDisplayList *dl)
// have the compiled code so we don't have to interpret anymore, we just run it. // have the compiled code so we don't have to interpret anymore, we just run it.
bool CompileAndRunDisplayList(u32 address, int size, CachedDisplayList *dl) bool CompileAndRunDisplayList(u32 address, int size, CachedDisplayList *dl)
{ {
VertexManager::Flush(); u8* old_pVideoData = g_pVideoData;
u8* startAddress = Memory_GetPtr(address);
u8 *old_datareader = g_pVideoData; // Avoid the crash if Memory_GetPtr failed ..
g_pVideoData = Memory_GetPtr(address); if (startAddress != 0)
u8 *end = g_pVideoData + size;
emitter.AlignCode4();
dl->compiled_code = emitter.GetCodePtr();
emitter.ABI_EmitPrologue(4);
while (g_pVideoData < end)
{ {
// Yet another reimplementation of the DL reading... g_pVideoData = startAddress;
int cmd_byte = DataReadU8();
switch (cmd_byte) // temporarily swap dl and non-dl (small "hack" for the stats)
Statistics::SwapDL();
u8 *end = g_pVideoData + size;
emitter.AlignCode4();
dl->compiled_code = emitter.GetCodePtr();
emitter.ABI_EmitPrologue(4);
while (g_pVideoData < end)
{ {
case GX_NOP: // Yet another reimplementation of the DL reading...
// Execute int cmd_byte = DataReadU8();
// Compile switch (cmd_byte)
break;
case GX_LOAD_CP_REG: //0x08
{ {
case GX_NOP:
// Execute // Execute
u8 sub_cmd = DataReadU8();
u32 value = DataReadU32();
LoadCPReg(sub_cmd, value);
INCSTAT(stats.thisFrame.numCPLoads);
// Compile // Compile
emitter.ABI_CallFunctionCC((void *)&LoadCPReg, sub_cmd, value); break;
}
break;
case GX_LOAD_XF_REG: case GX_LOAD_CP_REG: //0x08
{ {
// Execute // Execute
u32 Cmd2 = DataReadU32(); u8 sub_cmd = DataReadU8();
int transfer_size = ((Cmd2 >> 16) & 15) + 1; u32 value = DataReadU32();
u32 xf_address = Cmd2 & 0xFFFF; LoadCPReg(sub_cmd, value);
// TODO - speed this up. pshufb? INCSTAT(stats.thisFrame.numCPLoads);
u8 *real_data_buffer = AllocStaticData(4 * transfer_size);
u32 *data_buffer = (u32 *)real_data_buffer;
for (int i = 0; i < transfer_size; i++)
data_buffer[i] = DataReadU32();
LoadXFReg(transfer_size, xf_address, data_buffer);
INCSTAT(stats.thisFrame.numXFLoads);
// Compile // Compile
emitter.ABI_CallFunctionCCP((void *)&LoadXFReg, transfer_size, address, data_buffer); emitter.ABI_CallFunctionCC((void *)&LoadCPReg, sub_cmd, value);
} }
break; break;
case GX_LOAD_INDX_A: //used for position matrices case GX_LOAD_XF_REG:
{ {
u32 value = DataReadU32(); // Execute
// Execute u32 Cmd2 = DataReadU32();
LoadIndexedXF(value, 0xC); int transfer_size = ((Cmd2 >> 16) & 15) + 1;
// Compile u32 xf_address = Cmd2 & 0xFFFF;
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xC); // TODO - speed this up. pshufb?
} u8 *real_data_buffer = AllocStaticData(4 * transfer_size);
break; u32 *data_buffer = (u32 *)real_data_buffer;
case GX_LOAD_INDX_B: //used for normal matrices for (int i = 0; i < transfer_size; i++)
{ data_buffer[i] = DataReadU32();
u32 value = DataReadU32(); LoadXFReg(transfer_size, xf_address, data_buffer);
// Execute INCSTAT(stats.thisFrame.numXFLoads);
LoadIndexedXF(value, 0xD);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xD);
}
break;
case GX_LOAD_INDX_C: //used for postmatrices
{
u32 value = DataReadU32();
// Execute
LoadIndexedXF(value, 0xE);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xE);
}
break;
case GX_LOAD_INDX_D: //used for lights
{
u32 value = DataReadU32();
// Execute
LoadIndexedXF(value, 0xF);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xF);
}
break;
case GX_CMD_CALL_DL: // Compile
PanicAlert("Seeing DL call inside DL."); emitter.ABI_CallFunctionCCP((void *)&LoadXFReg, transfer_size, xf_address, data_buffer);
break; }
break;
case GX_CMD_UNKNOWN_METRICS: case GX_LOAD_INDX_A: //used for position matrices
// zelda 4 swords calls it and checks the metrics registers after that {
break; u32 value = DataReadU32();
// Execute
LoadIndexedXF(value, 0xC);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xC);
}
break;
case GX_LOAD_INDX_B: //used for normal matrices
{
u32 value = DataReadU32();
// Execute
LoadIndexedXF(value, 0xD);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xD);
}
break;
case GX_LOAD_INDX_C: //used for postmatrices
{
u32 value = DataReadU32();
// Execute
LoadIndexedXF(value, 0xE);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xE);
}
break;
case GX_LOAD_INDX_D: //used for lights
{
u32 value = DataReadU32();
// Execute
LoadIndexedXF(value, 0xF);
// Compile
emitter.ABI_CallFunctionCC((void *)&LoadIndexedXF, value, 0xF);
}
break;
case GX_CMD_INVL_VC:// Invalidate (vertex cache?) case GX_CMD_CALL_DL:
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)"); {
break; u32 address = DataReadU32();
u32 count = DataReadU32();
ExecuteDisplayList(address, count);
emitter.ABI_CallFunctionCC((void *)&ExecuteDisplayList, address, count);
}
break;
case GX_LOAD_BP_REG: //0x61 case GX_CMD_UNKNOWN_METRICS:
{ // zelda 4 swords calls it and checks the metrics registers after that
u32 bp_cmd = DataReadU32(); break;
// Execute
LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
// Compile
emitter.ABI_CallFunctionC((void *)&LoadBPReg, bp_cmd);
}
break;
// draw primitives case GX_CMD_INVL_VC:// Invalidate (vertex cache?)
default: DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
if (cmd_byte & 0x80) break;
{
// load vertices (use computed vertex size from FifoCommandRunnable above)
// Execute case GX_LOAD_BP_REG: //0x61
u16 numVertices = DataReadU16(); {
u32 bp_cmd = DataReadU32();
// Execute
LoadBPReg(bp_cmd);
INCSTAT(stats.thisFrame.numBPLoads);
// Compile
emitter.ABI_CallFunctionC((void *)&LoadBPReg, bp_cmd);
}
break;
u64 pre_draw_video_data = (u64)g_pVideoData; // draw primitives
default:
if (cmd_byte & 0x80)
{
// load vertices (use computed vertex size from FifoCommandRunnable above)
VertexLoaderManager::RunVertices( // Execute
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) u16 numVertices = DataReadU16();
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
// Compile u64 pre_draw_video_data = (u64)g_pVideoData;
#ifdef _M_X64
emitter.MOV(64, R(RAX), Imm64(pre_draw_video_data)); VertexLoaderManager::RunVertices(
emitter.MOV(64, M(&g_pVideoData), R(RAX)); cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
#else (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
emitter.MOV(32, R(EAX), Imm32((u32)pre_draw_video_data)); numVertices);
emitter.MOV(32, M(&g_pVideoData), R(EAX));
#endif // Compile
emitter.ABI_CallFunctionCCC( #ifdef _M_X64
(void *)&VertexLoaderManager::RunVertices, emitter.MOV(64, R(RAX), Imm64(pre_draw_video_data));
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7) emitter.MOV(64, M(&g_pVideoData), R(RAX));
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, #else
numVertices); emitter.MOV(32, R(EAX), Imm32((u32)pre_draw_video_data));
} emitter.MOV(32, M(&g_pVideoData), R(EAX));
else #endif
{ emitter.ABI_CallFunctionCCC(
ERROR_LOG(VIDEO, "DLCache::CompileAndRun: Illegal command %02x", cmd_byte); (void *)&VertexLoaderManager::RunVertices,
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
numVertices);
}
else
{
ERROR_LOG(VIDEO, "DLCache::CompileAndRun: Illegal command %02x", cmd_byte);
break;
}
break; break;
} }
break;
} }
emitter.ABI_EmitEpilogue(4);
} }
g_pVideoData = old_pVideoData;
emitter.ABI_EmitEpilogue(4);
g_pVideoData = old_datareader;
return true; return true;
} }
// This one's pretty expensive. We should check if we can get away with only
// hashing the entire DL the first 3 frames or something.
u32 ComputeDLHash(u32 address, u32 size)
{
u8 *ptr = Memory_GetPtr(address);
return HashFletcher(ptr, size & ~1);
}
void Init() void Init()
{ {
dlcode_cache = (u8 *)AllocateExecutableMemory(DL_CODE_CACHE_SIZE, false); // Don't need low memory. dlcode_cache = (u8 *)AllocateExecutableMemory(DL_CODE_CACHE_SIZE, false); // Don't need low memory.
@ -485,8 +476,12 @@ bool HandleDisplayList(u32 address, u32 size)
{ {
// Disable display list caching since the benefit isn't much to write home about // Disable display list caching since the benefit isn't much to write home about
// right now... // right now...
//Fixed DlistCaching now is fully functional benefits still marginal but when vertex data is stored here the story will be diferent :)
//to test remove the next line;
return false; return false;
if(size == 0) return false;
u64 dl_id = DLCache::CreateMapId(address, size); u64 dl_id = DLCache::CreateMapId(address, size);
DLCache::DLMap::iterator iter = DLCache::dl_map.find(dl_id); DLCache::DLMap::iterator iter = DLCache::dl_map.find(dl_id);
@ -509,7 +504,7 @@ bool HandleDisplayList(u32 address, u32 size)
break; break;
case DLCache::DLPASS_COMPILE: case DLCache::DLPASS_COMPILE:
// First, check that the hash is the same as the last time. // First, check that the hash is the same as the last time.
if (dl.dl_hash != HashAdler32(Memory_GetPtr(address), size)) if (dl.dl_hash != GetHash64(Memory_GetPtr(address), size,0))
{ {
// PanicAlert("uncachable %08x", address); // PanicAlert("uncachable %08x", address);
dl.uncachable = true; dl.uncachable = true;
@ -524,13 +519,13 @@ bool HandleDisplayList(u32 address, u32 size)
dl.check--; dl.check--;
if (dl.check <= 0) if (dl.check <= 0)
{ {
if (dl.dl_hash != HashAdler32(Memory_GetPtr(address), size)) if (dl.dl_hash != GetHash64(Memory_GetPtr(address), size,0))
{ {
dl.uncachable = true; dl.uncachable = true;
return false; return false;
} }
dl.check = dl.next_check; dl.check = dl.next_check;
dl.next_check *= 2; //dl.next_check *= 2;
if (dl.next_check > 1024) if (dl.next_check > 1024)
dl.next_check = 1024; dl.next_check = 1024;
} }
@ -546,7 +541,7 @@ bool HandleDisplayList(u32 address, u32 size)
DLCache::CachedDisplayList dl; DLCache::CachedDisplayList dl;
if (DLCache::AnalyzeAndRunDisplayList(address, size, &dl)) { if (DLCache::AnalyzeAndRunDisplayList(address, size, &dl)) {
dl.dl_hash = HashAdler32(Memory_GetPtr(address), size); dl.dl_hash = GetHash64(Memory_GetPtr(address), size,0);
dl.pass = DLCache::DLPASS_COMPILE; dl.pass = DLCache::DLPASS_COMPILE;
dl.check = 1; dl.check = 1;
dl.next_check = 1; dl.next_check = 1;

View File

@ -29,13 +29,13 @@
#define COMPILED_CODE_SIZE 4096 #define COMPILED_CODE_SIZE 4096
u32 s_prevcomponents; // previous state set u32 s_prevcomponents; // previous state set
/*
#ifdef _WIN32 #ifdef _WIN32
#ifdef _M_IX86 #ifdef _M_IX86
#define USE_JIT #define USE_JIT
#endif #endif
#endif #endif
*/
// Note the use of CallCdeclFunction3I etc. // Note the use of CallCdeclFunction3I etc.
// This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit // This is a horrible hack that is necessary because in 64-bit mode, Opengl32.dll is based way, way above the 32-bit
// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we // address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
@ -181,21 +181,21 @@ void GLVertexFormat::SetupVertexPointers() const {
#ifdef USE_JIT #ifdef USE_JIT
((void (*)())(void*)m_compiledCode)(); ((void (*)())(void*)m_compiledCode)();
#else #else
glVertexPointer(3, GL_FLOAT, vtx_decl.stride, 0); glVertexPointer(3, GL_FLOAT, vtx_decl.stride, VertexManager::s_pBaseBufferPointer);
if (vtx_decl.num_normals >= 1) { if (vtx_decl.num_normals >= 1) {
glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)vtx_decl.normal_offset[0]); glNormalPointer(VarToGL(vtx_decl.normal_gl_type), vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[0]));
if (vtx_decl.num_normals == 3) { if (vtx_decl.num_normals == 3) {
glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)vtx_decl.normal_offset[1]); glVertexAttribPointer(SHADER_NORM1_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[1]));
glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)vtx_decl.normal_offset[2]); glVertexAttribPointer(SHADER_NORM2_ATTRIB, vtx_decl.normal_gl_size, VarToGL(vtx_decl.normal_gl_type), GL_TRUE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.normal_offset[2]));
} }
} }
for (int i = 0; i < 2; i++) { for (int i = 0; i < 2; i++) {
if (vtx_decl.color_offset[i] != -1) { if (vtx_decl.color_offset[i] != -1) {
if (i == 0) if (i == 0)
glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)vtx_decl.color_offset[i]); glColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
else { else {
glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)vtx_decl.color_offset[i]); glSecondaryColorPointer(4, GL_UNSIGNED_BYTE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.color_offset[i]));
} }
} }
} }
@ -205,12 +205,12 @@ void GLVertexFormat::SetupVertexPointers() const {
int id = GL_TEXTURE0 + i; int id = GL_TEXTURE0 + i;
glClientActiveTexture(id); glClientActiveTexture(id);
glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]), glTexCoordPointer(vtx_decl.texcoord_size[i], VarToGL(vtx_decl.texcoord_gl_type[i]),
vtx_decl.stride, (void *)vtx_decl.texcoord_offset[i]); vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.texcoord_offset[i]));
} }
} }
if (vtx_decl.posmtx_offset != -1) { if (vtx_decl.posmtx_offset != -1) {
glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)vtx_decl.posmtx_offset); glVertexAttribPointer(SHADER_POSMTX_ATTRIB, 4, GL_UNSIGNED_BYTE, GL_FALSE, vtx_decl.stride, (void *)(VertexManager::s_pBaseBufferPointer + vtx_decl.posmtx_offset));
} }
#endif #endif
} }

View File

@ -381,7 +381,7 @@ u64 EncodeToRamFromTexture(u32 address,GLuint source_texture,float MValueX,float
EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer); EncodeToRamUsingShader(texconv_shader, source_texture, scaledSource, dest_ptr, expandedWidth / samples, expandedHeight, readStride, true, bScaleByHalf > 0 && !bFromZBuffer);
TextureMngr::MakeRangeDynamic(address,size_in_bytes); TextureMngr::MakeRangeDynamic(address,size_in_bytes);
return TexDecoder_GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples); return GetHash64(dest_ptr,size_in_bytes,g_ActiveConfig.iSafeTextureCache_ColorSamples);
} }
void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc,

View File

@ -290,7 +290,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
FullFormat = (tex_format | (tlutfmt << 16)); FullFormat = (tex_format | (tlutfmt << 16));
if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures) if (g_ActiveConfig.bSafeTextureCache || g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures)
{ {
texHash = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); texHash = GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{ {
// WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up) // WARNING! texID != address now => may break CopyRenderTargetToTexture (cf. TODO up)
@ -300,7 +300,7 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
// each other stored in a single texture, and uses the palette to make different characters // 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, // 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. // we must make sure that texture with different tluts get different IDs.
u64 tlutHash = TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); u64 tlutHash = GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
texHash ^= tlutHash; texHash ^= tlutHash;
if (g_ActiveConfig.bSafeTextureCache) if (g_ActiveConfig.bSafeTextureCache)
{ {
@ -324,10 +324,10 @@ TextureMngr::TCacheEntry* TextureMngr::Load(int texstage, u32 address, int width
{ {
if(!g_ActiveConfig.bCopyEFBToTexture) if(!g_ActiveConfig.bCopyEFBToTexture)
{ {
hash_value = TexDecoder_GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); hash_value = GetHash64(ptr,TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2)) if ((tex_format == GX_TF_C4) || (tex_format == GX_TF_C8) || (tex_format == GX_TF_C14X2))
{ {
hash_value ^= TexDecoder_GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples); hash_value ^= GetHash64(&texMem[tlutaddr], TexDecoder_GetPaletteSize(tex_format),g_ActiveConfig.iSafeTextureCache_ColorSamples);
} }
} }
else else

View File

@ -60,8 +60,8 @@ static GLint max_Index_size = 0;
#define MAXIBUFFERSIZE 0xFFFF #define MAXIBUFFERSIZE 0xFFFF
#define MAXVBOBUFFERCOUNT 0x8 #define MAXVBOBUFFERCOUNT 0x8
static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0}; //static GLuint s_vboBuffers[MAXVBOBUFFERCOUNT] = {0};
static int s_nCurVBOIndex = 0; // current free buffer //static int s_nCurVBOIndex = 0; // current free buffer
static bool Flushed=false; static bool Flushed=false;
@ -79,8 +79,9 @@ bool Init()
PIBuffer = new u16[max_Index_size]; PIBuffer = new u16[max_Index_size];
IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer); IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);
s_pCurBufferPointer = LocalVBuffer; s_pCurBufferPointer = LocalVBuffer;
s_nCurVBOIndex = 0; s_pBaseBufferPointer = LocalVBuffer;
glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); //s_nCurVBOIndex = 0;
//glGenBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_VERTEX_ARRAY);
g_nativeVertexFmt = NULL; g_nativeVertexFmt = NULL;
Flushed=false; Flushed=false;
@ -95,13 +96,13 @@ void Shutdown()
delete [] TIBuffer; delete [] TIBuffer;
delete [] LIBuffer; delete [] LIBuffer;
delete [] PIBuffer; delete [] PIBuffer;
glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers); //glDeleteBuffers(ARRAYSIZE(s_vboBuffers), s_vboBuffers);
s_nCurVBOIndex = 0; //s_nCurVBOIndex = 0;
} }
void ResetBuffer() void ResetBuffer()
{ {
s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers); //s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
s_pCurBufferPointer = LocalVBuffer; s_pCurBufferPointer = LocalVBuffer;
} }
@ -237,8 +238,8 @@ void Flush()
(void)GL_REPORT_ERROR(); (void)GL_REPORT_ERROR();
glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]); //glBindBuffer(GL_ARRAY_BUFFER, s_vboBuffers[s_nCurVBOIndex]);
glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - LocalVBuffer, LocalVBuffer, GL_STREAM_DRAW); //glBufferData(GL_ARRAY_BUFFER, s_pCurBufferPointer - LocalVBuffer, LocalVBuffer, GL_STREAM_DRAW);
GL_REPORT_ERRORD(); GL_REPORT_ERRORD();
// setup the pointers // setup the pointers
@ -339,7 +340,7 @@ void Flush()
if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract) if (bpmem.blendmode.blendenable || bpmem.blendmode.subtract)
glEnable(GL_BLEND); glEnable(GL_BLEND);
} }
s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers); //s_nCurVBOIndex = (s_nCurVBOIndex + 1) % ARRAYSIZE(s_vboBuffers);
s_pCurBufferPointer = LocalVBuffer; s_pCurBufferPointer = LocalVBuffer;
IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer); IndexGenerator::Start(TIBuffer,LIBuffer,PIBuffer);