Merge 'master' into shader-uids-awesome.
Conflicts: Source/Core/VideoCommon/Src/LightingShaderGen.cpp Source/Core/VideoCommon/Src/PixelShaderGen.cpp Source/Core/VideoCommon/Src/PixelShaderGen.h Source/Core/VideoCommon/Src/PixelShaderManager.cpp Source/Core/VideoCommon/Src/VertexShaderGen.cpp Source/Core/VideoCommon/Src/VertexShaderGen.h Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.cpp Source/Plugins/Plugin_VideoOGL/Src/PixelShaderCache.h Source/Plugins/Plugin_VideoOGL/Src/VertexManager.cpp Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.cpp Source/Plugins/Plugin_VideoOGL/Src/VertexShaderCache.h
This commit is contained in:
@@ -157,9 +157,21 @@ void AVIDump::Stop()
|
||||
NOTICE_LOG(VIDEO, "Stop");
|
||||
}
|
||||
|
||||
void AVIDump::AddFrame(char *data)
|
||||
void AVIDump::AddFrame(const u8* data, int w, int h)
|
||||
{
|
||||
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, (LPVOID) data, m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
|
||||
static bool shown_error = false;
|
||||
if ((w != m_bitmap.biWidth || h != m_bitmap.biHeight) && !shown_error)
|
||||
{
|
||||
PanicAlert("You have resized the window while dumping frames.\n"
|
||||
"Nothing sane can be done to handle this.\n"
|
||||
"Your video will likely be broken.");
|
||||
shown_error = true;
|
||||
|
||||
m_bitmap.biWidth = w;
|
||||
m_bitmap.biHeight = h;
|
||||
}
|
||||
|
||||
AVIStreamWrite(m_streamCompressed, ++m_frameCount, 1, const_cast<u8*>(data), m_bitmap.biSizeImage, AVIIF_KEYFRAME, NULL, &m_byteBuffer);
|
||||
m_totalBytes += m_byteBuffer;
|
||||
// Close the recording if the file is more than 2gb
|
||||
// VfW can't properly save files over 2gb in size, but can keep writing to them up to 4gb.
|
||||
@@ -298,9 +310,9 @@ bool AVIDump::CreateFile()
|
||||
return true;
|
||||
}
|
||||
|
||||
void AVIDump::AddFrame(uint8_t *data, int width, int height)
|
||||
void AVIDump::AddFrame(const u8* data, int width, int height)
|
||||
{
|
||||
avpicture_fill((AVPicture *)s_BGRFrame, data, PIX_FMT_BGR24, width, height);
|
||||
avpicture_fill((AVPicture *)s_BGRFrame, const_cast<u8*>(data), PIX_FMT_BGR24, width, height);
|
||||
|
||||
// Convert image from BGR24 to desired pixel format, and scale to initial
|
||||
// width and height
|
||||
|
||||
@@ -24,6 +24,8 @@
|
||||
#include <stdint.h>
|
||||
#endif
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
class AVIDump
|
||||
{
|
||||
private:
|
||||
@@ -36,11 +38,11 @@ class AVIDump
|
||||
public:
|
||||
#ifdef _WIN32
|
||||
static bool Start(HWND hWnd, int w, int h);
|
||||
static void AddFrame(char *data);
|
||||
#else
|
||||
static bool Start(int w, int h);
|
||||
static void AddFrame(uint8_t *data, int width, int height);
|
||||
#endif
|
||||
static void AddFrame(const u8* data, int width, int height);
|
||||
|
||||
static void Stop();
|
||||
};
|
||||
|
||||
|
||||
@@ -236,7 +236,7 @@ bool GetConfig(const int &type)
|
||||
case CONFIG_DISABLEFOG:
|
||||
return g_ActiveConfig.bDisableFog;
|
||||
case CONFIG_SHOWEFBREGIONS:
|
||||
return false;
|
||||
return g_ActiveConfig.bShowEFBCopyRegions;
|
||||
default:
|
||||
PanicAlert("GetConfig Error: Unknown Config Type!");
|
||||
return false;
|
||||
@@ -248,6 +248,7 @@ u8 *GetPointer(const u32 &address)
|
||||
return Memory::GetPointer(address);
|
||||
}
|
||||
|
||||
// Never used. All backends call SetSamplerState in VertexManager::Flush
|
||||
void SetTextureMode(const BPCmd &bp)
|
||||
{
|
||||
g_renderer->SetSamplerState(bp.address & 3, (bp.address & 0xE0) == 0xA0);
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -31,6 +31,7 @@
|
||||
#include "VertexShaderManager.h"
|
||||
#include "Thread.h"
|
||||
#include "HW/Memmap.h"
|
||||
#include "PerfQueryBase.h"
|
||||
|
||||
using namespace BPFunctions;
|
||||
|
||||
@@ -62,7 +63,6 @@ void RenderToXFB(const BPCmd &bp, const EFBRectangle &rc, float yScale, float xf
|
||||
{
|
||||
Renderer::RenderToXFB(xfbAddr, dstWidth, dstHeight, rc, gamma);
|
||||
}
|
||||
|
||||
void BPWritten(const BPCmd& bp)
|
||||
{
|
||||
/*
|
||||
@@ -144,7 +144,8 @@ void BPWritten(const BPCmd& bp)
|
||||
|| bp.address == BPMEM_LOADTLUT0
|
||||
|| bp.address == BPMEM_LOADTLUT1
|
||||
|| bp.address == BPMEM_TEXINVALIDATE
|
||||
|| bp.address == BPMEM_PRELOAD_MODE))
|
||||
|| bp.address == BPMEM_PRELOAD_MODE
|
||||
|| bp.address == BPMEM_CLEAR_PIXEL_PERF))
|
||||
{
|
||||
return;
|
||||
}
|
||||
@@ -212,7 +213,7 @@ void BPWritten(const BPCmd& bp)
|
||||
if (bp.changes & 4)
|
||||
SetDitherMode();
|
||||
// Set Blending Mode
|
||||
if (bp.changes & 0xFE1)
|
||||
if (bp.changes & 0xFF1)
|
||||
SetBlendMode();
|
||||
// Set Color Mask
|
||||
if (bp.changes & 0x18)
|
||||
@@ -224,6 +225,8 @@ void BPWritten(const BPCmd& bp)
|
||||
{
|
||||
PRIM_LOG("constalpha: alp=%d, en=%d", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
|
||||
PixelShaderManager::SetDestAlpha(bpmem.dstalpha);
|
||||
if(bp.changes & 0x100)
|
||||
SetBlendMode();
|
||||
break;
|
||||
}
|
||||
// This is called when the game is done drawing the new frame (eg: like in DX: Begin(); Draw(); End();)
|
||||
@@ -455,8 +458,11 @@ void BPWritten(const BPCmd& bp)
|
||||
break;
|
||||
|
||||
case BPMEM_ZCOMPARE: // Set the Z-Compare and EFB pixel format
|
||||
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
|
||||
OnPixelFormatChange();
|
||||
if(bp.changes & 7) {
|
||||
SetBlendMode(); // dual source could be activated by changing to PIXELFMT_RGBA6_Z24
|
||||
g_renderer->SetColorMask(); // alpha writing needs to be disabled if the new pixel format doesn't have an alpha channel
|
||||
}
|
||||
break;
|
||||
|
||||
case BPMEM_MIPMAP_STRIDE: // MipMap Stride Channel
|
||||
@@ -483,9 +489,10 @@ void BPWritten(const BPCmd& bp)
|
||||
case BPMEM_IND_IMASK: // Index Mask ?
|
||||
case BPMEM_REVBITS: // Always set to 0x0F when GX_InitRevBits() is called.
|
||||
break;
|
||||
|
||||
case BPMEM_UNKNOWN_57: // Sunshine alternates this register between values 0x000 and 0xAAA
|
||||
DEBUG_LOG(VIDEO, "Unknown BP Reg 0x57: %08x", bp.newvalue);
|
||||
|
||||
case BPMEM_CLEAR_PIXEL_PERF:
|
||||
// GXClearPixMetric writes 0xAAA here, Sunshine alternates this register between values 0x000 and 0xAAA
|
||||
g_perf_query->ResetQuery();
|
||||
break;
|
||||
|
||||
case BPMEM_PRELOAD_ADDR:
|
||||
@@ -573,8 +580,6 @@ void BPWritten(const BPCmd& bp)
|
||||
// ------------------------
|
||||
case BPMEM_TX_SETMODE0: // (0x90 for linear)
|
||||
case BPMEM_TX_SETMODE0_4:
|
||||
// Shouldn't need to call this here, we call it for each active texture right before rendering
|
||||
SetTextureMode(bp);
|
||||
break;
|
||||
|
||||
case BPMEM_TX_SETMODE1:
|
||||
@@ -716,14 +721,6 @@ void BPReload()
|
||||
SetBlendMode();
|
||||
SetColorMask();
|
||||
OnPixelFormatChange();
|
||||
{
|
||||
BPCmd bp = {BPMEM_TX_SETMODE0, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0])};
|
||||
SetTextureMode(bp);
|
||||
}
|
||||
{
|
||||
BPCmd bp = {BPMEM_TX_SETMODE0_4, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_TX_SETMODE0_4])};
|
||||
SetTextureMode(bp);
|
||||
}
|
||||
{
|
||||
BPCmd bp = {BPMEM_FIELDMASK, 0xFFFFFF, static_cast<int>(((u32*)&bpmem)[BPMEM_FIELDMASK])};
|
||||
SetInterlacingMode(bp);
|
||||
|
||||
@@ -25,18 +25,18 @@ enum
|
||||
{
|
||||
ARRAY_POSITION = 0,
|
||||
ARRAY_NORMAL = 1,
|
||||
ARRAY_COLOR = 2,
|
||||
ARRAY_COLOR2 = 3,
|
||||
ARRAY_TEXCOORD0 = 4,
|
||||
ARRAY_COLOR = 2,
|
||||
ARRAY_COLOR2 = 3,
|
||||
ARRAY_TEXCOORD0 = 4,
|
||||
};
|
||||
|
||||
// Vertex components
|
||||
enum
|
||||
{
|
||||
NOT_PRESENT = 0,
|
||||
DIRECT = 1,
|
||||
INDEX8 = 2,
|
||||
INDEX16 = 3,
|
||||
DIRECT = 1,
|
||||
INDEX8 = 2,
|
||||
INDEX16 = 3,
|
||||
};
|
||||
|
||||
enum
|
||||
@@ -74,14 +74,14 @@ union TVtxDesc
|
||||
// 0: not present
|
||||
// 1: present
|
||||
u32 PosMatIdx : 1;
|
||||
u32 Tex0MatIdx : 1;
|
||||
u32 Tex1MatIdx : 1;
|
||||
u32 Tex2MatIdx : 1;
|
||||
u32 Tex3MatIdx : 1;
|
||||
u32 Tex4MatIdx : 1;
|
||||
u32 Tex5MatIdx : 1;
|
||||
u32 Tex6MatIdx : 1;
|
||||
u32 Tex7MatIdx : 1;
|
||||
u32 Tex0MatIdx : 1;
|
||||
u32 Tex1MatIdx : 1;
|
||||
u32 Tex2MatIdx : 1;
|
||||
u32 Tex3MatIdx : 1;
|
||||
u32 Tex4MatIdx : 1;
|
||||
u32 Tex5MatIdx : 1;
|
||||
u32 Tex6MatIdx : 1;
|
||||
u32 Tex7MatIdx : 1;
|
||||
|
||||
// 00: not present
|
||||
// 01: direct
|
||||
@@ -89,156 +89,156 @@ union TVtxDesc
|
||||
// 11: 16 bit index
|
||||
u32 Position : 2;
|
||||
u32 Normal : 2;
|
||||
u32 Color0 : 2;
|
||||
u32 Color1 : 2;
|
||||
u32 Tex0Coord : 2;
|
||||
u32 Tex1Coord : 2;
|
||||
u32 Tex2Coord : 2;
|
||||
u32 Tex3Coord : 2;
|
||||
u32 Tex4Coord : 2;
|
||||
u32 Tex5Coord : 2;
|
||||
u32 Tex6Coord : 2;
|
||||
u32 Tex7Coord : 2;
|
||||
u32 Color0 : 2;
|
||||
u32 Color1 : 2;
|
||||
u32 Tex0Coord : 2;
|
||||
u32 Tex1Coord : 2;
|
||||
u32 Tex2Coord : 2;
|
||||
u32 Tex3Coord : 2;
|
||||
u32 Tex4Coord : 2;
|
||||
u32 Tex5Coord : 2;
|
||||
u32 Tex6Coord : 2;
|
||||
u32 Tex7Coord : 2;
|
||||
u32 :31;
|
||||
};
|
||||
struct {
|
||||
u32 Hex0, Hex1;
|
||||
};
|
||||
struct {
|
||||
u32 Hex0, Hex1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group0
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
u32 PosElements : 1;
|
||||
u32 PosFormat : 3;
|
||||
u32 PosFrac : 5;
|
||||
// 9:12
|
||||
u32 NormalElements : 1;
|
||||
u32 NormalFormat : 3;
|
||||
// 13:16
|
||||
u32 Color0Elements : 1;
|
||||
u32 Color0Comp : 3;
|
||||
// 17:20
|
||||
u32 Color1Elements : 1;
|
||||
u32 Color1Comp : 3;
|
||||
// 21:29
|
||||
u32 Tex0CoordElements : 1;
|
||||
u32 Tex0CoordFormat : 3;
|
||||
u32 Tex0Frac : 5;
|
||||
// 30:31
|
||||
u32 ByteDequant : 1;
|
||||
u32 NormalIndex3 : 1;
|
||||
};
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
u32 PosElements : 1;
|
||||
u32 PosFormat : 3;
|
||||
u32 PosFrac : 5;
|
||||
// 9:12
|
||||
u32 NormalElements : 1;
|
||||
u32 NormalFormat : 3;
|
||||
// 13:16
|
||||
u32 Color0Elements : 1;
|
||||
u32 Color0Comp : 3;
|
||||
// 17:20
|
||||
u32 Color1Elements : 1;
|
||||
u32 Color1Comp : 3;
|
||||
// 21:29
|
||||
u32 Tex0CoordElements : 1;
|
||||
u32 Tex0CoordFormat : 3;
|
||||
u32 Tex0Frac : 5;
|
||||
// 30:31
|
||||
u32 ByteDequant : 1;
|
||||
u32 NormalIndex3 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group1
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
u32 Tex1CoordElements : 1;
|
||||
u32 Tex1CoordFormat : 3;
|
||||
u32 Tex1Frac : 5;
|
||||
// 9:17
|
||||
u32 Tex2CoordElements : 1;
|
||||
u32 Tex2CoordFormat : 3;
|
||||
u32 Tex2Frac : 5;
|
||||
// 18:26
|
||||
u32 Tex3CoordElements : 1;
|
||||
u32 Tex3CoordFormat : 3;
|
||||
u32 Tex3Frac : 5;
|
||||
// 27:30
|
||||
u32 Tex4CoordElements : 1;
|
||||
u32 Tex4CoordFormat : 3;
|
||||
//
|
||||
u32 : 1;
|
||||
};
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:8
|
||||
u32 Tex1CoordElements : 1;
|
||||
u32 Tex1CoordFormat : 3;
|
||||
u32 Tex1Frac : 5;
|
||||
// 9:17
|
||||
u32 Tex2CoordElements : 1;
|
||||
u32 Tex2CoordFormat : 3;
|
||||
u32 Tex2Frac : 5;
|
||||
// 18:26
|
||||
u32 Tex3CoordElements : 1;
|
||||
u32 Tex3CoordFormat : 3;
|
||||
u32 Tex3Frac : 5;
|
||||
// 27:30
|
||||
u32 Tex4CoordElements : 1;
|
||||
u32 Tex4CoordFormat : 3;
|
||||
//
|
||||
u32 : 1;
|
||||
};
|
||||
};
|
||||
|
||||
union UVAT_group2
|
||||
{
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:4
|
||||
u32 Tex4Frac : 5;
|
||||
// 5:13
|
||||
u32 Tex5CoordElements : 1;
|
||||
u32 Tex5CoordFormat : 3;
|
||||
u32 Tex5Frac : 5;
|
||||
// 14:22
|
||||
u32 Tex6CoordElements : 1;
|
||||
u32 Tex6CoordFormat : 3;
|
||||
u32 Tex6Frac : 5;
|
||||
// 23:31
|
||||
u32 Tex7CoordElements : 1;
|
||||
u32 Tex7CoordFormat : 3;
|
||||
u32 Tex7Frac : 5;
|
||||
};
|
||||
u32 Hex;
|
||||
struct
|
||||
{
|
||||
// 0:4
|
||||
u32 Tex4Frac : 5;
|
||||
// 5:13
|
||||
u32 Tex5CoordElements : 1;
|
||||
u32 Tex5CoordFormat : 3;
|
||||
u32 Tex5Frac : 5;
|
||||
// 14:22
|
||||
u32 Tex6CoordElements : 1;
|
||||
u32 Tex6CoordFormat : 3;
|
||||
u32 Tex6Frac : 5;
|
||||
// 23:31
|
||||
u32 Tex7CoordElements : 1;
|
||||
u32 Tex7CoordFormat : 3;
|
||||
u32 Tex7Frac : 5;
|
||||
};
|
||||
};
|
||||
|
||||
struct ColorAttr
|
||||
{
|
||||
u8 Elements;
|
||||
u8 Comp;
|
||||
u8 Elements;
|
||||
u8 Comp;
|
||||
};
|
||||
|
||||
struct TexAttr
|
||||
{
|
||||
u8 Elements;
|
||||
u8 Format;
|
||||
u8 Frac;
|
||||
u8 Elements;
|
||||
u8 Format;
|
||||
u8 Frac;
|
||||
};
|
||||
|
||||
struct TVtxAttr
|
||||
{
|
||||
u8 PosElements;
|
||||
u8 PosFormat;
|
||||
u8 PosFrac;
|
||||
u8 NormalElements;
|
||||
u8 NormalFormat;
|
||||
ColorAttr color[2];
|
||||
TexAttr texCoord[8];
|
||||
u8 ByteDequant;
|
||||
u8 NormalIndex3;
|
||||
{
|
||||
u8 PosElements;
|
||||
u8 PosFormat;
|
||||
u8 PosFrac;
|
||||
u8 NormalElements;
|
||||
u8 NormalFormat;
|
||||
ColorAttr color[2];
|
||||
TexAttr texCoord[8];
|
||||
u8 ByteDequant;
|
||||
u8 NormalIndex3;
|
||||
};
|
||||
|
||||
// Matrix indices
|
||||
union TMatrixIndexA
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 PosNormalMtxIdx : 6;
|
||||
u32 Tex0MtxIdx : 6;
|
||||
u32 Tex1MtxIdx : 6;
|
||||
u32 Tex2MtxIdx : 6;
|
||||
u32 Tex3MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 30;
|
||||
u32 unused : 2;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 PosNormalMtxIdx : 6;
|
||||
u32 Tex0MtxIdx : 6;
|
||||
u32 Tex1MtxIdx : 6;
|
||||
u32 Tex2MtxIdx : 6;
|
||||
u32 Tex3MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 30;
|
||||
u32 unused : 2;
|
||||
};
|
||||
};
|
||||
|
||||
union TMatrixIndexB
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 Tex4MtxIdx : 6;
|
||||
u32 Tex5MtxIdx : 6;
|
||||
u32 Tex6MtxIdx : 6;
|
||||
u32 Tex7MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 24;
|
||||
u32 unused : 8;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Tex4MtxIdx : 6;
|
||||
u32 Tex5MtxIdx : 6;
|
||||
u32 Tex6MtxIdx : 6;
|
||||
u32 Tex7MtxIdx : 6;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 Hex : 24;
|
||||
u32 unused : 8;
|
||||
};
|
||||
};
|
||||
|
||||
#pragma pack()
|
||||
|
||||
@@ -32,6 +32,8 @@
|
||||
#include "HW/GPFifo.h"
|
||||
#include "HW/Memmap.h"
|
||||
#include "DLCache.h"
|
||||
#include "HW/SystemTimers.h"
|
||||
#include "Core.h"
|
||||
|
||||
namespace CommandProcessor
|
||||
{
|
||||
@@ -57,12 +59,15 @@ static bool bProcessFifoAllDistance = false;
|
||||
|
||||
volatile bool isPossibleWaitingSetDrawDone = false;
|
||||
volatile bool isHiWatermarkActive = false;
|
||||
volatile bool isLoWatermarkActive = false;
|
||||
volatile bool interruptSet= false;
|
||||
volatile bool interruptWaiting= false;
|
||||
volatile bool interruptTokenWaiting = false;
|
||||
volatile bool interruptFinishWaiting = false;
|
||||
volatile bool waitingForPEInterruptDisable = false;
|
||||
|
||||
volatile u32 VITicks = CommandProcessor::m_cpClockOrigin;
|
||||
|
||||
bool IsOnThread()
|
||||
{
|
||||
return SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread;
|
||||
@@ -88,6 +93,7 @@ void DoState(PointerWrap &p)
|
||||
p.Do(bProcessFifoToLoWatermark);
|
||||
p.Do(bProcessFifoAllDistance);
|
||||
p.Do(isHiWatermarkActive);
|
||||
p.Do(isLoWatermarkActive);
|
||||
p.Do(isPossibleWaitingSetDrawDone);
|
||||
p.Do(interruptSet);
|
||||
p.Do(interruptWaiting);
|
||||
@@ -119,7 +125,7 @@ void Init()
|
||||
m_tokenReg = 0;
|
||||
|
||||
memset(&fifo,0,sizeof(fifo));
|
||||
fifo.CPCmdIdle = 1 ;
|
||||
fifo.CPCmdIdle = 1;
|
||||
fifo.CPReadIdle = 1;
|
||||
fifo.bFF_Breakpoint = 0;
|
||||
fifo.bFF_HiWatermark = 0;
|
||||
@@ -136,8 +142,9 @@ void Init()
|
||||
bProcessFifoAllDistance = false;
|
||||
isPossibleWaitingSetDrawDone = false;
|
||||
isHiWatermarkActive = false;
|
||||
isLoWatermarkActive = false;
|
||||
|
||||
et_UpdateInterrupts = CoreTiming::RegisterEvent("UpdateInterrupts", UpdateInterrupts_Wrapper);
|
||||
et_UpdateInterrupts = CoreTiming::RegisterEvent("CPInterrupt", UpdateInterrupts_Wrapper);
|
||||
}
|
||||
|
||||
void Read16(u16& _rReturnValue, const u32 _Address)
|
||||
@@ -294,7 +301,6 @@ void Read16(u16& _rReturnValue, const u32 _Address)
|
||||
|
||||
void Write16(const u16 _Value, const u32 _Address)
|
||||
{
|
||||
|
||||
INFO_LOG(COMMANDPROCESSOR, "(write16): 0x%04x @ 0x%08x",_Value,_Address);
|
||||
|
||||
switch (_Address & 0xFFF)
|
||||
@@ -319,7 +325,7 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||
case CLEAR_REGISTER:
|
||||
{
|
||||
UCPClearReg tmpCtrl(_Value);
|
||||
m_CPClearReg.Hex = tmpCtrl.Hex;
|
||||
m_CPClearReg.Hex = tmpCtrl.Hex;
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"\t write to CLEAR_REGISTER : %04x", _Value);
|
||||
SetCpClearRegister();
|
||||
}
|
||||
@@ -405,9 +411,10 @@ void Write16(const u16 _Value, const u32 _Address)
|
||||
{
|
||||
GPFifo::ResetGatherPipe();
|
||||
ResetVideoBuffer();
|
||||
}else
|
||||
}
|
||||
else
|
||||
{
|
||||
ResetVideoBuffer();
|
||||
ResetVideoBuffer();
|
||||
}
|
||||
IncrementCheckContextId();
|
||||
DEBUG_LOG(COMMANDPROCESSOR,"try to write to FIFO_RW_DISTANCE_HI : %04x", _Value);
|
||||
@@ -455,13 +462,12 @@ void STACKALIGN GatherPipeBursted()
|
||||
ProcessFifoAllDistance();
|
||||
waitingForPEInterruptDisable = false;
|
||||
}
|
||||
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (IsOnThread())
|
||||
SetOverflowStatusFromGatherPipe();
|
||||
SetCpStatus(true);
|
||||
|
||||
// update the fifo-pointer
|
||||
if (fifo.CPWritePointer >= fifo.CPEnd)
|
||||
@@ -485,11 +491,11 @@ void STACKALIGN GatherPipeBursted()
|
||||
|
||||
void UpdateInterrupts(u64 userdata)
|
||||
{
|
||||
if (userdata)
|
||||
if (userdata)
|
||||
{
|
||||
interruptSet = true;
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -497,7 +503,7 @@ void UpdateInterrupts(u64 userdata)
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt cleared");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, false);
|
||||
}
|
||||
interruptWaiting = false;
|
||||
interruptWaiting = false;
|
||||
}
|
||||
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata)
|
||||
@@ -511,73 +517,75 @@ void AbortFrame()
|
||||
|
||||
}
|
||||
|
||||
void SetOverflowStatusFromGatherPipe()
|
||||
void SetCpStatus(bool isCPUThread)
|
||||
{
|
||||
// overflow & underflow check
|
||||
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
|
||||
isHiWatermarkActive = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt && m_CPCtrlReg.GPReadEnable;
|
||||
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
|
||||
|
||||
if (isHiWatermarkActive)
|
||||
// breakpoint
|
||||
if (!isCPUThread)
|
||||
{
|
||||
interruptSet = true;
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, true);
|
||||
}
|
||||
}
|
||||
|
||||
void SetCpStatus()
|
||||
{
|
||||
// overflow & underflow check
|
||||
fifo.bFF_HiWatermark = (fifo.CPReadWriteDistance > fifo.CPHiWatermark);
|
||||
fifo.bFF_LoWatermark = (fifo.CPReadWriteDistance < fifo.CPLoWatermark);
|
||||
|
||||
// breakpoint
|
||||
if (fifo.bFF_BPEnable)
|
||||
{
|
||||
if (fifo.CPBreakpoint == fifo.CPReadPointer)
|
||||
{
|
||||
if (!fifo.bFF_Breakpoint)
|
||||
if (fifo.bFF_BPEnable)
|
||||
{
|
||||
if (fifo.CPBreakpoint == fifo.CPReadPointer)
|
||||
{
|
||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
|
||||
fifo.bFF_Breakpoint = true;
|
||||
IncrementCheckContextId();
|
||||
if (!fifo.bFF_Breakpoint)
|
||||
{
|
||||
INFO_LOG(COMMANDPROCESSOR, "Hit breakpoint at %i", fifo.CPReadPointer);
|
||||
fifo.bFF_Breakpoint = true;
|
||||
IncrementCheckContextId();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fifo.bFF_Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
|
||||
fifo.bFF_Breakpoint = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fifo.bFF_Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
|
||||
fifo.bFF_Breakpoint = false;
|
||||
fifo.bFF_Breakpoint = false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (fifo.bFF_Breakpoint)
|
||||
INFO_LOG(COMMANDPROCESSOR, "Cleared breakpoint at %i", fifo.CPReadPointer);
|
||||
fifo.bFF_Breakpoint = false;
|
||||
}
|
||||
}
|
||||
|
||||
bool bpInt = fifo.bFF_Breakpoint && fifo.bFF_BPInt;
|
||||
bool ovfInt = fifo.bFF_HiWatermark && fifo.bFF_HiWatermarkInt;
|
||||
bool undfInt = fifo.bFF_LoWatermark && fifo.bFF_LoWatermarkInt;
|
||||
|
||||
|
||||
bool interrupt = (bpInt || ovfInt || undfInt) && m_CPCtrlReg.GPReadEnable;
|
||||
|
||||
isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
|
||||
isHiWatermarkActive = ovfInt && m_CPCtrlReg.GPReadEnable;
|
||||
isLoWatermarkActive = undfInt && m_CPCtrlReg.GPReadEnable;
|
||||
|
||||
if (interrupt != interruptSet && !interruptWaiting)
|
||||
{
|
||||
u64 userdata = interrupt?1:0;
|
||||
if (IsOnThread())
|
||||
{
|
||||
if(!interrupt || bpInt || undfInt)
|
||||
if (interrupt != interruptSet && !interruptWaiting)
|
||||
{
|
||||
u64 userdata = interrupt?1:0;
|
||||
if (IsOnThread())
|
||||
{
|
||||
if (!interrupt || bpInt || undfInt || ovfInt)
|
||||
{
|
||||
interruptWaiting = true;
|
||||
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
||||
if (!isCPUThread)
|
||||
{
|
||||
// GPU thread:
|
||||
interruptWaiting = true;
|
||||
CommandProcessor::UpdateInterruptsFromVideoBackend(userdata);
|
||||
}
|
||||
else
|
||||
{
|
||||
// CPU thread:
|
||||
interruptSet = interrupt;
|
||||
INFO_LOG(COMMANDPROCESSOR,"Interrupt set");
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_CP, interrupt);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
CommandProcessor::UpdateInterrupts(userdata);
|
||||
}
|
||||
}
|
||||
else
|
||||
CommandProcessor::UpdateInterrupts(userdata);
|
||||
}
|
||||
}
|
||||
|
||||
void ProcessFifoToLoWatermark()
|
||||
@@ -596,7 +604,7 @@ void ProcessFifoAllDistance()
|
||||
if (IsOnThread())
|
||||
{
|
||||
while (!CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable &&
|
||||
fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
|
||||
fifo.CPReadWriteDistance && !AtBreakpoint())
|
||||
Common::YieldCPU();
|
||||
}
|
||||
bProcessFifoAllDistance = false;
|
||||
@@ -617,15 +625,11 @@ void SetCpStatusRegister()
|
||||
{
|
||||
// Here always there is one fifo attached to the GPU
|
||||
m_CPStatusReg.Breakpoint = fifo.bFF_Breakpoint;
|
||||
m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || (fifo.CPReadPointer == fifo.CPWritePointer) || (fifo.CPReadPointer == fifo.CPBreakpoint) ;
|
||||
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance;
|
||||
m_CPStatusReg.ReadIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || (fifo.CPReadPointer == fifo.CPWritePointer);
|
||||
m_CPStatusReg.CommandIdle = !fifo.CPReadWriteDistance || AtBreakpoint() || !fifo.bFF_GPReadEnable;
|
||||
m_CPStatusReg.UnderflowLoWatermark = fifo.bFF_LoWatermark;
|
||||
m_CPStatusReg.OverflowHiWatermark = fifo.bFF_HiWatermark;
|
||||
|
||||
// HACK to compensate for slow response to PE interrupts in Time Splitters: Future Perfect
|
||||
if (IsOnThread())
|
||||
PixelEngine::ResumeWaitingForPEInterrupt();
|
||||
|
||||
INFO_LOG(COMMANDPROCESSOR,"\t Read from STATUS_REGISTER : %04x", m_CPStatusReg.Hex);
|
||||
DEBUG_LOG(COMMANDPROCESSOR, "(r) status: iBP %s | fReadIdle %s | fCmdIdle %s | iOvF %s | iUndF %s"
|
||||
, m_CPStatusReg.Breakpoint ? "ON" : "OFF"
|
||||
@@ -638,14 +642,11 @@ void SetCpStatusRegister()
|
||||
|
||||
void SetCpControlRegister()
|
||||
{
|
||||
// If the new fifo is being attached We make sure there wont be SetFinish event pending.
|
||||
// This protection fix eternal darkness booting, because the second SetFinish event when it is booting
|
||||
// seems invalid or has a bug and hang the game.
|
||||
|
||||
// If the new fifo is being attached, force an exception check
|
||||
// This fixes the hang while booting Eternal Darkness
|
||||
if (!fifo.bFF_GPReadEnable && m_CPCtrlReg.GPReadEnable && !m_CPCtrlReg.BPEnable)
|
||||
{
|
||||
ProcessFifoEvents();
|
||||
PixelEngine::ResetSetFinish();
|
||||
CoreTiming::ForceExceptionCheck(0);
|
||||
}
|
||||
|
||||
fifo.bFF_BPInt = m_CPCtrlReg.BPInt;
|
||||
@@ -693,4 +694,12 @@ void SetCpClearRegister()
|
||||
// }
|
||||
}
|
||||
|
||||
void Update()
|
||||
{
|
||||
while (VITicks > m_cpClockOrigin && fifo.isGpuReadingData && IsOnThread())
|
||||
Common::YieldCPU();
|
||||
|
||||
if (fifo.isGpuReadingData)
|
||||
Common::AtomicAdd(VITicks, SystemTimers::GetTicksPerSecond() / 10000);
|
||||
}
|
||||
} // end of namespace CommandProcessor
|
||||
|
||||
@@ -31,6 +31,7 @@ namespace CommandProcessor
|
||||
extern SCPFifoStruct fifo; //This one is shared between gfx thread and emulator thread.
|
||||
extern volatile bool isPossibleWaitingSetDrawDone; //This one is used for sync gfx thread and emulator thread.
|
||||
extern volatile bool isHiWatermarkActive;
|
||||
extern volatile bool isLoWatermarkActive;
|
||||
extern volatile bool interruptSet;
|
||||
extern volatile bool interruptWaiting;
|
||||
extern volatile bool interruptTokenWaiting;
|
||||
@@ -140,6 +141,9 @@ union UCPClearReg
|
||||
UCPClearReg(u16 _hex) {Hex = _hex; }
|
||||
};
|
||||
|
||||
// Can be any number, low enough to not be below the number of clocks executed by the GPU per CP_PERIOD
|
||||
const static u32 m_cpClockOrigin = 200000;
|
||||
|
||||
// Init
|
||||
void Init();
|
||||
void Shutdown();
|
||||
@@ -151,7 +155,7 @@ void Write16(const u16 _Data, const u32 _Address);
|
||||
void Read32(u32& _rReturnValue, const u32 _Address);
|
||||
void Write32(const u32 _Data, const u32 _Address);
|
||||
|
||||
void SetCpStatus();
|
||||
void SetCpStatus(bool isCPUThread = false);
|
||||
void GatherPipeBursted();
|
||||
void UpdateInterrupts(u64 userdata);
|
||||
void UpdateInterruptsFromVideoBackend(u64 userdata);
|
||||
@@ -161,11 +165,14 @@ bool AllowIdleSkipping();
|
||||
void SetCpClearRegister();
|
||||
void SetCpControlRegister();
|
||||
void SetCpStatusRegister();
|
||||
void SetOverflowStatusFromGatherPipe();
|
||||
void ProcessFifoToLoWatermark();
|
||||
void ProcessFifoAllDistance();
|
||||
void ProcessFifoEvents();
|
||||
void AbortFrame();
|
||||
|
||||
void Update();
|
||||
extern volatile u32 VITicks;
|
||||
|
||||
} // namespace CommandProcessor
|
||||
|
||||
#endif // _COMMANDPROCESSOR_H
|
||||
|
||||
@@ -20,6 +20,8 @@
|
||||
#ifndef _DATAREADER_H
|
||||
#define _DATAREADER_H
|
||||
|
||||
#include "VertexManagerBase.h"
|
||||
|
||||
extern u8* g_pVideoData;
|
||||
|
||||
#if _M_SSE >= 0x301 && !(defined __GNUC__ && !defined __SSSE3__)
|
||||
@@ -31,43 +33,63 @@ __forceinline void DataSkip(u32 skip)
|
||||
g_pVideoData += skip;
|
||||
}
|
||||
|
||||
// probably unnecessary
|
||||
template <int count>
|
||||
__forceinline void DataSkip()
|
||||
{
|
||||
g_pVideoData += count;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__forceinline T DataPeek(int _uOffset)
|
||||
{
|
||||
auto const result = Common::FromBigEndian(*reinterpret_cast<T*>(g_pVideoData + _uOffset));
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: kill these
|
||||
__forceinline u8 DataPeek8(int _uOffset)
|
||||
{
|
||||
return g_pVideoData[_uOffset];
|
||||
return DataPeek<u8>(_uOffset);
|
||||
}
|
||||
|
||||
__forceinline u16 DataPeek16(int _uOffset)
|
||||
{
|
||||
return Common::swap16(*(u16*)&g_pVideoData[_uOffset]);
|
||||
return DataPeek<u16>(_uOffset);
|
||||
}
|
||||
|
||||
__forceinline u32 DataPeek32(int _uOffset)
|
||||
{
|
||||
return Common::swap32(*(u32*)&g_pVideoData[_uOffset]);
|
||||
return DataPeek<u32>(_uOffset);
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__forceinline T DataRead()
|
||||
{
|
||||
auto const result = DataPeek<T>(0);
|
||||
DataSkip<sizeof(T)>();
|
||||
return result;
|
||||
}
|
||||
|
||||
// TODO: kill these
|
||||
__forceinline u8 DataReadU8()
|
||||
{
|
||||
return *g_pVideoData++;
|
||||
return DataRead<u8>();
|
||||
}
|
||||
|
||||
__forceinline s8 DataReadS8()
|
||||
{
|
||||
return (s8)(*g_pVideoData++);
|
||||
return DataRead<s8>();
|
||||
}
|
||||
|
||||
__forceinline u16 DataReadU16()
|
||||
{
|
||||
u16 tmp = Common::swap16(*(u16*)g_pVideoData);
|
||||
g_pVideoData += 2;
|
||||
return tmp;
|
||||
return DataRead<u16>();
|
||||
}
|
||||
|
||||
__forceinline u32 DataReadU32()
|
||||
{
|
||||
u32 tmp = Common::swap32(*(u32*)g_pVideoData);
|
||||
g_pVideoData += 4;
|
||||
return tmp;
|
||||
return DataRead<u32>();
|
||||
}
|
||||
|
||||
typedef void (*DataReadU32xNfunc)(u32 *buf);
|
||||
@@ -120,58 +142,16 @@ __forceinline u32 DataReadU32Unswapped()
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
__forceinline T DataRead()
|
||||
{
|
||||
T tmp = *(T*)g_pVideoData;
|
||||
g_pVideoData += sizeof(T);
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <>
|
||||
__forceinline u16 DataRead()
|
||||
{
|
||||
u16 tmp = Common::swap16(*(u16*)g_pVideoData);
|
||||
g_pVideoData += 2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <>
|
||||
__forceinline s16 DataRead()
|
||||
{
|
||||
s16 tmp = (s16)Common::swap16(*(u16*)g_pVideoData);
|
||||
g_pVideoData += 2;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <>
|
||||
__forceinline u32 DataRead()
|
||||
{
|
||||
u32 tmp = (u32)Common::swap32(*(u32*)g_pVideoData);
|
||||
g_pVideoData += 4;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
template <>
|
||||
__forceinline s32 DataRead()
|
||||
{
|
||||
s32 tmp = (s32)Common::swap32(*(u32*)g_pVideoData);
|
||||
g_pVideoData += 4;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
__forceinline float DataReadF32()
|
||||
{
|
||||
union {u32 i; float f;} temp;
|
||||
temp.i = Common::swap32(*(u32*)g_pVideoData);
|
||||
g_pVideoData += 4;
|
||||
float tmp = temp.f;
|
||||
return tmp;
|
||||
}
|
||||
|
||||
__forceinline u8* DataGetPosition()
|
||||
{
|
||||
return g_pVideoData;
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
__forceinline void DataWrite(T data)
|
||||
{
|
||||
*(T*)VertexManager::s_pCurBufferPointer = data;
|
||||
VertexManager::s_pCurBufferPointer += sizeof(T);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -80,7 +80,7 @@ void FreeLookInput( UINT iMsg, WPARAM wParam )
|
||||
static bool mouseLookEnabled = false;
|
||||
static bool mouseMoveEnabled = false;
|
||||
static float lastMouse[2];
|
||||
POINT point;
|
||||
POINT point;
|
||||
switch(iMsg)
|
||||
{
|
||||
case WM_USER_KEYDOWN:
|
||||
@@ -133,7 +133,7 @@ void FreeLookInput( UINT iMsg, WPARAM wParam )
|
||||
lastMouse[1] = (float)point.y;
|
||||
mouseLookEnabled= true;
|
||||
break;
|
||||
case WM_MBUTTONDOWN:
|
||||
case WM_MBUTTONDOWN:
|
||||
GetCursorPos(&point);
|
||||
lastMouse[0] = (float)point.x;
|
||||
lastMouse[1] = (float)point.y;
|
||||
@@ -205,10 +205,6 @@ LRESULT CALLBACK WndProc( HWND hWnd, UINT iMsg, WPARAM wParam, LPARAM lParam )
|
||||
OnKeyDown(lParam);
|
||||
FreeLookInput((u32)wParam, lParam);
|
||||
}
|
||||
else if (wParam == WIIMOTE_DISCONNECT)
|
||||
{
|
||||
PostMessage(m_hParent, WM_USER, wParam, lParam);
|
||||
}
|
||||
break;
|
||||
|
||||
// Called when a screensaver wants to show up while this window is active
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
#include "Fifo.h"
|
||||
#include "HW/Memmap.h"
|
||||
#include "Core.h"
|
||||
#include "CoreTiming.h"
|
||||
|
||||
volatile bool g_bSkipCurrentFrame = false;
|
||||
extern u8* g_pVideoData;
|
||||
@@ -42,10 +43,10 @@ static int size = 0;
|
||||
|
||||
void Fifo_DoState(PointerWrap &p)
|
||||
{
|
||||
p.DoArray(videoBuffer, FIFO_SIZE);
|
||||
p.Do(size);
|
||||
p.DoPointer(g_pVideoData, videoBuffer);
|
||||
p.Do(g_bSkipCurrentFrame);
|
||||
p.DoArray(videoBuffer, FIFO_SIZE);
|
||||
p.Do(size);
|
||||
p.DoPointer(g_pVideoData, videoBuffer);
|
||||
p.Do(g_bSkipCurrentFrame);
|
||||
}
|
||||
|
||||
void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock)
|
||||
@@ -68,21 +69,22 @@ void Fifo_PauseAndLock(bool doLock, bool unpauseOnUnlock)
|
||||
|
||||
|
||||
void Fifo_Init()
|
||||
{
|
||||
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
|
||||
{
|
||||
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
|
||||
size = 0;
|
||||
GpuRunningState = false;
|
||||
Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
|
||||
}
|
||||
|
||||
void Fifo_Shutdown()
|
||||
{
|
||||
if (GpuRunningState) PanicAlert("Fifo shutting down while active");
|
||||
FreeMemoryPages(videoBuffer, FIFO_SIZE);
|
||||
FreeMemoryPages(videoBuffer, FIFO_SIZE);
|
||||
}
|
||||
|
||||
u8* GetVideoBufferStartPtr()
|
||||
{
|
||||
return videoBuffer;
|
||||
return videoBuffer;
|
||||
}
|
||||
|
||||
u8* GetVideoBufferEndPtr()
|
||||
@@ -117,20 +119,20 @@ void EmulatorState(bool running)
|
||||
// Description: RunGpuLoop() sends data through this function.
|
||||
void ReadDataFromFifo(u8* _uData, u32 len)
|
||||
{
|
||||
if (size + len >= FIFO_SIZE)
|
||||
{
|
||||
if (size + len >= FIFO_SIZE)
|
||||
{
|
||||
int pos = (int)(g_pVideoData - videoBuffer);
|
||||
size -= pos;
|
||||
if (size + len > FIFO_SIZE)
|
||||
{
|
||||
PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
|
||||
}
|
||||
memmove(&videoBuffer[0], &videoBuffer[pos], size);
|
||||
if (size + len > FIFO_SIZE)
|
||||
{
|
||||
PanicAlert("FIFO out of bounds (sz = %i, len = %i at %08x)", size, len, pos);
|
||||
}
|
||||
memmove(&videoBuffer[0], &videoBuffer[pos], size);
|
||||
g_pVideoData = videoBuffer;
|
||||
}
|
||||
}
|
||||
// Copy new video instructions to videoBuffer for future use in rendering the new picture
|
||||
memcpy(videoBuffer + size, _uData, len);
|
||||
size += len;
|
||||
memcpy(videoBuffer + size, _uData, len);
|
||||
size += len;
|
||||
}
|
||||
|
||||
void ResetVideoBuffer()
|
||||
@@ -147,39 +149,50 @@ void RunGpuLoop()
|
||||
std::lock_guard<std::mutex> lk(m_csHWVidOccupied);
|
||||
GpuRunningState = true;
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
u32 cyclesExecuted = 0;
|
||||
|
||||
while (GpuRunningState)
|
||||
{
|
||||
g_video_backend->PeekMessages();
|
||||
|
||||
VideoFifo_CheckAsyncRequest();
|
||||
|
||||
|
||||
CommandProcessor::SetCpStatus();
|
||||
|
||||
Common::AtomicStore(CommandProcessor::VITicks, CommandProcessor::m_cpClockOrigin);
|
||||
|
||||
// check if we are able to run this buffer
|
||||
while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && !PixelEngine::WaitingForPEInterrupt())
|
||||
while (GpuRunningState && !CommandProcessor::interruptWaiting && fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint())
|
||||
{
|
||||
if (!GpuRunningState) break;
|
||||
|
||||
fifo.isGpuReadingData = true;
|
||||
CommandProcessor::isPossibleWaitingSetDrawDone = fifo.bFF_GPLinkEnable ? true : false;
|
||||
|
||||
u32 readPtr = fifo.CPReadPointer;
|
||||
u8 *uData = Memory::GetPointer(readPtr);
|
||||
|
||||
if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
|
||||
if (Common::AtomicLoad(CommandProcessor::VITicks) > CommandProcessor::m_cpClockOrigin || !Core::g_CoreStartupParameter.bSyncGPU)
|
||||
{
|
||||
u32 readPtr = fifo.CPReadPointer;
|
||||
u8 *uData = Memory::GetPointer(readPtr);
|
||||
|
||||
if (readPtr == fifo.CPEnd) readPtr = fifo.CPBase;
|
||||
else readPtr += 32;
|
||||
|
||||
_assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
|
||||
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce inestabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
|
||||
|
||||
ReadDataFromFifo(uData, 32);
|
||||
|
||||
OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||
|
||||
Common::AtomicStore(fifo.CPReadPointer, readPtr);
|
||||
Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
|
||||
if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
|
||||
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
|
||||
_assert_msg_(COMMANDPROCESSOR, (s32)fifo.CPReadWriteDistance - 32 >= 0 ,
|
||||
"Negative fifo.CPReadWriteDistance = %i in FIFO Loop !\nThat can produce instabilty in the game. Please report it.", fifo.CPReadWriteDistance - 32);
|
||||
|
||||
ReadDataFromFifo(uData, 32);
|
||||
|
||||
cyclesExecuted = OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||
|
||||
if (Common::AtomicLoad(CommandProcessor::VITicks) > cyclesExecuted && Core::g_CoreStartupParameter.bSyncGPU)
|
||||
Common::AtomicAdd(CommandProcessor::VITicks, -(s32)cyclesExecuted);
|
||||
|
||||
Common::AtomicStore(fifo.CPReadPointer, readPtr);
|
||||
Common::AtomicAdd(fifo.CPReadWriteDistance, -32);
|
||||
if((GetVideoBufferEndPtr() - g_pVideoData) == 0)
|
||||
Common::AtomicStore(fifo.SafeCPReadPointer, fifo.CPReadPointer);
|
||||
}
|
||||
|
||||
CommandProcessor::SetCpStatus();
|
||||
|
||||
// This call is pretty important in DualCore mode and must be called in the FIFO Loop.
|
||||
@@ -188,12 +201,18 @@ void RunGpuLoop()
|
||||
VideoFifo_CheckAsyncRequest();
|
||||
CommandProcessor::isPossibleWaitingSetDrawDone = false;
|
||||
}
|
||||
|
||||
|
||||
fifo.isGpuReadingData = false;
|
||||
|
||||
|
||||
if (EmuRunningState)
|
||||
{
|
||||
// NOTE(jsd): Calling SwitchToThread() on Windows 7 x64 is a hot spot, according to profiler.
|
||||
// See https://docs.google.com/spreadsheet/ccc?key=0Ah4nh0yGtjrgdFpDeF9pS3V6RUotRVE3S3J4TGM1NlE#gid=0
|
||||
// for benchmark details.
|
||||
#if 0
|
||||
Common::YieldCPU();
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
// While the emu is paused, we still handle async requests then sleep.
|
||||
@@ -217,23 +236,23 @@ bool AtBreakpoint()
|
||||
|
||||
void RunGpu()
|
||||
{
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
|
||||
{
|
||||
u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
|
||||
|
||||
SaveSSEState();
|
||||
LoadDefaultSSEState();
|
||||
ReadDataFromFifo(uData, 32);
|
||||
OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||
LoadSSEState();
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() )
|
||||
{
|
||||
u8 *uData = Memory::GetPointer(fifo.CPReadPointer);
|
||||
|
||||
//DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
|
||||
FPURoundMode::SaveSIMDState();
|
||||
FPURoundMode::LoadDefaultSIMDState();
|
||||
ReadDataFromFifo(uData, 32);
|
||||
OpcodeDecoder_Run(g_bSkipCurrentFrame);
|
||||
FPURoundMode::LoadSIMDState();
|
||||
|
||||
if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
|
||||
else fifo.CPReadPointer += 32;
|
||||
//DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base");
|
||||
|
||||
fifo.CPReadWriteDistance -= 32;
|
||||
}
|
||||
CommandProcessor::SetCpStatus();
|
||||
if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase;
|
||||
else fifo.CPReadPointer += 32;
|
||||
|
||||
fifo.CPReadWriteDistance -= 32;
|
||||
}
|
||||
CommandProcessor::SetCpStatus();
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
#define FIFO_SIZE (1024*1024)
|
||||
#define FIFO_SIZE (2*1024*1024)
|
||||
|
||||
extern volatile bool g_bSkipCurrentFrame;
|
||||
|
||||
|
||||
@@ -60,12 +60,12 @@ const XFBSourceBase* const* FramebufferManagerBase::GetRealXFBSource(u32 xfbAddr
|
||||
m_realXFBSource->texHeight = fbHeight;
|
||||
|
||||
// TODO: stuff only used by OGL... :/
|
||||
// OpenGL texture coordinates originate at the lower left, which is why
|
||||
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
||||
m_realXFBSource->sourceRc.left = 0;
|
||||
m_realXFBSource->sourceRc.top = fbHeight;
|
||||
m_realXFBSource->sourceRc.right = fbWidth;
|
||||
m_realXFBSource->sourceRc.bottom = 0;
|
||||
// OpenGL texture coordinates originate at the lower left, which is why
|
||||
// sourceRc.top = fbHeight and sourceRc.bottom = 0.
|
||||
m_realXFBSource->sourceRc.left = 0;
|
||||
m_realXFBSource->sourceRc.top = fbHeight;
|
||||
m_realXFBSource->sourceRc.right = fbWidth;
|
||||
m_realXFBSource->sourceRc.bottom = 0;
|
||||
|
||||
// Decode YUYV data from GameCube RAM
|
||||
m_realXFBSource->DecodeToTexture(xfbAddr, fbWidth, fbHeight);
|
||||
@@ -163,13 +163,9 @@ void FramebufferManagerBase::CopyToVirtualXFB(u32 xfbAddr, u32 fbWidth, u32 fbHe
|
||||
|
||||
// keep stale XFB data from being used
|
||||
ReplaceVirtualXFB();
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
// Copy EFB data to XFB and restore render target again
|
||||
vxfb->xfbSource->CopyEFB(Gamma);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
FramebufferManagerBase::VirtualXFBListType::iterator FramebufferManagerBase::FindVirtualXFB(u32 xfbAddr, u32 width, u32 height)
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright (C) 2003-2009 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
// TODO: Handle cache-is-full condition :p
|
||||
|
||||
|
||||
#include "Common.h"
|
||||
#include "DLCache.h"
|
||||
|
||||
namespace DLCache
|
||||
{
|
||||
|
||||
void Init()
|
||||
{
|
||||
}
|
||||
|
||||
void Shutdown()
|
||||
{
|
||||
}
|
||||
|
||||
void Clear()
|
||||
{
|
||||
}
|
||||
|
||||
void ProgressiveCleanup()
|
||||
{
|
||||
}
|
||||
} // namespace
|
||||
|
||||
// NOTE - outside the namespace on purpose.
|
||||
bool HandleDisplayList(u32 address, u32 size)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
void IncrementCheckContextId()
|
||||
{
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -25,22 +25,22 @@
|
||||
|
||||
struct TGA_HEADER
|
||||
{
|
||||
u8 identsize; // size of ID field that follows 18 u8 header (0 usually)
|
||||
u8 colourmaptype; // type of colour map 0=none, 1=has palette
|
||||
u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
|
||||
u8 identsize; // size of ID field that follows 18 u8 header (0 usually)
|
||||
u8 colourmaptype; // type of colour map 0=none, 1=has palette
|
||||
u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
|
||||
|
||||
s16 colourmapstart; // first colour map entry in palette
|
||||
s16 colourmaplength; // number of colours in palette
|
||||
u8 colourmapbits; // number of bits per palette entry 15,16,24,32
|
||||
s16 colourmapstart; // first colour map entry in palette
|
||||
s16 colourmaplength; // number of colours in palette
|
||||
u8 colourmapbits; // number of bits per palette entry 15,16,24,32
|
||||
|
||||
s16 xstart; // image x origin
|
||||
s16 ystart; // image y origin
|
||||
s16 width; // image width in pixels
|
||||
s16 height; // image height in pixels
|
||||
u8 bits; // image bits per pixel 8,16,24,32
|
||||
u8 descriptor; // image descriptor bits (vh flip bits)
|
||||
|
||||
// pixel data follows header
|
||||
s16 xstart; // image x origin
|
||||
s16 ystart; // image y origin
|
||||
s16 width; // image width in pixels
|
||||
s16 height; // image height in pixels
|
||||
u8 bits; // image bits per pixel 8,16,24,32
|
||||
u8 descriptor; // image descriptor bits (vh flip bits)
|
||||
|
||||
// pixel data follows header
|
||||
};
|
||||
|
||||
#pragma pack(pop)
|
||||
@@ -53,7 +53,7 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata)
|
||||
return false;
|
||||
|
||||
_assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18);
|
||||
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
hdr.imagetype = 2;
|
||||
hdr.bits = 32;
|
||||
@@ -69,7 +69,8 @@ bool SaveTGA(const char* filename, int width, int height, void* pdata)
|
||||
|
||||
bool SaveData(const char* filename, const char* data)
|
||||
{
|
||||
std::ofstream f(filename, std::ios::binary);
|
||||
std::ofstream f;
|
||||
OpenFStream(f, filename, std::ios::binary);
|
||||
f << data;
|
||||
|
||||
return true;
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "Common.h"
|
||||
#include "IndexGenerator.h"
|
||||
|
||||
/*
|
||||
@@ -27,24 +30,18 @@ QUAD simulator
|
||||
*/
|
||||
|
||||
//Init
|
||||
u16 *IndexGenerator::Tptr = 0;
|
||||
u16 *IndexGenerator::BASETptr = 0;
|
||||
u16 *IndexGenerator::Lptr = 0;
|
||||
u16 *IndexGenerator::BASELptr = 0;
|
||||
u16 *IndexGenerator::Pptr = 0;
|
||||
u16 *IndexGenerator::BASEPptr = 0;
|
||||
int IndexGenerator::numT = 0;
|
||||
int IndexGenerator::numL = 0;
|
||||
int IndexGenerator::numP = 0;
|
||||
int IndexGenerator::index = 0;
|
||||
int IndexGenerator::Tadds = 0;
|
||||
int IndexGenerator::Ladds = 0;
|
||||
int IndexGenerator::Padds = 0;
|
||||
IndexGenerator::IndexPrimitiveType IndexGenerator::LastTPrimitive = Prim_None;
|
||||
IndexGenerator::IndexPrimitiveType IndexGenerator::LastLPrimitive = Prim_None;
|
||||
bool IndexGenerator::used = false;
|
||||
u16 *IndexGenerator::Tptr;
|
||||
u16 *IndexGenerator::BASETptr;
|
||||
u16 *IndexGenerator::Lptr;
|
||||
u16 *IndexGenerator::BASELptr;
|
||||
u16 *IndexGenerator::Pptr;
|
||||
u16 *IndexGenerator::BASEPptr;
|
||||
u32 IndexGenerator::numT;
|
||||
u32 IndexGenerator::numL;
|
||||
u32 IndexGenerator::numP;
|
||||
u32 IndexGenerator::index;
|
||||
|
||||
void IndexGenerator::Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr)
|
||||
void IndexGenerator::Start(u16* Triangleptr, u16* Lineptr, u16* Pointptr)
|
||||
{
|
||||
Tptr = Triangleptr;
|
||||
Lptr = Lineptr;
|
||||
@@ -56,288 +53,123 @@ void IndexGenerator::Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr)
|
||||
numT = 0;
|
||||
numL = 0;
|
||||
numP = 0;
|
||||
Tadds = 0;
|
||||
Ladds = 0;
|
||||
Padds = 0;
|
||||
LastTPrimitive = Prim_None;
|
||||
LastLPrimitive = Prim_None;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddIndices(int primitive, u32 numVerts)
|
||||
{
|
||||
//switch (primitive)
|
||||
//{
|
||||
//case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVerts); break;
|
||||
//case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVerts); break;
|
||||
//case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVerts); break;
|
||||
//case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVerts); break;
|
||||
//case GX_DRAW_LINES: IndexGenerator::AddLineList(numVerts); break;
|
||||
//case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVerts); break;
|
||||
//case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVerts); break;
|
||||
//}
|
||||
|
||||
static void (*const primitive_table[])(u32) =
|
||||
{
|
||||
IndexGenerator::AddQuads,
|
||||
NULL,
|
||||
IndexGenerator::AddList,
|
||||
IndexGenerator::AddStrip,
|
||||
IndexGenerator::AddFan,
|
||||
IndexGenerator::AddLineList,
|
||||
IndexGenerator::AddLineStrip,
|
||||
IndexGenerator::AddPoints,
|
||||
};
|
||||
|
||||
primitive_table[primitive](numVerts);
|
||||
index += numVerts;
|
||||
}
|
||||
|
||||
// Triangles
|
||||
void IndexGenerator::AddList(int numVerts)
|
||||
__forceinline void IndexGenerator::WriteTriangle(u32 index1, u32 index2, u32 index3)
|
||||
{
|
||||
//if we have no vertices return
|
||||
if(numVerts <= 0) return;
|
||||
int numTris = numVerts / 3;
|
||||
if (!numTris)
|
||||
{
|
||||
//if we have less than 3 verts
|
||||
if(numVerts == 1)
|
||||
{
|
||||
// discard
|
||||
index++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we have two verts render a degenerated triangle
|
||||
numTris = 1;
|
||||
*Tptr++ = index;
|
||||
*Tptr++ = index+1;
|
||||
*Tptr++ = index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numTris; i++)
|
||||
{
|
||||
*Tptr++ = index+i*3;
|
||||
*Tptr++ = index+i*3+1;
|
||||
*Tptr++ = index+i*3+2;
|
||||
}
|
||||
int baseRemainingverts = numVerts - numVerts % 3;
|
||||
switch (numVerts % 3)
|
||||
{
|
||||
case 2:
|
||||
//whe have 2 remaining verts use strip method
|
||||
*Tptr++ = index + baseRemainingverts - 1;
|
||||
*Tptr++ = index + baseRemainingverts;
|
||||
*Tptr++ = index + baseRemainingverts + 1;
|
||||
numTris++;
|
||||
break;
|
||||
case 1:
|
||||
//whe have 1 remaining verts use strip method this is only a conjeture
|
||||
*Tptr++ = index + baseRemainingverts - 2;
|
||||
*Tptr++ = index + baseRemainingverts - 1;
|
||||
*Tptr++ = index + baseRemainingverts;
|
||||
numTris++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
index += numVerts;
|
||||
numT += numTris;
|
||||
Tadds++;
|
||||
LastTPrimitive = Prim_List;
|
||||
*Tptr++ = index1;
|
||||
*Tptr++ = index2;
|
||||
*Tptr++ = index3;
|
||||
|
||||
++numT;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddStrip(int numVerts)
|
||||
void IndexGenerator::AddList(u32 const numVerts)
|
||||
{
|
||||
if(numVerts <= 0) return;
|
||||
int numTris = numVerts - 2;
|
||||
if (numTris < 1)
|
||||
auto const numTris = numVerts / 3;
|
||||
for (u32 i = 0; i != numTris; ++i)
|
||||
{
|
||||
//if we have less than 3 verts
|
||||
if(numVerts == 1)
|
||||
{
|
||||
// discard
|
||||
index++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we have two verts render a degenerated triangle
|
||||
numTris = 1;
|
||||
*Tptr++ = index;
|
||||
*Tptr++ = index+1;
|
||||
*Tptr++ = index;
|
||||
}
|
||||
WriteTriangle(index + i * 3, index + i * 3 + 1, index + i * 3 + 2);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool wind = false;
|
||||
for (int i = 0; i < numTris; i++)
|
||||
{
|
||||
*Tptr++ = index+i;
|
||||
*Tptr++ = index+i+(wind?2:1);
|
||||
*Tptr++ = index+i+(wind?1:2);
|
||||
wind = !wind;
|
||||
}
|
||||
}
|
||||
index += numVerts;
|
||||
numT += numTris;
|
||||
Tadds++;
|
||||
LastTPrimitive = Prim_Strip;
|
||||
}
|
||||
void IndexGenerator::AddFan(int numVerts)
|
||||
{
|
||||
if(numVerts <= 0) return;
|
||||
int numTris = numVerts - 2;
|
||||
if (numTris < 1)
|
||||
{
|
||||
//if we have less than 3 verts
|
||||
if(numVerts == 1)
|
||||
{
|
||||
//Discard
|
||||
index++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we have two verts render a degenerated triangle
|
||||
numTris = 1;
|
||||
*Tptr++ = index;
|
||||
*Tptr++ = index+1;
|
||||
*Tptr++ = index;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numTris; i++)
|
||||
{
|
||||
*Tptr++ = index;
|
||||
*Tptr++ = index+i+1;
|
||||
*Tptr++ = index+i+2;
|
||||
}
|
||||
}
|
||||
index += numVerts;
|
||||
numT += numTris;
|
||||
Tadds++;
|
||||
LastTPrimitive = Prim_Fan;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddQuads(int numVerts)
|
||||
void IndexGenerator::AddStrip(u32 const numVerts)
|
||||
{
|
||||
if(numVerts <= 0) return;
|
||||
int numTris = (numVerts/4)*2;
|
||||
if (numTris == 0)
|
||||
bool wind = false;
|
||||
for (u32 i = 2; i < numVerts; ++i)
|
||||
{
|
||||
//if we have less than 3 verts
|
||||
if(numVerts == 1)
|
||||
{
|
||||
//discard
|
||||
index++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
if(numVerts == 2)
|
||||
{
|
||||
//we have two verts render a degenerated triangle
|
||||
numTris = 1;
|
||||
*Tptr++ = index;
|
||||
*Tptr++ = index + 1;
|
||||
*Tptr++ = index;
|
||||
}
|
||||
else
|
||||
{
|
||||
//we have 3 verts render a full triangle
|
||||
numTris = 1;
|
||||
*Tptr++ = index;
|
||||
*Tptr++ = index + 1;
|
||||
*Tptr++ = index + 2;
|
||||
}
|
||||
}
|
||||
WriteTriangle(
|
||||
index + i - 2,
|
||||
index + i - !wind,
|
||||
index + i - wind);
|
||||
|
||||
wind ^= true;
|
||||
}
|
||||
else
|
||||
}
|
||||
|
||||
void IndexGenerator::AddFan(u32 numVerts)
|
||||
{
|
||||
for (u32 i = 2; i < numVerts; ++i)
|
||||
{
|
||||
for (int i = 0; i < numTris / 2; i++)
|
||||
{
|
||||
*Tptr++ = index+i*4;
|
||||
*Tptr++ = index+i*4+1;
|
||||
*Tptr++ = index+i*4+2;
|
||||
*Tptr++ = index+i*4;
|
||||
*Tptr++ = index+i*4+2;
|
||||
*Tptr++ = index+i*4+3;
|
||||
}
|
||||
int baseRemainingverts = numVerts - numVerts % 4;
|
||||
switch (numVerts % 4)
|
||||
{
|
||||
case 3:
|
||||
//whe have 3 remaining verts use strip method
|
||||
*Tptr++ = index + baseRemainingverts;
|
||||
*Tptr++ = index + baseRemainingverts + 1;
|
||||
*Tptr++ = index + baseRemainingverts + 2;
|
||||
numTris++;
|
||||
break;
|
||||
case 2:
|
||||
//whe have 2 remaining verts use strip method
|
||||
*Tptr++ = index + baseRemainingverts - 1;
|
||||
*Tptr++ = index + baseRemainingverts;
|
||||
*Tptr++ = index + baseRemainingverts + 1;
|
||||
numTris++;
|
||||
break;
|
||||
case 1:
|
||||
//whe have 1 remaining verts use strip method this is only a conjeture
|
||||
*Tptr++ = index + baseRemainingverts - 2;
|
||||
*Tptr++ = index + baseRemainingverts - 1;
|
||||
*Tptr++ = index + baseRemainingverts;
|
||||
numTris++;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
WriteTriangle(index, index + i - 1, index + i);
|
||||
}
|
||||
}
|
||||
|
||||
void IndexGenerator::AddQuads(u32 numVerts)
|
||||
{
|
||||
auto const numQuads = numVerts / 4;
|
||||
for (u32 i = 0; i != numQuads; ++i)
|
||||
{
|
||||
WriteTriangle(index + i * 4, index + i * 4 + 1, index + i * 4 + 2);
|
||||
WriteTriangle(index + i * 4, index + i * 4 + 2, index + i * 4 + 3);
|
||||
}
|
||||
}
|
||||
|
||||
// Lines
|
||||
void IndexGenerator::AddLineList(u32 numVerts)
|
||||
{
|
||||
auto const numLines = numVerts / 2;
|
||||
for (u32 i = 0; i != numLines; ++i)
|
||||
{
|
||||
*Lptr++ = index + i * 2;
|
||||
*Lptr++ = index + i * 2 + 1;
|
||||
++numL;
|
||||
}
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineStrip(u32 numVerts)
|
||||
{
|
||||
for (u32 i = 1; i < numVerts; ++i)
|
||||
{
|
||||
*Lptr++ = index + i - 1;
|
||||
*Lptr++ = index + i;
|
||||
++numL;
|
||||
}
|
||||
}
|
||||
|
||||
// Points
|
||||
void IndexGenerator::AddPoints(u32 numVerts)
|
||||
{
|
||||
for (u32 i = 0; i != numVerts; ++i)
|
||||
{
|
||||
*Pptr++ = index + i;
|
||||
++numP;
|
||||
}
|
||||
index += numVerts;
|
||||
numT += numTris;
|
||||
Tadds++;
|
||||
LastTPrimitive = Prim_List;
|
||||
}
|
||||
|
||||
|
||||
//Lines
|
||||
void IndexGenerator::AddLineList(int numVerts)
|
||||
u32 IndexGenerator::GetRemainingIndices()
|
||||
{
|
||||
if(numVerts <= 0) return;
|
||||
int numLines = numVerts / 2;
|
||||
if (!numLines)
|
||||
{
|
||||
//Discard
|
||||
index++;
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
for (int i = 0; i < numLines; i++)
|
||||
{
|
||||
*Lptr++ = index+i*2;
|
||||
*Lptr++ = index+i*2+1;
|
||||
}
|
||||
if((numVerts & 1) != 0)
|
||||
{
|
||||
//use line strip for remaining vert
|
||||
*Lptr++ = index + numLines * 2 - 1;
|
||||
*Lptr++ = index + numLines * 2;
|
||||
}
|
||||
}
|
||||
index += numVerts;
|
||||
numL += numLines;
|
||||
Ladds++;
|
||||
LastLPrimitive = Prim_List;
|
||||
}
|
||||
|
||||
void IndexGenerator::AddLineStrip(int numVerts)
|
||||
{
|
||||
int numLines = numVerts - 1;
|
||||
if (numLines <= 0)
|
||||
{
|
||||
if(numVerts == 1)
|
||||
{
|
||||
index++;
|
||||
}
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < numLines; i++)
|
||||
{
|
||||
*Lptr++ = index+i;
|
||||
*Lptr++ = index+i+1;
|
||||
}
|
||||
index += numVerts;
|
||||
numL += numLines;
|
||||
Ladds++;
|
||||
LastLPrimitive = Prim_Strip;
|
||||
}
|
||||
|
||||
|
||||
|
||||
//Points
|
||||
void IndexGenerator::AddPoints(int numVerts)
|
||||
{
|
||||
for (int i = 0; i < numVerts; i++)
|
||||
{
|
||||
*Pptr++ = index+i;
|
||||
}
|
||||
index += numVerts;
|
||||
numP += numVerts;
|
||||
Padds++;
|
||||
u32 max_index = 65535;
|
||||
return max_index - index;
|
||||
}
|
||||
|
||||
@@ -25,53 +25,60 @@
|
||||
class IndexGenerator
|
||||
{
|
||||
public:
|
||||
//Init
|
||||
// Init
|
||||
static void Start(u16 *Triangleptr,u16 *Lineptr,u16 *Pointptr);
|
||||
//Triangles
|
||||
static void AddList(int numVerts);
|
||||
static void AddStrip(int numVerts);
|
||||
static void AddFan(int numVerts);
|
||||
static void AddQuads(int numVerts);
|
||||
//Lines
|
||||
static void AddLineList(int numVerts);
|
||||
static void AddLineStrip(int numVerts);
|
||||
//Points
|
||||
static void AddPoints(int numVerts);
|
||||
//Interface
|
||||
static int GetNumTriangles() {used = true; return numT;}
|
||||
static int GetNumLines() {used = true;return numL;}
|
||||
static int GetNumPoints() {used = true;return numP;}
|
||||
static int GetNumVerts() {return index;} //returns numprimitives
|
||||
static int GetNumAdds() {return Tadds + Ladds + Padds;}
|
||||
static int GetTriangleindexLen() {return (int)(Tptr - BASETptr);}
|
||||
static int GetLineindexLen() {return (int)(Lptr - BASELptr);}
|
||||
static int GetPointindexLen() {return (int)(Pptr - BASEPptr);}
|
||||
|
||||
static void AddIndices(int primitive, u32 numVertices);
|
||||
|
||||
// Interface
|
||||
static u32 GetNumTriangles() {return numT;}
|
||||
static u32 GetNumLines() {return numL;}
|
||||
static u32 GetNumPoints() {return numP;}
|
||||
|
||||
// returns numprimitives
|
||||
static u32 GetNumVerts() {return index;}
|
||||
|
||||
static u32 GetTriangleindexLen() {return (u32)(Tptr - BASETptr);}
|
||||
static u32 GetLineindexLen() {return (u32)(Lptr - BASELptr);}
|
||||
static u32 GetPointindexLen() {return (u32)(Pptr - BASEPptr);}
|
||||
|
||||
static u32 GetRemainingIndices();
|
||||
/*
|
||||
enum IndexPrimitiveType
|
||||
{
|
||||
Prim_None = 0,
|
||||
Prim_List,
|
||||
Prim_Strip,
|
||||
Prim_Fan
|
||||
} ;
|
||||
};
|
||||
*/
|
||||
private:
|
||||
// Triangles
|
||||
static void AddList(u32 numVerts);
|
||||
static void AddStrip(u32 numVerts);
|
||||
static void AddFan(u32 numVerts);
|
||||
static void AddQuads(u32 numVerts);
|
||||
|
||||
// Lines
|
||||
static void AddLineList(u32 numVerts);
|
||||
static void AddLineStrip(u32 numVerts);
|
||||
|
||||
// Points
|
||||
static void AddPoints(u32 numVerts);
|
||||
|
||||
static void WriteTriangle(u32 index1, u32 index2, u32 index3);
|
||||
|
||||
static u16 *Tptr;
|
||||
static u16 *BASETptr;
|
||||
static u16 *Lptr;
|
||||
static u16 *BASELptr;
|
||||
static u16 *Pptr;
|
||||
static u16 *BASEPptr;
|
||||
static int numT;
|
||||
static int numL;
|
||||
static int numP;
|
||||
static int index;
|
||||
static int Tadds;
|
||||
static int Ladds;
|
||||
static int Padds;
|
||||
static IndexPrimitiveType LastTPrimitive;
|
||||
static IndexPrimitiveType LastLPrimitive;
|
||||
static bool used;
|
||||
|
||||
// TODO: redundant variables
|
||||
static u32 numT;
|
||||
static u32 numL;
|
||||
static u32 numP;
|
||||
static u32 index;
|
||||
};
|
||||
|
||||
#endif // _INDEXGENERATOR_H
|
||||
|
||||
@@ -38,12 +38,12 @@ void GenerateLightShader(T& object, int index, int litchan_index, const char* li
|
||||
// atten disabled
|
||||
switch (chan.diffusefunc) {
|
||||
case LIGHTDIF_NONE:
|
||||
object.Write("lacc.%s += %s.lights[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
|
||||
object.Write("lacc.%s += %s[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
case LIGHTDIF_CLAMP:
|
||||
object.Write("ldir = normalize(%s.lights[%d].pos.xyz - pos.xyz);\n", lightsName, index);
|
||||
object.Write("lacc.%s += %sdot(ldir, _norm0)) * %s.lights[%d].col.%s;\n",
|
||||
object.Write("ldir = normalize(%s[%d].pos.xyz - pos.xyz);\n", lightsName, index);
|
||||
object.Write("lacc.%s += %sdot(ldir, _norm0)) * %s[%d].col.%s;\n",
|
||||
swizzle, chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(", lightsName, index, swizzle);
|
||||
break;
|
||||
default: _assert_(0);
|
||||
@@ -53,28 +53,28 @@ void GenerateLightShader(T& object, int index, int litchan_index, const char* li
|
||||
|
||||
if (chan.attnfunc == 3)
|
||||
{ // spot
|
||||
object.Write("ldir = %s.lights[%d].pos.xyz - pos.xyz;\n", lightsName, index);
|
||||
object.Write("ldir = %s[%d].pos.xyz - pos.xyz;\n", lightsName, index);
|
||||
object.Write("dist2 = dot(ldir, ldir);\n"
|
||||
"dist = sqrt(dist2);\n"
|
||||
"ldir = ldir / dist;\n"
|
||||
"attn = max(0.0f, dot(ldir, %s.lights[%d].dir.xyz));\n", lightsName, index);
|
||||
object.Write("attn = max(0.0f, dot(%s.lights[%d].cosatt.xyz, float3(1.0f, attn, attn*attn))) / dot(%s.lights[%d].distatt.xyz, float3(1.0f,dist,dist2));\n", lightsName, index, lightsName, index);
|
||||
"attn = max(0.0f, dot(ldir, %s[%d].dir.xyz));\n", lightsName, index);
|
||||
object.Write("attn = max(0.0f, dot(%s[%d].cosatt.xyz, float3(1.0f, attn, attn*attn))) / dot(%s[%d].distatt.xyz, float3(1.0f,dist,dist2));\n", lightsName, index, lightsName, index);
|
||||
}
|
||||
else if (chan.attnfunc == 1)
|
||||
{ // specular
|
||||
object.Write("ldir = normalize(%s.lights[%d].pos.xyz);\n", lightsName, index);
|
||||
object.Write("attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s.lights[%d].dir.xyz)) : 0.0f;\n", lightsName, index);
|
||||
object.Write("attn = max(0.0f, dot(%s.lights[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot(%s.lights[%d].distatt.xyz, float3(1,attn,attn*attn));\n", lightsName, index, lightsName, index);
|
||||
object.Write("ldir = normalize(%s[%d].pos.xyz);\n", lightsName, index);
|
||||
object.Write("attn = (dot(_norm0,ldir) >= 0.0f) ? max(0.0f, dot(_norm0, %s[%d].dir.xyz)) : 0.0f;\n", lightsName, index);
|
||||
object.Write("attn = max(0.0f, dot(%s[%d].cosatt.xyz, float3(1,attn,attn*attn))) / dot(%s[%d].distatt.xyz, float3(1,attn,attn*attn));\n", lightsName, index, lightsName, index);
|
||||
}
|
||||
|
||||
switch (chan.diffusefunc)
|
||||
{
|
||||
case LIGHTDIF_NONE:
|
||||
object.Write("lacc.%s += attn * %s.lights[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
|
||||
object.Write("lacc.%s += attn * %s[%d].col.%s;\n", swizzle, lightsName, index, swizzle);
|
||||
break;
|
||||
case LIGHTDIF_SIGN:
|
||||
case LIGHTDIF_CLAMP:
|
||||
object.Write("lacc.%s += attn * %sdot(ldir, _norm0)) * %s.lights[%d].col.%s;\n",
|
||||
object.Write("lacc.%s += attn * %sdot(ldir, _norm0)) * %s[%d].col.%s;\n",
|
||||
swizzle,
|
||||
chan.diffusefunc != LIGHTDIF_SIGN ? "max(0.0f," :"(",
|
||||
lightsName,
|
||||
@@ -112,7 +112,7 @@ void GenerateLightingShader(T& object, int components, const char* materialsName
|
||||
object.Write("mat = float4(1.0f, 1.0f, 1.0f, 1.0f);\n");
|
||||
}
|
||||
else // from color
|
||||
object.Write("mat = %s.C%d;\n", materialsName, j+2);
|
||||
object.Write("mat = %s[%d];\n", materialsName, j+2);
|
||||
|
||||
SetUidField(lit_chans[j].enablelighting, xfregs.color[j].enablelighting);
|
||||
if (color.enablelighting) {
|
||||
@@ -126,7 +126,7 @@ void GenerateLightingShader(T& object, int components, const char* materialsName
|
||||
object.Write("lacc = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
|
||||
}
|
||||
else // from color
|
||||
object.Write("lacc = %s.C%d;\n", materialsName, j);
|
||||
object.Write("lacc = %s[%d];\n", materialsName, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -144,7 +144,7 @@ void GenerateLightingShader(T& object, int components, const char* materialsName
|
||||
else object.Write("mat.w = 1.0f;\n");
|
||||
}
|
||||
else // from color
|
||||
object.Write("mat.w = %s.C%d.w;\n", materialsName, j+2);
|
||||
object.Write("mat.w = %s[%d].w;\n", materialsName, j+2);
|
||||
}
|
||||
|
||||
SetUidField(lit_chans[j+2].enablelighting, xfregs.alpha[j].enablelighting);
|
||||
@@ -160,7 +160,7 @@ void GenerateLightingShader(T& object, int components, const char* materialsName
|
||||
object.Write("lacc.w = 0.0f;\n");
|
||||
}
|
||||
else // from color
|
||||
object.Write("lacc.w = %s.C%d.w;\n", materialsName, j);
|
||||
object.Write("lacc.w = %s[%d].w;\n", materialsName, j);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -21,6 +21,10 @@ volatile u32 s_swapRequested = false;
|
||||
u32 s_efbAccessRequested = false;
|
||||
volatile u32 s_FifoShuttingDown = false;
|
||||
|
||||
std::condition_variable s_perf_query_cond;
|
||||
std::mutex s_perf_query_lock;
|
||||
static volatile bool s_perf_query_requested;
|
||||
|
||||
static volatile struct
|
||||
{
|
||||
u32 xfbAddr;
|
||||
@@ -169,6 +173,43 @@ u32 VideoBackendHardware::Video_AccessEFB(EFBAccessType type, u32 x, u32 y, u32
|
||||
return 0;
|
||||
}
|
||||
|
||||
static bool QueryResultIsReady()
|
||||
{
|
||||
return !s_perf_query_requested || s_FifoShuttingDown;
|
||||
}
|
||||
|
||||
void VideoFifo_CheckPerfQueryRequest()
|
||||
{
|
||||
if (s_perf_query_requested)
|
||||
{
|
||||
g_perf_query->FlushResults();
|
||||
|
||||
{
|
||||
std::lock_guard<std::mutex> lk(s_perf_query_lock);
|
||||
s_perf_query_requested = false;
|
||||
}
|
||||
|
||||
s_perf_query_cond.notify_one();
|
||||
}
|
||||
}
|
||||
|
||||
u32 VideoBackendHardware::Video_GetQueryResult(PerfQueryType type)
|
||||
{
|
||||
// TODO: Is this check sane?
|
||||
if (!g_perf_query->IsFlushed())
|
||||
{
|
||||
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bCPUThread)
|
||||
{
|
||||
s_perf_query_requested = true;
|
||||
std::unique_lock<std::mutex> lk(s_perf_query_lock);
|
||||
s_perf_query_cond.wait(lk, QueryResultIsReady);
|
||||
}
|
||||
else
|
||||
g_perf_query->FlushResults();
|
||||
}
|
||||
|
||||
return g_perf_query->GetQueryResult(type);
|
||||
}
|
||||
|
||||
void VideoBackendHardware::InitializeShared()
|
||||
{
|
||||
@@ -176,6 +217,7 @@ void VideoBackendHardware::InitializeShared()
|
||||
|
||||
s_swapRequested = 0;
|
||||
s_efbAccessRequested = 0;
|
||||
s_perf_query_requested = false;
|
||||
s_FifoShuttingDown = 0;
|
||||
memset((void*)&s_beginFieldArgs, 0, sizeof(s_beginFieldArgs));
|
||||
memset(&s_accessEFBArgs, 0, sizeof(s_accessEFBArgs));
|
||||
@@ -186,6 +228,11 @@ void VideoBackendHardware::InitializeShared()
|
||||
// Run from the CPU thread
|
||||
void VideoBackendHardware::DoState(PointerWrap& p)
|
||||
{
|
||||
bool software = false;
|
||||
p.Do(software);
|
||||
if (p.GetMode() == PointerWrap::MODE_READ && software == true)
|
||||
// change mode to abort load of incompatible save state.
|
||||
p.SetMode(PointerWrap::MODE_VERIFY);
|
||||
VideoCommon_DoState(p);
|
||||
p.DoMarker("VideoCommon");
|
||||
|
||||
@@ -233,6 +280,7 @@ void VideoFifo_CheckAsyncRequest()
|
||||
{
|
||||
VideoFifo_CheckSwapRequest();
|
||||
VideoFifo_CheckEFBAccess();
|
||||
VideoFifo_CheckPerfQueryRequest();
|
||||
}
|
||||
|
||||
void VideoBackendHardware::Video_GatherPipeBursted()
|
||||
|
||||
@@ -102,7 +102,7 @@ public:
|
||||
virtual void SetupVertexPointers() = 0;
|
||||
virtual void EnableComponents(u32 components) {}
|
||||
|
||||
int GetVertexStride() const { return vertex_stride; }
|
||||
u32 GetVertexStride() const { return vertex_stride; }
|
||||
|
||||
// TODO: move this under private:
|
||||
u32 m_components; // VB_HAS_X. Bitmask telling what vertex components are present.
|
||||
|
||||
@@ -22,7 +22,7 @@ namespace OSD
|
||||
{
|
||||
|
||||
// On-screen message display
|
||||
void AddMessage(const char* str, u32 ms);
|
||||
void AddMessage(const char* str, u32 ms = 2000);
|
||||
void DrawMessages(); // draw the current messages on the screen. Only call once per frame.
|
||||
void ClearMessages();
|
||||
|
||||
|
||||
@@ -123,7 +123,7 @@ void InterpretDisplayList(u32 address, u32 size)
|
||||
Statistics::SwapDL();
|
||||
}
|
||||
|
||||
// reset to the old pointer
|
||||
// reset to the old pointer
|
||||
g_pVideoData = old_pVideoData;
|
||||
}
|
||||
|
||||
@@ -136,74 +136,114 @@ void ExecuteDisplayList(u32 address, u32 size)
|
||||
InterpretDisplayList(address, size);
|
||||
}
|
||||
|
||||
bool FifoCommandRunnable()
|
||||
u32 FifoCommandRunnable(u32 &command_size)
|
||||
{
|
||||
u32 cycleTime = 0;
|
||||
u32 buffer_size = (u32)(GetVideoBufferEndPtr() - g_pVideoData);
|
||||
if (buffer_size == 0)
|
||||
return false; // can't peek
|
||||
if (buffer_size == 0)
|
||||
return 0; // can't peek
|
||||
|
||||
u8 cmd_byte = DataPeek8(0);
|
||||
u32 command_size = 0;
|
||||
|
||||
switch (cmd_byte)
|
||||
{
|
||||
case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
|
||||
switch (cmd_byte)
|
||||
{
|
||||
case GX_NOP: // Hm, this means that we scan over nop streams pretty slowly...
|
||||
command_size = 1;
|
||||
cycleTime = 6;
|
||||
break;
|
||||
case GX_CMD_INVL_VC: // Invalidate Vertex Cache - no parameters
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
command_size = 1;
|
||||
break;
|
||||
command_size = 1;
|
||||
cycleTime = 6;
|
||||
break;
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
command_size = 1;
|
||||
cycleTime = 6;
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG:
|
||||
command_size = 5;
|
||||
break;
|
||||
case GX_LOAD_BP_REG:
|
||||
command_size = 5;
|
||||
cycleTime = 12;
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG:
|
||||
command_size = 6;
|
||||
break;
|
||||
case GX_LOAD_CP_REG:
|
||||
command_size = 6;
|
||||
cycleTime = 12;
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
command_size = 5;
|
||||
break;
|
||||
case GX_LOAD_INDX_A:
|
||||
case GX_LOAD_INDX_B:
|
||||
case GX_LOAD_INDX_C:
|
||||
case GX_LOAD_INDX_D:
|
||||
command_size = 5;
|
||||
cycleTime = 6; // TODO
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
command_size = 9;
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
// FIXME: Calculate the cycle time of the display list.
|
||||
//u32 address = DataPeek32(1);
|
||||
//u32 size = DataPeek32(5);
|
||||
//u8* old_pVideoData = g_pVideoData;
|
||||
//u8* startAddress = Memory::GetPointer(address);
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
// check if we can read the header
|
||||
if (buffer_size >= 5)
|
||||
{
|
||||
command_size = 1 + 4;
|
||||
u32 Cmd2 = DataPeek32(1);
|
||||
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
|
||||
command_size += transfer_size * 4;
|
||||
}
|
||||
else
|
||||
//// Avoid the crash if Memory::GetPointer failed ..
|
||||
//if (startAddress != 0)
|
||||
//{
|
||||
// g_pVideoData = startAddress;
|
||||
// u8 *end = g_pVideoData + size;
|
||||
// u32 step = 0;
|
||||
// while (g_pVideoData < end)
|
||||
// {
|
||||
// cycleTime += FifoCommandRunnable(step);
|
||||
// g_pVideoData += step;
|
||||
// }
|
||||
//}
|
||||
//else
|
||||
//{
|
||||
// cycleTime = 45;
|
||||
//}
|
||||
|
||||
//// reset to the old pointer
|
||||
//g_pVideoData = old_pVideoData;
|
||||
command_size = 9;
|
||||
cycleTime = 45; // This is unverified
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
// check if we can read the header
|
||||
if (buffer_size >= 5)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// check if we can read the header
|
||||
if (buffer_size >= 3)
|
||||
{
|
||||
command_size = 1 + 2;
|
||||
u16 numVertices = DataPeek16(1);
|
||||
command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK);
|
||||
}
|
||||
command_size = 1 + 4;
|
||||
u32 Cmd2 = DataPeek32(1);
|
||||
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
|
||||
command_size += transfer_size * 4;
|
||||
cycleTime = 18 + 6 * transfer_size;
|
||||
}
|
||||
else
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// check if we can read the header
|
||||
if (buffer_size >= 3)
|
||||
{
|
||||
command_size = 1 + 2;
|
||||
u16 numVertices = DataPeek16(1);
|
||||
command_size += numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK);
|
||||
cycleTime = 1600; // This depends on the number of pixels rendered
|
||||
}
|
||||
else
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO(Omega): Maybe dump FIFO to file on this error
|
||||
@@ -218,7 +258,7 @@ bool FifoCommandRunnable()
|
||||
Host_SysMessage(szTemp);
|
||||
INFO_LOG(VIDEO, "%s", szTemp);
|
||||
{
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
SCPFifoStruct &fifo = CommandProcessor::fifo;
|
||||
|
||||
char szTmp[512];
|
||||
// sprintf(szTmp, "Illegal command %02x (at %08x)",cmd_byte,g_pDataReader->GetPtr());
|
||||
@@ -243,197 +283,205 @@ bool FifoCommandRunnable()
|
||||
Host_SysMessage(szTmp);
|
||||
INFO_LOG(VIDEO, "%s", szTmp);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (command_size > buffer_size)
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
|
||||
if (command_size > buffer_size)
|
||||
return 0;
|
||||
|
||||
return true;
|
||||
// INFO_LOG("OP detected: cmd_byte 0x%x size %i buffer %i",cmd_byte, command_size, buffer_size);
|
||||
if (cycleTime == 0)
|
||||
cycleTime = 6;
|
||||
|
||||
return cycleTime;
|
||||
}
|
||||
|
||||
u32 FifoCommandRunnable()
|
||||
{
|
||||
u32 command_size = 0;
|
||||
return FifoCommandRunnable(command_size);
|
||||
}
|
||||
|
||||
static void Decode()
|
||||
{
|
||||
u8 *opcodeStart = g_pVideoData;
|
||||
u8 *opcodeStart = g_pVideoData;
|
||||
|
||||
int cmd_byte = DataReadU8();
|
||||
switch (cmd_byte)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
int cmd_byte = DataReadU8();
|
||||
switch (cmd_byte)
|
||||
{
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u8 sub_cmd = DataReadU8();
|
||||
u32 value = DataReadU32();
|
||||
LoadCPReg(sub_cmd, value);
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
{
|
||||
u8 sub_cmd = DataReadU8();
|
||||
u32 value = DataReadU32();
|
||||
LoadCPReg(sub_cmd, value);
|
||||
INCSTAT(stats.thisFrame.numCPLoads);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
|
||||
u32 xf_address = Cmd2 & 0xFFFF;
|
||||
GC_ALIGNED128(u32 data_buffer[16]);
|
||||
DataReadU32xFuncs[transfer_size-1](data_buffer);
|
||||
LoadXFReg(transfer_size, xf_address, data_buffer);
|
||||
LoadXFReg(transfer_size, xf_address, data_buffer);
|
||||
|
||||
INCSTAT(stats.thisFrame.numXFLoads);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 address = DataReadU32();
|
||||
u32 count = DataReadU32();
|
||||
ExecuteDisplayList(address, count);
|
||||
}
|
||||
break;
|
||||
case GX_CMD_CALL_DL:
|
||||
{
|
||||
u32 address = DataReadU32();
|
||||
u32 count = DataReadU32();
|
||||
ExecuteDisplayList(address, count);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte);
|
||||
break;
|
||||
break;
|
||||
|
||||
case GX_CMD_INVL_VC: // Invalidate Vertex Cache
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
case GX_CMD_INVL_VC: // Invalidate Vertex Cache
|
||||
DEBUG_LOG(VIDEO, "Invalidate (vertex cache?)");
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
{
|
||||
u32 bp_cmd = DataReadU32();
|
||||
LoadBPReg(bp_cmd);
|
||||
LoadBPReg(bp_cmd);
|
||||
INCSTAT(stats.thisFrame.numBPLoads);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// load vertices (use computed vertex size from FifoCommandRunnable above)
|
||||
// draw primitives
|
||||
default:
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// load vertices (use computed vertex size from FifoCommandRunnable above)
|
||||
u16 numVertices = DataReadU16();
|
||||
|
||||
VertexLoaderManager::RunVertices(
|
||||
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
|
||||
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
|
||||
numVertices);
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
// Display lists get added directly into the FIFO stream
|
||||
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
|
||||
}
|
||||
|
||||
static void DecodeSemiNop()
|
||||
{
|
||||
u8 *opcodeStart = g_pVideoData;
|
||||
u8 *opcodeStart = g_pVideoData;
|
||||
|
||||
int cmd_byte = DataReadU8();
|
||||
switch (cmd_byte)
|
||||
{
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
case GX_CMD_INVL_VC: // Invalidate Vertex Cache
|
||||
case GX_NOP:
|
||||
int cmd_byte = DataReadU8();
|
||||
switch (cmd_byte)
|
||||
{
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
case GX_CMD_INVL_VC: // Invalidate Vertex Cache
|
||||
case GX_NOP:
|
||||
break;
|
||||
|
||||
case GX_LOAD_CP_REG: //0x08
|
||||
// We have to let CP writes through because they determine the size of vertices.
|
||||
{
|
||||
u8 sub_cmd = DataReadU8();
|
||||
u32 value = DataReadU32();
|
||||
LoadCPReg(sub_cmd, value);
|
||||
INCSTAT(stats.thisFrame.numCPLoads);
|
||||
}
|
||||
break;
|
||||
{
|
||||
u8 sub_cmd = DataReadU8();
|
||||
u32 value = DataReadU32();
|
||||
LoadCPReg(sub_cmd, value);
|
||||
INCSTAT(stats.thisFrame.numCPLoads);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
|
||||
u32 address = Cmd2 & 0xFFFF;
|
||||
GC_ALIGNED128(u32 data_buffer[16]);
|
||||
DataReadU32xFuncs[transfer_size-1](data_buffer);
|
||||
LoadXFReg(transfer_size, address, data_buffer);
|
||||
INCSTAT(stats.thisFrame.numXFLoads);
|
||||
}
|
||||
break;
|
||||
case GX_LOAD_XF_REG:
|
||||
{
|
||||
u32 Cmd2 = DataReadU32();
|
||||
int transfer_size = ((Cmd2 >> 16) & 15) + 1;
|
||||
u32 address = Cmd2 & 0xFFFF;
|
||||
GC_ALIGNED128(u32 data_buffer[16]);
|
||||
DataReadU32xFuncs[transfer_size-1](data_buffer);
|
||||
LoadXFReg(transfer_size, address, data_buffer);
|
||||
INCSTAT(stats.thisFrame.numXFLoads);
|
||||
}
|
||||
break;
|
||||
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
case GX_LOAD_INDX_A: //used for position matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xC);
|
||||
break;
|
||||
case GX_LOAD_INDX_B: //used for normal matrices
|
||||
LoadIndexedXF(DataReadU32(), 0xD);
|
||||
break;
|
||||
case GX_LOAD_INDX_C: //used for postmatrices
|
||||
LoadIndexedXF(DataReadU32(), 0xE);
|
||||
break;
|
||||
case GX_LOAD_INDX_D: //used for lights
|
||||
LoadIndexedXF(DataReadU32(), 0xF);
|
||||
break;
|
||||
|
||||
case GX_CMD_CALL_DL:
|
||||
case GX_CMD_CALL_DL:
|
||||
// Hm, wonder if any games put tokens in display lists - in that case,
|
||||
// we'll have to parse them too.
|
||||
DataSkip(8);
|
||||
break;
|
||||
DataSkip(8);
|
||||
break;
|
||||
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
case GX_LOAD_BP_REG: //0x61
|
||||
// We have to let BP writes through because they set tokens and stuff.
|
||||
// TODO: Call a much simplified LoadBPReg instead.
|
||||
{
|
||||
{
|
||||
u32 bp_cmd = DataReadU32();
|
||||
LoadBPReg(bp_cmd);
|
||||
LoadBPReg(bp_cmd);
|
||||
INCSTAT(stats.thisFrame.numBPLoads);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
// draw primitives
|
||||
default:
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// load vertices (use computed vertex size from FifoCommandRunnable above)
|
||||
// draw primitives
|
||||
default:
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// load vertices (use computed vertex size from FifoCommandRunnable above)
|
||||
u16 numVertices = DataReadU16();
|
||||
DataSkip(numVertices * VertexLoaderManager::GetVertexSize(cmd_byte & GX_VAT_MASK));
|
||||
}
|
||||
else
|
||||
{
|
||||
}
|
||||
else
|
||||
{
|
||||
ERROR_LOG(VIDEO, "OpcodeDecoding::Decode: Illegal command %02x", cmd_byte);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (g_bRecordFifoData && cmd_byte != GX_CMD_CALL_DL)
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, g_pVideoData - opcodeStart);
|
||||
FifoRecorder::GetInstance().WriteGPCommand(opcodeStart, u32(g_pVideoData - opcodeStart));
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Init()
|
||||
{
|
||||
{
|
||||
g_pVideoData = GetVideoBufferStartPtr();
|
||||
|
||||
#if _M_SSE >= 0x301
|
||||
@@ -446,8 +494,8 @@ void OpcodeDecoder_Init()
|
||||
|
||||
if (g_Config.bEnableOpenCL)
|
||||
{
|
||||
OpenCL::Initialize();
|
||||
TexDecoder_OpenCL_Initialize();
|
||||
OpenCL::Initialize();
|
||||
TexDecoder_OpenCL_Initialize();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -456,21 +504,20 @@ void OpcodeDecoder_Shutdown()
|
||||
{
|
||||
if (g_Config.bEnableOpenCL)
|
||||
{
|
||||
TexDecoder_OpenCL_Shutdown();
|
||||
OpenCL::Destroy();
|
||||
TexDecoder_OpenCL_Shutdown();
|
||||
OpenCL::Destroy();
|
||||
}
|
||||
}
|
||||
|
||||
void OpcodeDecoder_Run(bool skipped_frame)
|
||||
u32 OpcodeDecoder_Run(bool skipped_frame)
|
||||
{
|
||||
if (!skipped_frame)
|
||||
u32 totalCycles = 0;
|
||||
u32 cycles = FifoCommandRunnable();
|
||||
while (cycles > 0)
|
||||
{
|
||||
while (FifoCommandRunnable())
|
||||
Decode();
|
||||
}
|
||||
else
|
||||
{
|
||||
while (FifoCommandRunnable())
|
||||
DecodeSemiNop();
|
||||
skipped_frame ? DecodeSemiNop() : Decode();
|
||||
totalCycles += cycles;
|
||||
cycles = FifoCommandRunnable();
|
||||
}
|
||||
return totalCycles;
|
||||
}
|
||||
|
||||
@@ -44,12 +44,12 @@
|
||||
#define GX_DRAW_LINES 0x5 // 0xA8
|
||||
#define GX_DRAW_LINE_STRIP 0x6 // 0xB0
|
||||
#define GX_DRAW_POINTS 0x7 // 0xB8
|
||||
#define GX_DRAW_NONE 0x1; //Tis is a fake value to used in the backends
|
||||
#define GX_DRAW_NONE 0x1; //Tis is a fake value to used in the backends
|
||||
|
||||
extern bool g_bRecordFifoData;
|
||||
|
||||
void OpcodeDecoder_Init();
|
||||
void OpcodeDecoder_Shutdown();
|
||||
void OpcodeDecoder_Run(bool skipped_frame);
|
||||
u32 OpcodeDecoder_Run(bool skipped_frame);
|
||||
void ExecuteDisplayList(u32 address, u32 size);
|
||||
#endif // _OPCODE_DECODING_H
|
||||
|
||||
@@ -148,25 +148,25 @@ cl_program CompileProgram(const char *Kernel)
|
||||
// Build the program executable
|
||||
err = clBuildProgram(program , 0, NULL, NULL, NULL, NULL);
|
||||
if(err != CL_SUCCESS) {
|
||||
HandleCLError(err, "Error: failed to build program");
|
||||
HandleCLError(err, "Error: failed to build program");
|
||||
|
||||
char *buildlog = NULL;
|
||||
size_t buildlog_size = 0;
|
||||
size_t buildlog_size = 0;
|
||||
|
||||
clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, 0, NULL, &buildlog_size);
|
||||
buildlog = new char[buildlog_size + 1];
|
||||
err = clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, buildlog_size, buildlog, NULL);
|
||||
buildlog[buildlog_size] = 0;
|
||||
|
||||
if(err != CL_SUCCESS)
|
||||
{
|
||||
HandleCLError(err, "Error: can't get build log");
|
||||
} else
|
||||
{
|
||||
ERROR_LOG(COMMON, "Error log:\n%s\n", buildlog);
|
||||
}
|
||||
buildlog = new char[buildlog_size + 1];
|
||||
err = clGetProgramBuildInfo(program, OpenCL::device_id, CL_PROGRAM_BUILD_LOG, buildlog_size, buildlog, NULL);
|
||||
buildlog[buildlog_size] = 0;
|
||||
|
||||
if(err != CL_SUCCESS)
|
||||
{
|
||||
HandleCLError(err, "Error: can't get build log");
|
||||
} else
|
||||
{
|
||||
ERROR_LOG(COMMON, "Error log:\n%s\n", buildlog);
|
||||
}
|
||||
|
||||
delete[] buildlog;
|
||||
delete[] buildlog;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ void TexDecoder_OpenCL_Initialize()
|
||||
size_t nDevices = 0;
|
||||
cl_device_id *devices = NULL;
|
||||
size_t *binary_sizes = NULL;
|
||||
char **binaries = NULL;
|
||||
char **binaries = NULL;
|
||||
std::string filename;
|
||||
char dolphin_rev[HEADER_SIZE];
|
||||
|
||||
@@ -132,7 +132,7 @@ void TexDecoder_OpenCL_Initialize()
|
||||
{
|
||||
OpenCL::HandleCLError(err, "clCreateProgramWithBinary");
|
||||
}
|
||||
|
||||
|
||||
if (!err)
|
||||
{
|
||||
err = clBuildProgram(g_program, 1, &OpenCL::device_id, NULL, NULL, NULL);
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
#include "PerfQueryBase.h"
|
||||
|
||||
PerfQueryBase* g_perf_query = 0;
|
||||
@@ -0,0 +1,54 @@
|
||||
#ifndef _PERFQUERY_BASE_H_
|
||||
#define _PERFQUERY_BASE_H_
|
||||
|
||||
#include "CommonTypes.h"
|
||||
|
||||
enum PerfQueryType
|
||||
{
|
||||
PQ_ZCOMP_INPUT_ZCOMPLOC = 0,
|
||||
PQ_ZCOMP_OUTPUT_ZCOMPLOC,
|
||||
PQ_ZCOMP_INPUT,
|
||||
PQ_ZCOMP_OUTPUT,
|
||||
PQ_BLEND_INPUT,
|
||||
PQ_EFB_COPY_CLOCKS,
|
||||
PQ_NUM_MEMBERS
|
||||
};
|
||||
|
||||
enum PerfQueryGroup
|
||||
{
|
||||
PQG_ZCOMP_ZCOMPLOC,
|
||||
PQG_ZCOMP,
|
||||
PQG_EFB_COPY_CLOCKS,
|
||||
PQG_NUM_MEMBERS,
|
||||
};
|
||||
|
||||
class PerfQueryBase
|
||||
{
|
||||
public:
|
||||
PerfQueryBase() {};
|
||||
virtual ~PerfQueryBase() {}
|
||||
|
||||
// Begin querying the specified value for the following host GPU commands
|
||||
virtual void EnableQuery(PerfQueryGroup type) {}
|
||||
|
||||
// Stop querying the specified value for the following host GPU commands
|
||||
virtual void DisableQuery(PerfQueryGroup type) {}
|
||||
|
||||
// Reset query counters to zero and drop any pending queries
|
||||
virtual void ResetQuery() {}
|
||||
|
||||
// Return the measured value for the specified query type
|
||||
// NOTE: Called from CPU thread
|
||||
virtual u32 GetQueryResult(PerfQueryType type) { return 0; }
|
||||
|
||||
// Request the value of any pending queries - causes a pipeline flush and thus should be used carefully!
|
||||
virtual void FlushResults() {}
|
||||
|
||||
// True if there are no further pending query results
|
||||
// NOTE: Called from CPU thread
|
||||
virtual bool IsFlushed() const { return true; }
|
||||
};
|
||||
|
||||
extern PerfQueryBase* g_perf_query;
|
||||
|
||||
#endif // _PERFQUERY_H_
|
||||
@@ -28,10 +28,12 @@
|
||||
#include "ConfigManager.h"
|
||||
|
||||
#include "PixelEngine.h"
|
||||
#include "RenderBase.h"
|
||||
#include "CommandProcessor.h"
|
||||
#include "HW/ProcessorInterface.h"
|
||||
#include "DLCache.h"
|
||||
#include "State.h"
|
||||
|
||||
namespace PixelEngine
|
||||
{
|
||||
|
||||
@@ -110,22 +112,22 @@ static UPEAlphaReadReg m_AlphaRead;
|
||||
static UPECtrlReg m_Control;
|
||||
//static u16 m_Token; // token value most recently encountered
|
||||
|
||||
static bool g_bSignalTokenInterrupt;
|
||||
static bool g_bSignalFinishInterrupt;
|
||||
volatile u32 g_bSignalTokenInterrupt;
|
||||
volatile u32 g_bSignalFinishInterrupt;
|
||||
|
||||
static int et_SetTokenOnMainThread;
|
||||
static int et_SetFinishOnMainThread;
|
||||
|
||||
volatile bool interruptSetToken = false;
|
||||
volatile bool interruptSetFinish = false;
|
||||
volatile u32 interruptSetToken = 0;
|
||||
volatile u32 interruptSetFinish = 0;
|
||||
|
||||
u16 bbox[4];
|
||||
bool bbox_active;
|
||||
|
||||
enum
|
||||
{
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||
INT_CAUSE_PE_TOKEN = 0x200, // GP Token
|
||||
INT_CAUSE_PE_FINISH = 0x400, // GP Finished
|
||||
};
|
||||
|
||||
void DoState(PointerWrap &p)
|
||||
@@ -161,10 +163,10 @@ void Init()
|
||||
m_AlphaModeConf.Hex = 0;
|
||||
m_AlphaRead.Hex = 0;
|
||||
|
||||
g_bSignalTokenInterrupt = false;
|
||||
g_bSignalFinishInterrupt = false;
|
||||
interruptSetToken = false;
|
||||
interruptSetFinish = false;
|
||||
g_bSignalTokenInterrupt = 0;
|
||||
g_bSignalFinishInterrupt = 0;
|
||||
interruptSetToken = 0;
|
||||
interruptSetFinish = 0;
|
||||
|
||||
et_SetTokenOnMainThread = CoreTiming::RegisterEvent("SetToken", SetToken_OnMainThread);
|
||||
et_SetFinishOnMainThread = CoreTiming::RegisterEvent("SetFinish", SetFinish_OnMainThread);
|
||||
@@ -211,7 +213,7 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||
break;
|
||||
|
||||
case PE_TOKEN_REG:
|
||||
_uReturnValue = CommandProcessor::fifo.PEToken;
|
||||
_uReturnValue = Common::AtomicLoad(*(volatile u32*)&CommandProcessor::fifo.PEToken);
|
||||
INFO_LOG(PIXELENGINE, "(r16) TOKEN_REG : %04x", _uReturnValue);
|
||||
break;
|
||||
|
||||
@@ -255,23 +257,59 @@ void Read16(u16& _uReturnValue, const u32 _iAddress)
|
||||
break;
|
||||
}
|
||||
|
||||
case PE_PERF_0L:
|
||||
case PE_PERF_0H:
|
||||
case PE_PERF_1L:
|
||||
case PE_PERF_1H:
|
||||
case PE_PERF_2L:
|
||||
case PE_PERF_2H:
|
||||
case PE_PERF_3L:
|
||||
case PE_PERF_3H:
|
||||
case PE_PERF_4L:
|
||||
case PE_PERF_4H:
|
||||
case PE_PERF_5L:
|
||||
case PE_PERF_5H:
|
||||
INFO_LOG(PIXELENGINE, "(r16) perf counter @ %08x", _iAddress);
|
||||
// git r90a2096a24f4 (svn r3663) added the PE_PERF cases, without setting
|
||||
// _uReturnValue to anything, this reverts to the previous behaviour which allows
|
||||
// The timer in SMS:Scrubbing Serena Beach to countdown correctly
|
||||
_uReturnValue = 1;
|
||||
// NOTE(neobrain): only PE_PERF_ZCOMP_OUTPUT is implemented in D3D11, but the other values shouldn't be contradictionary to the value of that register (i.e. INPUT registers should always be greater or equal to their corresponding OUTPUT registers).
|
||||
case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) & 0xFFFF;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT_ZCOMPLOC) >> 16;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) & 0xFFFF;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT_ZCOMPLOC) >> 16;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_INPUT_L:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) & 0xFFFF;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_INPUT_H:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_INPUT) >> 16;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_OUTPUT_L:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) & 0xFFFF;
|
||||
break;
|
||||
|
||||
case PE_PERF_ZCOMP_OUTPUT_H:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_ZCOMP_OUTPUT) >> 16;
|
||||
break;
|
||||
|
||||
case PE_PERF_BLEND_INPUT_L:
|
||||
// Super Mario Sunshine uses this register in episode 6 of Sirena Beach:
|
||||
// The amount of remaining goop is determined by checking how many pixels reach the blending stage.
|
||||
// Once this register falls below a particular value (around 0x90), the game regards the challenge finished.
|
||||
// In very old builds, Dolphin only returned 0. That caused the challenge to be immediately finished without any goop being cleaned (the timer just didn't even start counting from 3:00:00).
|
||||
// Later builds returned 1 for the high register. That caused the timer to actually count down, but made the challenge unbeatable because the game always thought you didn't clear any goop at all.
|
||||
// Note that currently this functionality is only implemented in the D3D11 backend.
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) & 0xFFFF;
|
||||
break;
|
||||
|
||||
case PE_PERF_BLEND_INPUT_H:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_BLEND_INPUT) >> 16;
|
||||
break;
|
||||
|
||||
case PE_PERF_EFB_COPY_CLOCKS_L:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) & 0xFFFF;
|
||||
break;
|
||||
|
||||
case PE_PERF_EFB_COPY_CLOCKS_H:
|
||||
_uReturnValue = g_video_backend->Video_GetQueryResult(PQ_EFB_COPY_CLOCKS) >> 16;
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -312,8 +350,8 @@ void Write16(const u16 _iValue, const u32 _iAddress)
|
||||
{
|
||||
UPECtrlReg tmpCtrl(_iValue);
|
||||
|
||||
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = false;
|
||||
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = false;
|
||||
if (tmpCtrl.PEToken) g_bSignalTokenInterrupt = 0;
|
||||
if (tmpCtrl.PEFinish) g_bSignalFinishInterrupt = 0;
|
||||
|
||||
m_Control.PETokenEnable = tmpCtrl.PETokenEnable;
|
||||
m_Control.PEFinishEnable = tmpCtrl.PEFinishEnable;
|
||||
@@ -359,14 +397,14 @@ void UpdateInterrupts()
|
||||
|
||||
void UpdateTokenInterrupt(bool active)
|
||||
{
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
|
||||
interruptSetToken = active;
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, active);
|
||||
Common::AtomicStore(interruptSetToken, active ? 1 : 0);
|
||||
}
|
||||
|
||||
void UpdateFinishInterrupt(bool active)
|
||||
{
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
|
||||
interruptSetFinish = active;
|
||||
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, active);
|
||||
Common::AtomicStore(interruptSetFinish, active ? 1 : 0);
|
||||
}
|
||||
|
||||
// TODO(mb2): Refactor SetTokenINT_OnMainThread(u64 userdata, int cyclesLate).
|
||||
@@ -376,20 +414,23 @@ void UpdateFinishInterrupt(bool active)
|
||||
// Called only if BPMEM_PE_TOKEN_INT_ID is ack by GP
|
||||
void SetToken_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
//if (userdata >> 16)
|
||||
//{
|
||||
g_bSignalTokenInterrupt = true;
|
||||
//_dbg_assert_msg_(PIXELENGINE, (CommandProcessor::fifo.PEToken == (userdata&0xFFFF)), "WTF? BPMEM_PE_TOKEN_INT_ID's token != BPMEM_PE_TOKEN_ID's token" );
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
|
||||
// XXX: No 16-bit atomic store available, so cheat and use 32-bit.
|
||||
// That's what we've always done. We're counting on fifo.PEToken to be
|
||||
// 4-byte padded.
|
||||
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, userdata & 0xffff);
|
||||
INFO_LOG(PIXELENGINE, "VIDEO Backend raises INT_CAUSE_PE_TOKEN (btw, token: %04x)", CommandProcessor::fifo.PEToken);
|
||||
if (userdata >> 16)
|
||||
{
|
||||
Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
|
||||
UpdateInterrupts();
|
||||
CommandProcessor::interruptTokenWaiting = false;
|
||||
IncrementCheckContextId();
|
||||
//}
|
||||
}
|
||||
CommandProcessor::interruptTokenWaiting = false;
|
||||
IncrementCheckContextId();
|
||||
}
|
||||
|
||||
void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||
{
|
||||
g_bSignalFinishInterrupt = 1;
|
||||
Common::AtomicStore(*(volatile u32*)&g_bSignalFinishInterrupt, 1);
|
||||
UpdateInterrupts();
|
||||
CommandProcessor::interruptFinishWaiting = false;
|
||||
CommandProcessor::isPossibleWaitingSetDrawDone = false;
|
||||
@@ -399,23 +440,13 @@ void SetFinish_OnMainThread(u64 userdata, int cyclesLate)
|
||||
// THIS IS EXECUTED FROM VIDEO THREAD
|
||||
void SetToken(const u16 _token, const int _bSetTokenAcknowledge)
|
||||
{
|
||||
// TODO?: set-token-value and set-token-INT could be merged since set-token-INT own the token value.
|
||||
if (_bSetTokenAcknowledge) // set token INT
|
||||
{
|
||||
Common::AtomicStore(*(volatile u32*)&g_bSignalTokenInterrupt, 1);
|
||||
}
|
||||
|
||||
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
|
||||
CommandProcessor::interruptTokenWaiting = true;
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||
}
|
||||
else // set token value
|
||||
{
|
||||
// we do it directly from videoThread because of
|
||||
// Super Monkey Ball
|
||||
// XXX: No 16-bit atomic store available, so cheat and use 32-bit.
|
||||
// That's what we've always done. We're counting on fifo.PEToken to be
|
||||
// 4-byte padded.
|
||||
Common::AtomicStore(*(volatile u32*)&CommandProcessor::fifo.PEToken, _token);
|
||||
}
|
||||
CommandProcessor::interruptTokenWaiting = true;
|
||||
CoreTiming::ScheduleEvent_Threadsafe(0, et_SetTokenOnMainThread, _token | (_bSetTokenAcknowledge << 16));
|
||||
IncrementCheckContextId();
|
||||
}
|
||||
|
||||
@@ -438,7 +469,6 @@ void ResetSetFinish()
|
||||
{
|
||||
UpdateFinishInterrupt(false);
|
||||
g_bSignalFinishInterrupt = false;
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -452,8 +482,7 @@ void ResetSetToken()
|
||||
if (g_bSignalTokenInterrupt)
|
||||
{
|
||||
UpdateTokenInterrupt(false);
|
||||
g_bSignalTokenInterrupt = false;
|
||||
|
||||
g_bSignalTokenInterrupt = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -461,17 +490,4 @@ void ResetSetToken()
|
||||
}
|
||||
CommandProcessor::interruptTokenWaiting = false;
|
||||
}
|
||||
|
||||
bool WaitingForPEInterrupt()
|
||||
{
|
||||
return !CommandProcessor::waitingForPEInterruptDisable && (CommandProcessor::interruptFinishWaiting || CommandProcessor::interruptTokenWaiting || interruptSetFinish || interruptSetToken);
|
||||
}
|
||||
|
||||
void ResumeWaitingForPEInterrupt()
|
||||
{
|
||||
interruptSetFinish = false;
|
||||
interruptSetToken = false;
|
||||
CommandProcessor::interruptFinishWaiting = false;
|
||||
CommandProcessor::interruptTokenWaiting = false;
|
||||
}
|
||||
} // end of namespace PixelEngine
|
||||
|
||||
@@ -24,31 +24,32 @@ class PointerWrap;
|
||||
// internal hardware addresses
|
||||
enum
|
||||
{
|
||||
PE_ZCONF = 0x00, // Z Config
|
||||
PE_ALPHACONF = 0x02, // Alpha Config
|
||||
PE_DSTALPHACONF = 0x04, // Destination Alpha Config
|
||||
PE_ALPHAMODE = 0x06, // Alpha Mode Config
|
||||
PE_ALPHAREAD = 0x08, // Alpha Read
|
||||
PE_ZCONF = 0x00, // Z Config
|
||||
PE_ALPHACONF = 0x02, // Alpha Config
|
||||
PE_DSTALPHACONF = 0x04, // Destination Alpha Config
|
||||
PE_ALPHAMODE = 0x06, // Alpha Mode Config
|
||||
PE_ALPHAREAD = 0x08, // Alpha Read
|
||||
PE_CTRL_REGISTER = 0x0a, // Control
|
||||
PE_TOKEN_REG = 0x0e, // Token
|
||||
PE_TOKEN_REG = 0x0e, // Token
|
||||
PE_BBOX_LEFT = 0x10, // Flip Left
|
||||
PE_BBOX_RIGHT = 0x12, // Flip Right
|
||||
PE_BBOX_TOP = 0x14, // Flip Top
|
||||
PE_BBOX_BOTTOM = 0x16, // Flip Bottom
|
||||
|
||||
// These have not yet been RE:d. They are the perf counters.
|
||||
PE_PERF_0L = 0x18,
|
||||
PE_PERF_0H = 0x1a,
|
||||
PE_PERF_1L = 0x1c,
|
||||
PE_PERF_1H = 0x1e,
|
||||
PE_PERF_2L = 0x20,
|
||||
PE_PERF_2H = 0x22,
|
||||
PE_PERF_3L = 0x24,
|
||||
PE_PERF_3H = 0x26,
|
||||
PE_PERF_4L = 0x28,
|
||||
PE_PERF_4H = 0x2a,
|
||||
PE_PERF_5L = 0x2c,
|
||||
PE_PERF_5H = 0x2e,
|
||||
// NOTE: Order not verified
|
||||
// These indicate the number of quads that are being used as input/output for each particular stage
|
||||
PE_PERF_ZCOMP_INPUT_ZCOMPLOC_L = 0x18,
|
||||
PE_PERF_ZCOMP_INPUT_ZCOMPLOC_H = 0x1a,
|
||||
PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_L = 0x1c,
|
||||
PE_PERF_ZCOMP_OUTPUT_ZCOMPLOC_H = 0x1e,
|
||||
PE_PERF_ZCOMP_INPUT_L = 0x20,
|
||||
PE_PERF_ZCOMP_INPUT_H = 0x22,
|
||||
PE_PERF_ZCOMP_OUTPUT_L = 0x24,
|
||||
PE_PERF_ZCOMP_OUTPUT_H = 0x26,
|
||||
PE_PERF_BLEND_INPUT_L = 0x28,
|
||||
PE_PERF_BLEND_INPUT_H = 0x2a,
|
||||
PE_PERF_EFB_COPY_CLOCKS_L = 0x2c,
|
||||
PE_PERF_EFB_COPY_CLOCKS_H = 0x2e,
|
||||
};
|
||||
|
||||
namespace PixelEngine
|
||||
@@ -80,8 +81,6 @@ void SetToken(const u16 _token, const int _bSetTokenAcknowledge);
|
||||
void SetFinish(void);
|
||||
void ResetSetFinish(void);
|
||||
void ResetSetToken(void);
|
||||
bool WaitingForPEInterrupt();
|
||||
void ResumeWaitingForPEInterrupt();
|
||||
|
||||
// Bounding box functionality. Paper Mario (both) are a couple of the few games that use it.
|
||||
extern u16 bbox[4];
|
||||
|
||||
@@ -39,7 +39,7 @@
|
||||
|
||||
template<class T, GenOutput type> static void WriteStage(char *&p, int n, API_TYPE ApiType);
|
||||
template<class T, GenOutput type> static void SampleTexture(T& out, const char *destination, const char *texcoords, const char *texswap, int texmap, API_TYPE ApiType);
|
||||
template<class T, GenOutput type> static void WriteAlphaTest(T& out, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode);
|
||||
template<class T, GenOutput type> static void WriteAlphaTest(T& out, API_TYPE ApiType,DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth);
|
||||
template<class T, GenOutput type> static void WriteFog(T& out);
|
||||
|
||||
static const char *tevKSelTableC[] = // KCSEL
|
||||
@@ -137,38 +137,38 @@ static const char *tevOpTable[] = { // TEV
|
||||
|
||||
static const char *tevCInputTable[] = // CC
|
||||
{
|
||||
"(prev.rgb)", // CPREV,
|
||||
"(prev.rgb)", // CPREV,
|
||||
"(prev.aaa)", // APREV,
|
||||
"(c0.rgb)", // C0,
|
||||
"(c0.rgb)", // C0,
|
||||
"(c0.aaa)", // A0,
|
||||
"(c1.rgb)", // C1,
|
||||
"(c1.rgb)", // C1,
|
||||
"(c1.aaa)", // A1,
|
||||
"(c2.rgb)", // C2,
|
||||
"(c2.rgb)", // C2,
|
||||
"(c2.aaa)", // A2,
|
||||
"(textemp.rgb)", // TEXC,
|
||||
"(textemp.rgb)", // TEXC,
|
||||
"(textemp.aaa)", // TEXA,
|
||||
"(rastemp.rgb)", // RASC,
|
||||
"(rastemp.rgb)", // RASC,
|
||||
"(rastemp.aaa)", // RASA,
|
||||
"float3(1.0f, 1.0f, 1.0f)", // ONE
|
||||
"float3(0.5f, 0.5f, 0.5f)", // HALF
|
||||
"(konsttemp.rgb)", //"konsttemp.rgb", // KONST
|
||||
"float3(0.5f, 0.5f, 0.5f)", // HALF
|
||||
"(konsttemp.rgb)", //"konsttemp.rgb", // KONST
|
||||
"float3(0.0f, 0.0f, 0.0f)", // ZERO
|
||||
///aded extra values to map clamped values
|
||||
"(cprev.rgb)", // CPREV,
|
||||
"(cprev.aaa)", // APREV,
|
||||
"(cc0.rgb)", // C0,
|
||||
"(cc0.aaa)", // A0,
|
||||
"(cc1.rgb)", // C1,
|
||||
"(cc1.aaa)", // A1,
|
||||
"(cc2.rgb)", // C2,
|
||||
"(cc2.aaa)", // A2,
|
||||
"(textemp.rgb)", // TEXC,
|
||||
"(cprev.rgb)", // CPREV,
|
||||
"(cprev.aaa)", // APREV,
|
||||
"(cc0.rgb)", // C0,
|
||||
"(cc0.aaa)", // A0,
|
||||
"(cc1.rgb)", // C1,
|
||||
"(cc1.aaa)", // A1,
|
||||
"(cc2.rgb)", // C2,
|
||||
"(cc2.aaa)", // A2,
|
||||
"(textemp.rgb)", // TEXC,
|
||||
"(textemp.aaa)", // TEXA,
|
||||
"(crastemp.rgb)", // RASC,
|
||||
"(crastemp.aaa)", // RASA,
|
||||
"(crastemp.rgb)", // RASC,
|
||||
"(crastemp.aaa)", // RASA,
|
||||
"float3(1.0f, 1.0f, 1.0f)", // ONE
|
||||
"float3(0.5f, 0.5f, 0.5f)", // HALF
|
||||
"(ckonsttemp.rgb)", //"konsttemp.rgb", // KONST
|
||||
"float3(0.5f, 0.5f, 0.5f)", // HALF
|
||||
"(ckonsttemp.rgb)", //"konsttemp.rgb", // KONST
|
||||
"float3(0.0f, 0.0f, 0.0f)", // ZERO
|
||||
"PADERROR1", "PADERROR2", "PADERROR3", "PADERROR4"
|
||||
};
|
||||
@@ -188,7 +188,7 @@ static const char *tevAInputTable[] = // CA
|
||||
"cc0", // A0,
|
||||
"cc1", // A1,
|
||||
"cc2", // A2,
|
||||
"textemp", // TEXA,
|
||||
"textemp", // TEXA,
|
||||
"crastemp", // RASA,
|
||||
"ckonsttemp", // KONST, (hw1 had quarter)
|
||||
"float4(0.0f, 0.0f, 0.0f, 0.0f)", // ZERO
|
||||
@@ -203,8 +203,8 @@ static const char *tevRasTable[] =
|
||||
"ERROR13", //2
|
||||
"ERROR14", //3
|
||||
"ERROR15", //4
|
||||
"alphabump", // use bump alpha
|
||||
"(alphabump*(255.0f/248.0f))", //normalized
|
||||
"float4(alphabump,alphabump,alphabump,alphabump)", // use bump alpha
|
||||
"(float4(alphabump,alphabump,alphabump,alphabump)*(255.0f/248.0f))", //normalized
|
||||
"float4(0.0f, 0.0f, 0.0f, 0.0f)", // zero
|
||||
};
|
||||
|
||||
@@ -246,6 +246,26 @@ static void BuildSwapModeTable()
|
||||
}
|
||||
}
|
||||
|
||||
const char* WriteRegister(API_TYPE ApiType, const char *prefix, const u32 num)
|
||||
{
|
||||
if (ApiType == API_OPENGL)
|
||||
return ""; // Nothing to do here
|
||||
|
||||
static char result[64];
|
||||
sprintf(result, " : register(%s%d)", prefix, num);
|
||||
return result;
|
||||
}
|
||||
|
||||
const char *WriteLocation(API_TYPE ApiType)
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
return "";
|
||||
|
||||
static char result[64];
|
||||
sprintf(result, "uniform ");
|
||||
return result;
|
||||
}
|
||||
|
||||
template<class T, GenOutput type>
|
||||
void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
|
||||
{
|
||||
@@ -262,6 +282,8 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
unsigned int numStages = bpmem.genMode.numtevstages + 1;
|
||||
unsigned int numTexgen = bpmem.genMode.numtexgens;
|
||||
|
||||
bool per_pixel_depth = bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable;
|
||||
|
||||
out.Write("//Pixel Shader for TEV stages\n");
|
||||
out.Write("//%i TEV stages, %i texgens, XXX IND stages\n",
|
||||
numStages, numTexgen/*, bpmem.genMode.numindstages*/);
|
||||
@@ -273,114 +295,186 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
SetUidField(genMode.numtevstages, bpmem.genMode.numtevstages);
|
||||
SetUidField(genMode.numtexgens, bpmem.genMode.numtexgens);
|
||||
|
||||
// Declare samplers
|
||||
out.Write((ApiType != API_D3D11) ? "uniform sampler2D " : "sampler ");
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("%s samp%d : register(s%d)", (i==0)?"":",", i, i);
|
||||
|
||||
out.Write(";\n");
|
||||
if(ApiType == API_D3D11)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
out.Write("Texture2D ");
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("%s Tex%d : register(t%d)", (i==0)?"":",", i, i);
|
||||
// Fmod implementation gleaned from Nvidia
|
||||
// At http://http.developer.nvidia.com/Cg/fmod.html
|
||||
out.Write("float fmod( float x, float y )\n");
|
||||
out.Write("{\n");
|
||||
out.Write("\tfloat z = fract( abs( x / y) ) * abs( y );\n");
|
||||
out.Write("\treturn (x < 0) ? -z : z;\n");
|
||||
out.Write("}\n\n");
|
||||
|
||||
out.Write(";\n");
|
||||
// Declare samplers
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("uniform sampler2D samp%d;\n", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Declare samplers
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("%s samp%d %s;\n", (ApiType == API_D3D11) ? "sampler" : "uniform sampler2D", (i==0)?"":",", i, WriteRegister(ApiType, "s", i));
|
||||
|
||||
if (ApiType == API_D3D11)
|
||||
{
|
||||
out.Write("\n");
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
out.Write("Texture2D Tex%d : register(t%d);\n", i, i);
|
||||
}
|
||||
}
|
||||
}
|
||||
out.Write("\n");
|
||||
|
||||
out.Write("uniform float4 " I_COLORS"[4] : register(c%d);\n", C_COLORS); // TODO: first element not used??
|
||||
out.Write("uniform float4 " I_KCOLORS"[4] : register(c%d);\n", C_KCOLORS);
|
||||
out.Write("uniform float4 " I_ALPHA"[1] : register(c%d);\n", C_ALPHA); // TODO: Why is this an array...-.-
|
||||
out.Write("uniform float4 " I_TEXDIMS"[8] : register(c%d);\n", C_TEXDIMS);
|
||||
out.Write("uniform float4 " I_ZBIAS"[2] : register(c%d);\n", C_ZBIAS);
|
||||
out.Write("uniform float4 " I_INDTEXSCALE"[2] : register(c%d);\n", C_INDTEXSCALE);
|
||||
out.Write("uniform float4 " I_INDTEXMTX"[6] : register(c%d);\n", C_INDTEXMTX);
|
||||
out.Write("uniform float4 " I_FOG"[3] : register(c%d);\n", C_FOG);
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
out.Write("layout(std140) uniform PSBlock {\n");
|
||||
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
out.Write("typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n");
|
||||
out.Write("typedef struct { Light lights[8]; } s_" I_PLIGHTS";\n");
|
||||
out.Write("uniform s_" I_PLIGHTS" " I_PLIGHTS" : register(c%d);\n", C_PLIGHTS);
|
||||
out.Write("typedef struct { float4 C0, C1, C2, C3; } s_" I_PMATERIALS";\n");
|
||||
out.Write("uniform s_" I_PMATERIALS" " I_PMATERIALS" : register(c%d);\n", C_PMATERIALS);
|
||||
}
|
||||
out.Write("\t%sfloat4 " I_COLORS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_COLORS)); // TODO: first element not used??
|
||||
out.Write("\t%sfloat4 " I_KCOLORS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_KCOLORS));
|
||||
out.Write("\t%sfloat4 " I_ALPHA"[1] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_ALPHA)); // TODO: Why is this an array...-.-
|
||||
out.Write("\t%sfloat4 " I_TEXDIMS"[8] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_TEXDIMS));
|
||||
out.Write("\t%sfloat4 " I_ZBIAS"[2] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_ZBIAS));
|
||||
out.Write("\t%sfloat4 " I_INDTEXSCALE"[2] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_INDTEXSCALE));
|
||||
out.Write("\t%sfloat4 " I_INDTEXMTX"[6] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_INDTEXMTX));
|
||||
out.Write("\t%sfloat4 " I_FOG"[3] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_FOG));
|
||||
|
||||
// For pixel lighting - TODO: Should only be defined when per pixel lighting is enabled!
|
||||
out.Write("struct Light { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; };\n");
|
||||
out.Write("\t%sLight " I_PLIGHTS"[8] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PLIGHTS));
|
||||
out.Write("\t%sfloat4 " I_PMATERIALS"[4] %s;\n", WriteLocation(ApiType), WriteRegister(ApiType, "c", C_PMATERIALS));
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
out.Write("};\n");
|
||||
|
||||
// TODO: Somehow should put ApiType in the hash..
|
||||
out.Write("void main(\n");
|
||||
if(ApiType != API_D3D11)
|
||||
if (ApiType == API_OPENGL)
|
||||
{
|
||||
out.Write(" out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
|
||||
"\n out float depth : DEPTH,",
|
||||
ApiType & API_OPENGL ? "WPOS" : ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write(" out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
|
||||
"\n out float depth : SV_Depth,");
|
||||
}
|
||||
out.Write("out float4 ocol0;\n");
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
out.Write("out float4 ocol1;\n");
|
||||
|
||||
if (per_pixel_depth)
|
||||
out.Write("#define depth gl_FragDepth\n");
|
||||
out.Write("float4 rawpos = gl_FragCoord;\n");
|
||||
|
||||
out.Write(" in float4 colors_0 : COLOR0,\n");
|
||||
out.Write(" in float4 colors_1 : COLOR1");
|
||||
out.Write("VARYIN float4 colors_02;\n");
|
||||
out.Write("VARYIN float4 colors_12;\n");
|
||||
out.Write("float4 colors_0 = colors_02;\n");
|
||||
out.Write("float4 colors_1 = colors_12;\n");
|
||||
|
||||
// TODO: ... this looks like an incredibly ugly hack - is it still needed?
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
if (numTexgen < 7)
|
||||
{
|
||||
for (unsigned int i = 0; i < numTexgen; ++i)
|
||||
out.Write(",\n in float3 uv%d : TEXCOORD%d", i, i);
|
||||
out.Write(",\n in float4 clipPos : TEXCOORD%d", numTexgen);
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
out.Write(",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
// Let's set up attributes
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write(",\n in float4 uv%d : TEXCOORD%d", i, i);
|
||||
{
|
||||
out.Write("VARYIN float3 uv%d_2;\n", i);
|
||||
out.Write("float3 uv%d = uv%d_2;\n", i, i);
|
||||
}
|
||||
out.Write("VARYIN float4 clipPos_2;\n");
|
||||
out.Write("float4 clipPos = clipPos_2;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
out.Write("VARYIN float4 Normal_2;\n");
|
||||
out.Write("float4 Normal = Normal_2;\n");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// TODO: Not necessary...
|
||||
SetUidField(xfregs_numTexGen_numTexGens, xfregs.numTexGen.numTexGens);
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
out.Write(",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
|
||||
// wpos is in w of first 4 texcoords
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
out.Write("VARYIN float4 uv%d_2;\n", i);
|
||||
out.Write("float4 uv%d = uv%d_2;\n", i, i);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
{
|
||||
out.Write("VARYIN float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
|
||||
out.Write("float%d uv%d = uv%d_2;\n", i < 4 ? 4 : 3 , i, i);
|
||||
}
|
||||
}
|
||||
out.Write("float4 clipPos;\n");
|
||||
}
|
||||
out.Write("void main()\n{\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("void main(\n");
|
||||
if(ApiType != API_D3D11)
|
||||
{
|
||||
out.Write(" out float4 ocol0 : COLOR0,%s%s\n in float4 rawpos : %s,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : COLOR1," : "",
|
||||
per_pixel_depth ? "\n out float depth : DEPTH," : "",
|
||||
ApiType & API_D3D9_SM20 ? "POSITION" : "VPOS");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write(" out float4 ocol0 : SV_Target0,%s%s\n in float4 rawpos : SV_Position,\n",
|
||||
dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND ? "\n out float4 ocol1 : SV_Target1," : "",
|
||||
per_pixel_depth ? "\n out float depth : SV_Depth," : "");
|
||||
}
|
||||
|
||||
out.Write(" in float4 colors_0 : COLOR0,\n");
|
||||
out.Write(" in float4 colors_1 : COLOR1");
|
||||
|
||||
// compute window position if needed because binding semantic WPOS is not widely supported
|
||||
if (numTexgen < 7)
|
||||
{
|
||||
for (unsigned int i = 0; i < numTexgen; ++i)
|
||||
out.Write(",\n in float3 uv%d : TEXCOORD%d", i, i);
|
||||
out.Write(",\n in float4 clipPos : TEXCOORD%d", numTexgen);
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
out.Write(",\n in float4 Normal : TEXCOORD%d", numTexgen + 1);
|
||||
out.Write(" ) {\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write(",\n in float4 uv%d : TEXCOORD%d", i, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
out.Write(",\n in float%d uv%d : TEXCOORD%d", i < 4 ? 4 : 3 , i, i);
|
||||
}
|
||||
out.Write(" ) {\n");
|
||||
out.Write("\tfloat4 clipPos = float4(0.0f, 0.0f, 0.0f, 0.0f);");
|
||||
}
|
||||
}
|
||||
out.Write(" ) {\n");
|
||||
|
||||
out.Write(" float4 c0 = " I_COLORS"[1], c1 = " I_COLORS"[2], c2 = " I_COLORS"[3], prev = float4(0.0f, 0.0f, 0.0f, 0.0f), textemp = float4(0.0f, 0.0f, 0.0f, 0.0f), rastemp = float4(0.0f, 0.0f, 0.0f, 0.0f), konsttemp = float4(0.0f, 0.0f, 0.0f, 0.0f);\n"
|
||||
" float3 comp16 = float3(1.0f, 255.0f, 0.0f), comp24 = float3(1.0f, 255.0f, 255.0f*255.0f);\n"
|
||||
" float4 alphabump=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float alphabump=0.0f;\n"
|
||||
" float3 tevcoord=float3(0.0f, 0.0f, 0.0f);\n"
|
||||
" float2 wrappedcoord=float2(0.0f,0.0f), tempcoord=float2(0.0f,0.0f);\n"
|
||||
" float4 cc0=float4(0.0f,0.0f,0.0f,0.0f), cc1=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float4 cc2=float4(0.0f,0.0f,0.0f,0.0f), cprev=float4(0.0f,0.0f,0.0f,0.0f);\n"
|
||||
" float4 crastemp=float4(0.0f,0.0f,0.0f,0.0f),ckonsttemp=float4(0.0f,0.0f,0.0f,0.0f);\n\n");
|
||||
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
SetUidField(xfregs_numTexGen_numTexGens, xfregs.numTexGen.numTexGens);
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
out.Write("float3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||
out.Write("float3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
|
||||
out.Write("\tfloat3 _norm0 = normalize(Normal.xyz);\n\n");
|
||||
out.Write("\tfloat3 pos = float3(clipPos.x,clipPos.y,Normal.w);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write(" float3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
|
||||
out.Write("float3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
|
||||
out.Write("\tfloat3 _norm0 = normalize(float3(uv4.w,uv5.w,uv6.w));\n\n");
|
||||
out.Write("\tfloat3 pos = float3(uv0.w,uv1.w,uv7.w);\n");
|
||||
}
|
||||
|
||||
|
||||
out.Write("float4 mat, lacc;\n"
|
||||
"float3 ldir, h;\n"
|
||||
"float dist, dist2, attn;\n");
|
||||
out.Write("\tfloat4 mat, lacc;\n"
|
||||
"\tfloat3 ldir, h;\n"
|
||||
"\tfloat dist, dist2, attn;\n");
|
||||
/// TODO
|
||||
out.SetConstantsUsed(C_PLIGHTS, C_PLIGHTS+39); // TODO: Can be optimized further
|
||||
out.SetConstantsUsed(C_PMATERIALS, C_PMATERIALS+3);
|
||||
@@ -388,14 +482,14 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
}
|
||||
|
||||
if (numTexgen < 7)
|
||||
out.Write("clipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
|
||||
out.Write("\tclipPos = float4(rawpos.x, rawpos.y, clipPos.z, clipPos.w);\n");
|
||||
else
|
||||
out.Write("float4 clipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
|
||||
out.Write("\tfloat4 clipPos = float4(rawpos.x, rawpos.y, uv2.w, uv3.w);\n");
|
||||
|
||||
// HACK to handle cases where the tex gen is not enabled
|
||||
if (numTexgen == 0)
|
||||
{
|
||||
out.Write("float3 uv0 = float3(0.0f, 0.0f, 0.0f);\n");
|
||||
out.Write("\tfloat3 uv0 = float3(0.0f, 0.0f, 0.0f);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -406,8 +500,8 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
SetUidField(texMtxInfo[i].projection, xfregs.texMtxInfo[i].projection);
|
||||
if (xfregs.texMtxInfo[i].projection == XF_TEXPROJ_STQ)
|
||||
{
|
||||
out.Write("if (uv%d.z)", i);
|
||||
out.Write(" uv%d.xy = uv%d.xy / uv%d.z;\n", i, i, i);
|
||||
out.Write("\tif (uv%d.z != 0.0f)", i);
|
||||
out.Write("\t\tuv%d.xy = uv%d.xy / uv%d.z;\n", i, i, i);
|
||||
}
|
||||
|
||||
out.Write("uv%d.xy = uv%d.xy * " I_TEXDIMS"[%d].zw;\n", i, i, i);
|
||||
@@ -426,7 +520,7 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
}
|
||||
|
||||
SetUidField(nIndirectStagesUsed, nIndirectStagesUsed);
|
||||
for(u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||
for (u32 i = 0; i < bpmem.genMode.numindstages; ++i)
|
||||
{
|
||||
if (nIndirectStagesUsed & (1 << i))
|
||||
{
|
||||
@@ -457,10 +551,10 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
if (texcoord < numTexgen)
|
||||
{
|
||||
out.SetConstantsUsed(C_INDTEXSCALE+i/2,C_INDTEXSCALE+i/2);
|
||||
out.Write("tempcoord = uv%d.xy * " I_INDTEXSCALE"[%d].%s;\n", texcoord, i/2, (i&1)?"zw":"xy");
|
||||
out.Write("\ttempcoord = uv%d.xy * " I_INDTEXSCALE"[%d].%s;\n", texcoord, i/2, (i&1)?"zw":"xy");
|
||||
}
|
||||
else
|
||||
out.Write("tempcoord = float2(0.0f, 0.0f);\n");
|
||||
out.Write("\ttempcoord = float2(0.0f, 0.0f);\n");
|
||||
|
||||
char buffer[32];
|
||||
sprintf(buffer, "float3 indtex%d", i);
|
||||
@@ -483,7 +577,7 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
for (unsigned int i = 0; i < numStages; i++)
|
||||
WriteStage<T, type>(out, i, ApiType); // build the equation for this stage
|
||||
|
||||
if(numStages)
|
||||
if (numStages)
|
||||
{
|
||||
// The results of the last texenv stage are put onto the screen,
|
||||
// regardless of the used destination register
|
||||
@@ -493,37 +587,45 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
{
|
||||
/// SetUidField(combiners[numStages-1].colorC.dest, bpmem.combiners[numStages-1].colorC.dest);
|
||||
bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].AuxStored;
|
||||
out.Write("prev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
|
||||
out.Write("\tprev.rgb = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevCOutputTable[bpmem.combiners[numStages - 1].colorC.dest]);
|
||||
RegisterStates[0].ColorNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].colorC.dest].ColorNeedOverflowControl;
|
||||
}
|
||||
if(bpmem.combiners[numStages - 1].alphaC.dest != 0)
|
||||
{
|
||||
bool retrieveFromAuxRegister = !RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl && RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AuxStored;
|
||||
out.Write("prev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
|
||||
out.Write("\tprev.a = %s%s;\n", retrieveFromAuxRegister ? "c" : "" , tevAOutputTable[bpmem.combiners[numStages - 1].alphaC.dest]);
|
||||
RegisterStates[0].AlphaNeedOverflowControl = RegisterStates[bpmem.combiners[numStages - 1].alphaC.dest].AlphaNeedOverflowControl;
|
||||
}
|
||||
}
|
||||
// emulation of unsigned 8 overflow when casting if needed
|
||||
if(RegisterStates[0].AlphaNeedOverflowControl || RegisterStates[0].ColorNeedOverflowControl)
|
||||
out.Write("prev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
|
||||
out.Write("\tprev = frac(prev * (255.0f/256.0f)) * (256.0f/255.0f);\n");
|
||||
|
||||
AlphaTest::TEST_RESULT Pretest = bpmem.alpha_test.TestResult();
|
||||
SetUidField(Pretest, Pretest);
|
||||
if (Pretest == AlphaTest::UNDETERMINED)
|
||||
WriteAlphaTest<T, type>(out, ApiType, dstAlphaMode);
|
||||
WriteAlphaTest<T, type>(out, ApiType, dstAlphaMode, per_pixel_depth);
|
||||
|
||||
|
||||
// the screen space depth value = far z + (clip z / clip w) * z range
|
||||
out.SetConstantsUsed(C_ZBIAS+1, C_ZBIAS+1);
|
||||
out.Write("float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n");
|
||||
if(ApiType == API_OPENGL || ApiType == API_D3D11)
|
||||
out.Write("float zCoord = rawpos.z;\n");
|
||||
else
|
||||
{
|
||||
out.SetConstantsUsed(C_ZBIAS+1, C_ZBIAS+1);
|
||||
// dx9 doesn't support 4 component position, so we have to calculate it again
|
||||
out.Write("float zCoord = " I_ZBIAS"[1].x + (clipPos.z / clipPos.w) * " I_ZBIAS"[1].y;\n");
|
||||
}
|
||||
|
||||
// Note: depth textures are disabled if early depth test is enabled
|
||||
SetUidField(Pretest, Pretest);
|
||||
SetUidField(ztex.op, bpmem.ztex2.op);
|
||||
SetUidField(early_z, bpmem.zcontrol.early_ztest);
|
||||
SetUidField(ztestenable, bpmem.zmode.testenable);
|
||||
if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest && bpmem.zmode.testenable)
|
||||
SetUidField(early_z, bpmem.zcontrol.early_ztest); // TODO: Should be per_pixel_depth instead...
|
||||
SetUidField(ztestenable, bpmem.zmode.testenable); // TODO: Should be fog instead...
|
||||
|
||||
// depth texture can safely be ignored if the result won't be written to the depth buffer (early_ztest) and isn't used for fog either
|
||||
bool skip_ztexture = !per_pixel_depth && !bpmem.fog.c_proj_fsel.fsel;
|
||||
if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !skip_ztexture)
|
||||
{
|
||||
// TODO: Implement type??
|
||||
// use the texture input of the last texture stage (textemp), hopefully this has been read and is in correct format...
|
||||
out.SetConstantsUsed(C_ZBIAS, C_ZBIAS+1);
|
||||
out.Write("zCoord = dot(" I_ZBIAS"[0].xyzw, textemp.xyzw) + " I_ZBIAS"[1].w %s;\n",
|
||||
@@ -533,18 +635,21 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
out.Write("zCoord = zCoord * (16777215.0f/16777216.0f);\n");
|
||||
out.Write("zCoord = frac(zCoord);\n");
|
||||
out.Write("zCoord = zCoord * (16777216.0f/16777215.0f);\n");
|
||||
// Note: depth texture output is only written to depth buffer if late depth test is used
|
||||
// TODO: Should this be outside the ztex if-block?
|
||||
if (per_pixel_depth)
|
||||
out.Write("depth = zCoord;\n");
|
||||
}
|
||||
out.Write("depth = zCoord;\n");
|
||||
|
||||
if (dstAlphaMode == DSTALPHA_ALPHA_PASS)
|
||||
{
|
||||
out.SetConstantsUsed(C_ALPHA, C_ALPHA);
|
||||
out.Write(" ocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
|
||||
out.Write("\tocol0 = float4(prev.rgb, " I_ALPHA"[0].a);\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteFog<T, type>(out);
|
||||
out.Write(" ocol0 = prev;\n");
|
||||
out.Write("\tocol0 = prev;\n");
|
||||
}
|
||||
|
||||
// On D3D11, use dual-source color blending to perform dst alpha in a
|
||||
@@ -553,9 +658,9 @@ void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u
|
||||
{
|
||||
out.SetConstantsUsed(C_ALPHA, C_ALPHA);
|
||||
// Colors will be blended against the alpha from ocol1...
|
||||
out.Write(" ocol1 = ocol0;\n");
|
||||
out.Write("\tocol1 = prev;\n");
|
||||
// ...and the alpha from ocol0 will be written to the framebuffer.
|
||||
out.Write(" ocol0.a = " I_ALPHA"[0].a;\n");
|
||||
out.Write("\tocol0.a = " I_ALPHA"[0].a;\n");
|
||||
}
|
||||
|
||||
out.Write("}\n");
|
||||
@@ -678,10 +783,10 @@ static void WriteStage(T& out, int n, API_TYPE ApiType)
|
||||
out.Write("float2 indtevtrans%d = " I_INDTEXMTX"[%d].ww * uv%d.xy * indtevcrd%d.yy;\n", n, mtxidx, texcoord, n);
|
||||
}
|
||||
else
|
||||
out.Write("float2 indtevtrans%d = 0;\n", n);
|
||||
out.Write("float2 indtevtrans%d = float2(0.0f, 0.0f);\n", n);
|
||||
}
|
||||
else
|
||||
out.Write("float2 indtevtrans%d = 0;\n", n);
|
||||
out.Write("float2 indtevtrans%d = float2(0.0f, 0.0f);\n", n);
|
||||
|
||||
// ---------
|
||||
// Wrapping
|
||||
@@ -743,7 +848,7 @@ static void WriteStage(T& out, int n, API_TYPE ApiType)
|
||||
|
||||
if (bpmem.tevorders[n/2].getEnable(n&1))
|
||||
{
|
||||
if(!bHasIndStage)
|
||||
if (!bHasIndStage)
|
||||
{
|
||||
// calc tevcord
|
||||
if(bHasTexCoord)
|
||||
@@ -992,7 +1097,7 @@ void SampleTexture(T& out, const char *destination, const char *texcoords, const
|
||||
if (ApiType == API_D3D11)
|
||||
out.Write("%s=Tex%d.Sample(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, texmap,texmap, texcoords, texmap, texswap);
|
||||
else
|
||||
out.Write("%s=tex2D(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, texmap, texcoords, texmap, texswap);
|
||||
out.Write("%s=%s(samp%d,%s.xy * " I_TEXDIMS"[%d].xy).%s;\n", destination, ApiType == API_OPENGL ? "texture" : "tex2D", texmap, texcoords, texmap, texswap);
|
||||
}
|
||||
|
||||
static const char *tevAlphaFuncsTable[] =
|
||||
@@ -1016,7 +1121,7 @@ static const char *tevAlphaFunclogicTable[] =
|
||||
};
|
||||
|
||||
template<class T, GenOutput type>
|
||||
static void WriteAlphaTest(T& out, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode)
|
||||
static void WriteAlphaTest(T& out, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode, bool per_pixel_depth)
|
||||
{
|
||||
static const char *alphaRef[2] =
|
||||
{
|
||||
@@ -1026,8 +1131,9 @@ static void WriteAlphaTest(T& out, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode)
|
||||
|
||||
out.SetConstantsUsed(C_ALPHA, C_ALPHA);
|
||||
|
||||
|
||||
// using discard then return works the same in cg and dx9 but not in dx11
|
||||
out.Write("if(!( ");
|
||||
out.Write("\tif(!( ");
|
||||
|
||||
SetUidField(alpha_test.comp0, bpmem.alpha_test.comp0);
|
||||
SetUidField(alpha_test.logic, bpmem.alpha_test.comp1);
|
||||
@@ -1044,10 +1150,11 @@ static void WriteAlphaTest(T& out, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode)
|
||||
out.Write(tevAlphaFuncsTable[compindex], alphaRef[1]);
|
||||
out.Write(")) {\n");
|
||||
|
||||
out.Write("ocol0 = 0;\n");
|
||||
out.Write("\t\tocol0 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
|
||||
if (dstAlphaMode == DSTALPHA_DUAL_SOURCE_BLEND)
|
||||
out.Write("ocol1 = 0;\n");
|
||||
out.Write("depth = 1.f;\n");
|
||||
out.Write("\t\tocol1 = float4(0.0f, 0.0f, 0.0f, 0.0f);\n");
|
||||
if(per_pixel_depth)
|
||||
out.Write("\t\tdepth = 1.f;\n");
|
||||
|
||||
// HAXX: zcomploc (aka early_ztest) is a way to control whether depth test is done before
|
||||
// or after texturing and alpha test. PC GPUs have no way to support this
|
||||
@@ -1061,9 +1168,9 @@ static void WriteAlphaTest(T& out, API_TYPE ApiType, DSTALPHA_MODE dstAlphaMode)
|
||||
// we don't have a choice.
|
||||
if (!(bpmem.zcontrol.early_ztest && bpmem.zmode.updateenable))
|
||||
{
|
||||
out.Write("discard;\n");
|
||||
out.Write("\t\tdiscard;\n");
|
||||
if (ApiType != API_D3D11)
|
||||
out.Write("return;\n");
|
||||
out.Write("\t\treturn;\n");
|
||||
}
|
||||
|
||||
out.Write("}\n");
|
||||
@@ -1075,10 +1182,10 @@ static const char *tevFogFuncsTable[] =
|
||||
"", //?
|
||||
"", //Linear
|
||||
"", //?
|
||||
" fog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp
|
||||
" fog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2
|
||||
" fog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp
|
||||
" fog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2
|
||||
"\tfog = 1.0f - pow(2.0f, -8.0f * fog);\n", //exp
|
||||
"\tfog = 1.0f - pow(2.0f, -8.0f * fog * fog);\n", //exp2
|
||||
"\tfog = pow(2.0f, -8.0f * (1.0f - fog));\n", //backward exp
|
||||
"\tfog = 1.0f - fog;\n fog = pow(2.0f, -8.0f * fog * fog);\n" //backward exp2
|
||||
};
|
||||
|
||||
template<class T, GenOutput type>
|
||||
@@ -1086,7 +1193,7 @@ static void WriteFog(T& out)
|
||||
{
|
||||
SetUidField(fog.fsel, bpmem.fog.c_proj_fsel.fsel);
|
||||
if(bpmem.fog.c_proj_fsel.fsel == 0)
|
||||
return; //no Fog
|
||||
return; // no Fog
|
||||
|
||||
SetUidField(fog.proj, bpmem.fog.c_proj_fsel.proj);
|
||||
|
||||
@@ -1095,13 +1202,13 @@ static void WriteFog(T& out)
|
||||
{
|
||||
// perspective
|
||||
// ze = A/(B - (Zs >> B_SHF)
|
||||
out.Write(" float ze = " I_FOG"[1].x / (" I_FOG"[1].y - (zCoord / " I_FOG"[1].w));\n");
|
||||
out.Write("\tfloat ze = " I_FOG"[1].x / (" I_FOG"[1].y - (zCoord / " I_FOG"[1].w));\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// orthographic
|
||||
// ze = a*Zs (here, no B_SHF)
|
||||
out.Write(" float ze = " I_FOG"[1].x * zCoord;\n");
|
||||
out.Write("\tfloat ze = " I_FOG"[1].x * zCoord;\n");
|
||||
}
|
||||
|
||||
// x_adjust = sqrt((x-center)^2 + k^2)/k
|
||||
@@ -1111,24 +1218,24 @@ static void WriteFog(T& out)
|
||||
if(bpmem.fogRange.Base.Enabled)
|
||||
{
|
||||
out.SetConstantsUsed(C_FOG+2, C_FOG+2);
|
||||
out.Write(" float x_adjust = (2.0f * (clipPos.x / " I_FOG"[2].y)) - 1.0f - " I_FOG"[2].x;\n");
|
||||
out.Write(" x_adjust = sqrt(x_adjust * x_adjust + " I_FOG"[2].z * " I_FOG"[2].z) / " I_FOG"[2].z;\n");
|
||||
out.Write(" ze *= x_adjust;\n");
|
||||
out.Write("\tfloat x_adjust = (2.0f * (clipPos.x / " I_FOG"[2].y)) - 1.0f - " I_FOG"[2].x;\n");
|
||||
out.Write("\tx_adjust = sqrt(x_adjust * x_adjust + " I_FOG"[2].z * " I_FOG"[2].z) / " I_FOG"[2].z;\n");
|
||||
out.Write("\tze *= x_adjust;\n");
|
||||
}
|
||||
|
||||
out.Write("float fog = saturate(ze - " I_FOG"[1].z);\n");
|
||||
out.Write("\tfloat fog = saturate(ze - " I_FOG"[1].z);\n");
|
||||
|
||||
if(bpmem.fog.c_proj_fsel.fsel > 3)
|
||||
if (bpmem.fog.c_proj_fsel.fsel > 3)
|
||||
{
|
||||
out.Write("%s", tevFogFuncsTable[bpmem.fog.c_proj_fsel.fsel]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if(bpmem.fog.c_proj_fsel.fsel != 2)
|
||||
if (bpmem.fog.c_proj_fsel.fsel != 2)
|
||||
WARN_LOG(VIDEO, "Unknown Fog Type! %08x", bpmem.fog.c_proj_fsel.fsel);
|
||||
}
|
||||
|
||||
out.Write(" prev.rgb = lerp(prev.rgb," I_FOG"[0].rgb,fog);\n");
|
||||
out.Write("\tprev.rgb = lerp(prev.rgb, " I_FOG"[0].rgb, fog);\n");
|
||||
}
|
||||
|
||||
void GetPixelShaderUid(PixelShaderUid& object, DSTALPHA_MODE dstAlphaMode, API_TYPE ApiType, u32 components)
|
||||
|
||||
@@ -30,8 +30,8 @@
|
||||
#define I_INDTEXSCALE "cindscale"
|
||||
#define I_INDTEXMTX "cindmtx"
|
||||
#define I_FOG "cfog"
|
||||
#define I_PLIGHTS "cLights"
|
||||
#define I_PMATERIALS "cmtrl"
|
||||
#define I_PLIGHTS "cPLights"
|
||||
#define I_PMATERIALS "cPmtrl"
|
||||
|
||||
#define C_COLORMATRIX 0 // 0
|
||||
#define C_COLORS 0 // 0
|
||||
@@ -55,6 +55,19 @@ enum DSTALPHA_MODE
|
||||
DSTALPHA_DUAL_SOURCE_BLEND // Use dual-source blending
|
||||
};
|
||||
|
||||
// Annoying sure, can be removed once we get up to GLSL ~1.3
|
||||
const s_svar PSVar_Loc[] = { {I_COLORS, C_COLORS, 4 },
|
||||
{I_KCOLORS, C_KCOLORS, 4 },
|
||||
{I_ALPHA, C_ALPHA, 1 },
|
||||
{I_TEXDIMS, C_TEXDIMS, 8 },
|
||||
{I_ZBIAS , C_ZBIAS, 2 },
|
||||
{I_INDTEXSCALE , C_INDTEXSCALE, 2 },
|
||||
{I_INDTEXMTX, C_INDTEXMTX, 6 },
|
||||
{I_FOG, C_FOG, 3 },
|
||||
{I_PLIGHTS, C_PLIGHTS, 40 },
|
||||
{I_PMATERIALS, C_PMATERIALS, 4 },
|
||||
};
|
||||
|
||||
struct pixel_shader_uid_data
|
||||
{
|
||||
u32 components;
|
||||
|
||||
@@ -67,7 +67,7 @@ inline void SetPSConstant4fv(unsigned int const_number, const float *f)
|
||||
s_constant_cache[const_number*4] = f[0];
|
||||
s_constant_cache[const_number*4+1] = f[1];
|
||||
s_constant_cache[const_number*4+2] = f[2];
|
||||
s_constant_cache[const_number*4+3] == f[3];
|
||||
s_constant_cache[const_number*4+3] = f[3];
|
||||
}
|
||||
|
||||
inline void SetMultiPSConstant4fv(unsigned int const_number, unsigned int count, const float *f)
|
||||
@@ -112,6 +112,10 @@ void PixelShaderManager::Shutdown()
|
||||
|
||||
void PixelShaderManager::SetConstants(u32 components)
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.APIType == API_OPENGL && !g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
Dirty();
|
||||
|
||||
// TODO: Probably broken in the non-UBO path
|
||||
PixelShaderConstantProfile constant_profile(C_PENVCONST_END);
|
||||
/// TODO: dst alpha/api/components type parameter...
|
||||
GetPixelShaderConstantProfile(constant_profile, DSTALPHA_DUAL_SOURCE_BLEND, API_OPENGL, components);
|
||||
@@ -143,11 +147,11 @@ void PixelShaderManager::SetConstants(u32 components)
|
||||
|
||||
if (s_nTexDimsChanged)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
for (int i = 0; i < 8; ++i)
|
||||
{
|
||||
if (s_nTexDimsChanged & (1<<i) && constant_profile.ConstantIsUsed(C_TEXDIMS+i))
|
||||
{
|
||||
++necessary_updates;
|
||||
++necessary_updates;
|
||||
SetPSTextureDims(i);
|
||||
s_nTexDimsChanged &= ~(1<<i);
|
||||
}else if (s_nTexDimsChanged & (1<<i)) IncStuff();
|
||||
@@ -156,37 +160,37 @@ void PixelShaderManager::SetConstants(u32 components)
|
||||
|
||||
if (s_bAlphaChanged && constant_profile.ConstantIsUsed(C_ALPHA))
|
||||
{
|
||||
++necessary_updates;
|
||||
++necessary_updates;
|
||||
SetPSConstant4f(C_ALPHA, (lastAlpha&0xff)/255.0f, ((lastAlpha>>8)&0xff)/255.0f, 0, ((lastAlpha>>16)&0xff)/255.0f);
|
||||
s_bAlphaChanged = false;
|
||||
} else if (s_bAlphaChanged) IncStuff();
|
||||
|
||||
if (s_bZTextureTypeChanged && constant_profile.ConstantIsUsed(C_ZBIAS))
|
||||
{
|
||||
float ftemp[4];
|
||||
switch (bpmem.ztex2.type)
|
||||
float ftemp[4];
|
||||
switch (bpmem.ztex2.type)
|
||||
{
|
||||
case 0:
|
||||
// 8 bits
|
||||
ftemp[0] = 0; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 255.0f/16777215.0f;
|
||||
break;
|
||||
case 1:
|
||||
// 16 bits
|
||||
ftemp[0] = 255.0f/16777215.0f; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 65280.0f/16777215.0f;
|
||||
break;
|
||||
case 2:
|
||||
// 24 bits
|
||||
case 0:
|
||||
// 8 bits
|
||||
ftemp[0] = 0; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 255.0f/16777215.0f;
|
||||
break;
|
||||
case 1:
|
||||
// 16 bits
|
||||
ftemp[0] = 255.0f/16777215.0f; ftemp[1] = 0; ftemp[2] = 0; ftemp[3] = 65280.0f/16777215.0f;
|
||||
break;
|
||||
case 2:
|
||||
// 24 bits
|
||||
ftemp[0] = 16711680.0f/16777215.0f; ftemp[1] = 65280.0f/16777215.0f; ftemp[2] = 255.0f/16777215.0f; ftemp[3] = 0;
|
||||
break;
|
||||
}
|
||||
++necessary_updates;
|
||||
++necessary_updates;
|
||||
SetPSConstant4fv(C_ZBIAS, ftemp);
|
||||
s_bZTextureTypeChanged = false;
|
||||
} else if (s_bZTextureTypeChanged) IncStuff();
|
||||
|
||||
if ((s_bZBiasChanged || s_bDepthRangeChanged) && constant_profile.ConstantIsUsed(C_ZBIAS+1))
|
||||
{
|
||||
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
||||
// reversed gxsetviewport(xorig, yorig, width, height, nearz, farz)
|
||||
// [0] = width/2
|
||||
// [1] = height/2
|
||||
// [2] = 16777215 * (farz - nearz)
|
||||
@@ -200,21 +204,21 @@ void PixelShaderManager::SetConstants(u32 components)
|
||||
s_bZBiasChanged = s_bDepthRangeChanged = false;
|
||||
}else if ((s_bZBiasChanged || s_bDepthRangeChanged)) IncStuff();
|
||||
|
||||
// indirect incoming texture scales
|
||||
if (s_nIndTexScaleChanged)
|
||||
// indirect incoming texture scales
|
||||
if (s_nIndTexScaleChanged)
|
||||
{
|
||||
// set as two sets of vec4s, each containing S and T of two ind stages.
|
||||
float f[8];
|
||||
float f[8];
|
||||
|
||||
if ((s_nIndTexScaleChanged & 0x03) && constant_profile.ConstantIsUsed(C_INDTEXSCALE))
|
||||
{
|
||||
for (u32 i = 0; i < 2; ++i)
|
||||
for (u32 i = 0; i < 2; ++i)
|
||||
{
|
||||
f[2 * i] = bpmem.texscale[0].getScaleS(i & 1);
|
||||
f[2 * i + 1] = bpmem.texscale[0].getScaleT(i & 1);
|
||||
PRIM_LOG("tex indscale%d: %f %f\n", i, f[2 * i], f[2 * i + 1]);
|
||||
}
|
||||
++necessary_updates;
|
||||
++necessary_updates;
|
||||
SetPSConstant4fv(C_INDTEXSCALE, f);
|
||||
s_nIndTexScaleChanged &= ~0x03;
|
||||
}
|
||||
@@ -226,16 +230,16 @@ void PixelShaderManager::SetConstants(u32 components)
|
||||
f[2 * i + 1] = bpmem.texscale[1].getScaleT(i & 1);
|
||||
PRIM_LOG("tex indscale%d: %f %f\n", i, f[2 * i], f[2 * i + 1]);
|
||||
}
|
||||
++necessary_updates;
|
||||
++necessary_updates;
|
||||
SetPSConstant4fv(C_INDTEXSCALE+1, &f[4]);
|
||||
s_nIndTexScaleChanged &= ~0x0c;
|
||||
}
|
||||
else if ((s_nIndTexScaleChanged & 0x0c)) IncStuff();
|
||||
}
|
||||
|
||||
if (s_nIndTexMtxChanged)
|
||||
if (s_nIndTexMtxChanged)
|
||||
{
|
||||
for (int i = 0; i < 3; ++i)
|
||||
for (int i = 0; i < 3; ++i)
|
||||
{
|
||||
if ((s_nIndTexMtxChanged & (1 << i)) && (constant_profile.ConstantIsUsed(C_INDTEXMTX+2*i) || constant_profile.ConstantIsUsed(C_INDTEXMTX+2*i+1)))
|
||||
{
|
||||
@@ -250,12 +254,12 @@ void PixelShaderManager::SetConstants(u32 components)
|
||||
++necessary_updates;
|
||||
++necessary_updates;
|
||||
SetPSConstant4f(C_INDTEXMTX + 2 * i,
|
||||
bpmem.indmtx[i].col0.ma * fscale,
|
||||
bpmem.indmtx[i].col0.ma * fscale,
|
||||
bpmem.indmtx[i].col1.mc * fscale,
|
||||
bpmem.indmtx[i].col2.me * fscale,
|
||||
fscale * 4.0f);
|
||||
SetPSConstant4f(C_INDTEXMTX + 2 * i + 1,
|
||||
bpmem.indmtx[i].col0.mb * fscale,
|
||||
SetPSConstant4f(C_INDTEXMTX + 2 * i + 1,
|
||||
bpmem.indmtx[i].col0.mb * fscale,
|
||||
bpmem.indmtx[i].col1.md * fscale,
|
||||
bpmem.indmtx[i].col2.mf * fscale,
|
||||
fscale * 4.0f);
|
||||
@@ -398,11 +402,11 @@ void PixelShaderManager::SetConstants(u32 components)
|
||||
|
||||
void PixelShaderManager::SetPSTextureDims(int texid)
|
||||
{
|
||||
// texdims.xy are reciprocals of the real texture dimensions
|
||||
// texdims.zw are the scaled dimensions
|
||||
float fdims[4];
|
||||
// texdims.xy are reciprocals of the real texture dimensions
|
||||
// texdims.zw are the scaled dimensions
|
||||
float fdims[4];
|
||||
|
||||
TCoordInfo& tc = bpmem.texcoords[texid];
|
||||
TCoordInfo& tc = bpmem.texcoords[texid];
|
||||
fdims[0] = 1.0f / (float)(lastTexDims[texid] & 0xffff);
|
||||
fdims[1] = 1.0f / (float)((lastTexDims[texid] >> 16) & 0xfff);
|
||||
fdims[2] = (float)(tc.s.scale_minus_1 + 1);
|
||||
@@ -417,7 +421,7 @@ void PixelShaderManager::SetPSTextureDims(int texid)
|
||||
// and update it when the shader constant is set, only.
|
||||
void PixelShaderManager::SetColorChanged(int type, int num, bool high)
|
||||
{
|
||||
float *pf = &lastRGBAfull[type][num][0];
|
||||
float *pf = &lastRGBAfull[type][num][0];
|
||||
if (!high) {
|
||||
int r = bpmem.tevregs[num].low.a;
|
||||
int a = bpmem.tevregs[num].low.b;
|
||||
@@ -429,60 +433,61 @@ void PixelShaderManager::SetColorChanged(int type, int num, bool high)
|
||||
pf[1] = (float)g * (1.0f / 255.0f);
|
||||
pf[2] = (float)b * (1.0f / 255.0f);
|
||||
}
|
||||
s_nColorsChanged[type] |= 1 << num;
|
||||
PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]);
|
||||
s_nColorsChanged[type] |= 1 << num;
|
||||
PRIM_LOG("pixel %scolor%d: %f %f %f %f\n", type?"k":"", num, pf[0], pf[1], pf[2], pf[3]);
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetAlpha(const AlphaTest& alpha)
|
||||
{
|
||||
if ((alpha.hex & 0xffff) != lastAlpha)
|
||||
if ((alpha.hex & 0xffff) != lastAlpha)
|
||||
{
|
||||
lastAlpha = (lastAlpha & ~0xffff) | (alpha.hex & 0xffff);
|
||||
s_bAlphaChanged = true;
|
||||
}
|
||||
lastAlpha = (lastAlpha & ~0xffff) | (alpha.hex & 0xffff);
|
||||
s_bAlphaChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetDestAlpha(const ConstantAlpha& alpha)
|
||||
{
|
||||
if (alpha.alpha != (lastAlpha >> 16))
|
||||
if (alpha.alpha != (lastAlpha >> 16))
|
||||
{
|
||||
lastAlpha = (lastAlpha & ~0xff0000) | ((alpha.hex & 0xff) << 16);
|
||||
s_bAlphaChanged = true;
|
||||
}
|
||||
lastAlpha = (lastAlpha & ~0xff0000) | ((alpha.hex & 0xff) << 16);
|
||||
s_bAlphaChanged = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt)
|
||||
{
|
||||
u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30);
|
||||
if (lastTexDims[texmapid] != wh)
|
||||
u32 wh = width | (height << 16) | (wraps << 28) | (wrapt << 30);
|
||||
if (lastTexDims[texmapid] != wh)
|
||||
{
|
||||
lastTexDims[texmapid] = wh;
|
||||
lastTexDims[texmapid] = wh;
|
||||
s_nTexDimsChanged |= 1 << texmapid;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetZTextureBias(u32 bias)
|
||||
{
|
||||
if (lastZBias != bias)
|
||||
if (lastZBias != bias)
|
||||
{
|
||||
s_bZBiasChanged = true;
|
||||
lastZBias = bias;
|
||||
}
|
||||
s_bZBiasChanged = true;
|
||||
lastZBias = bias;
|
||||
}
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetViewportChanged()
|
||||
{
|
||||
s_bDepthRangeChanged = true;
|
||||
s_bFogRangeAdjustChanged = true; // TODO: Shouldn't be necessary with an accurate fog range adjust implementation
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetIndTexScaleChanged(u8 stagemask)
|
||||
{
|
||||
s_nIndTexScaleChanged |= stagemask;
|
||||
s_nIndTexScaleChanged |= stagemask;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetIndMatrixChanged(int matrixidx)
|
||||
{
|
||||
s_nIndTexMtxChanged |= 1 << matrixidx;
|
||||
s_nIndTexMtxChanged |= 1 << matrixidx;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetZTextureTypeChanged()
|
||||
@@ -492,22 +497,22 @@ void PixelShaderManager::SetZTextureTypeChanged()
|
||||
|
||||
void PixelShaderManager::SetTexCoordChanged(u8 texmapid)
|
||||
{
|
||||
s_nTexDimsChanged |= 1 << texmapid;
|
||||
s_nTexDimsChanged |= 1 << texmapid;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetFogColorChanged()
|
||||
{
|
||||
s_bFogColorChanged = true;
|
||||
s_bFogColorChanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetFogParamChanged()
|
||||
{
|
||||
s_bFogParamChanged = true;
|
||||
s_bFogParamChanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetFogRangeAdjustChanged()
|
||||
{
|
||||
s_bFogRangeAdjustChanged = true;
|
||||
s_bFogRangeAdjustChanged = true;
|
||||
}
|
||||
|
||||
void PixelShaderManager::SetColorMatrix(const float* pmatrix)
|
||||
|
||||
@@ -54,7 +54,6 @@ public:
|
||||
static void SetColorMatrix(const float* pmatrix);
|
||||
static void InvalidateXFRange(int start, int end);
|
||||
static void SetMaterialColorChanged(int index);
|
||||
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -83,7 +83,9 @@ unsigned int Renderer::efb_scale_denominatorY = 1;
|
||||
unsigned int Renderer::ssaa_multiplier = 1;
|
||||
|
||||
|
||||
Renderer::Renderer() : frame_data(NULL), bLastFrameDumped(false)
|
||||
Renderer::Renderer()
|
||||
: frame_data()
|
||||
, bLastFrameDumped(false)
|
||||
{
|
||||
UpdateActiveConfig();
|
||||
TextureCache::OnConfigChanged(g_ActiveConfig);
|
||||
@@ -110,7 +112,6 @@ Renderer::~Renderer()
|
||||
if (pFrameDump.IsOpen())
|
||||
pFrameDump.Close();
|
||||
#endif
|
||||
delete[] frame_data;
|
||||
}
|
||||
|
||||
void Renderer::RenderToXFB(u32 xfbAddr, u32 fbWidth, u32 fbHeight, const EFBRectangle& sourceRc, float Gamma)
|
||||
|
||||
@@ -52,6 +52,15 @@ public:
|
||||
Renderer();
|
||||
virtual ~Renderer();
|
||||
|
||||
enum PixelPerfQuery {
|
||||
PP_ZCOMP_INPUT_ZCOMPLOC,
|
||||
PP_ZCOMP_OUTPUT_ZCOMPLOC,
|
||||
PP_ZCOMP_INPUT,
|
||||
PP_ZCOMP_OUTPUT,
|
||||
PP_BLEND_INPUT,
|
||||
PP_EFB_COPY_CLOCKS
|
||||
};
|
||||
|
||||
virtual void SetColorMask() = 0;
|
||||
virtual void SetBlendMode(bool forceUpdate) = 0;
|
||||
virtual void SetScissorRect(const TargetRectangle& rc) = 0;
|
||||
@@ -147,7 +156,7 @@ protected:
|
||||
#else
|
||||
File::IOFile pFrameDump;
|
||||
#endif
|
||||
char* frame_data;
|
||||
std::vector<u8> frame_data;
|
||||
bool bLastFrameDumped;
|
||||
|
||||
// The framebuffer size
|
||||
|
||||
@@ -53,8 +53,8 @@ char *Statistics::ToString(char *ptr)
|
||||
ptr+=sprintf(ptr,"pshaders (unique, delete cache first): %i\n",stats.numUniquePixelShaders);
|
||||
ptr+=sprintf(ptr,"vshaders created: %i\n",stats.numVertexShadersCreated);
|
||||
ptr+=sprintf(ptr,"vshaders alive: %i\n",stats.numVertexShadersAlive);
|
||||
ptr+=sprintf(ptr,"dlists called: %i\n",stats.numDListsCalled);
|
||||
ptr+=sprintf(ptr,"dlists called(f): %i\n",stats.thisFrame.numDListsCalled);
|
||||
ptr+=sprintf(ptr,"dlists called: %i\n",stats.numDListsCalled);
|
||||
ptr+=sprintf(ptr,"dlists called(f): %i\n",stats.thisFrame.numDListsCalled);
|
||||
ptr+=sprintf(ptr,"dlists alive: %i\n",stats.numDListsAlive);
|
||||
ptr+=sprintf(ptr,"primitive joins: %i\n",stats.thisFrame.numPrimitiveJoins);
|
||||
ptr+=sprintf(ptr,"draw calls: %i\n",stats.thisFrame.numDrawCalls);
|
||||
|
||||
@@ -24,20 +24,20 @@
|
||||
|
||||
struct Statistics
|
||||
{
|
||||
int numPixelShadersCreated;
|
||||
int numPixelShadersAlive;
|
||||
int numVertexShadersCreated;
|
||||
int numVertexShadersAlive;
|
||||
int numPixelShadersCreated;
|
||||
int numPixelShadersAlive;
|
||||
int numVertexShadersCreated;
|
||||
int numVertexShadersAlive;
|
||||
|
||||
int numTexturesCreated;
|
||||
int numTexturesAlive;
|
||||
int numTexturesCreated;
|
||||
int numTexturesAlive;
|
||||
|
||||
int numRenderTargetsCreated;
|
||||
int numRenderTargetsAlive;
|
||||
|
||||
int numDListsCalled;
|
||||
int numDListsCreated;
|
||||
int numDListsAlive;
|
||||
int numRenderTargetsCreated;
|
||||
int numRenderTargetsAlive;
|
||||
|
||||
int numDListsCalled;
|
||||
int numDListsCreated;
|
||||
int numDListsAlive;
|
||||
|
||||
int numVertexLoaders;
|
||||
|
||||
@@ -52,30 +52,30 @@ struct Statistics
|
||||
|
||||
std::vector<EFBRectangle> efb_regions;
|
||||
|
||||
struct ThisFrame
|
||||
{
|
||||
int numBPLoads;
|
||||
int numCPLoads;
|
||||
int numXFLoads;
|
||||
|
||||
int numBPLoadsInDL;
|
||||
int numCPLoadsInDL;
|
||||
int numXFLoadsInDL;
|
||||
|
||||
int numDLs;
|
||||
int numPrims;
|
||||
int numDLPrims;
|
||||
int numShaderChanges;
|
||||
struct ThisFrame
|
||||
{
|
||||
int numBPLoads;
|
||||
int numCPLoads;
|
||||
int numXFLoads;
|
||||
|
||||
int numBPLoadsInDL;
|
||||
int numCPLoadsInDL;
|
||||
int numXFLoadsInDL;
|
||||
|
||||
int numDLs;
|
||||
int numPrims;
|
||||
int numDLPrims;
|
||||
int numShaderChanges;
|
||||
|
||||
int numPrimitiveJoins;
|
||||
int numDrawCalls;
|
||||
int numIndexedDrawCalls;
|
||||
int numBufferSplits;
|
||||
int numPrimitiveJoins;
|
||||
int numDrawCalls;
|
||||
int numIndexedDrawCalls;
|
||||
int numBufferSplits;
|
||||
|
||||
int numDListsCalled;
|
||||
};
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame();
|
||||
};
|
||||
ThisFrame thisFrame;
|
||||
void ResetFrame();
|
||||
static void SwapDL();
|
||||
|
||||
// Yeah, this is unsafe, but we really don't wanna faff around allocating
|
||||
|
||||
@@ -56,7 +56,7 @@ TextureCache::TextureCache()
|
||||
if (!temp)
|
||||
temp = (u8*)AllocateAlignedMemory(temp_size, 16);
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
||||
if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
|
||||
if(g_ActiveConfig.bHiresTextures && !g_ActiveConfig.bDumpTextures)
|
||||
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
|
||||
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
||||
}
|
||||
@@ -84,35 +84,34 @@ TextureCache::~TextureCache()
|
||||
|
||||
void TextureCache::OnConfigChanged(VideoConfig& config)
|
||||
{
|
||||
if (!g_texture_cache)
|
||||
goto skip_checks;
|
||||
|
||||
// TODO: Invalidating texcache is really stupid in some of these cases
|
||||
if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples ||
|
||||
config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay ||
|
||||
config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center ||
|
||||
config.bHiresTextures != backup_config.s_hires_textures)
|
||||
if (g_texture_cache)
|
||||
{
|
||||
g_texture_cache->Invalidate();
|
||||
// TODO: Invalidating texcache is really stupid in some of these cases
|
||||
if (config.iSafeTextureCache_ColorSamples != backup_config.s_colorsamples ||
|
||||
config.bTexFmtOverlayEnable != backup_config.s_texfmt_overlay ||
|
||||
config.bTexFmtOverlayCenter != backup_config.s_texfmt_overlay_center ||
|
||||
config.bHiresTextures != backup_config.s_hires_textures)
|
||||
{
|
||||
g_texture_cache->Invalidate();
|
||||
|
||||
if(g_ActiveConfig.bHiresTextures)
|
||||
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
|
||||
if(g_ActiveConfig.bHiresTextures)
|
||||
HiresTextures::Init(SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str());
|
||||
|
||||
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
||||
SetHash64Function(g_ActiveConfig.bHiresTextures || g_ActiveConfig.bDumpTextures);
|
||||
TexDecoder_SetTexFmtOverlayOptions(g_ActiveConfig.bTexFmtOverlayEnable, g_ActiveConfig.bTexFmtOverlayCenter);
|
||||
}
|
||||
|
||||
// TODO: Probably shouldn't clear all render targets here, just mark them dirty or something.
|
||||
if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed?
|
||||
config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture ||
|
||||
config.bCopyEFBScaled != backup_config.s_copy_efb_scaled ||
|
||||
config.bEFBCopyEnable != backup_config.s_copy_efb ||
|
||||
config.iEFBScale != backup_config.s_efb_scale)
|
||||
{
|
||||
g_texture_cache->ClearRenderTargets();
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Probably shouldn't clear all render targets here, just mark them dirty or something.
|
||||
if (config.bEFBCopyCacheEnable != backup_config.s_copy_cache_enable || // TODO: not sure if this is needed?
|
||||
config.bCopyEFBToTexture != backup_config.s_copy_efb_to_texture ||
|
||||
config.bCopyEFBScaled != backup_config.s_copy_efb_scaled ||
|
||||
config.bEFBCopyEnable != backup_config.s_copy_efb ||
|
||||
config.iEFBScale != backup_config.s_efb_scale)
|
||||
{
|
||||
g_texture_cache->ClearRenderTargets();
|
||||
}
|
||||
|
||||
skip_checks:
|
||||
|
||||
backup_config.s_colorsamples = config.iSafeTextureCache_ColorSamples;
|
||||
backup_config.s_copy_efb_to_texture = config.bCopyEFBToTexture;
|
||||
backup_config.s_copy_efb_scaled = config.bCopyEFBScaled;
|
||||
@@ -130,7 +129,10 @@ void TextureCache::Cleanup()
|
||||
TexCache::iterator tcend = textures.end();
|
||||
while (iter != tcend)
|
||||
{
|
||||
if (frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount) // TODO: Deleting EFB copies might not be a good idea here...
|
||||
if ( frameCount > TEXTURE_KILL_THRESHOLD + iter->second->frameCount
|
||||
|
||||
// EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted
|
||||
&& ! iter->second->IsEfbCopy() )
|
||||
{
|
||||
delete iter->second;
|
||||
textures.erase(iter++);
|
||||
@@ -218,6 +220,9 @@ void TextureCache::ClearRenderTargets()
|
||||
|
||||
bool TextureCache::CheckForCustomTextureLODs(u64 tex_hash, int texformat, unsigned int levels)
|
||||
{
|
||||
if (levels == 1)
|
||||
return false;
|
||||
|
||||
// Just checking if the necessary files exist, if they can't be loaded or have incorrect dimensions LODs will be black
|
||||
char texBasePathTemp[MAX_PATH];
|
||||
char texPathTemp[MAX_PATH];
|
||||
@@ -298,14 +303,30 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level)
|
||||
entry->Save(szTemp, level);
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
u32 address, unsigned int width, unsigned int height, int texformat,
|
||||
unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem)
|
||||
static u32 CalculateLevelSize(u32 level_0_size, u32 level)
|
||||
{
|
||||
return (level_0_size + ((1 << level) - 1)) >> level;
|
||||
}
|
||||
|
||||
// Used by TextureCache::Load
|
||||
static TextureCache::TCacheEntryBase* ReturnEntry(unsigned int stage, TextureCache::TCacheEntryBase* entry)
|
||||
{
|
||||
entry->frameCount = frameCount;
|
||||
entry->Bind(stage);
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true);
|
||||
|
||||
return entry;
|
||||
}
|
||||
|
||||
TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage,
|
||||
u32 const address, unsigned int width, unsigned int height, int const texformat,
|
||||
unsigned int const tlutaddr, int const tlutfmt, bool const use_mipmaps, unsigned int maxlevel, bool const from_tmem)
|
||||
{
|
||||
if (0 == address)
|
||||
return NULL;
|
||||
|
||||
// TexelSizeInNibbles(format)*width*height/16;
|
||||
// TexelSizeInNibbles(format) * width * height / 16;
|
||||
const unsigned int bsw = TexDecoder_GetBlockWidthInTexels(texformat) - 1;
|
||||
const unsigned int bsh = TexDecoder_GetBlockHeightInTexels(texformat) - 1;
|
||||
|
||||
@@ -314,11 +335,9 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
const unsigned int nativeW = width;
|
||||
const unsigned int nativeH = height;
|
||||
|
||||
bool using_custom_texture = false;
|
||||
bool using_custom_lods = false;
|
||||
|
||||
u32 texID = address;
|
||||
u64 tex_hash = TEXHASH_INVALID; // Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup)
|
||||
// Hash assigned to texcache entry (also used to generate filenames used for texture dumping and custom texture lookup)
|
||||
u64 tex_hash = TEXHASH_INVALID;
|
||||
u64 tlut_hash = TEXHASH_INVALID;
|
||||
|
||||
u32 full_format = texformat;
|
||||
@@ -329,9 +348,12 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
full_format = texformat | (tlutfmt << 16);
|
||||
|
||||
const u32 texture_size = TexDecoder_GetTextureSizeInBytes(expandedWidth, expandedHeight, texformat);
|
||||
u8* src_data;
|
||||
if (from_tmem) src_data = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE];
|
||||
else src_data = Memory::GetPointer(address);
|
||||
|
||||
const u8* src_data;
|
||||
if (from_tmem)
|
||||
src_data = &texMem[bpmem.tex[stage / 4].texImage1[stage % 4].tmem_even * TMEM_LINE_SIZE];
|
||||
else
|
||||
src_data = Memory::GetPointer(address);
|
||||
|
||||
// TODO: This doesn't hash GB tiles for preloaded RGBA8 textures (instead, it's hashing more data from the low tmem bank than it should)
|
||||
tex_hash = GetHash64(src_data, texture_size, g_ActiveConfig.iSafeTextureCache_ColorSamples);
|
||||
@@ -353,6 +375,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
tex_hash ^= tlut_hash;
|
||||
}
|
||||
|
||||
// D3D doesn't like when the specified mipmap count would require more than one 1x1-sized LOD in the mipmap chain
|
||||
// e.g. 64x64 with 7 LODs would have the mipmap chain 64x64,32x32,16x16,8x8,4x4,2x2,1x1,1x1, so we limit the mipmap count to 6 there
|
||||
while (g_ActiveConfig.backend_info.bUseMinimalMipCount && max(expandedWidth, expandedHeight) >> maxlevel == 0)
|
||||
--maxlevel;
|
||||
|
||||
TCacheEntryBase *entry = textures[texID];
|
||||
if (entry)
|
||||
{
|
||||
@@ -366,15 +393,17 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
{
|
||||
entry->type = TCET_EC_VRAM;
|
||||
|
||||
// TODO: Print a warning if the format changes! In this case, we could reinterpret the internal texture object data to the new pixel format (similiar to what is already being done in Renderer::ReinterpretPixelFormat())
|
||||
goto return_entry;
|
||||
// TODO: Print a warning if the format changes! In this case,
|
||||
// we could reinterpret the internal texture object data to the new pixel format
|
||||
// (similiar to what is already being done in Renderer::ReinterpretPixelFormat())
|
||||
return ReturnEntry(stage, entry);
|
||||
}
|
||||
|
||||
// 2. b) For normal textures, all texture parameters need to match
|
||||
if (address == entry->addr && tex_hash == entry->hash && full_format == entry->format &&
|
||||
entry->num_mipmaps == maxlevel && entry->native_width == nativeW && entry->native_height == nativeH)
|
||||
entry->num_mipmaps > maxlevel && entry->native_width == nativeW && entry->native_height == nativeH)
|
||||
{
|
||||
goto return_entry;
|
||||
return ReturnEntry(stage, entry);
|
||||
}
|
||||
|
||||
// 3. If we reach this line, we'll have to upload the new texture data to VRAM.
|
||||
@@ -382,7 +411,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
//
|
||||
// TODO: Don't we need to force texture decoding to RGBA8 for dynamic EFB copies?
|
||||
// TODO: Actually, it should be enough if the internal texture format matches...
|
||||
if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height && full_format == entry->format && entry->num_mipmaps == maxlevel)
|
||||
if ((entry->type == TCET_NORMAL && width == entry->virtual_width && height == entry->virtual_height
|
||||
&& full_format == entry->format && entry->num_mipmaps > maxlevel)
|
||||
|| (entry->type == TCET_EC_DYNAMIC && entry->native_width == width && entry->native_height == height))
|
||||
{
|
||||
// reuse the texture
|
||||
@@ -395,9 +425,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
}
|
||||
}
|
||||
|
||||
bool using_custom_texture = false;
|
||||
|
||||
if (g_ActiveConfig.bHiresTextures)
|
||||
{
|
||||
// This function may modify width/height.
|
||||
pcfmt = LoadCustomTexture(tex_hash, texformat, 0, width, height);
|
||||
if (pcfmt != PC_TEX_FMT_NONE)
|
||||
{
|
||||
@@ -428,115 +460,100 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int stage,
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Cleanup. Plus, we still autogenerate mipmaps in certain cases (we shouldn't do that)
|
||||
bool isPow2;
|
||||
unsigned int texLevels;
|
||||
isPow2 = !((width & (width - 1)) || (height & (height - 1)));
|
||||
texLevels = (isPow2 && maxlevel) ? GetPow2(std::max(width, height)) : !isPow2;
|
||||
texLevels = maxlevel ? std::min(texLevels, maxlevel + 1) : texLevels;
|
||||
using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
||||
UseNativeMips = UseNativeMips && !using_custom_lods && (width == nativeW && height == nativeH); // Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||
texLevels = (UseNativeMips || using_custom_lods) ? texLevels : !isPow2;
|
||||
u32 texLevels = use_mipmaps ? (maxlevel + 1) : 1;
|
||||
const bool using_custom_lods = using_custom_texture && CheckForCustomTextureLODs(tex_hash, texformat, texLevels);
|
||||
// Only load native mips if their dimensions fit to our virtual texture dimensions
|
||||
const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH);
|
||||
texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR)
|
||||
|
||||
// create the entry/texture
|
||||
if (NULL == entry) {
|
||||
if (NULL == entry)
|
||||
{
|
||||
textures[texID] = entry = g_texture_cache->CreateTexture(width, height, expandedWidth, texLevels, pcfmt);
|
||||
|
||||
// Sometimes, we can get around recreating a texture if only the number of mip levels changes
|
||||
// e.g. if our texture cache entry got too many mipmap levels we can limit the number of used levels by setting the appropriate render states
|
||||
// Thus, we don't update this member for every Load, but just whenever the texture gets recreated
|
||||
//
|
||||
// TODO: Won't we end up recreating textures all the time because maxlevel doesn't necessarily equal texLevels?
|
||||
entry->num_mipmaps = maxlevel; // TODO: Does this actually work? We can't really adjust mipmap settings per-stage...
|
||||
// TODO: D3D9 doesn't support min_lod. We should add a workaround for that here!
|
||||
|
||||
// TODO: This is the wrong value. We should be storing the number of levels our actual texture has.
|
||||
// But that will currently make the above "existing entry" tests fail as "texLevels" is not calculated until after.
|
||||
// Currently, we might try to reuse a texture which appears to have more levels than actual, maybe..
|
||||
entry->num_mipmaps = maxlevel + 1;
|
||||
entry->type = TCET_NORMAL;
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_NEW_TEXTURE, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
// load texture (CreateTexture also loads level 0)
|
||||
entry->Load(width, height, expandedWidth, 0);
|
||||
}
|
||||
|
||||
entry->SetGeneralParameters(address, texture_size, full_format, entry->num_mipmaps);
|
||||
entry->SetDimensions(nativeW, nativeH, width, height);
|
||||
entry->hash = tex_hash;
|
||||
if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture) entry->type = TCET_EC_DYNAMIC;
|
||||
else entry->type = TCET_NORMAL;
|
||||
|
||||
// load texture
|
||||
entry->Load(width, height, expandedWidth, 0, (texLevels == 0));
|
||||
|
||||
if (entry->IsEfbCopy() && !g_ActiveConfig.bCopyEFBToTexture)
|
||||
entry->type = TCET_EC_DYNAMIC;
|
||||
else
|
||||
entry->type = TCET_NORMAL;
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures && !using_custom_texture)
|
||||
DumpTexture(entry, 0);
|
||||
|
||||
u32 level = 1;
|
||||
// load mips - TODO: Loading mipmaps from tmem is untested!
|
||||
if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && UseNativeMips)
|
||||
if (pcfmt != PC_TEX_FMT_NONE)
|
||||
{
|
||||
const unsigned int bsdepth = TexDecoder_GetTexelSizeInNibbles(texformat);
|
||||
|
||||
unsigned int level = 1;
|
||||
unsigned int mipWidth = (width + 1) >> 1;
|
||||
unsigned int mipHeight = (height + 1) >> 1;
|
||||
|
||||
u8* ptr_even = NULL, *ptr_odd = NULL;
|
||||
if (from_tmem)
|
||||
if (use_native_mips)
|
||||
{
|
||||
ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size];
|
||||
ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE];
|
||||
src_data += texture_size;
|
||||
|
||||
const u8* ptr_even = NULL;
|
||||
const u8* ptr_odd = NULL;
|
||||
if (from_tmem)
|
||||
{
|
||||
ptr_even = &texMem[bpmem.tex[stage/4].texImage1[stage%4].tmem_even * TMEM_LINE_SIZE + texture_size];
|
||||
ptr_odd = &texMem[bpmem.tex[stage/4].texImage2[stage%4].tmem_odd * TMEM_LINE_SIZE];
|
||||
}
|
||||
|
||||
for (; level != texLevels; ++level)
|
||||
{
|
||||
const u32 mip_width = CalculateLevelSize(width, level);
|
||||
const u32 mip_height = CalculateLevelSize(height, level);
|
||||
const u32 expanded_mip_width = (mip_width + bsw) & (~bsw);
|
||||
const u32 expanded_mip_height = (mip_height + bsh) & (~bsh);
|
||||
|
||||
const u8*& mip_src_data = from_tmem
|
||||
? ((level % 2) ? ptr_odd : ptr_even)
|
||||
: src_data;
|
||||
TexDecoder_Decode(temp, mip_src_data, expanded_mip_width, expanded_mip_height, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
||||
mip_src_data += TexDecoder_GetTextureSizeInBytes(expanded_mip_width, expanded_mip_height, texformat);
|
||||
|
||||
entry->Load(mip_width, mip_height, expanded_mip_width, level);
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures)
|
||||
DumpTexture(entry, level);
|
||||
}
|
||||
}
|
||||
src_data += texture_size;
|
||||
|
||||
while ((mipHeight || mipWidth) && (level < texLevels))
|
||||
else if (using_custom_lods)
|
||||
{
|
||||
u8** ptr;
|
||||
if (from_tmem) ptr = (level % 2) ? &ptr_odd : &ptr_even;
|
||||
else ptr = &src_data;
|
||||
for (; level != texLevels; ++level)
|
||||
{
|
||||
unsigned int mip_width = CalculateLevelSize(width, level);
|
||||
unsigned int mip_height = CalculateLevelSize(height, level);
|
||||
|
||||
const unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1;
|
||||
const unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
||||
|
||||
expandedWidth = (currentWidth + bsw) & (~bsw);
|
||||
expandedHeight = (currentHeight + bsh) & (~bsh);
|
||||
|
||||
TexDecoder_Decode(temp, *ptr, expandedWidth, expandedHeight, texformat, tlutaddr, tlutfmt, g_ActiveConfig.backend_info.bUseRGBATextures);
|
||||
entry->Load(currentWidth, currentHeight, expandedWidth, level, false);
|
||||
|
||||
if (g_ActiveConfig.bDumpTextures)
|
||||
DumpTexture(entry, level);
|
||||
|
||||
*ptr += ((std::max(mipWidth, bsw) * std::max(mipHeight, bsh) * bsdepth) >> 1);
|
||||
mipWidth >>= 1;
|
||||
mipHeight >>= 1;
|
||||
++level;
|
||||
}
|
||||
}
|
||||
else if (texLevels > 1 && pcfmt != PC_TEX_FMT_NONE && using_custom_lods)
|
||||
{
|
||||
unsigned int level = 1;
|
||||
unsigned int mipWidth = (width + 1) >> 1;
|
||||
unsigned int mipHeight = (height + 1) >> 1;
|
||||
|
||||
while ((mipHeight || mipWidth) && (level < texLevels))
|
||||
{
|
||||
unsigned int currentWidth = (mipWidth > 0) ? mipWidth : 1;
|
||||
unsigned int currentHeight = (mipHeight > 0) ? mipHeight : 1;
|
||||
|
||||
LoadCustomTexture(tex_hash, texformat, level, currentWidth, currentHeight);
|
||||
entry->Load(currentWidth, currentHeight, currentWidth, level, false);
|
||||
|
||||
mipWidth >>= 1;
|
||||
mipHeight >>= 1;
|
||||
++level;
|
||||
LoadCustomTexture(tex_hash, texformat, level, mip_width, mip_height);
|
||||
entry->Load(mip_width, mip_height, mip_width, level);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
INCSTAT(stats.numTexturesCreated);
|
||||
SETSTAT(stats.numTexturesAlive, textures.size());
|
||||
|
||||
return_entry:
|
||||
|
||||
entry->frameCount = frameCount;
|
||||
entry->Bind(stage);
|
||||
|
||||
GFX_DEBUGGER_PAUSE_AT(NEXT_TEXTURE_CHANGE, true);
|
||||
|
||||
return entry;
|
||||
return ReturnEntry(stage, entry);
|
||||
}
|
||||
|
||||
void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
||||
@@ -708,7 +725,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
case 1: // R8
|
||||
case 8: // R8
|
||||
colmat[0] = colmat[4] = colmat[8] = colmat[12] = 1;
|
||||
cbufid = 13;
|
||||
cbufid = 13;
|
||||
break;
|
||||
|
||||
case 2: // RA4
|
||||
@@ -729,11 +746,11 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
|
||||
case 9: // G8
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[13] = 1.0f;
|
||||
cbufid = 17;
|
||||
cbufid = 17;
|
||||
break;
|
||||
case 10: // B8
|
||||
colmat[2] = colmat[6] = colmat[10] = colmat[14] = 1.0f;
|
||||
cbufid = 18;
|
||||
cbufid = 18;
|
||||
break;
|
||||
|
||||
case 11: // RG8
|
||||
@@ -742,7 +759,7 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
break;
|
||||
|
||||
case 12: // GB8
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
|
||||
colmat[1] = colmat[5] = colmat[9] = colmat[14] = 1.0f;
|
||||
cbufid = 20;
|
||||
break;
|
||||
|
||||
@@ -814,9 +831,5 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat
|
||||
|
||||
entry->frameCount = frameCount;
|
||||
|
||||
g_renderer->ResetAPIState(); // reset any game specific settings
|
||||
|
||||
entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat);
|
||||
|
||||
g_renderer->RestoreAPIState();
|
||||
}
|
||||
|
||||
@@ -60,26 +60,26 @@ public:
|
||||
int frameCount;
|
||||
|
||||
|
||||
void SetGeneralParameters(u32 addr, u32 size, u32 format, unsigned int num_mipmaps)
|
||||
void SetGeneralParameters(u32 _addr, u32 _size, u32 _format, unsigned int _num_mipmaps)
|
||||
{
|
||||
this->addr = addr;
|
||||
this->size_in_bytes = size;
|
||||
this->format = format;
|
||||
this->num_mipmaps = num_mipmaps;
|
||||
addr = _addr;
|
||||
size_in_bytes = _size;
|
||||
format = _format;
|
||||
num_mipmaps = _num_mipmaps;
|
||||
}
|
||||
|
||||
void SetDimensions(unsigned int native_width, unsigned int native_height, unsigned int virtual_width, unsigned int virtual_height)
|
||||
void SetDimensions(unsigned int _native_width, unsigned int _native_height, unsigned int _virtual_width, unsigned int _virtual_height)
|
||||
{
|
||||
this->native_width = native_width;
|
||||
this->native_height = native_height;
|
||||
this->virtual_width = virtual_width;
|
||||
this->virtual_height = virtual_height;
|
||||
native_width = _native_width;
|
||||
native_height = _native_height;
|
||||
virtual_width = _virtual_width;
|
||||
virtual_height = _virtual_height;
|
||||
}
|
||||
|
||||
void SetHashes(u64 hash/*, u32 pal_hash*/)
|
||||
void SetHashes(u64 _hash/*, u32 _pal_hash*/)
|
||||
{
|
||||
this->hash = hash;
|
||||
//this->pal_hash = pal_hash;
|
||||
hash = _hash;
|
||||
//pal_hash = _pal_hash;
|
||||
}
|
||||
|
||||
|
||||
@@ -89,7 +89,7 @@ public:
|
||||
virtual bool Save(const char filename[], unsigned int level) = 0;
|
||||
|
||||
virtual void Load(unsigned int width, unsigned int height,
|
||||
unsigned int expanded_width, unsigned int level, bool autogen_mips) = 0;
|
||||
unsigned int expanded_width, unsigned int level) = 0;
|
||||
virtual void FromRenderTarget(u32 dstAddr, unsigned int dstFormat,
|
||||
unsigned int srcFormat, const EFBRectangle& srcRect,
|
||||
bool isIntensity, bool scaleByHalf, unsigned int cbufid,
|
||||
@@ -116,7 +116,7 @@ public:
|
||||
virtual TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) = 0;
|
||||
|
||||
static TCacheEntryBase* Load(unsigned int stage, u32 address, unsigned int width, unsigned int height,
|
||||
int format, unsigned int tlutaddr, int tlutfmt, bool UseNativeMips, unsigned int maxlevel, bool from_tmem);
|
||||
int format, unsigned int tlutaddr, int tlutfmt, bool use_mipmaps, unsigned int maxlevel, bool from_tmem);
|
||||
static void CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat, unsigned int srcFormat,
|
||||
const EFBRectangle& srcRect, bool isIntensity, bool scaleByHalf);
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -27,41 +27,41 @@ extern GC_ALIGNED16(u8 texMem[TMEM_SIZE]);
|
||||
|
||||
enum TextureFormat
|
||||
{
|
||||
GX_TF_I4 = 0x0,
|
||||
GX_TF_I8 = 0x1,
|
||||
GX_TF_IA4 = 0x2,
|
||||
GX_TF_IA8 = 0x3,
|
||||
GX_TF_RGB565 = 0x4,
|
||||
GX_TF_RGB5A3 = 0x5,
|
||||
GX_TF_RGBA8 = 0x6,
|
||||
GX_TF_C4 = 0x8,
|
||||
GX_TF_C8 = 0x9,
|
||||
GX_TF_C14X2 = 0xA,
|
||||
GX_TF_CMPR = 0xE,
|
||||
GX_TF_I4 = 0x0,
|
||||
GX_TF_I8 = 0x1,
|
||||
GX_TF_IA4 = 0x2,
|
||||
GX_TF_IA8 = 0x3,
|
||||
GX_TF_RGB565 = 0x4,
|
||||
GX_TF_RGB5A3 = 0x5,
|
||||
GX_TF_RGBA8 = 0x6,
|
||||
GX_TF_C4 = 0x8,
|
||||
GX_TF_C8 = 0x9,
|
||||
GX_TF_C14X2 = 0xA,
|
||||
GX_TF_CMPR = 0xE,
|
||||
|
||||
_GX_TF_CTF = 0x20, // copy-texture-format only (simply means linear?)
|
||||
_GX_TF_ZTF = 0x10, // Z-texture-format
|
||||
_GX_TF_CTF = 0x20, // copy-texture-format only (simply means linear?)
|
||||
_GX_TF_ZTF = 0x10, // Z-texture-format
|
||||
|
||||
// these formats are also valid when copying targets
|
||||
GX_CTF_R4 = 0x0 | _GX_TF_CTF,
|
||||
GX_CTF_RA4 = 0x2 | _GX_TF_CTF,
|
||||
GX_CTF_RA8 = 0x3 | _GX_TF_CTF,
|
||||
GX_CTF_YUVA8 = 0x6 | _GX_TF_CTF,
|
||||
GX_CTF_A8 = 0x7 | _GX_TF_CTF,
|
||||
GX_CTF_R8 = 0x8 | _GX_TF_CTF,
|
||||
GX_CTF_G8 = 0x9 | _GX_TF_CTF,
|
||||
GX_CTF_B8 = 0xA | _GX_TF_CTF,
|
||||
GX_CTF_RG8 = 0xB | _GX_TF_CTF,
|
||||
GX_CTF_GB8 = 0xC | _GX_TF_CTF,
|
||||
// these formats are also valid when copying targets
|
||||
GX_CTF_R4 = 0x0 | _GX_TF_CTF,
|
||||
GX_CTF_RA4 = 0x2 | _GX_TF_CTF,
|
||||
GX_CTF_RA8 = 0x3 | _GX_TF_CTF,
|
||||
GX_CTF_YUVA8 = 0x6 | _GX_TF_CTF,
|
||||
GX_CTF_A8 = 0x7 | _GX_TF_CTF,
|
||||
GX_CTF_R8 = 0x8 | _GX_TF_CTF,
|
||||
GX_CTF_G8 = 0x9 | _GX_TF_CTF,
|
||||
GX_CTF_B8 = 0xA | _GX_TF_CTF,
|
||||
GX_CTF_RG8 = 0xB | _GX_TF_CTF,
|
||||
GX_CTF_GB8 = 0xC | _GX_TF_CTF,
|
||||
|
||||
GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
|
||||
GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
|
||||
GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
|
||||
GX_TF_Z8 = 0x1 | _GX_TF_ZTF,
|
||||
GX_TF_Z16 = 0x3 | _GX_TF_ZTF,
|
||||
GX_TF_Z24X8 = 0x6 | _GX_TF_ZTF,
|
||||
|
||||
GX_CTF_Z4 = 0x0 | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z8M = 0x9 | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z8L = 0xA | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z16L = 0xC | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z4 = 0x0 | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z8M = 0x9 | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z8L = 0xA | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
GX_CTF_Z16L = 0xC | _GX_TF_ZTF | _GX_TF_CTF,
|
||||
};
|
||||
|
||||
int TexDecoder_GetTexelSizeInNibbles(int format);
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
#include "MemoryUtil.h"
|
||||
#include "StringUtil.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "x64ABI.h"
|
||||
#include "PixelEngine.h"
|
||||
#include "Host.h"
|
||||
|
||||
@@ -43,8 +43,11 @@
|
||||
//BBox
|
||||
#include "XFMemory.h"
|
||||
extern float GC_ALIGNED16(g_fProjectionMatrix[16]);
|
||||
|
||||
#ifndef _M_GENERIC
|
||||
#ifndef __APPLE__
|
||||
#define USE_JIT
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#define COMPILED_CODE_SIZE 4096
|
||||
|
||||
@@ -72,6 +75,10 @@ int colElements[2];
|
||||
float posScale;
|
||||
float tcScale[8];
|
||||
|
||||
// bbox must read vertex position, so convert it to this buffer
|
||||
static float s_bbox_vertex_buffer[3];
|
||||
static u8 *s_bbox_pCurBufferPointer_orig;
|
||||
|
||||
static const float fractionTable[32] = {
|
||||
1.0f / (1U << 0), 1.0f / (1U << 1), 1.0f / (1U << 2), 1.0f / (1U << 3),
|
||||
1.0f / (1U << 4), 1.0f / (1U << 5), 1.0f / (1U << 6), 1.0f / (1U << 7),
|
||||
@@ -93,10 +100,21 @@ void LOADERDECL PosMtx_ReadDirect_UByte()
|
||||
|
||||
void LOADERDECL PosMtx_Write()
|
||||
{
|
||||
*VertexManager::s_pCurBufferPointer++ = s_curposmtx;
|
||||
*VertexManager::s_pCurBufferPointer++ = 0;
|
||||
*VertexManager::s_pCurBufferPointer++ = 0;
|
||||
*VertexManager::s_pCurBufferPointer++ = 0;
|
||||
DataWrite<u8>(s_curposmtx);
|
||||
DataWrite<u8>(0);
|
||||
DataWrite<u8>(0);
|
||||
DataWrite<u8>(0);
|
||||
}
|
||||
|
||||
void LOADERDECL UpdateBoundingBoxPrepare()
|
||||
{
|
||||
if (!PixelEngine::bbox_active)
|
||||
return;
|
||||
|
||||
// set our buffer as videodata buffer, so we will get a copy of the vertex positions
|
||||
// this is a big hack, but so we can use the same converting function then without bbox
|
||||
s_bbox_pCurBufferPointer_orig = VertexManager::s_pCurBufferPointer;
|
||||
VertexManager::s_pCurBufferPointer = (u8*)s_bbox_vertex_buffer;
|
||||
}
|
||||
|
||||
void LOADERDECL UpdateBoundingBox()
|
||||
@@ -104,12 +122,16 @@ void LOADERDECL UpdateBoundingBox()
|
||||
if (!PixelEngine::bbox_active)
|
||||
return;
|
||||
|
||||
// Truly evil hack, reading backwards from the write pointer. If we were writing to write-only
|
||||
// memory like we might have been with a D3D vertex buffer, this would have been a bad idea.
|
||||
float *data = (float *)(VertexManager::s_pCurBufferPointer - 12);
|
||||
// reset videodata pointer
|
||||
VertexManager::s_pCurBufferPointer = s_bbox_pCurBufferPointer_orig;
|
||||
|
||||
// copy vertex pointers
|
||||
memcpy(VertexManager::s_pCurBufferPointer, s_bbox_vertex_buffer, 12);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
|
||||
// We must transform the just loaded point by the current world and projection matrix - in software.
|
||||
// Then convert to screen space and update the bounding box.
|
||||
float p[3] = {data[0], data[1], data[2]};
|
||||
float p[3] = {s_bbox_vertex_buffer[0], s_bbox_vertex_buffer[1], s_bbox_vertex_buffer[2]};
|
||||
|
||||
const float *world_matrix = (float*)xfmem + MatrixIndexA.PosNormalMtxIdx * 4;
|
||||
const float *proj_matrix = &g_fProjectionMatrix[0];
|
||||
@@ -147,24 +169,22 @@ void LOADERDECL TexMtx_ReadDirect_UByte()
|
||||
|
||||
void LOADERDECL TexMtx_Write_Float()
|
||||
{
|
||||
*(float*)VertexManager::s_pCurBufferPointer = (float)s_curtexmtx[s_texmtxwrite++];
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
||||
}
|
||||
|
||||
void LOADERDECL TexMtx_Write_Float2()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = 0;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)s_curtexmtx[s_texmtxwrite++];
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
DataWrite(0.f);
|
||||
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
||||
}
|
||||
|
||||
void LOADERDECL TexMtx_Write_Float4()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = 0;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = 0;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = s_curtexmtx[s_texmtxwrite++];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[3] = 0; // Just to fill out with 0.
|
||||
VertexManager::s_pCurBufferPointer += 16;
|
||||
DataWrite(0.f);
|
||||
DataWrite(0.f);
|
||||
DataWrite(float(s_curtexmtx[s_texmtxwrite++]));
|
||||
// Just to fill out with 0.
|
||||
DataWrite(0.f);
|
||||
}
|
||||
|
||||
VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
|
||||
@@ -182,14 +202,21 @@ VertexLoader::VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr)
|
||||
m_VtxDesc = vtx_desc;
|
||||
SetVAT(vtx_attr.g0.Hex, vtx_attr.g1.Hex, vtx_attr.g2.Hex);
|
||||
|
||||
#ifdef USE_JIT
|
||||
AllocCodeSpace(COMPILED_CODE_SIZE);
|
||||
CompileVertexTranslator();
|
||||
WriteProtect();
|
||||
#else
|
||||
CompileVertexTranslator();
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
VertexLoader::~VertexLoader()
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
FreeCodeSpace();
|
||||
#endif
|
||||
delete m_NativeFmt;
|
||||
}
|
||||
|
||||
@@ -267,15 +294,16 @@ void VertexLoader::CompileVertexTranslator()
|
||||
if (m_VtxDesc.Tex7MatIdx) {m_VertexSize += 1; m_NativeFmt->m_components |= VB_HAS_TEXMTXIDX7; WriteCall(TexMtx_ReadDirect_UByte); }
|
||||
|
||||
// Write vertex position loader
|
||||
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
|
||||
if(g_ActiveConfig.bUseBBox) {
|
||||
WriteCall(UpdateBoundingBoxPrepare);
|
||||
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
|
||||
WriteCall(UpdateBoundingBox);
|
||||
} else {
|
||||
WriteCall(VertexLoader_Position::GetFunction(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements));
|
||||
}
|
||||
m_VertexSize += VertexLoader_Position::GetSize(m_VtxDesc.Position, m_VtxAttr.PosFormat, m_VtxAttr.PosElements);
|
||||
nat_offset += 12;
|
||||
|
||||
// OK, so we just got a point. Let's go back and read it for the bounding box.
|
||||
|
||||
if(g_ActiveConfig.bUseBBox)
|
||||
WriteCall(UpdateBoundingBox);
|
||||
|
||||
// Normals
|
||||
vtx_decl.num_normals = 0;
|
||||
if (m_VtxDesc.Normal != NOT_PRESENT)
|
||||
@@ -307,7 +335,7 @@ void VertexLoader::CompileVertexTranslator()
|
||||
nat_offset += 12;
|
||||
vtx_decl.normal_offset[2] = nat_offset;
|
||||
nat_offset += 12;
|
||||
}
|
||||
}
|
||||
|
||||
int numNormals = (m_VtxAttr.NormalElements == 1) ? NRM_THREE : NRM_ONE;
|
||||
m_NativeFmt->m_components |= VB_HAS_NRM0;
|
||||
@@ -339,7 +367,7 @@ void VertexLoader::CompileVertexTranslator()
|
||||
default: _assert_(0); break;
|
||||
}
|
||||
break;
|
||||
case INDEX8:
|
||||
case INDEX8:
|
||||
m_VertexSize += 1;
|
||||
switch (m_VtxAttr.color[i].Comp)
|
||||
{
|
||||
@@ -474,7 +502,8 @@ void VertexLoader::WriteCall(TPipelineFunction func)
|
||||
m_PipelineStages[m_numPipelineStages++] = func;
|
||||
#endif
|
||||
}
|
||||
|
||||
// ARMTODO: This should be done in a better way
|
||||
#ifndef _M_GENERIC
|
||||
void VertexLoader::WriteGetVariable(int bits, OpArg dest, void *address)
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
@@ -498,8 +527,9 @@ void VertexLoader::WriteSetVariable(int bits, void *address, OpArg value)
|
||||
#endif
|
||||
#endif
|
||||
}
|
||||
#endif
|
||||
|
||||
void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||
int VertexLoader::SetupRunVertices(int vtx_attr_group, int primitive, int const count)
|
||||
{
|
||||
m_numLoadedVertices += count;
|
||||
|
||||
@@ -518,7 +548,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||
{
|
||||
// if cull mode is none, ignore triangles and quads
|
||||
DataSkip(count * m_VertexSize);
|
||||
return;
|
||||
return 0;
|
||||
}
|
||||
|
||||
m_NativeFmt->EnableComponents(m_NativeFmt->m_components);
|
||||
@@ -528,7 +558,7 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||
m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac;
|
||||
m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac;
|
||||
m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac;
|
||||
m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac;
|
||||
m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac;
|
||||
m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac;
|
||||
@@ -542,157 +572,48 @@ void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int count)
|
||||
for (int i = 0; i < 2; i++)
|
||||
colElements[i] = m_VtxAttr.color[i].Elements;
|
||||
|
||||
// if strips or fans, make sure all vertices can fit in buffer, otherwise flush
|
||||
int granularity = 1;
|
||||
switch (primitive) {
|
||||
case 3: // strip .. hm, weird
|
||||
case 4: // fan
|
||||
if (VertexManager::GetRemainingSize() < 3 * native_stride)
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
case 6: // line strip
|
||||
if (VertexManager::GetRemainingSize() < 2 * native_stride)
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
case 0: granularity = 4; break; // quads
|
||||
case 2: granularity = 3; break; // tris
|
||||
case 5: granularity = 2; break; // lines
|
||||
}
|
||||
|
||||
int startv = 0, extraverts = 0;
|
||||
int v = 0;
|
||||
|
||||
//int remainingVerts2 = VertexManager::GetRemainingVertices(primitive);
|
||||
while (v < count)
|
||||
{
|
||||
int remainingVerts = VertexManager::GetRemainingSize() / native_stride;
|
||||
//if (remainingVerts2 - v + startv < remainingVerts)
|
||||
//remainingVerts = remainingVerts2 - v + startv;
|
||||
if (remainingVerts < granularity) {
|
||||
INCSTAT(stats.thisFrame.numBufferSplits);
|
||||
// This buffer full - break current primitive and flush, to switch to the next buffer.
|
||||
u8* plastptr = VertexManager::s_pCurBufferPointer;
|
||||
if (v - startv > 0)
|
||||
VertexManager::AddVertices(primitive, v - startv + extraverts);
|
||||
VertexManager::Flush();
|
||||
//remainingVerts2 = VertexManager::GetRemainingVertices(primitive);
|
||||
// Why does this need to be so complicated?
|
||||
switch (primitive) {
|
||||
case 3: // triangle strip, copy last two vertices
|
||||
// a little trick since we have to keep track of signs
|
||||
if (v & 1) {
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-2*native_stride, native_stride);
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer+native_stride, plastptr-native_stride*2, 2*native_stride);
|
||||
VertexManager::s_pCurBufferPointer += native_stride*3;
|
||||
extraverts = 3;
|
||||
}
|
||||
else {
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*2, native_stride*2);
|
||||
VertexManager::s_pCurBufferPointer += native_stride*2;
|
||||
extraverts = 2;
|
||||
}
|
||||
break;
|
||||
case 4: // tri fan, copy first and last vert
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride*(v-startv+extraverts), native_stride);
|
||||
VertexManager::s_pCurBufferPointer += native_stride;
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride);
|
||||
VertexManager::s_pCurBufferPointer += native_stride;
|
||||
extraverts = 2;
|
||||
break;
|
||||
case 6: // line strip
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, plastptr-native_stride, native_stride);
|
||||
VertexManager::s_pCurBufferPointer += native_stride;
|
||||
extraverts = 1;
|
||||
break;
|
||||
default:
|
||||
extraverts = 0;
|
||||
break;
|
||||
}
|
||||
startv = v;
|
||||
}
|
||||
int remainingPrims = remainingVerts / granularity;
|
||||
remainingVerts = remainingPrims * granularity;
|
||||
if (count - v < remainingVerts)
|
||||
remainingVerts = count - v;
|
||||
|
||||
#ifdef USE_JIT
|
||||
if (remainingVerts > 0) {
|
||||
loop_counter = remainingVerts;
|
||||
((void (*)())(void*)m_compiledCode)();
|
||||
}
|
||||
#else
|
||||
for (int s = 0; s < remainingVerts; s++)
|
||||
{
|
||||
tcIndex = 0;
|
||||
colIndex = 0;
|
||||
s_texmtxwrite = s_texmtxread = 0;
|
||||
for (int i = 0; i < m_numPipelineStages; i++)
|
||||
m_PipelineStages[i]();
|
||||
PRIM_LOG("\n");
|
||||
}
|
||||
#endif
|
||||
v += remainingVerts;
|
||||
}
|
||||
|
||||
if (startv < count)
|
||||
VertexManager::AddVertices(primitive, count - startv + extraverts);
|
||||
VertexManager::PrepareForAdditionalData(primitive, count, native_stride);
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data)
|
||||
void VertexLoader::RunVertices(int vtx_attr_group, int primitive, int const count)
|
||||
{
|
||||
m_numLoadedVertices += count;
|
||||
|
||||
// Flush if our vertex format is different from the currently set.
|
||||
if (g_nativeVertexFmt != NULL && g_nativeVertexFmt != m_NativeFmt)
|
||||
{
|
||||
// We really must flush here. It's possible that the native representations
|
||||
// of the two vtx formats are the same, but we have no way to easily check that
|
||||
// now.
|
||||
VertexManager::Flush();
|
||||
// Also move the Set() here?
|
||||
}
|
||||
g_nativeVertexFmt = m_NativeFmt;
|
||||
|
||||
if (bpmem.genMode.cullmode == 3 && primitive < 5)
|
||||
{
|
||||
// if cull mode is none, ignore triangles and quads
|
||||
DataSkip(count * m_VertexSize);
|
||||
return;
|
||||
}
|
||||
|
||||
m_NativeFmt->EnableComponents(m_NativeFmt->m_components);
|
||||
|
||||
// Load position and texcoord scale factors.
|
||||
m_VtxAttr.PosFrac = g_VtxAttr[vtx_attr_group].g0.PosFrac;
|
||||
m_VtxAttr.texCoord[0].Frac = g_VtxAttr[vtx_attr_group].g0.Tex0Frac;
|
||||
m_VtxAttr.texCoord[1].Frac = g_VtxAttr[vtx_attr_group].g1.Tex1Frac;
|
||||
m_VtxAttr.texCoord[2].Frac = g_VtxAttr[vtx_attr_group].g1.Tex2Frac;
|
||||
m_VtxAttr.texCoord[3].Frac = g_VtxAttr[vtx_attr_group].g1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[4].Frac = g_VtxAttr[vtx_attr_group].g2.Tex4Frac;
|
||||
m_VtxAttr.texCoord[5].Frac = g_VtxAttr[vtx_attr_group].g2.Tex5Frac;
|
||||
m_VtxAttr.texCoord[6].Frac = g_VtxAttr[vtx_attr_group].g2.Tex6Frac;
|
||||
m_VtxAttr.texCoord[7].Frac = g_VtxAttr[vtx_attr_group].g2.Tex7Frac;
|
||||
|
||||
pVtxAttr = &m_VtxAttr;
|
||||
posScale = fractionTable[m_VtxAttr.PosFrac];
|
||||
if (m_NativeFmt->m_components & VB_HAS_UVALL)
|
||||
for (int i = 0; i < 8; i++)
|
||||
tcScale[i] = fractionTable[m_VtxAttr.texCoord[i].Frac];
|
||||
for (int i = 0; i < 2; i++)
|
||||
colElements[i] = m_VtxAttr.color[i].Elements;
|
||||
|
||||
if(VertexManager::GetRemainingSize() < native_stride * count)
|
||||
VertexManager::Flush();
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * count);
|
||||
VertexManager::s_pCurBufferPointer += native_stride * count;
|
||||
DataSkip(count * m_VertexSize);
|
||||
VertexManager::AddVertices(primitive, count);
|
||||
auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
|
||||
ConvertVertices(new_count);
|
||||
VertexManager::AddVertices(primitive, new_count);
|
||||
}
|
||||
|
||||
void VertexLoader::ConvertVertices ( int count )
|
||||
{
|
||||
#ifdef USE_JIT
|
||||
if (count > 0) {
|
||||
loop_counter = count;
|
||||
((void (*)())(void*)m_compiledCode)();
|
||||
}
|
||||
#else
|
||||
for (int s = 0; s < count; s++)
|
||||
{
|
||||
tcIndex = 0;
|
||||
colIndex = 0;
|
||||
s_texmtxwrite = s_texmtxread = 0;
|
||||
for (int i = 0; i < m_numPipelineStages; i++)
|
||||
m_PipelineStages[i]();
|
||||
PRIM_LOG("\n");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
void VertexLoader::RunCompiledVertices(int vtx_attr_group, int primitive, int const count, u8* Data)
|
||||
{
|
||||
auto const new_count = SetupRunVertices(vtx_attr_group, primitive, count);
|
||||
|
||||
memcpy_gc(VertexManager::s_pCurBufferPointer, Data, native_stride * new_count);
|
||||
VertexManager::s_pCurBufferPointer += native_stride * new_count;
|
||||
DataSkip(new_count * m_VertexSize);
|
||||
|
||||
VertexManager::AddVertices(primitive, new_count);
|
||||
}
|
||||
|
||||
void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
|
||||
{
|
||||
@@ -724,7 +645,7 @@ void VertexLoader::SetVAT(u32 _group0, u32 _group1, u32 _group2)
|
||||
m_VtxAttr.texCoord[2].Frac = vat.g1.Tex2Frac;
|
||||
m_VtxAttr.texCoord[3].Elements = vat.g1.Tex3CoordElements;
|
||||
m_VtxAttr.texCoord[3].Format = vat.g1.Tex3CoordFormat;
|
||||
m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[3].Frac = vat.g1.Tex3Frac;
|
||||
m_VtxAttr.texCoord[4].Elements = vat.g1.Tex4CoordElements;
|
||||
m_VtxAttr.texCoord[4].Format = vat.g1.Tex4CoordFormat;
|
||||
|
||||
|
||||
@@ -76,13 +76,20 @@ private:
|
||||
}
|
||||
};
|
||||
|
||||
// ARMTODO: This should be done in a better way
|
||||
#ifndef _M_GENERIC
|
||||
class VertexLoader : public Gen::XCodeBlock, NonCopyable
|
||||
#else
|
||||
class VertexLoader
|
||||
#endif
|
||||
{
|
||||
public:
|
||||
VertexLoader(const TVtxDesc &vtx_desc, const VAT &vtx_attr);
|
||||
~VertexLoader();
|
||||
|
||||
int GetVertexSize() const {return m_VertexSize;}
|
||||
|
||||
int SetupRunVertices(int vtx_attr_group, int primitive, int const count);
|
||||
void RunVertices(int vtx_attr_group, int primitive, int count);
|
||||
void RunCompiledVertices(int vtx_attr_group, int primitive, int count, u8* Data);
|
||||
|
||||
@@ -119,11 +126,14 @@ private:
|
||||
void SetVAT(u32 _group0, u32 _group1, u32 _group2);
|
||||
|
||||
void CompileVertexTranslator();
|
||||
void ConvertVertices(int count);
|
||||
|
||||
void WriteCall(TPipelineFunction);
|
||||
|
||||
#ifndef _M_GENERIC
|
||||
void WriteGetVariable(int bits, Gen::OpArg dest, void *address);
|
||||
void WriteSetVariable(int bits, void *address, Gen::OpArg dest);
|
||||
};
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,9 +15,6 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _VERTEXLOADERCOLOR_H
|
||||
#define _VERTEXLOADERCOLOR_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "LookUpTables.h"
|
||||
@@ -37,8 +34,7 @@ extern int colElements[2];
|
||||
|
||||
__forceinline void _SetCol(u32 val)
|
||||
{
|
||||
*(u32*)VertexManager::s_pCurBufferPointer = val;
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
DataWrite(val);
|
||||
colIndex++;
|
||||
}
|
||||
|
||||
@@ -132,80 +128,65 @@ void LOADERDECL Color_ReadDirect_32b_8888()
|
||||
_SetCol(col);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LOADERDECL Color_ReadIndex8_16b_565()
|
||||
template <typename I>
|
||||
void Color_ReadIndex_16b_565()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
auto const Index = DataRead<I>();
|
||||
u16 val = Common::swap16(*(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex])));
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_888()
|
||||
|
||||
template <typename I>
|
||||
void Color_ReadIndex_24b_888()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
auto const Index = DataRead<I>();
|
||||
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_888x()
|
||||
|
||||
template <typename I>
|
||||
void Color_ReadIndex_32b_888x()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
auto const Index = DataRead<I>();
|
||||
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_16b_4444()
|
||||
|
||||
template <typename I>
|
||||
void Color_ReadIndex_16b_4444()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
auto const Index = DataRead<I>();
|
||||
u16 val = *(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]));
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_24b_6666()
|
||||
|
||||
template <typename I>
|
||||
void Color_ReadIndex_24b_6666()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
auto const Index = DataRead<I>();
|
||||
const u8* pData = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]) - 1;
|
||||
u32 val = Common::swap32(pData);
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex8_32b_8888()
|
||||
|
||||
template <typename I>
|
||||
void Color_ReadIndex_32b_8888()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
auto const Index = DataRead<I>();
|
||||
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_16b_565()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u16 val = Common::swap16(*(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex])));
|
||||
_SetCol565(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_888()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_888x()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read24(iAddress));
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_16b_4444()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
u16 val = *(const u16 *)(cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]));
|
||||
_SetCol4444(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_24b_6666()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *pData = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]) - 1;
|
||||
u32 val = Common::swap32(pData);
|
||||
_SetCol6666(val);
|
||||
}
|
||||
void LOADERDECL Color_ReadIndex16_32b_8888()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *iAddress = cached_arraybases[ARRAY_COLOR+colIndex] + (Index * arraystrides[ARRAY_COLOR+colIndex]);
|
||||
_SetCol(_Read32(iAddress));
|
||||
}
|
||||
#endif
|
||||
|
||||
void LOADERDECL Color_ReadIndex8_16b_565() { Color_ReadIndex_16b_565<u8>(); }
|
||||
void LOADERDECL Color_ReadIndex8_24b_888() { Color_ReadIndex_24b_888<u8>(); }
|
||||
void LOADERDECL Color_ReadIndex8_32b_888x() { Color_ReadIndex_32b_888x<u8>(); }
|
||||
void LOADERDECL Color_ReadIndex8_16b_4444() { Color_ReadIndex_16b_4444<u8>(); }
|
||||
void LOADERDECL Color_ReadIndex8_24b_6666() { Color_ReadIndex_24b_6666<u8>(); }
|
||||
void LOADERDECL Color_ReadIndex8_32b_8888() { Color_ReadIndex_32b_8888<u8>(); }
|
||||
|
||||
void LOADERDECL Color_ReadIndex16_16b_565() { Color_ReadIndex_16b_565<u16>(); }
|
||||
void LOADERDECL Color_ReadIndex16_24b_888() { Color_ReadIndex_24b_888<u16>(); }
|
||||
void LOADERDECL Color_ReadIndex16_32b_888x() { Color_ReadIndex_32b_888x<u16>(); }
|
||||
void LOADERDECL Color_ReadIndex16_16b_4444() { Color_ReadIndex_16b_4444<u16>(); }
|
||||
void LOADERDECL Color_ReadIndex16_24b_6666() { Color_ReadIndex_24b_6666<u16>(); }
|
||||
void LOADERDECL Color_ReadIndex16_32b_8888() { Color_ReadIndex_32b_8888<u16>(); }
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "VertexManagerBase.h"
|
||||
#include "CPUDetect.h"
|
||||
#include <cmath>
|
||||
#include <limits>
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
#include <smmintrin.h>
|
||||
@@ -30,78 +31,163 @@
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
|
||||
// warning: mapping buffer should be disabled to use this
|
||||
#define LOG_NORM() // PRIM_LOG("norm: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
|
||||
|
||||
VertexLoader_Normal::Set VertexLoader_Normal::m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
|
||||
|
||||
namespace
|
||||
{
|
||||
|
||||
template <typename T>
|
||||
__forceinline float FracAdjust(T val)
|
||||
{
|
||||
//auto const S8FRAC = 1.f / (1u << 6);
|
||||
//auto const U8FRAC = 1.f / (1u << 7);
|
||||
//auto const S16FRAC = 1.f / (1u << 14);
|
||||
//auto const U16FRAC = 1.f / (1u << 15);
|
||||
|
||||
// TODO: is this right?
|
||||
return val / float(1u << (sizeof(T) * 8 - std::numeric_limits<T>::is_signed - 1));
|
||||
}
|
||||
|
||||
template <>
|
||||
__forceinline float FracAdjust(float val)
|
||||
{ return val; }
|
||||
|
||||
template <typename T, int N>
|
||||
__forceinline void ReadIndirect(const T* data)
|
||||
{
|
||||
static_assert(3 == N || 9 == N, "N is only sane as 3 or 9!");
|
||||
|
||||
for (int i = 0; i != N; ++i)
|
||||
{
|
||||
DataWrite(FracAdjust(Common::FromBigEndian(data[i])));
|
||||
}
|
||||
|
||||
LOG_NORM();
|
||||
}
|
||||
|
||||
template <typename T, int N>
|
||||
struct Normal_Direct
|
||||
{
|
||||
static void LOADERDECL function()
|
||||
{
|
||||
auto const source = reinterpret_cast<const T*>(DataGetPosition());
|
||||
ReadIndirect<T, N * 3>(source);
|
||||
DataSkip<N * 3 * sizeof(T)>();
|
||||
}
|
||||
|
||||
static const int size = sizeof(T) * N * 3;
|
||||
};
|
||||
|
||||
template <typename I, typename T, int N, int Offset>
|
||||
__forceinline void Normal_Index_Offset()
|
||||
{
|
||||
static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
|
||||
|
||||
auto const index = DataRead<I>();
|
||||
auto const data = reinterpret_cast<const T*>(cached_arraybases[ARRAY_NORMAL]
|
||||
+ (index * arraystrides[ARRAY_NORMAL]) + sizeof(T) * 3 * Offset);
|
||||
ReadIndirect<T, N * 3>(data);
|
||||
}
|
||||
|
||||
template <typename I, typename T, int N>
|
||||
struct Normal_Index
|
||||
{
|
||||
static void LOADERDECL function()
|
||||
{
|
||||
Normal_Index_Offset<I, T, N, 0>();
|
||||
}
|
||||
|
||||
static const int size = sizeof(I);
|
||||
};
|
||||
|
||||
template <typename I, typename T>
|
||||
struct Normal_Index_Indices3
|
||||
{
|
||||
static void LOADERDECL function()
|
||||
{
|
||||
Normal_Index_Offset<I, T, 1, 0>();
|
||||
Normal_Index_Offset<I, T, 1, 1>();
|
||||
Normal_Index_Offset<I, T, 1, 2>();
|
||||
}
|
||||
|
||||
static const int size = sizeof(I) * 3;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void VertexLoader_Normal::Init(void)
|
||||
{
|
||||
// HACK is for signed instead of unsigned to prevent crashes.
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
|
||||
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(3, Normal_DirectByte); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(3, Normal_DirectByte);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(6, Normal_DirectShort); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(6, Normal_DirectShort);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(12, Normal_DirectFloat);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(9, Normal_DirectByte3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(9, Normal_DirectByte3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(18, Normal_DirectShort3); //HACK
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(18, Normal_DirectShort3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(36, Normal_DirectFloat3);
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(1, Normal_Index8_Byte3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(1, Normal_Index8_Byte3_Indices1);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(1, Normal_Index8_Short3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(1, Normal_Index8_Short3_Indices1);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(1, Normal_Index8_Float3_Indices1);
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(1, Normal_Index8_Byte); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(1, Normal_Index8_Byte);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(1, Normal_Index8_Short); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(1, Normal_Index8_Short);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(1, Normal_Index8_Float);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(3, Normal_Index8_Byte3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(3, Normal_Index8_Byte3_Indices3);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(3, Normal_Index8_Short3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(3, Normal_Index8_Short3_Indices3);
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(3, Normal_Index8_Float3_Indices3);
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Set(2, Normal_Index16_Byte3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Set(2, Normal_Index16_Byte3_Indices1);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Set(2, Normal_Index16_Short3_Indices1); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Set(2, Normal_Index16_Short3_Indices1);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Set(2, Normal_Index16_Float3_Indices1);
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Set(2, Normal_Index16_Byte); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Set(2, Normal_Index16_Byte);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Set(2, Normal_Index16_Short); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Set(2, Normal_Index16_Short);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Set(2, Normal_Index16_Float);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Set(6, Normal_Index16_Byte3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Set(6, Normal_Index16_Byte3_Indices3);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Set(6, Normal_Index16_Short3_Indices3); //HACK
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Set(6, Normal_Index16_Short3_Indices3);
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Set(6, Normal_Index16_Float3_Indices3);
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Direct<u8, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Direct<s8, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Direct<u16, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Direct<s16, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Direct<float, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Direct<u8, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Direct<s8, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Direct<u16, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Direct<s16, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Direct<float, 3>();
|
||||
|
||||
// Same as above
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Direct<u8, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Direct<s8, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Direct<u16, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Direct<s16, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Direct<float, 1>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Direct<u8, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Direct<s8, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Direct<u16, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Direct<s16, 3>();
|
||||
m_Table[NRM_DIRECT] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Direct<float, 3>();
|
||||
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u8, u8, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u8, s8, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u8, u16, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u8, s16, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u8, float, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Index<u8, u8, 3>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Index<u8, s8, 3>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Index<u8, u16, 3>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Index<u8, s16, 3>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Index<u8, float, 3>();
|
||||
|
||||
// Same as above for NRM_NBT
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u8, u8, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u8, s8, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u8, u16, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u8, s16, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u8, float, 1>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Index_Indices3<u8, u8>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Index_Indices3<u8, s8>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Index_Indices3<u8, u16>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Index_Indices3<u8, s16>();
|
||||
m_Table[NRM_INDEX8] [NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Index_Indices3<u8, float>();
|
||||
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u16, u8, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u16, s8, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u16, u16, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u16, s16, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u16, float, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_UBYTE] = Normal_Index<u16, u8, 3>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_BYTE] = Normal_Index<u16, s8, 3>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_USHORT] = Normal_Index<u16, u16, 3>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_SHORT] = Normal_Index<u16, s16, 3>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES1][NRM_NBT3][FORMAT_FLOAT] = Normal_Index<u16, float, 3>();
|
||||
|
||||
// Same as above for NRM_NBT
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_UBYTE] = Normal_Index<u16, u8, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_BYTE] = Normal_Index<u16, s8, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_USHORT] = Normal_Index<u16, u16, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_SHORT] = Normal_Index<u16, s16, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT] [FORMAT_FLOAT] = Normal_Index<u16, float, 1>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_UBYTE] = Normal_Index_Indices3<u16, u8>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_BYTE] = Normal_Index_Indices3<u16, s8>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_USHORT] = Normal_Index_Indices3<u16, u16>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_SHORT] = Normal_Index_Indices3<u16, s16>();
|
||||
m_Table[NRM_INDEX16][NRM_INDICES3][NRM_NBT3][FORMAT_FLOAT] = Normal_Index_Indices3<u16, float>();
|
||||
}
|
||||
|
||||
unsigned int VertexLoader_Normal::GetSize(unsigned int _type,
|
||||
@@ -116,312 +202,3 @@ TPipelineFunction VertexLoader_Normal::GetFunction(unsigned int _type,
|
||||
TPipelineFunction pFunc = m_Table[_type][_index3][_elements][_format].function;
|
||||
return pFunc;
|
||||
}
|
||||
|
||||
// This fracs are fixed acording to format
|
||||
#define S8FRAC 0.015625f; // 1.0f / (1U << 6)
|
||||
#define S16FRAC 0.00006103515625f; // 1.0f / (1U << 14)
|
||||
// --- Direct ---
|
||||
|
||||
inline void ReadIndirectS8x3(const s8* pData)
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = pData[0] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = pData[1] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = pData[2] * S8FRAC;
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORM();
|
||||
}
|
||||
|
||||
inline void ReadIndirectS8x9(const s8* pData)
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = pData[0] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = pData[1] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = pData[2] * S8FRAC;
|
||||
LOG_NORM();
|
||||
((float*)VertexManager::s_pCurBufferPointer)[3] = pData[3] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[4] = pData[4] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[5] = pData[5] * S8FRAC;
|
||||
LOG_NORM();
|
||||
((float*)VertexManager::s_pCurBufferPointer)[6] = pData[6] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[7] = pData[7] * S8FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[8] = pData[8] * S8FRAC;
|
||||
LOG_NORM();
|
||||
VertexManager::s_pCurBufferPointer += 36;
|
||||
}
|
||||
|
||||
inline void ReadIndirectS16x3(const u16* pData)
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = ((s16)Common::swap16(pData[0])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = ((s16)Common::swap16(pData[1])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = ((s16)Common::swap16(pData[2])) * S16FRAC;
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORM()
|
||||
}
|
||||
|
||||
inline void ReadIndirectS16x9(const u16* pData)
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = ((s16)Common::swap16(pData[0])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = ((s16)Common::swap16(pData[1])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = ((s16)Common::swap16(pData[2])) * S16FRAC;
|
||||
LOG_NORM()
|
||||
((float*)VertexManager::s_pCurBufferPointer)[3] = ((s16)Common::swap16(pData[3])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[4] = ((s16)Common::swap16(pData[4])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[5] = ((s16)Common::swap16(pData[5])) * S16FRAC;
|
||||
LOG_NORM()
|
||||
((float*)VertexManager::s_pCurBufferPointer)[6] = ((s16)Common::swap16(pData[6])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[7] = ((s16)Common::swap16(pData[7])) * S16FRAC;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[8] = ((s16)Common::swap16(pData[8])) * S16FRAC;
|
||||
LOG_NORM()
|
||||
VertexManager::s_pCurBufferPointer += 36;
|
||||
}
|
||||
|
||||
inline void ReadIndirectFloatx3(const u32* pData)
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]);
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
LOG_NORM();
|
||||
}
|
||||
|
||||
inline void ReadIndirectFloatx9(const u32* pData)
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]);
|
||||
LOG_NORM();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[3] = Common::swap32(pData[3]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[4] = Common::swap32(pData[4]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[5] = Common::swap32(pData[5]);
|
||||
LOG_NORM();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[6] = Common::swap32(pData[6]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[7] = Common::swap32(pData[7]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[8] = Common::swap32(pData[8]);
|
||||
LOG_NORM();
|
||||
VertexManager::s_pCurBufferPointer += 36;
|
||||
}
|
||||
|
||||
inline void ReadDirectS8x3()
|
||||
{
|
||||
const s8* Source = (const s8*)DataGetPosition();
|
||||
ReadIndirectS8x3(Source);
|
||||
DataSkip(3);
|
||||
}
|
||||
|
||||
inline void ReadDirectS8x9()
|
||||
{
|
||||
const s8* Source = (const s8*)DataGetPosition();
|
||||
ReadIndirectS8x9(Source);
|
||||
DataSkip(9);
|
||||
}
|
||||
|
||||
inline void ReadDirectS16x3()
|
||||
{
|
||||
const u16* Source = (const u16*)DataGetPosition();
|
||||
ReadIndirectS16x3(Source);
|
||||
DataSkip(6);
|
||||
}
|
||||
|
||||
inline void ReadDirectS16x9()
|
||||
{
|
||||
const u16* Source = (const u16*)DataGetPosition();
|
||||
ReadIndirectS16x9(Source);
|
||||
DataSkip(18);
|
||||
}
|
||||
|
||||
inline void ReadDirectFloatx3()
|
||||
{
|
||||
const u32* Source = (const u32*)DataGetPosition();
|
||||
ReadIndirectFloatx3(Source);
|
||||
DataSkip(12);
|
||||
}
|
||||
|
||||
inline void ReadDirectFloatx9()
|
||||
{
|
||||
const u32* Source = (const u32*)DataGetPosition();
|
||||
ReadIndirectFloatx9(Source);
|
||||
DataSkip(36);
|
||||
}
|
||||
|
||||
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectByte()
|
||||
{
|
||||
ReadDirectS8x3();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectShort()
|
||||
{
|
||||
ReadDirectS16x3();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectFloat()
|
||||
{
|
||||
ReadDirectFloatx3();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectByte3()
|
||||
{
|
||||
ReadDirectS8x9();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectShort3()
|
||||
{
|
||||
ReadDirectS16x9();
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_DirectFloat3()
|
||||
{
|
||||
ReadDirectFloatx9();
|
||||
}
|
||||
|
||||
|
||||
// --- Index8 ---
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS8x3(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS16x3(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectFloatx3(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS8x9(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS16x9(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectFloatx9(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Byte3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const s8* pData = (const s8*)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i);
|
||||
ReadIndirectS8x3(pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Short3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i);
|
||||
ReadIndirectS16x3(pData);
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index8_Float3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i);
|
||||
ReadIndirectFloatx3(pData);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// --- Index16 ---
|
||||
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS8x3(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS16x3(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectFloatx3(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const s8* pData = (const s8 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS8x9(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectS16x9(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]));
|
||||
ReadIndirectFloatx9(pData);
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Byte3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const s8* pData = (const s8*)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 1*3*i);
|
||||
ReadIndirectS8x3(pData);
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Short3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 2*3*i);
|
||||
ReadIndirectS16x3(pData);
|
||||
}
|
||||
}
|
||||
|
||||
void LOADERDECL VertexLoader_Normal::Normal_Index16_Float3_Indices3()
|
||||
{
|
||||
for (int i = 0; i < 3; i++)
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_NORMAL] + (Index * arraystrides[ARRAY_NORMAL]) + 4*3*i);
|
||||
ReadIndirectFloatx3(pData);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,43 +25,43 @@ class VertexLoader_Normal
|
||||
{
|
||||
public:
|
||||
|
||||
// Init
|
||||
static void Init(void);
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format,
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format,
|
||||
unsigned int _elements, unsigned int _index3);
|
||||
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type,
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type,
|
||||
unsigned int _format, unsigned int _elements, unsigned int _index3);
|
||||
|
||||
private:
|
||||
enum ENormalType
|
||||
{
|
||||
NRM_NOT_PRESENT = 0,
|
||||
NRM_DIRECT = 1,
|
||||
NRM_INDEX8 = 2,
|
||||
NRM_INDEX16 = 3,
|
||||
NUM_NRM_TYPE
|
||||
};
|
||||
enum ENormalType
|
||||
{
|
||||
NRM_NOT_PRESENT = 0,
|
||||
NRM_DIRECT = 1,
|
||||
NRM_INDEX8 = 2,
|
||||
NRM_INDEX16 = 3,
|
||||
NUM_NRM_TYPE
|
||||
};
|
||||
|
||||
enum ENormalFormat
|
||||
{
|
||||
FORMAT_UBYTE = 0,
|
||||
FORMAT_BYTE = 1,
|
||||
FORMAT_USHORT = 2,
|
||||
FORMAT_SHORT = 3,
|
||||
FORMAT_FLOAT = 4,
|
||||
NUM_NRM_FORMAT
|
||||
};
|
||||
enum ENormalFormat
|
||||
{
|
||||
FORMAT_UBYTE = 0,
|
||||
FORMAT_BYTE = 1,
|
||||
FORMAT_USHORT = 2,
|
||||
FORMAT_SHORT = 3,
|
||||
FORMAT_FLOAT = 4,
|
||||
NUM_NRM_FORMAT
|
||||
};
|
||||
|
||||
enum ENormalElements
|
||||
{
|
||||
NRM_NBT = 0,
|
||||
NRM_NBT3 = 1,
|
||||
NUM_NRM_ELEMENTS
|
||||
};
|
||||
enum ENormalElements
|
||||
{
|
||||
NRM_NBT = 0,
|
||||
NRM_NBT3 = 1,
|
||||
NUM_NRM_ELEMENTS
|
||||
};
|
||||
|
||||
enum ENormalIndices
|
||||
{
|
||||
@@ -70,45 +70,20 @@ private:
|
||||
NUM_NRM_INDICES
|
||||
};
|
||||
|
||||
struct Set {
|
||||
Set() {}
|
||||
Set(int gc_size_, TPipelineFunction function_) : gc_size(gc_size_), function(function_) {}
|
||||
struct Set
|
||||
{
|
||||
template <typename T>
|
||||
void operator=(const T&)
|
||||
{
|
||||
gc_size = T::size;
|
||||
function = T::function;
|
||||
}
|
||||
|
||||
int gc_size;
|
||||
TPipelineFunction function;
|
||||
// int pc_size;
|
||||
};
|
||||
|
||||
static Set m_Table[NUM_NRM_TYPE][NUM_NRM_INDICES][NUM_NRM_ELEMENTS][NUM_NRM_FORMAT];
|
||||
|
||||
// direct
|
||||
static void LOADERDECL Normal_DirectByte();
|
||||
static void LOADERDECL Normal_DirectShort();
|
||||
static void LOADERDECL Normal_DirectFloat();
|
||||
static void LOADERDECL Normal_DirectByte3();
|
||||
static void LOADERDECL Normal_DirectShort3();
|
||||
static void LOADERDECL Normal_DirectFloat3();
|
||||
|
||||
// index8
|
||||
static void LOADERDECL Normal_Index8_Byte();
|
||||
static void LOADERDECL Normal_Index8_Short();
|
||||
static void LOADERDECL Normal_Index8_Float();
|
||||
static void LOADERDECL Normal_Index8_Byte3_Indices1();
|
||||
static void LOADERDECL Normal_Index8_Short3_Indices1();
|
||||
static void LOADERDECL Normal_Index8_Float3_Indices1();
|
||||
static void LOADERDECL Normal_Index8_Byte3_Indices3();
|
||||
static void LOADERDECL Normal_Index8_Short3_Indices3();
|
||||
static void LOADERDECL Normal_Index8_Float3_Indices3();
|
||||
|
||||
// index16
|
||||
static void LOADERDECL Normal_Index16_Byte();
|
||||
static void LOADERDECL Normal_Index16_Short();
|
||||
static void LOADERDECL Normal_Index16_Float();
|
||||
static void LOADERDECL Normal_Index16_Byte3_Indices1();
|
||||
static void LOADERDECL Normal_Index16_Short3_Indices1();
|
||||
static void LOADERDECL Normal_Index16_Float3_Indices1();
|
||||
static void LOADERDECL Normal_Index16_Byte3_Indices3();
|
||||
static void LOADERDECL Normal_Index16_Short3_Indices3();
|
||||
static void LOADERDECL Normal_Index16_Float3_Indices3();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -15,6 +15,8 @@
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <limits>
|
||||
|
||||
#include "Common.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "VertexLoader.h"
|
||||
@@ -71,101 +73,42 @@ MOVUPS(MOffset(EDI, 0), XMM0);
|
||||
|
||||
*/
|
||||
|
||||
// ==============================================================================
|
||||
// Direct
|
||||
// ==============================================================================
|
||||
|
||||
template <class T, bool three>
|
||||
void Pos_ReadDirect()
|
||||
template <typename T>
|
||||
float PosScale(T val)
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(T)DataRead<T>() * posScale;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(T)DataRead<T>() * posScale;
|
||||
if (three)
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = (float)(T)DataRead<T>() * posScale;
|
||||
else
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
|
||||
return val * posScale;
|
||||
}
|
||||
|
||||
template <>
|
||||
float PosScale(float val)
|
||||
{ return val; }
|
||||
|
||||
template <typename T, int N>
|
||||
void LOADERDECL Pos_ReadDirect()
|
||||
{
|
||||
static_assert(N <= 3, "N > 3 is not sane!");
|
||||
|
||||
for (int i = 0; i < 3; ++i)
|
||||
DataWrite(i<N ? PosScale(DataRead<T>()) : 0.f);
|
||||
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_UByte3() { Pos_ReadDirect<u8, true>(); }
|
||||
void LOADERDECL Pos_ReadDirect_Byte3() { Pos_ReadDirect<s8, true>(); }
|
||||
void LOADERDECL Pos_ReadDirect_UShort3() { Pos_ReadDirect<u16, true>(); }
|
||||
void LOADERDECL Pos_ReadDirect_Short3() { Pos_ReadDirect<s16, true>(); }
|
||||
void LOADERDECL Pos_ReadDirect_UByte2() { Pos_ReadDirect<u8, false>(); }
|
||||
void LOADERDECL Pos_ReadDirect_Byte2() { Pos_ReadDirect<s8, false>(); }
|
||||
void LOADERDECL Pos_ReadDirect_UShort2() { Pos_ReadDirect<u16, false>(); }
|
||||
void LOADERDECL Pos_ReadDirect_Short2() { Pos_ReadDirect<s16, false>(); }
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_Float3()
|
||||
template <typename I, typename T, int N>
|
||||
void LOADERDECL Pos_ReadIndex()
|
||||
{
|
||||
// No need to use floating point here.
|
||||
((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
((u32 *)VertexManager::s_pCurBufferPointer)[2] = DataReadU32();
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
|
||||
static_assert(N <= 3, "N > 3 is not sane!");
|
||||
|
||||
void LOADERDECL Pos_ReadDirect_Float2()
|
||||
{
|
||||
// No need to use floating point here.
|
||||
((u32 *)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32 *)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
((u32 *)VertexManager::s_pCurBufferPointer)[2] = 0;
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
|
||||
|
||||
template<class T, bool three,int MaxSize>
|
||||
inline void Pos_ReadIndex_Byte(int Index)
|
||||
{
|
||||
if(Index < MaxSize)
|
||||
auto const index = DataRead<I>();
|
||||
if (index < std::numeric_limits<I>::max())
|
||||
{
|
||||
const u8* pData = cached_arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)(pData[0])) * posScale;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)(pData[1])) * posScale;
|
||||
if (three)
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)(pData[2])) * posScale;
|
||||
else
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
}
|
||||
auto const data = reinterpret_cast<const T*>(cached_arraybases[ARRAY_POSITION] + (index * arraystrides[ARRAY_POSITION]));
|
||||
|
||||
template<class T, bool three,int MaxSize>
|
||||
inline void Pos_ReadIndex_Short(int Index)
|
||||
{
|
||||
if(Index < MaxSize)
|
||||
{
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_POSITION] + ((u32)Index * arraystrides[ARRAY_POSITION]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = ((float)(T)Common::swap16(pData[0])) * posScale;
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = ((float)(T)Common::swap16(pData[1])) * posScale;
|
||||
if (three)
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = ((float)(T)Common::swap16(pData[2])) * posScale;
|
||||
else
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
}
|
||||
for (int i = 0; i < 3; ++i)
|
||||
DataWrite(i<N ? PosScale(Common::FromBigEndian(data[i])) : 0.f);
|
||||
|
||||
template<bool three,int MaxSize>
|
||||
void Pos_ReadIndex_Float(int Index)
|
||||
{
|
||||
if(Index < MaxSize)
|
||||
{
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]));
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
|
||||
if (three)
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[2] = Common::swap32(pData[2]);
|
||||
else
|
||||
((float*)VertexManager::s_pCurBufferPointer)[2] = 0.0f;
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,87 +116,22 @@ void Pos_ReadIndex_Float(int Index)
|
||||
static const __m128i kMaskSwap32_3 = _mm_set_epi32(0xFFFFFFFFL, 0x08090A0BL, 0x04050607L, 0x00010203L);
|
||||
static const __m128i kMaskSwap32_2 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L);
|
||||
|
||||
template<bool three,int MaxSize>
|
||||
void Pos_ReadIndex_Float_SSSE3(int Index)
|
||||
template <typename I, bool three>
|
||||
void LOADERDECL Pos_ReadIndex_Float_SSSE3()
|
||||
{
|
||||
if(Index < MaxSize)
|
||||
auto const index = DataRead<I>();
|
||||
if (index < std::numeric_limits<I>::max())
|
||||
{
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (Index * arraystrides[ARRAY_POSITION]));
|
||||
const u32* pData = (const u32 *)(cached_arraybases[ARRAY_POSITION] + (index * arraystrides[ARRAY_POSITION]));
|
||||
GC_ALIGNED128(const __m128i a = _mm_loadu_si128((__m128i*)pData));
|
||||
GC_ALIGNED128(__m128i b = _mm_shuffle_epi8(a, three ? kMaskSwap32_3 : kMaskSwap32_2));
|
||||
_mm_storeu_si128((__m128i*)VertexManager::s_pCurBufferPointer, b);
|
||||
VertexManager::s_pCurBufferPointer += sizeof(float) * 3;
|
||||
LOG_VTX();
|
||||
VertexManager::s_pCurBufferPointer += 12;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Explicitly instantiate these functions to decrease the possibility of
|
||||
// symbol binding problems when (only) calling them from JIT compiled code.
|
||||
template void Pos_ReadDirect<u8, true>();
|
||||
template void Pos_ReadDirect<s8, true>();
|
||||
template void Pos_ReadDirect<u16, true>();
|
||||
template void Pos_ReadDirect<s16, true>();
|
||||
template void Pos_ReadDirect<u8, false>();
|
||||
template void Pos_ReadDirect<s8, false>();
|
||||
template void Pos_ReadDirect<u16, false>();
|
||||
template void Pos_ReadDirect<s16, false>();
|
||||
template void Pos_ReadIndex_Byte<u8, true, 255>(int Index);
|
||||
template void Pos_ReadIndex_Byte<s8, true, 255>(int Index);
|
||||
template void Pos_ReadIndex_Short<u16, true, 255>(int Index);
|
||||
template void Pos_ReadIndex_Short<s16, true, 255>(int Index);
|
||||
template void Pos_ReadIndex_Float<true, 255>(int Index);
|
||||
template void Pos_ReadIndex_Byte<u8, false, 255>(int Index);
|
||||
template void Pos_ReadIndex_Byte<s8, false, 255>(int Index);
|
||||
template void Pos_ReadIndex_Short<u16, false, 255>(int Index);
|
||||
template void Pos_ReadIndex_Short<s16, false, 255>(int Index);
|
||||
template void Pos_ReadIndex_Float<false, 255>(int Index);
|
||||
template void Pos_ReadIndex_Byte<u8, true, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Byte<s8, true, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Short<u16, true, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Short<s16, true, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Float<true, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Byte<u8, false, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Byte<s8, false, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Short<u16, false, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Short<s16, false, 65535>(int Index);
|
||||
template void Pos_ReadIndex_Float<false, 65535>(int Index);
|
||||
|
||||
// ==============================================================================
|
||||
// Index 8
|
||||
// ==============================================================================
|
||||
void LOADERDECL Pos_ReadIndex8_UByte3() {Pos_ReadIndex_Byte<u8, true, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Byte3() {Pos_ReadIndex_Byte<s8, true, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_UShort3() {Pos_ReadIndex_Short<u16, true, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Short3() {Pos_ReadIndex_Short<s16, true, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Float3() {Pos_ReadIndex_Float<true, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_UByte2() {Pos_ReadIndex_Byte<u8, false, 255>(DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Byte2() {Pos_ReadIndex_Byte<s8, false, 255>(DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_UShort2() {Pos_ReadIndex_Short<u16, false, 255>(DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Short2() {Pos_ReadIndex_Short<s16, false, 255>(DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Float2() {Pos_ReadIndex_Float<false, 255> (DataReadU8());}
|
||||
|
||||
// ==============================================================================
|
||||
// Index 16
|
||||
// ==============================================================================
|
||||
void LOADERDECL Pos_ReadIndex16_UByte3() {Pos_ReadIndex_Byte<u8, true, 65535> (DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Byte3() {Pos_ReadIndex_Byte<s8, true, 65535> (DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_UShort3() {Pos_ReadIndex_Short<u16, true, 65535> (DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Short3() {Pos_ReadIndex_Short<s16, true, 65535> (DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Float3() {Pos_ReadIndex_Float<true, 65535> (DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_UByte2() {Pos_ReadIndex_Byte<u8, false, 65535>(DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Byte2() {Pos_ReadIndex_Byte<s8, false, 65535>(DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_UShort2() {Pos_ReadIndex_Short<u16, false, 65535>(DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Short2() {Pos_ReadIndex_Short<s16, false, 65535>(DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Float2() {Pos_ReadIndex_Float<false, 65535> (DataReadU16());}
|
||||
|
||||
#if _M_SSE >= 0x301
|
||||
void LOADERDECL Pos_ReadIndex8_Float3_SSSE3() {Pos_ReadIndex_Float_SSSE3<true, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex8_Float2_SSSE3() {Pos_ReadIndex_Float_SSSE3<false, 255> (DataReadU8());}
|
||||
void LOADERDECL Pos_ReadIndex16_Float3_SSSE3() {Pos_ReadIndex_Float_SSSE3<true, 65535> (DataReadU16());}
|
||||
void LOADERDECL Pos_ReadIndex16_Float2_SSSE3() {Pos_ReadIndex_Float_SSSE3<false, 65535> (DataReadU16());}
|
||||
#endif
|
||||
|
||||
static TPipelineFunction tableReadPosition[4][8][2] = {
|
||||
{
|
||||
{NULL, NULL,},
|
||||
@@ -263,56 +141,40 @@ static TPipelineFunction tableReadPosition[4][8][2] = {
|
||||
{NULL, NULL,},
|
||||
},
|
||||
{
|
||||
{Pos_ReadDirect_UByte2, Pos_ReadDirect_UByte3,},
|
||||
{Pos_ReadDirect_Byte2, Pos_ReadDirect_Byte3,},
|
||||
{Pos_ReadDirect_UShort2, Pos_ReadDirect_UShort3,},
|
||||
{Pos_ReadDirect_Short2, Pos_ReadDirect_Short3,},
|
||||
{Pos_ReadDirect_Float2, Pos_ReadDirect_Float3,},
|
||||
{Pos_ReadDirect<u8, 2>, Pos_ReadDirect<u8, 3>,},
|
||||
{Pos_ReadDirect<s8, 2>, Pos_ReadDirect<s8, 3>,},
|
||||
{Pos_ReadDirect<u16, 2>, Pos_ReadDirect<u16, 3>,},
|
||||
{Pos_ReadDirect<s16, 2>, Pos_ReadDirect<s16, 3>,},
|
||||
{Pos_ReadDirect<float, 2>, Pos_ReadDirect<float, 3>,},
|
||||
},
|
||||
{
|
||||
{Pos_ReadIndex8_UByte2, Pos_ReadIndex8_UByte3,},
|
||||
{Pos_ReadIndex8_Byte2, Pos_ReadIndex8_Byte3,},
|
||||
{Pos_ReadIndex8_UShort2, Pos_ReadIndex8_UShort3,},
|
||||
{Pos_ReadIndex8_Short2, Pos_ReadIndex8_Short3,},
|
||||
{Pos_ReadIndex8_Float2, Pos_ReadIndex8_Float3,},
|
||||
{Pos_ReadIndex<u8, u8, 2>, Pos_ReadIndex<u8, u8, 3>,},
|
||||
{Pos_ReadIndex<u8, s8, 2>, Pos_ReadIndex<u8, s8, 3>,},
|
||||
{Pos_ReadIndex<u8, u16, 2>, Pos_ReadIndex<u8, u16, 3>,},
|
||||
{Pos_ReadIndex<u8, s16, 2>, Pos_ReadIndex<u8, s16, 3>,},
|
||||
{Pos_ReadIndex<u8, float, 2>, Pos_ReadIndex<u8, float, 3>,},
|
||||
},
|
||||
{
|
||||
{Pos_ReadIndex16_UByte2, Pos_ReadIndex16_UByte3,},
|
||||
{Pos_ReadIndex16_Byte2, Pos_ReadIndex16_Byte3,},
|
||||
{Pos_ReadIndex16_UShort2, Pos_ReadIndex16_UShort3,},
|
||||
{Pos_ReadIndex16_Short2, Pos_ReadIndex16_Short3,},
|
||||
{Pos_ReadIndex16_Float2, Pos_ReadIndex16_Float3,},
|
||||
{Pos_ReadIndex<u16, u8, 2>, Pos_ReadIndex<u16, u8, 3>,},
|
||||
{Pos_ReadIndex<u16, s8, 2>, Pos_ReadIndex<u16, s8, 3>,},
|
||||
{Pos_ReadIndex<u16, u16, 2>, Pos_ReadIndex<u16, u16, 3>,},
|
||||
{Pos_ReadIndex<u16, s16, 2>, Pos_ReadIndex<u16, s16, 3>,},
|
||||
{Pos_ReadIndex<u16, float, 2>, Pos_ReadIndex<u16, float, 3>,},
|
||||
},
|
||||
};
|
||||
|
||||
static int tableReadPositionVertexSize[4][8][2] = {
|
||||
{
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,},
|
||||
},
|
||||
{
|
||||
{2, 3,},
|
||||
{2, 3,},
|
||||
{4, 6,},
|
||||
{4, 6,},
|
||||
{8, 12,},
|
||||
{2, 3,}, {2, 3,}, {4, 6,}, {4, 6,}, {8, 12,},
|
||||
},
|
||||
{
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,},
|
||||
},
|
||||
{
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -322,10 +184,10 @@ void VertexLoader_Position::Init(void) {
|
||||
#if _M_SSE >= 0x301
|
||||
|
||||
if (cpu_info.bSSSE3) {
|
||||
tableReadPosition[2][4][0] = Pos_ReadIndex8_Float2_SSSE3;
|
||||
tableReadPosition[2][4][1] = Pos_ReadIndex8_Float3_SSSE3;
|
||||
tableReadPosition[3][4][0] = Pos_ReadIndex16_Float2_SSSE3;
|
||||
tableReadPosition[3][4][1] = Pos_ReadIndex16_Float3_SSSE3;
|
||||
tableReadPosition[2][4][0] = Pos_ReadIndex_Float_SSSE3<u8, false>;
|
||||
tableReadPosition[2][4][1] = Pos_ReadIndex_Float_SSSE3<u8, true>;
|
||||
tableReadPosition[3][4][0] = Pos_ReadIndex_Float_SSSE3<u16, false>;
|
||||
tableReadPosition[3][4][1] = Pos_ReadIndex_Float_SSSE3<u16, true>;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
class VertexLoader_Position {
|
||||
public:
|
||||
|
||||
// Init
|
||||
static void Init(void);
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -28,8 +28,22 @@
|
||||
#include <tmmintrin.h>
|
||||
#endif
|
||||
|
||||
#define LOG_TEX1() // PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0]);
|
||||
#define LOG_TEX2() // PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1]);
|
||||
template <int N>
|
||||
void LOG_TEX();
|
||||
|
||||
template <>
|
||||
__forceinline void LOG_TEX<1>()
|
||||
{
|
||||
// warning: mapping buffer should be disabled to use this
|
||||
// PRIM_LOG("tex: %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-1]);
|
||||
}
|
||||
|
||||
template <>
|
||||
__forceinline void LOG_TEX<2>()
|
||||
{
|
||||
// warning: mapping buffer should be disabled to use this
|
||||
// PRIM_LOG("tex: %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
|
||||
}
|
||||
|
||||
extern int tcIndex;
|
||||
extern float tcScale[8];
|
||||
@@ -39,279 +53,54 @@ void LOADERDECL TexCoord_Read_Dummy()
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_UByte1()
|
||||
template <typename T>
|
||||
float TCScale(T val)
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadDirect_UByte2()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU8() * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU8() * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
return val * tcScale[tcIndex];
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_Byte1()
|
||||
template <>
|
||||
float TCScale(float val)
|
||||
{ return val; }
|
||||
|
||||
template <typename T, int N>
|
||||
void LOADERDECL TexCoord_ReadDirect()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadDirect_Byte2()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)DataReadU8() * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)DataReadU8() * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
for (int i = 0; i != N; ++i)
|
||||
DataWrite(TCScale(DataRead<T>()));
|
||||
|
||||
LOG_TEX<N>();
|
||||
|
||||
++tcIndex;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_UShort1()
|
||||
template <typename I, typename T, int N>
|
||||
void LOADERDECL TexCoord_ReadIndex()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadDirect_UShort2()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)DataReadU16() * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)DataReadU16() * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
|
||||
|
||||
auto const index = DataRead<I>();
|
||||
auto const data = reinterpret_cast<const T*>(cached_arraybases[ARRAY_TEXCOORD0 + tcIndex]
|
||||
+ (index * arraystrides[ARRAY_TEXCOORD0 + tcIndex]));
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_Short1()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadDirect_Short2()
|
||||
{
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)DataReadU16() * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)DataReadU16() * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
for (int i = 0; i != N; ++i)
|
||||
DataWrite(TCScale(Common::FromBigEndian(data[i])));
|
||||
|
||||
void LOADERDECL TexCoord_ReadDirect_Float1()
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadDirect_Float2()
|
||||
{
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = DataReadU32();
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = DataReadU32();
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
void LOADERDECL TexCoord_ReadIndex8_UByte1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(*pData) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_UByte2()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex8_Byte1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(*pData) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_Byte2()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex8_UShort1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(*pData) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_UShort2()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Common::swap16(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex8_Short1()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_Short2()
|
||||
{
|
||||
u8 Index = DataReadU8();
|
||||
const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Common::swap16(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex8_Float1()
|
||||
{
|
||||
u16 Index = DataReadU8();
|
||||
const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex8_Float2()
|
||||
{
|
||||
u16 Index = DataReadU8();
|
||||
const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
// ==================================================================================
|
||||
void LOADERDECL TexCoord_ReadIndex16_UByte1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex16_UByte2()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u8)(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u8)(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Byte1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex16_Byte2()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u8 *pData = cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]);
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s8)(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s8)(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_UShort1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
void LOADERDECL TexCoord_ReadIndex16_UShort2()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u16* pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(u16)Common::swap16(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(u16)Common::swap16(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Short1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(*pData) * tcScale[tcIndex];
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Short2()
|
||||
{
|
||||
// Heavy in ZWW
|
||||
u16 Index = DataReadU16();
|
||||
const u16 *pData = (const u16 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((float*)VertexManager::s_pCurBufferPointer)[0] = (float)(s16)Common::swap16(pData[0]) * tcScale[tcIndex];
|
||||
((float*)VertexManager::s_pCurBufferPointer)[1] = (float)(s16)Common::swap16(pData[1]) * tcScale[tcIndex];
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
LOG_TEX<N>();
|
||||
++tcIndex;
|
||||
}
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
static const __m128i kMaskSwap16_2 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0xFFFFFFFFL, 0x02030001L);
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Short2_SSE4()
|
||||
template <typename I>
|
||||
void LOADERDECL TexCoord_ReadIndex_Short2_SSE4()
|
||||
{
|
||||
static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
|
||||
|
||||
// Heavy in ZWW
|
||||
u16 Index = DataReadU16();
|
||||
const s32 *pData = (const s32*)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
auto const index = DataRead<I>();
|
||||
const s32 *pData = (const s32*)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
const __m128i a = _mm_cvtsi32_si128(*pData);
|
||||
const __m128i b = _mm_shuffle_epi8(a, kMaskSwap16_2);
|
||||
const __m128i c = _mm_cvtepi16_epi32(b);
|
||||
@@ -319,47 +108,27 @@ void LOADERDECL TexCoord_ReadIndex16_Short2_SSE4()
|
||||
const __m128 e = _mm_load1_ps(&tcScale[tcIndex]);
|
||||
const __m128 f = _mm_mul_ps(d, e);
|
||||
_mm_storeu_ps((float*)VertexManager::s_pCurBufferPointer, f);
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
VertexManager::s_pCurBufferPointer += sizeof(float) * 2;
|
||||
LOG_TEX<2>();
|
||||
tcIndex++;
|
||||
}
|
||||
#endif
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Float1()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
LOG_TEX1();
|
||||
VertexManager::s_pCurBufferPointer += 4;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Float2()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[0] = Common::swap32(pData[0]);
|
||||
((u32*)VertexManager::s_pCurBufferPointer)[1] = Common::swap32(pData[1]);
|
||||
LOG_TEX2();
|
||||
VertexManager::s_pCurBufferPointer += 8;
|
||||
tcIndex++;
|
||||
}
|
||||
|
||||
#if _M_SSE >= 0x301
|
||||
static const __m128i kMaskSwap32 = _mm_set_epi32(0xFFFFFFFFL, 0xFFFFFFFFL, 0x04050607L, 0x00010203L);
|
||||
|
||||
void LOADERDECL TexCoord_ReadIndex16_Float2_SSSE3()
|
||||
template <typename I>
|
||||
void LOADERDECL TexCoord_ReadIndex_Float2_SSSE3()
|
||||
{
|
||||
u16 Index = DataReadU16();
|
||||
const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (Index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
static_assert(!std::numeric_limits<I>::is_signed, "Only unsigned I is sane!");
|
||||
|
||||
auto const index = DataRead<I>();
|
||||
const u32 *pData = (const u32 *)(cached_arraybases[ARRAY_TEXCOORD0+tcIndex] + (index * arraystrides[ARRAY_TEXCOORD0+tcIndex]));
|
||||
GC_ALIGNED128(const __m128i a = _mm_loadl_epi64((__m128i*)pData));
|
||||
GC_ALIGNED128(const __m128i b = _mm_shuffle_epi8(a, kMaskSwap32));
|
||||
u8* p = VertexManager::s_pCurBufferPointer;
|
||||
_mm_storel_epi64((__m128i*)p, b);
|
||||
LOG_TEX2();
|
||||
p += 8;
|
||||
VertexManager::s_pCurBufferPointer = p;
|
||||
_mm_storel_epi64((__m128i*)VertexManager::s_pCurBufferPointer, b);
|
||||
VertexManager::s_pCurBufferPointer += sizeof(float) * 2;
|
||||
LOG_TEX<2>();
|
||||
tcIndex++;
|
||||
}
|
||||
#endif
|
||||
@@ -373,56 +142,40 @@ static TPipelineFunction tableReadTexCoord[4][8][2] = {
|
||||
{NULL, NULL,},
|
||||
},
|
||||
{
|
||||
{TexCoord_ReadDirect_UByte1, TexCoord_ReadDirect_UByte2,},
|
||||
{TexCoord_ReadDirect_Byte1, TexCoord_ReadDirect_Byte2,},
|
||||
{TexCoord_ReadDirect_UShort1, TexCoord_ReadDirect_UShort2,},
|
||||
{TexCoord_ReadDirect_Short1, TexCoord_ReadDirect_Short2,},
|
||||
{TexCoord_ReadDirect_Float1, TexCoord_ReadDirect_Float2,},
|
||||
{TexCoord_ReadDirect<u8, 1>, TexCoord_ReadDirect<u8, 2>,},
|
||||
{TexCoord_ReadDirect<s8, 1>, TexCoord_ReadDirect<s8, 2>,},
|
||||
{TexCoord_ReadDirect<u16, 1>, TexCoord_ReadDirect<u16, 2>,},
|
||||
{TexCoord_ReadDirect<s16, 1>, TexCoord_ReadDirect<s16, 2>,},
|
||||
{TexCoord_ReadDirect<float, 1>, TexCoord_ReadDirect<float, 2>,},
|
||||
},
|
||||
{
|
||||
{TexCoord_ReadIndex8_UByte1, TexCoord_ReadIndex8_UByte2,},
|
||||
{TexCoord_ReadIndex8_Byte1, TexCoord_ReadIndex8_Byte2,},
|
||||
{TexCoord_ReadIndex8_UShort1, TexCoord_ReadIndex8_UShort2,},
|
||||
{TexCoord_ReadIndex8_Short1, TexCoord_ReadIndex8_Short2,},
|
||||
{TexCoord_ReadIndex8_Float1, TexCoord_ReadIndex8_Float2,},
|
||||
{TexCoord_ReadIndex<u8, u8, 1>, TexCoord_ReadIndex<u8, u8, 2>,},
|
||||
{TexCoord_ReadIndex<u8, s8, 1>, TexCoord_ReadIndex<u8, s8, 2>,},
|
||||
{TexCoord_ReadIndex<u8, u16, 1>, TexCoord_ReadIndex<u8, u16, 2>,},
|
||||
{TexCoord_ReadIndex<u8, s16, 1>, TexCoord_ReadIndex<u8, s16, 2>,},
|
||||
{TexCoord_ReadIndex<u8, float, 1>, TexCoord_ReadIndex<u8, float, 2>,},
|
||||
},
|
||||
{
|
||||
{TexCoord_ReadIndex16_UByte1, TexCoord_ReadIndex16_UByte2,},
|
||||
{TexCoord_ReadIndex16_Byte1, TexCoord_ReadIndex16_Byte2,},
|
||||
{TexCoord_ReadIndex16_UShort1, TexCoord_ReadIndex16_UShort2,},
|
||||
{TexCoord_ReadIndex16_Short1, TexCoord_ReadIndex16_Short2,},
|
||||
{TexCoord_ReadIndex16_Float1, TexCoord_ReadIndex16_Float2,},
|
||||
{TexCoord_ReadIndex<u16, u8, 1>, TexCoord_ReadIndex<u16, u8, 2>,},
|
||||
{TexCoord_ReadIndex<u16, s8, 1>, TexCoord_ReadIndex<u16, s8, 2>,},
|
||||
{TexCoord_ReadIndex<u16, u16, 1>, TexCoord_ReadIndex<u16, u16, 2>,},
|
||||
{TexCoord_ReadIndex<u16, s16, 1>, TexCoord_ReadIndex<u16, s16, 2>,},
|
||||
{TexCoord_ReadIndex<u16, float, 1>, TexCoord_ReadIndex<u16, float, 2>,},
|
||||
},
|
||||
};
|
||||
|
||||
static int tableReadTexCoordVertexSize[4][8][2] = {
|
||||
{
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,},
|
||||
{0, 0,}, {0, 0,}, {0, 0,}, {0, 0,}, {0, 0,},
|
||||
},
|
||||
{
|
||||
{1, 2,},
|
||||
{1, 2,},
|
||||
{2, 4,},
|
||||
{2, 4,},
|
||||
{4, 8,},
|
||||
{1, 2,}, {1, 2,}, {2, 4,}, {2, 4,}, {4, 8,},
|
||||
},
|
||||
{
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,},
|
||||
{1, 1,}, {1, 1,}, {1, 1,}, {1, 1,}, {1, 1,},
|
||||
},
|
||||
{
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,},
|
||||
{2, 2,}, {2, 2,}, {2, 2,}, {2, 2,}, {2, 2,},
|
||||
},
|
||||
};
|
||||
|
||||
@@ -430,16 +183,20 @@ void VertexLoader_TextCoord::Init(void) {
|
||||
|
||||
#if _M_SSE >= 0x301
|
||||
|
||||
if (cpu_info.bSSSE3) {
|
||||
tableReadTexCoord[3][4][1] = TexCoord_ReadIndex16_Float2_SSSE3;
|
||||
if (cpu_info.bSSSE3)
|
||||
{
|
||||
tableReadTexCoord[2][4][1] = TexCoord_ReadIndex_Float2_SSSE3<u8>;
|
||||
tableReadTexCoord[3][4][1] = TexCoord_ReadIndex_Float2_SSSE3<u16>;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if _M_SSE >= 0x401
|
||||
|
||||
if (cpu_info.bSSE4_1) {
|
||||
tableReadTexCoord[3][3][1] = TexCoord_ReadIndex16_Short2_SSE4;
|
||||
if (cpu_info.bSSE4_1)
|
||||
{
|
||||
tableReadTexCoord[2][3][1] = TexCoord_ReadIndex_Short2_SSE4<u8>;
|
||||
tableReadTexCoord[3][3][1] = TexCoord_ReadIndex_Short2_SSE4<u16>;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
@@ -24,18 +24,18 @@ class VertexLoader_TextCoord
|
||||
{
|
||||
public:
|
||||
|
||||
// Init
|
||||
static void Init(void);
|
||||
// Init
|
||||
static void Init(void);
|
||||
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
// GetSize
|
||||
static unsigned int GetSize(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
// GetFunction
|
||||
static TPipelineFunction GetFunction(unsigned int _type, unsigned int _format, unsigned int _elements);
|
||||
|
||||
// GetDummyFunction
|
||||
// GetDummyFunction
|
||||
// It is important to synchronize tcIndex.
|
||||
static TPipelineFunction GetDummyFunction();
|
||||
static TPipelineFunction GetDummyFunction();
|
||||
};
|
||||
|
||||
#endif
|
||||
|
||||
@@ -12,171 +12,122 @@
|
||||
#include "BPStructs.h"
|
||||
|
||||
#include "VertexManagerBase.h"
|
||||
#include "MainBase.h"
|
||||
#include "VideoConfig.h"
|
||||
|
||||
VertexManager *g_vertex_manager;
|
||||
|
||||
u8 *VertexManager::s_pCurBufferPointer;
|
||||
u8 *VertexManager::s_pBaseBufferPointer;
|
||||
|
||||
u8 *VertexManager::LocalVBuffer;
|
||||
u16 *VertexManager::TIBuffer;
|
||||
u16 *VertexManager::LIBuffer;
|
||||
u16 *VertexManager::PIBuffer;
|
||||
|
||||
bool VertexManager::Flushed;
|
||||
u8 *VertexManager::s_pEndBufferPointer;
|
||||
|
||||
VertexManager::VertexManager()
|
||||
{
|
||||
Flushed = false;
|
||||
LocalVBuffer.resize(MAXVBUFFERSIZE);
|
||||
s_pCurBufferPointer = s_pBaseBufferPointer = &LocalVBuffer[0];
|
||||
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
|
||||
|
||||
LocalVBuffer = new u8[MAXVBUFFERSIZE];
|
||||
s_pCurBufferPointer = s_pBaseBufferPointer = LocalVBuffer;
|
||||
TIBuffer.resize(MAXIBUFFERSIZE);
|
||||
LIBuffer.resize(MAXIBUFFERSIZE);
|
||||
PIBuffer.resize(MAXIBUFFERSIZE);
|
||||
|
||||
TIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
LIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
PIBuffer = new u16[MAXIBUFFERSIZE];
|
||||
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
}
|
||||
|
||||
void VertexManager::ResetBuffer()
|
||||
{
|
||||
s_pCurBufferPointer = LocalVBuffer;
|
||||
}
|
||||
|
||||
VertexManager::~VertexManager()
|
||||
{
|
||||
delete[] LocalVBuffer;
|
||||
|
||||
delete[] TIBuffer;
|
||||
delete[] LIBuffer;
|
||||
delete[] PIBuffer;
|
||||
|
||||
// TODO: necessary??
|
||||
ResetBuffer();
|
||||
}
|
||||
|
||||
void VertexManager::AddIndices(int primitive, int numVertices)
|
||||
{
|
||||
//switch (primitive)
|
||||
//{
|
||||
//case GX_DRAW_QUADS: IndexGenerator::AddQuads(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLES: IndexGenerator::AddList(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLE_STRIP: IndexGenerator::AddStrip(numVertices); break;
|
||||
//case GX_DRAW_TRIANGLE_FAN: IndexGenerator::AddFan(numVertices); break;
|
||||
//case GX_DRAW_LINES: IndexGenerator::AddLineList(numVertices); break;
|
||||
//case GX_DRAW_LINE_STRIP: IndexGenerator::AddLineStrip(numVertices); break;
|
||||
//case GX_DRAW_POINTS: IndexGenerator::AddPoints(numVertices); break;
|
||||
//}
|
||||
VertexManager::~VertexManager()
|
||||
{}
|
||||
|
||||
static void (*const primitive_table[])(int) =
|
||||
void VertexManager::ResetBuffer()
|
||||
{
|
||||
s_pCurBufferPointer = s_pBaseBufferPointer;
|
||||
IndexGenerator::Start(GetTriangleIndexBuffer(), GetLineIndexBuffer(), GetPointIndexBuffer());
|
||||
}
|
||||
|
||||
u32 VertexManager::GetRemainingSize()
|
||||
{
|
||||
return (u32)(s_pEndBufferPointer - s_pCurBufferPointer);
|
||||
}
|
||||
|
||||
void VertexManager::PrepareForAdditionalData(int primitive, u32 count, u32 stride)
|
||||
{
|
||||
u32 const needed_vertex_bytes = count * stride;
|
||||
|
||||
if (count > IndexGenerator::GetRemainingIndices() || count > GetRemainingIndices(primitive) || needed_vertex_bytes > GetRemainingSize())
|
||||
{
|
||||
IndexGenerator::AddQuads,
|
||||
NULL,
|
||||
IndexGenerator::AddList,
|
||||
IndexGenerator::AddStrip,
|
||||
IndexGenerator::AddFan,
|
||||
IndexGenerator::AddLineList,
|
||||
IndexGenerator::AddLineStrip,
|
||||
IndexGenerator::AddPoints,
|
||||
};
|
||||
|
||||
primitive_table[primitive](numVertices);
|
||||
Flush();
|
||||
|
||||
if(count > IndexGenerator::GetRemainingIndices())
|
||||
ERROR_LOG(VIDEO, "Too less index values. Use 32bit or reset them on flush.");
|
||||
if (count > GetRemainingIndices(primitive))
|
||||
ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all indices! "
|
||||
"Increase MAXIBUFFERSIZE or we need primitive breaking afterall.");
|
||||
if (needed_vertex_bytes > GetRemainingSize())
|
||||
ERROR_LOG(VIDEO, "VertexManager: Buffer not large enough for all vertices! "
|
||||
"Increase MAXVBUFFERSIZE or we need primitive breaking afterall.");
|
||||
}
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingSize()
|
||||
bool VertexManager::IsFlushed() const
|
||||
{
|
||||
return MAXVBUFFERSIZE - (int)(s_pCurBufferPointer - LocalVBuffer);
|
||||
return s_pBaseBufferPointer == s_pCurBufferPointer;
|
||||
}
|
||||
|
||||
int VertexManager::GetRemainingVertices(int primitive)
|
||||
u32 VertexManager::GetRemainingIndices(int primitive)
|
||||
{
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 6 * 4;
|
||||
case GX_DRAW_TRIANGLES:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen());
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2;
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3;
|
||||
break;
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen()) / 3 + 2;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen());
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2;
|
||||
break;
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen()) / 2 + 1;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
return (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen());
|
||||
break;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void VertexManager::AddVertices(int primitive, int numVertices)
|
||||
void VertexManager::AddVertices(int primitive, u32 numVertices)
|
||||
{
|
||||
if (numVertices <= 0)
|
||||
return;
|
||||
|
||||
switch (primitive)
|
||||
{
|
||||
case GX_DRAW_QUADS:
|
||||
case GX_DRAW_TRIANGLES:
|
||||
case GX_DRAW_TRIANGLE_STRIP:
|
||||
case GX_DRAW_TRIANGLE_FAN:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetTriangleindexLen() < 3 * numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_LINES:
|
||||
case GX_DRAW_LINE_STRIP:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetLineindexLen() < 2 * numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
case GX_DRAW_POINTS:
|
||||
if (MAXIBUFFERSIZE - IndexGenerator::GetPointindexLen() < numVertices)
|
||||
Flush();
|
||||
break;
|
||||
|
||||
default:
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (Flushed)
|
||||
{
|
||||
IndexGenerator::Start(TIBuffer, LIBuffer, PIBuffer);
|
||||
Flushed = false;
|
||||
}
|
||||
|
||||
ADDSTAT(stats.thisFrame.numPrims, numVertices);
|
||||
INCSTAT(stats.thisFrame.numPrimitiveJoins);
|
||||
AddIndices(primitive, numVertices);
|
||||
|
||||
IndexGenerator::AddIndices(primitive, numVertices);
|
||||
}
|
||||
|
||||
void VertexManager::Flush()
|
||||
{
|
||||
if (g_vertex_manager->IsFlushed())
|
||||
return;
|
||||
|
||||
// loading a state will invalidate BP, so check for it
|
||||
g_video_backend->CheckInvalidState();
|
||||
|
||||
|
||||
VideoFifo_CheckEFBAccess();
|
||||
|
||||
g_vertex_manager->vFlush();
|
||||
|
||||
g_vertex_manager->ResetBuffer();
|
||||
}
|
||||
|
||||
// TODO: need to merge more stuff into VideoCommon to use this
|
||||
#if (0)
|
||||
void VertexManager::Flush()
|
||||
{
|
||||
if (LocalVBuffer == s_pCurBufferPointer || Flushed)
|
||||
return;
|
||||
|
||||
Flushed = true;
|
||||
|
||||
VideoFifo_CheckEFBAccess();
|
||||
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
PRIM_LOG("frame%d:\n texgen=%d, numchan=%d, dualtex=%d, ztex=%d, cole=%d, alpe=%d, ze=%d", g_ActiveConfig.iSaveTargetId, xfregs.numTexGens,
|
||||
xfregs.nNumChans, (int)xfregs.bEnableDualTexTransform, bpmem.ztex2.op,
|
||||
@@ -249,21 +200,23 @@ void VertexManager::Flush()
|
||||
|
||||
// finally bind
|
||||
if (false == PixelShaderCache::SetShader(false, g_nativeVertexFmt->m_components))
|
||||
goto shader_fail;
|
||||
return;
|
||||
if (false == VertexShaderCache::SetShader(g_nativeVertexFmt->m_components))
|
||||
goto shader_fail;
|
||||
return;
|
||||
|
||||
const int stride = g_nativeVertexFmt->GetVertexStride();
|
||||
//if (g_nativeVertexFmt)
|
||||
g_nativeVertexFmt->SetupVertexPointers();
|
||||
|
||||
g_renderer->ResumePixelPerf(false);
|
||||
g_vertex_manager->Draw(stride, false);
|
||||
g_renderer->PausePixelPerf(false);
|
||||
|
||||
// run through vertex groups again to set alpha
|
||||
if (false == g_ActiveConfig.bDstAlphaPass && bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate)
|
||||
{
|
||||
if (false == PixelShaderCache::SetShader(true, g_nativeVertexFmt->m_components))
|
||||
goto shader_fail;
|
||||
return;
|
||||
|
||||
g_vertex_manager->Draw(stride, true);
|
||||
}
|
||||
@@ -277,10 +230,12 @@ void VertexManager::Flush()
|
||||
// save the shaders
|
||||
char strfile[255];
|
||||
sprintf(strfile, "%sps%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
|
||||
std::ofstream fps(strfile);
|
||||
std::ofstream fps;
|
||||
OpenFStream(fps, strfile, std::ios_base::out);
|
||||
fps << ps->strprog.c_str();
|
||||
sprintf(strfile, "%svs%.3d.txt", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId);
|
||||
std::ofstream fvs(strfile);
|
||||
std::ofstream fvs;
|
||||
OpenFStream(fvs, strfile, std::ios_base::out);
|
||||
fvs << vs->strprog.c_str();
|
||||
}
|
||||
|
||||
@@ -297,9 +252,6 @@ void VertexManager::Flush()
|
||||
}
|
||||
#endif
|
||||
++g_Config.iSaveTargetId;
|
||||
|
||||
shader_fail:
|
||||
ResetBuffer();
|
||||
}
|
||||
#endif
|
||||
|
||||
@@ -310,12 +262,16 @@ void VertexManager::DoState(PointerWrap& p)
|
||||
|
||||
void VertexManager::DoStateShared(PointerWrap& p)
|
||||
{
|
||||
p.DoPointer(s_pCurBufferPointer, LocalVBuffer);
|
||||
p.DoArray(LocalVBuffer, MAXVBUFFERSIZE);
|
||||
p.DoArray(TIBuffer, MAXIBUFFERSIZE);
|
||||
p.DoArray(LIBuffer, MAXIBUFFERSIZE);
|
||||
p.DoArray(PIBuffer, MAXIBUFFERSIZE);
|
||||
|
||||
if (p.GetMode() == PointerWrap::MODE_READ)
|
||||
Flushed = false;
|
||||
// It seems we half-assume to be flushed here
|
||||
// We update s_pCurBufferPointer yet don't worry about IndexGenerator's outdated pointers
|
||||
// and maybe other things are overlooked
|
||||
|
||||
p.Do(LocalVBuffer);
|
||||
p.Do(TIBuffer);
|
||||
p.Do(LIBuffer);
|
||||
p.Do(PIBuffer);
|
||||
|
||||
s_pBaseBufferPointer = &LocalVBuffer[0];
|
||||
s_pEndBufferPointer = s_pBaseBufferPointer + LocalVBuffer.size();
|
||||
p.DoPointer(s_pCurBufferPointer, s_pBaseBufferPointer);
|
||||
}
|
||||
|
||||
@@ -2,72 +2,70 @@
|
||||
#ifndef _VERTEXMANAGERBASE_H
|
||||
#define _VERTEXMANAGERBASE_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <vector>
|
||||
|
||||
class NativeVertexFormat;
|
||||
class PointerWrap;
|
||||
|
||||
class VertexManager
|
||||
{
|
||||
private:
|
||||
static const u32 SMALLEST_POSSIBLE_VERTEX = sizeof(float)*3; // 3 pos
|
||||
static const u32 LARGEST_POSSIBLE_VERTEX = sizeof(float)*45 + sizeof(u32)*2; // 3 pos, 3*3 normal, 2*u32 color, 8*4 tex, 1 posMat
|
||||
|
||||
static const u32 MAX_PRIMITIVES_PER_COMMAND = (u16)-1;
|
||||
|
||||
public:
|
||||
|
||||
enum
|
||||
{
|
||||
// values from OGL backend
|
||||
//MAXVBUFFERSIZE = 0x1FFFF,
|
||||
//MAXIBUFFERSIZE = 0xFFFF,
|
||||
|
||||
// values from DX9 backend
|
||||
//MAXVBUFFERSIZE = 0x50000,
|
||||
//MAXIBUFFERSIZE = 0xFFFF,
|
||||
|
||||
// values from DX11 backend
|
||||
MAXVBUFFERSIZE = 0x50000,
|
||||
MAXIBUFFERSIZE = 0xFFFF,
|
||||
};
|
||||
static const u32 MAXVBUFFERSIZE = ROUND_UP_POW2 (MAX_PRIMITIVES_PER_COMMAND * LARGEST_POSSIBLE_VERTEX);
|
||||
|
||||
// We may convert triangle-fans to triangle-lists, almost 3x as many indices.
|
||||
static const u32 MAXIBUFFERSIZE = ROUND_UP_POW2 (MAX_PRIMITIVES_PER_COMMAND * 3);
|
||||
|
||||
VertexManager();
|
||||
virtual ~VertexManager(); // needs to be virtual for DX11's dtor
|
||||
// needs to be virtual for DX11's dtor
|
||||
virtual ~VertexManager();
|
||||
|
||||
static void AddVertices(int _primitive, int _numVertices);
|
||||
static void AddVertices(int _primitive, u32 _numVertices);
|
||||
|
||||
// TODO: protected?
|
||||
static u8 *s_pCurBufferPointer;
|
||||
static u8 *s_pBaseBufferPointer;
|
||||
static u8 *s_pEndBufferPointer;
|
||||
|
||||
static int GetRemainingSize();
|
||||
static int GetRemainingVertices(int primitive);
|
||||
static u32 GetRemainingSize();
|
||||
static void PrepareForAdditionalData(int primitive, u32 count, u32 stride);
|
||||
static u32 GetRemainingIndices(int primitive);
|
||||
|
||||
static void Flush();
|
||||
|
||||
virtual ::NativeVertexFormat* CreateNativeVertexFormat() = 0;
|
||||
|
||||
static u16* GetTriangleIndexBuffer() { return TIBuffer; }
|
||||
static u16* GetLineIndexBuffer() { return LIBuffer; }
|
||||
static u16* GetPointIndexBuffer() { return PIBuffer; }
|
||||
static u8* GetVertexBuffer() { return LocalVBuffer; }
|
||||
|
||||
static void DoState(PointerWrap& p);
|
||||
virtual void CreateDeviceObjects(){};
|
||||
virtual void DestroyDeviceObjects(){};
|
||||
|
||||
protected:
|
||||
// TODO: make private after Flush() is merged
|
||||
static void ResetBuffer();
|
||||
|
||||
static u8 *LocalVBuffer;
|
||||
static u16 *TIBuffer;
|
||||
static u16 *LIBuffer;
|
||||
static u16 *PIBuffer;
|
||||
|
||||
static bool Flushed;
|
||||
u16* GetTriangleIndexBuffer() { return &TIBuffer[0]; }
|
||||
u16* GetLineIndexBuffer() { return &LIBuffer[0]; }
|
||||
u16* GetPointIndexBuffer() { return &PIBuffer[0]; }
|
||||
u8* GetVertexBuffer() { return &s_pBaseBufferPointer[0]; }
|
||||
|
||||
virtual void vDoState(PointerWrap& p) { DoStateShared(p); }
|
||||
void DoStateShared(PointerWrap& p);
|
||||
|
||||
private:
|
||||
static void AddIndices(int primitive, int numVertices);
|
||||
bool IsFlushed() const;
|
||||
|
||||
void ResetBuffer();
|
||||
|
||||
//virtual void Draw(u32 stride, bool alphapass) = 0;
|
||||
// temp
|
||||
virtual void vFlush() = 0;
|
||||
|
||||
|
||||
std::vector<u8> LocalVBuffer;
|
||||
std::vector<u16> TIBuffer;
|
||||
std::vector<u16> LIBuffer;
|
||||
std::vector<u16> PIBuffer;
|
||||
};
|
||||
|
||||
extern VertexManager *g_vertex_manager;
|
||||
|
||||
@@ -28,41 +28,57 @@
|
||||
|
||||
static char text[16768];
|
||||
|
||||
template<class T>
|
||||
void DefineVSOutputStructMember(T& object, API_TYPE api_type, const char* type, const char* name, int var_index, const char* semantic, int semantic_index = -1)
|
||||
{
|
||||
object.Write(" %s %s", type, name);
|
||||
if (var_index != -1)
|
||||
object.Write("%d", var_index);
|
||||
|
||||
if (api_type == API_OPENGL)
|
||||
object.Write(";\n");
|
||||
else
|
||||
{
|
||||
if (semantic_index != -1)
|
||||
object.Write(" : %s%d;\n", semantic, semantic_index);
|
||||
else
|
||||
object.Write(" : %s;\n", semantic);
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Check if something goes wrong if the cached shaders used pixel lighting but it's disabled later??
|
||||
template<class T>
|
||||
void GenerateVSOutputStruct(T& object, u32 components, API_TYPE api_type)
|
||||
{
|
||||
object.Write("struct VS_OUTPUT {\n");
|
||||
object.Write(" float4 pos : POSITION;\n");
|
||||
object.Write(" float4 colors_0 : COLOR0;\n");
|
||||
object.Write(" float4 colors_1 : COLOR1;\n");
|
||||
DefineVSOutputStructMember(object, api_type, "float4", "pos", -1, "POSITION");
|
||||
DefineVSOutputStructMember(object, api_type, "float4", "colors_", 0, "COLOR", 0);
|
||||
DefineVSOutputStructMember(object, api_type, "float4", "colors_", 1, "COLOR", 1);
|
||||
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
object.Write(" float3 tex%d : TEXCOORD%d;\n", i, i);
|
||||
DefineVSOutputStructMember(object, api_type, "float3", "tex", i, "TEXCOORD", i);
|
||||
|
||||
object.Write(" float4 clipPos : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens);
|
||||
/// if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
/// object.Write(" float4 Normal : TEXCOORD%d;\n", xfregs.numTexGen.numTexGens + 1);
|
||||
DefineVSOutputStructMember(object, api_type, "float4", "clipPos", -1, "TEXCOORD", xfregs.numTexGen.numTexGens);
|
||||
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
DefineVSOutputStructMember(object, api_type, "float4", "Normal", -1, "TEXCOORD", xfregs.numTexGen.numTexGens + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
// clip position is in w of first 4 texcoords
|
||||
/// if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
/// {
|
||||
/// for (int i = 0; i < 8; ++i)
|
||||
/// object.Write(" float4 tex%d : TEXCOORD%d;\n", i, i);
|
||||
/// }
|
||||
/// else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
object.Write(" float%d tex%d : TEXCOORD%d;\n", i < 4 ? 4 : 3 , i, i);
|
||||
}
|
||||
// Store clip position in the w component of first 4 texcoords
|
||||
bool ppl = g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting;
|
||||
int num_texcoords = ppl ? 8 : xfregs.numTexGen.numTexGens;
|
||||
for (int i = 0; i < num_texcoords; ++i)
|
||||
DefineVSOutputStructMember(object, api_type, (ppl || i < 4) ? "float4" : "float3", "tex", i, "TEXCOORD", i);
|
||||
}
|
||||
object.Write("};\n");
|
||||
}
|
||||
|
||||
// TODO: Seriously? -.-
|
||||
extern const char *WriteRegister(API_TYPE api_type, const char *prefix, const u32 num);
|
||||
extern const char *WriteLocation(API_TYPE api_type);
|
||||
|
||||
template<class T, GenOutput type>
|
||||
void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
@@ -76,7 +92,11 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
setlocale(LC_NUMERIC, "C"); // Reset locale for compilation
|
||||
}
|
||||
|
||||
/// text[sizeof(text) - 1] = 0x7C; // canary
|
||||
|
||||
// text[sizeof(text) - 1] = 0x7C; // canary
|
||||
|
||||
_assert_(bpmem.genMode.numtexgens == xfregs.numTexGen.numTexGens);
|
||||
_assert_(bpmem.genMode.numcolchans == xfregs.numChan.numColorChans);
|
||||
|
||||
bool is_d3d = (api_type & API_D3D9 || api_type == API_D3D11);
|
||||
u32 lightMask = 0;
|
||||
@@ -85,74 +105,117 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
if (xfregs.numChan.numColorChans > 1)
|
||||
lightMask |= xfregs.color[1].GetFullLightMask() | xfregs.alpha[1].GetFullLightMask();
|
||||
|
||||
out.Write("//Vertex Shader: comp:%x, \n", components);
|
||||
out.Write("typedef struct { float4 T0, T1, T2; float4 N0, N1, N2; } s_" I_POSNORMALMATRIX";\n"
|
||||
"typedef struct { float4 t; } FLT4;\n"
|
||||
"typedef struct { FLT4 T[24]; } s_" I_TEXMATRICES";\n"
|
||||
"typedef struct { FLT4 T[64]; } s_" I_TRANSFORMMATRICES";\n"
|
||||
"typedef struct { FLT4 T[32]; } s_" I_NORMALMATRICES";\n"
|
||||
"typedef struct { FLT4 T[64]; } s_" I_POSTTRANSFORMMATRICES";\n"
|
||||
"typedef struct { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; } Light;\n"
|
||||
"typedef struct { Light lights[8]; } s_" I_LIGHTS";\n"
|
||||
"typedef struct { float4 C0, C1, C2, C3; } s_" I_MATERIALS";\n"
|
||||
"typedef struct { float4 T0, T1, T2, T3; } s_" I_PROJECTION";\n"
|
||||
);
|
||||
|
||||
/// p = GenerateVSOutputStruct(p, components, api_type);
|
||||
GenerateVSOutputStruct(out, components, api_type);
|
||||
|
||||
// uniforms
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
out.Write("layout(std140) uniform VSBlock {\n");
|
||||
|
||||
out.Write("uniform s_" I_TRANSFORMMATRICES" " I_TRANSFORMMATRICES" : register(c%d);\n", C_TRANSFORMMATRICES);
|
||||
out.Write("uniform s_" I_TEXMATRICES" " I_TEXMATRICES" : register(c%d);\n", C_TEXMATRICES);
|
||||
out.Write("uniform s_" I_NORMALMATRICES" " I_NORMALMATRICES" : register(c%d);\n", C_NORMALMATRICES);
|
||||
out.Write("uniform s_" I_POSNORMALMATRIX" " I_POSNORMALMATRIX" : register(c%d);\n", C_POSNORMALMATRIX);
|
||||
out.Write("uniform s_" I_POSTTRANSFORMMATRICES" " I_POSTTRANSFORMMATRICES" : register(c%d);\n", C_POSTTRANSFORMMATRICES);
|
||||
out.Write("uniform s_" I_LIGHTS" " I_LIGHTS" : register(c%d);\n", C_LIGHTS);
|
||||
out.Write("uniform s_" I_MATERIALS" " I_MATERIALS" : register(c%d);\n", C_MATERIALS);
|
||||
out.Write("uniform s_" I_PROJECTION" " I_PROJECTION" : register(c%d);\n", C_PROJECTION);
|
||||
out.Write("uniform float4 " I_DEPTHPARAMS" : register(c%d);\n", C_DEPTHPARAMS);
|
||||
out.Write("%sfloat4 " I_POSNORMALMATRIX"[6] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_POSNORMALMATRIX));
|
||||
out.Write("%sfloat4 " I_PROJECTION"[4] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_PROJECTION));
|
||||
out.Write("%sfloat4 " I_MATERIALS"[4] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_MATERIALS));
|
||||
out.Write("struct Light { float4 col; float4 cosatt; float4 distatt; float4 pos; float4 dir; };\n");
|
||||
out.Write("%sLight " I_LIGHTS"[8] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_LIGHTS));
|
||||
out.Write("%sfloat4 " I_TEXMATRICES"[24] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_TEXMATRICES)); // also using tex matrices
|
||||
out.Write("%sfloat4 " I_TRANSFORMMATRICES"[64] %s;\n", WriteLocation(api_type),WriteRegister(api_type, "c", C_TRANSFORMMATRICES));
|
||||
out.Write("%sfloat4 " I_NORMALMATRICES"[32] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_NORMALMATRICES));
|
||||
out.Write("%sfloat4 " I_POSTTRANSFORMMATRICES"[64] %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_POSTTRANSFORMMATRICES));
|
||||
out.Write("%sfloat4 " I_DEPTHPARAMS" %s;\n", WriteLocation(api_type), WriteRegister(api_type, "c", C_DEPTHPARAMS));
|
||||
|
||||
out.Write("VS_OUTPUT main(\n");
|
||||
if (g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
out.Write("};\n");
|
||||
|
||||
GenerateVSOutputStruct(out, components, api_type);
|
||||
|
||||
SetUidField(numTexGens, xfregs.numTexGen.numTexGens);
|
||||
SetUidField(components, components);
|
||||
// inputs
|
||||
if (components & VB_HAS_NRM0)
|
||||
out.Write(" float3 rawnorm0 : NORMAL0,\n");
|
||||
if (components & VB_HAS_NRM1)
|
||||
|
||||
if(api_type == API_OPENGL)
|
||||
{
|
||||
if (is_d3d)
|
||||
out.Write(" float3 rawnorm1 : NORMAL1,\n");
|
||||
else
|
||||
out.Write(" float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_NRM2)
|
||||
{
|
||||
if (is_d3d)
|
||||
out.Write(" float3 rawnorm2 : NORMAL2,\n");
|
||||
else
|
||||
out.Write(" float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_COL0)
|
||||
out.Write(" float4 color0 : COLOR0,\n");
|
||||
if (components & VB_HAS_COL1)
|
||||
out.Write(" float4 color1 : COLOR1,\n");
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
|
||||
if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
|
||||
out.Write(" float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
|
||||
}
|
||||
if (components & VB_HAS_POSMTXIDX) {
|
||||
if (is_d3d)
|
||||
out.Write("ATTRIN float4 rawpos; // ATTR%d,\n", SHADER_POSITION_ATTRIB);
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
out.Write("ATTRIN int posmtx; // ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
if (components & VB_HAS_NRM0)
|
||||
out.Write("ATTRIN float3 rawnorm0; // ATTR%d,\n", SHADER_NORM0_ATTRIB);
|
||||
if (components & VB_HAS_NRM1)
|
||||
out.Write("ATTRIN float3 rawnorm1; // ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
if (components & VB_HAS_NRM2)
|
||||
out.Write("ATTRIN float3 rawnorm2; // ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
|
||||
if (components & VB_HAS_COL0)
|
||||
out.Write("ATTRIN float4 color0; // ATTR%d,\n", SHADER_COLOR0_ATTRIB);
|
||||
if (components & VB_HAS_COL1)
|
||||
out.Write("ATTRIN float4 color1; // ATTR%d,\n", SHADER_COLOR1_ATTRIB);
|
||||
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
|
||||
if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
|
||||
out.Write("ATTRIN float%d tex%d; // ATTR%d,\n", hastexmtx ? 3 : 2, i, SHADER_TEXTURE0_ATTRIB + i);
|
||||
}
|
||||
|
||||
// Let's set up attributes
|
||||
if (xfregs.numTexGen.numTexGens < 7)
|
||||
{
|
||||
out.Write(" float4 blend_indices : BLENDINDICES,\n");
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("VARYOUT float3 uv%d_2;\n", i);
|
||||
out.Write("VARYOUT float4 clipPos_2;\n");
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
out.Write("VARYOUT float4 Normal_2;\n");
|
||||
}
|
||||
else
|
||||
out.Write(" float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
{
|
||||
// wpos is in w of first 4 texcoords
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write("VARYOUT float4 uv%d_2;\n", i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
out.Write("VARYOUT float%d uv%d_2;\n", i < 4 ? 4 : 3 , i);
|
||||
}
|
||||
}
|
||||
out.Write("VARYOUT float4 colors_02;\n");
|
||||
out.Write("VARYOUT float4 colors_12;\n");
|
||||
|
||||
out.Write("void main()\n{\n");
|
||||
}
|
||||
out.Write(" float4 rawpos : POSITION) {\n");
|
||||
out.Write("VS_OUTPUT o;\n");
|
||||
else
|
||||
{
|
||||
out.Write("VS_OUTPUT main(\n");
|
||||
|
||||
// inputs
|
||||
if (components & VB_HAS_NRM0)
|
||||
out.Write(" float3 rawnorm0 : NORMAL0,\n");
|
||||
if (components & VB_HAS_NRM1) {
|
||||
if (is_d3d)
|
||||
out.Write(" float3 rawnorm1 : NORMAL1,\n");
|
||||
else
|
||||
out.Write(" float3 rawnorm1 : ATTR%d,\n", SHADER_NORM1_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_NRM2) {
|
||||
if (is_d3d)
|
||||
out.Write(" float3 rawnorm2 : NORMAL2,\n");
|
||||
else
|
||||
out.Write(" float3 rawnorm2 : ATTR%d,\n", SHADER_NORM2_ATTRIB);
|
||||
}
|
||||
if (components & VB_HAS_COL0)
|
||||
out.Write(" float4 color0 : COLOR0,\n");
|
||||
if (components & VB_HAS_COL1)
|
||||
out.Write(" float4 color1 : COLOR1,\n");
|
||||
for (int i = 0; i < 8; ++i) {
|
||||
u32 hastexmtx = (components & (VB_HAS_TEXMTXIDX0<<i));
|
||||
if ((components & (VB_HAS_UV0<<i)) || hastexmtx)
|
||||
out.Write(" float%d tex%d : TEXCOORD%d,\n", hastexmtx ? 3 : 2, i, i);
|
||||
}
|
||||
if (components & VB_HAS_POSMTXIDX) {
|
||||
if (is_d3d)
|
||||
out.Write(" float4 blend_indices : BLENDINDICES,\n");
|
||||
else
|
||||
out.Write(" float fposmtx : ATTR%d,\n", SHADER_POSMTX_ATTRIB);
|
||||
}
|
||||
out.Write(" float4 rawpos : POSITION) {\n");
|
||||
}
|
||||
out.Write("VS_OUTPUT o;\n");
|
||||
|
||||
// transforms
|
||||
if (components & VB_HAS_POSMTXIDX)
|
||||
@@ -166,16 +229,12 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
{
|
||||
out.Write("int posmtx = blend_indices.x * 255.0f;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("int posmtx = fposmtx;\n");
|
||||
}
|
||||
|
||||
out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES".T[posmtx].t, rawpos), dot(" I_TRANSFORMMATRICES".T[posmtx+1].t, rawpos), dot(" I_TRANSFORMMATRICES".T[posmtx+2].t, rawpos), 1);\n");
|
||||
out.Write("float4 pos = float4(dot(" I_TRANSFORMMATRICES"[posmtx], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+1], rawpos), dot(" I_TRANSFORMMATRICES"[posmtx+2], rawpos), 1);\n");
|
||||
|
||||
if (components & VB_HAS_NRMALL) {
|
||||
out.Write("int normidx = posmtx >= 32 ? (posmtx-32) : posmtx;\n");
|
||||
out.Write("float3 N0 = " I_NORMALMATRICES".T[normidx].t.xyz, N1 = " I_NORMALMATRICES".T[normidx+1].t.xyz, N2 = " I_NORMALMATRICES".T[normidx+2].t.xyz;\n");
|
||||
out.Write("float3 N0 = " I_NORMALMATRICES"[normidx].xyz, N1 = " I_NORMALMATRICES"[normidx+1].xyz, N2 = " I_NORMALMATRICES"[normidx+2].xyz;\n");
|
||||
}
|
||||
|
||||
if (components & VB_HAS_NRM0)
|
||||
@@ -187,28 +246,27 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("float4 pos = float4(dot(" I_POSNORMALMATRIX".T0, rawpos), dot(" I_POSNORMALMATRIX".T1, rawpos), dot(" I_POSNORMALMATRIX".T2, rawpos), 1.0f);\n");
|
||||
out.Write("float4 pos = float4(dot(" I_POSNORMALMATRIX"[0], rawpos), dot(" I_POSNORMALMATRIX"[1], rawpos), dot(" I_POSNORMALMATRIX"[2], rawpos), 1.0f);\n");
|
||||
if (components & VB_HAS_NRM0)
|
||||
out.Write("float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm0), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm0), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm0)));\n");
|
||||
out.Write("float3 _norm0 = normalize(float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm0), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm0)));\n");
|
||||
if (components & VB_HAS_NRM1)
|
||||
out.Write("float3 _norm1 = float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm1), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm1), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm1));\n");
|
||||
out.Write("float3 _norm1 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm1), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm1));\n");
|
||||
if (components & VB_HAS_NRM2)
|
||||
out.Write("float3 _norm2 = float3(dot(" I_POSNORMALMATRIX".N0.xyz, rawnorm2), dot(" I_POSNORMALMATRIX".N1.xyz, rawnorm2), dot(" I_POSNORMALMATRIX".N2.xyz, rawnorm2));\n");
|
||||
out.Write("float3 _norm2 = float3(dot(" I_POSNORMALMATRIX"[3].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[4].xyz, rawnorm2), dot(" I_POSNORMALMATRIX"[5].xyz, rawnorm2));\n");
|
||||
}
|
||||
|
||||
if (!(components & VB_HAS_NRM0))
|
||||
out.Write("float3 _norm0 = float3(0.0f, 0.0f, 0.0f);\n");
|
||||
|
||||
|
||||
|
||||
out.Write("o.pos = float4(dot(" I_PROJECTION".T0, pos), dot(" I_PROJECTION".T1, pos), dot(" I_PROJECTION".T2, pos), dot(" I_PROJECTION".T3, pos));\n");
|
||||
out.Write("o.pos = float4(dot(" I_PROJECTION"[0], pos), dot(" I_PROJECTION"[1], pos), dot(" I_PROJECTION"[2], pos), dot(" I_PROJECTION"[3], pos));\n");
|
||||
|
||||
out.Write("float4 mat, lacc;\n"
|
||||
"float3 ldir, h;\n"
|
||||
"float dist, dist2, attn;\n");
|
||||
|
||||
SetUidField(numColorChans, xfregs.numChan.numColorChans);
|
||||
if(xfregs.numChan.numColorChans == 0)
|
||||
if (xfregs.numChan.numColorChans == 0)
|
||||
{
|
||||
if (components & VB_HAS_COL0)
|
||||
out.Write("o.colors_0 = color0;\n");
|
||||
@@ -219,7 +277,7 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
// TODO: This probably isn't necessary if pixel lighting is enabled.
|
||||
GenerateLightingShader<T,type>(out, components, I_MATERIALS, I_LIGHTS, "color", "o.colors_");
|
||||
|
||||
if(xfregs.numChan.numColorChans < 2)
|
||||
if (xfregs.numChan.numColorChans < 2)
|
||||
{
|
||||
if (components & VB_HAS_COL1)
|
||||
out.Write("o.colors_1 = color1;\n");
|
||||
@@ -285,7 +343,7 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
// transform the light dir into tangent space
|
||||
SetUidField(texMtxInfo[i].embosslightshift, xfregs.texMtxInfo[i].embosslightshift);
|
||||
SetUidField(texMtxInfo[i].embosssourceshift, xfregs.texMtxInfo[i].embosssourceshift);
|
||||
out.Write("ldir = normalize(" I_LIGHTS".lights[%d].pos.xyz - pos.xyz);\n", texinfo.embosslightshift);
|
||||
out.Write("ldir = normalize(" I_LIGHTS"[%d].pos.xyz - pos.xyz);\n", texinfo.embosslightshift);
|
||||
out.Write("o.tex%d.xyz = o.tex%d.xyz + float3(dot(ldir, _norm1), dot(ldir, _norm2), 0.0f);\n", i, texinfo.embosssourceshift);
|
||||
}
|
||||
else
|
||||
@@ -307,18 +365,20 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
case XF_TEXGEN_REGULAR:
|
||||
default:
|
||||
SetUidField(texMtxInfo[i].projection, xfregs.texMtxInfo[i].projection);
|
||||
if (components & (VB_HAS_TEXMTXIDX0<<i)) {
|
||||
if (components & (VB_HAS_TEXMTXIDX0<<i))
|
||||
{
|
||||
out.Write("int tmp = int(tex%d.z);\n", i);
|
||||
if (texinfo.projection == XF_TEXPROJ_STQ)
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+1].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+2].t));\n", i, i, i, i);
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), dot(coord, " I_TRANSFORMMATRICES"[tmp+2]));\n", i);
|
||||
else {
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z].t), dot(coord, " I_TRANSFORMMATRICES".T[tex%d.z+1].t), 1);\n", i, i, i);
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TRANSFORMMATRICES"[tmp]), dot(coord, " I_TRANSFORMMATRICES"[tmp+1]), 1);\n", i);
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (texinfo.projection == XF_TEXPROJ_STQ)
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t));\n", i, 3*i, 3*i+1, 3*i+2);
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]));\n", i, 3*i, 3*i+1, 3*i+2);
|
||||
else
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES".T[%d].t), dot(coord, " I_TEXMATRICES".T[%d].t), 1);\n", i, 3*i, 3*i+1);
|
||||
out.Write("o.tex%d.xyz = float3(dot(coord, " I_TEXMATRICES"[%d]), dot(coord, " I_TEXMATRICES"[%d]), 1);\n", i, 3*i, 3*i+1);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -329,10 +389,10 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
|
||||
SetUidField(postMtxInfo[i].index, xfregs.postMtxInfo[i].index);
|
||||
int postidx = postInfo.index;
|
||||
out.Write("float4 P0 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
||||
"float4 P1 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n"
|
||||
"float4 P2 = " I_POSTTRANSFORMMATRICES".T[%d].t;\n",
|
||||
postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);
|
||||
out.Write("float4 P0 = " I_POSTTRANSFORMMATRICES"[%d];\n"
|
||||
"float4 P1 = " I_POSTTRANSFORMMATRICES"[%d];\n"
|
||||
"float4 P2 = " I_POSTTRANSFORMMATRICES"[%d];\n",
|
||||
postidx&0x3f, (postidx+1)&0x3f, (postidx+2)&0x3f);
|
||||
|
||||
if (texGenSpecialCase) {
|
||||
// no normalization
|
||||
@@ -388,33 +448,32 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
|
||||
//write the true depth value, if the game uses depth textures pixel shaders will override with the correct values
|
||||
//if not early z culling will improve speed
|
||||
// TODO: Can probably be dropped?
|
||||
if (is_d3d)
|
||||
{
|
||||
out.Write("o.pos.z = " I_DEPTHPARAMS".x * o.pos.w + o.pos.z * " I_DEPTHPARAMS".y;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
// this results in a scale from -1..0 to -1..1 after perspective
|
||||
// divide
|
||||
out.Write("o.pos.z = o.pos.w + o.pos.z * 2.0f;\n");
|
||||
// this results in a scale from -1..0 to -1..1 after perspective
|
||||
// divide
|
||||
out.Write("o.pos.z = o.pos.w + o.pos.z * 2.0f;\n");
|
||||
|
||||
// Sonic Unleashed puts its final rendering at the near or
|
||||
// far plane of the viewing frustrum(actually box, they use
|
||||
// orthogonal projection for that), and we end up putting it
|
||||
// just beyond, and the rendering gets clipped away. (The
|
||||
// primitive gets dropped)
|
||||
out.Write("o.pos.z = o.pos.z * 1048575.0f/1048576.0f;\n");
|
||||
// Sonic Unleashed puts its final rendering at the near or
|
||||
// far plane of the viewing frustrum(actually box, they use
|
||||
// orthogonal projection for that), and we end up putting it
|
||||
// just beyond, and the rendering gets clipped away. (The
|
||||
// primitive gets dropped)
|
||||
out.Write("o.pos.z = o.pos.z * 1048575.0f/1048576.0f;\n");
|
||||
|
||||
// the next steps of the OGL pipeline are:
|
||||
// (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology
|
||||
// clipping to -w_c <= (x_c,y_c,z_c) <= w_c
|
||||
// (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
|
||||
// z_w = (f-n)/2*z_d + (n+f)/2
|
||||
// z_w now contains the value to go to the 0..1 depth buffer
|
||||
// the next steps of the OGL pipeline are:
|
||||
// (x_c,y_c,z_c,w_c) = o.pos //switch to OGL spec terminology
|
||||
// clipping to -w_c <= (x_c,y_c,z_c) <= w_c
|
||||
// (x_d,y_d,z_d) = (x_c,y_c,z_c)/w_c//perspective divide
|
||||
// z_w = (f-n)/2*z_d + (n+f)/2
|
||||
// z_w now contains the value to go to the 0..1 depth buffer
|
||||
|
||||
//trying to get the correct semantic while not using glDepthRange
|
||||
//seems to get rather complicated
|
||||
//trying to get the correct semantic while not using glDepthRange
|
||||
//seems to get rather complicated
|
||||
}
|
||||
|
||||
if (api_type & API_D3D9)
|
||||
@@ -424,8 +483,42 @@ void GenerateVertexShader(T& out, u32 components, API_TYPE api_type)
|
||||
out.Write("o.pos = o.pos + float4(" I_DEPTHPARAMS".z, " I_DEPTHPARAMS".w, 0.f, 0.f);\n");
|
||||
}
|
||||
|
||||
out.Write("return o;\n}\n");
|
||||
if(api_type == API_OPENGL)
|
||||
{
|
||||
// Bit ugly here
|
||||
// TODO: Make pretty
|
||||
// Will look better when we bind uniforms in GLSL 1.3
|
||||
// clipPos/w needs to be done in pixel shader, not here
|
||||
|
||||
if (xfregs.numTexGen.numTexGens < 7) {
|
||||
for (unsigned int i = 0; i < 8; ++i)
|
||||
if(i < xfregs.numTexGen.numTexGens)
|
||||
out.Write(" uv%d_2.xyz = o.tex%d;\n", i, i);
|
||||
else
|
||||
out.Write(" uv%d_2.xyz = float3(0.0f, 0.0f, 0.0f);\n", i);
|
||||
out.Write(" clipPos_2 = o.clipPos;\n");
|
||||
if(g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
out.Write(" Normal_2 = o.Normal;\n");
|
||||
} else {
|
||||
// clip position is in w of first 4 texcoords
|
||||
if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting)
|
||||
{
|
||||
for (int i = 0; i < 8; ++i)
|
||||
out.Write(" uv%d_2 = o.tex%d;\n", i, i);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i)
|
||||
out.Write(" uv%d_2%s = o.tex%d;\n", i, i < 4 ? ".xyzw" : ".xyz" , i);
|
||||
}
|
||||
}
|
||||
out.Write("colors_02 = o.colors_0;\n");
|
||||
out.Write("colors_12 = o.colors_1;\n");
|
||||
out.Write("gl_Position = o.pos;\n");
|
||||
out.Write("}\n");
|
||||
}
|
||||
else
|
||||
out.Write("return o;\n}\n");
|
||||
|
||||
/// if (text[sizeof(text) - 1] != 0x7C)
|
||||
/// PanicAlert("VertexShader generator - buffer too small, canary has been eaten!");
|
||||
|
||||
@@ -23,9 +23,24 @@
|
||||
#include "VideoCommon.h"
|
||||
#include "ShaderGenCommon.h"
|
||||
|
||||
#define SHADER_POSMTX_ATTRIB 1
|
||||
#define SHADER_NORM1_ATTRIB 6
|
||||
#define SHADER_NORM2_ATTRIB 7
|
||||
// TODO should be reordered
|
||||
#define SHADER_POSITION_ATTRIB 0
|
||||
#define SHADER_POSMTX_ATTRIB 1
|
||||
#define SHADER_NORM0_ATTRIB 2
|
||||
#define SHADER_NORM1_ATTRIB 3
|
||||
#define SHADER_NORM2_ATTRIB 4
|
||||
#define SHADER_COLOR0_ATTRIB 5
|
||||
#define SHADER_COLOR1_ATTRIB 6
|
||||
|
||||
#define SHADER_TEXTURE0_ATTRIB 8
|
||||
#define SHADER_TEXTURE1_ATTRIB 9
|
||||
#define SHADER_TEXTURE2_ATTRIB 10
|
||||
#define SHADER_TEXTURE3_ATTRIB 11
|
||||
#define SHADER_TEXTURE4_ATTRIB 12
|
||||
#define SHADER_TEXTURE5_ATTRIB 13
|
||||
#define SHADER_TEXTURE6_ATTRIB 14
|
||||
#define SHADER_TEXTURE7_ATTRIB 15
|
||||
|
||||
|
||||
|
||||
// shader variables
|
||||
@@ -48,10 +63,22 @@
|
||||
#define C_NORMALMATRICES (C_TRANSFORMMATRICES + 64)
|
||||
#define C_POSTTRANSFORMMATRICES (C_NORMALMATRICES + 32)
|
||||
#define C_DEPTHPARAMS (C_POSTTRANSFORMMATRICES + 64)
|
||||
#define C_VENVCONST_END (C_DEPTHPARAMS + 4)
|
||||
#define C_VENVCONST_END (C_DEPTHPARAMS + 1)
|
||||
|
||||
const s_svar VSVar_Loc[] = { {I_POSNORMALMATRIX, C_POSNORMALMATRIX, 6 },
|
||||
{I_PROJECTION , C_PROJECTION, 4 },
|
||||
{I_MATERIALS, C_MATERIALS, 4 },
|
||||
{I_LIGHTS, C_LIGHTS, 40 },
|
||||
{I_TEXMATRICES, C_TEXMATRICES, 24 },
|
||||
{I_TRANSFORMMATRICES , C_TRANSFORMMATRICES, 64 },
|
||||
{I_NORMALMATRICES , C_NORMALMATRICES, 32 },
|
||||
{I_POSTTRANSFORMMATRICES, C_POSTTRANSFORMMATRICES, 64 },
|
||||
{I_DEPTHPARAMS, C_DEPTHPARAMS, 1 },
|
||||
};
|
||||
|
||||
// TODO: Need packing?
|
||||
struct vertex_shader_uid_data
|
||||
|
||||
{
|
||||
u32 components;
|
||||
u32 numColorChans : 2;
|
||||
|
||||
@@ -1,92 +0,0 @@
|
||||
// Copyright (C) 2003 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef GCOGL_VERTEXSHADER_H
|
||||
#define GCOGL_VERTEXSHADER_H
|
||||
|
||||
#include <stdarg.h>
|
||||
#include "XFMemory.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "ShaderGenCommon.h"
|
||||
|
||||
#define SHADER_POSMTX_ATTRIB 1
|
||||
#define SHADER_NORM1_ATTRIB 6
|
||||
#define SHADER_NORM2_ATTRIB 7
|
||||
|
||||
|
||||
// shader variables
|
||||
#define I_POSNORMALMATRIX "cpnmtx"
|
||||
#define I_PROJECTION "cproj"
|
||||
#define I_MATERIALS "cmtrl"
|
||||
#define I_LIGHTS "clights"
|
||||
#define I_TEXMATRICES "ctexmtx"
|
||||
#define I_TRANSFORMMATRICES "ctrmtx"
|
||||
#define I_NORMALMATRICES "cnmtx"
|
||||
#define I_POSTTRANSFORMMATRICES "cpostmtx"
|
||||
#define I_DEPTHPARAMS "cDepth" // farZ, zRange, scaled viewport width, scaled viewport height
|
||||
|
||||
#define C_POSNORMALMATRIX 0
|
||||
#define C_PROJECTION (C_POSNORMALMATRIX + 6)
|
||||
#define C_MATERIALS (C_PROJECTION + 4)
|
||||
#define C_LIGHTS (C_MATERIALS + 4)
|
||||
#define C_TEXMATRICES (C_LIGHTS + 40)
|
||||
#define C_TRANSFORMMATRICES (C_TEXMATRICES + 24)
|
||||
#define C_NORMALMATRICES (C_TRANSFORMMATRICES + 64)
|
||||
#define C_POSTTRANSFORMMATRICES (C_NORMALMATRICES + 32)
|
||||
#define C_DEPTHPARAMS (C_POSTTRANSFORMMATRICES + 64)
|
||||
#define C_VENVCONST_END (C_DEPTHPARAMS + 4)
|
||||
|
||||
// TODO: Need packing?
|
||||
struct uid_data
|
||||
{
|
||||
u32 components;
|
||||
u32 numColorChans : 2;
|
||||
u32 numTexGens : 4;
|
||||
|
||||
struct {
|
||||
u32 projection : 1; // XF_TEXPROJ_X
|
||||
u32 inputform : 2; // XF_TEXINPUT_X
|
||||
u32 texgentype : 3; // XF_TEXGEN_X
|
||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||
u32 embosslightshift : 3; // light index that is used
|
||||
} texMtxInfo[8];
|
||||
struct {
|
||||
u32 index : 6; // base row of dual transform matrix
|
||||
u32 normalize : 1; // normalize before send operation
|
||||
} postMtxInfo[8];
|
||||
struct {
|
||||
u32 enabled : 1;
|
||||
} dualTexTrans;
|
||||
struct {
|
||||
u32 matsource : 1;
|
||||
u32 enablelighting : 1;
|
||||
u32 ambsource : 1;
|
||||
u32 diffusefunc : 2;
|
||||
u32 attnfunc : 2;
|
||||
u32 light_mask : 8;
|
||||
} lit_chans[4];
|
||||
};
|
||||
|
||||
typedef ShaderUid<uid_data> VertexShaderUid;
|
||||
typedef ShaderCode<uid_data> VertexShaderCode;
|
||||
|
||||
void GetVertexShaderUid(VertexShaderUid& object, u32 components, API_TYPE api_type);
|
||||
void GenerateVertexShaderCode(VertexShaderCode& object, u32 components, API_TYPE api_type);
|
||||
|
||||
|
||||
#endif // GCOGL_VERTEXSHADER_H
|
||||
@@ -102,7 +102,7 @@ float PHackValue(std::string sValue)
|
||||
c[i] = (cStr[i] == ',') ? '.' : *(cStr+i);
|
||||
if (c[i] == '.')
|
||||
fp = true;
|
||||
}
|
||||
}
|
||||
cStr = c;
|
||||
sTof.str(cStr);
|
||||
sTof >> f;
|
||||
@@ -119,22 +119,22 @@ void UpdateProjectionHack(int iPhackvalue[], std::string sPhackvalue[])
|
||||
float fhacksign1 = 1.0, fhacksign2 = 1.0;
|
||||
bool bProjHack3 = false;
|
||||
const char *sTemp[2];
|
||||
|
||||
|
||||
if (iPhackvalue[0] == 1)
|
||||
{
|
||||
NOTICE_LOG(VIDEO, "\t\t--- Ortographic Projection Hack ON ---");
|
||||
|
||||
|
||||
fhacksign1 *= (iPhackvalue[1] == 1) ? -1.0f : fhacksign1;
|
||||
sTemp[0] = (iPhackvalue[1] == 1) ? " * (-1)" : "";
|
||||
fhacksign2 *= (iPhackvalue[2] == 1) ? -1.0f : fhacksign2;
|
||||
sTemp[1] = (iPhackvalue[2] == 1) ? " * (-1)" : "";
|
||||
|
||||
|
||||
fhackvalue1 = PHackValue(sPhackvalue[0]);
|
||||
NOTICE_LOG(VIDEO, "- zNear Correction = (%f + zNear)%s", fhackvalue1, sTemp[0]);
|
||||
|
||||
fhackvalue2 = PHackValue(sPhackvalue[1]);
|
||||
NOTICE_LOG(VIDEO, "- zFar Correction = (%f + zFar)%s", fhackvalue2, sTemp[1]);
|
||||
|
||||
|
||||
sTemp[0] = "DISABLED";
|
||||
bProjHack3 = (iPhackvalue[3] == 1) ? true : bProjHack3;
|
||||
if (bProjHack3)
|
||||
@@ -171,22 +171,22 @@ void VertexShaderManager::Dirty()
|
||||
{
|
||||
nTransformMatricesChanged[0] = 0;
|
||||
nTransformMatricesChanged[1] = 256;
|
||||
|
||||
|
||||
nNormalMatricesChanged[0] = 0;
|
||||
nNormalMatricesChanged[1] = 96;
|
||||
|
||||
|
||||
nPostTransformMatricesChanged[0] = 0;
|
||||
nPostTransformMatricesChanged[1] = 256;
|
||||
|
||||
|
||||
nLightsChanged[0] = 0;
|
||||
nLightsChanged[1] = 0x80;
|
||||
|
||||
|
||||
bPosNormalMatrixChanged = true;
|
||||
bTexMatricesChanged[0] = true;
|
||||
bTexMatricesChanged[1] = true;
|
||||
|
||||
|
||||
bProjectionChanged = true;
|
||||
|
||||
|
||||
nMaterialsChanged = 15;
|
||||
}
|
||||
|
||||
@@ -194,6 +194,8 @@ void VertexShaderManager::Dirty()
|
||||
// TODO: A cleaner way to control the matricies without making a mess in the parameters field
|
||||
void VertexShaderManager::SetConstants()
|
||||
{
|
||||
if (g_ActiveConfig.backend_info.APIType == API_OPENGL && !g_ActiveConfig.backend_info.bSupportsGLSLUBO)
|
||||
Dirty();
|
||||
if (nTransformMatricesChanged[0] >= 0)
|
||||
{
|
||||
int startn = nTransformMatricesChanged[0] / 4;
|
||||
@@ -356,7 +358,7 @@ void VertexShaderManager::SetConstants()
|
||||
switch(xfregs.projection.type)
|
||||
{
|
||||
case GX_PERSPECTIVE:
|
||||
|
||||
|
||||
g_fProjectionMatrix[0] = rawProjection[0] * g_ActiveConfig.fAspectRatioHackW;
|
||||
g_fProjectionMatrix[1] = 0.0f;
|
||||
g_fProjectionMatrix[2] = rawProjection[1];
|
||||
@@ -372,7 +374,7 @@ void VertexShaderManager::SetConstants()
|
||||
g_fProjectionMatrix[10] = rawProjection[4];
|
||||
|
||||
g_fProjectionMatrix[11] = rawProjection[5];
|
||||
|
||||
|
||||
g_fProjectionMatrix[12] = 0.0f;
|
||||
g_fProjectionMatrix[13] = 0.0f;
|
||||
// donkopunchstania: GC GPU rounds differently?
|
||||
@@ -397,9 +399,9 @@ void VertexShaderManager::SetConstants()
|
||||
SETSTAT_FT(stats.gproj_14, g_fProjectionMatrix[14]);
|
||||
SETSTAT_FT(stats.gproj_15, g_fProjectionMatrix[15]);
|
||||
break;
|
||||
|
||||
|
||||
case GX_ORTHOGRAPHIC:
|
||||
|
||||
|
||||
g_fProjectionMatrix[0] = rawProjection[0];
|
||||
g_fProjectionMatrix[1] = 0.0f;
|
||||
g_fProjectionMatrix[2] = 0.0f;
|
||||
@@ -424,10 +426,10 @@ void VertexShaderManager::SetConstants()
|
||||
this hack was added...setting g_fProjectionMatrix[14] to -1 might make the hack more stable, needs more testing.
|
||||
Only works for OGL and DX9...this is not helping DX11
|
||||
*/
|
||||
|
||||
|
||||
g_fProjectionMatrix[14] = 0.0f;
|
||||
g_fProjectionMatrix[15] = (g_ProjHack3 && rawProjection[0] == 2.0f ? 0.0f : 1.0f); //causes either the efb copy or bloom layer not to show if proj hack enabled
|
||||
|
||||
|
||||
SETSTAT_FT(stats.g2proj_0, g_fProjectionMatrix[0]);
|
||||
SETSTAT_FT(stats.g2proj_1, g_fProjectionMatrix[1]);
|
||||
SETSTAT_FT(stats.g2proj_2, g_fProjectionMatrix[2]);
|
||||
@@ -451,7 +453,7 @@ void VertexShaderManager::SetConstants()
|
||||
SETSTAT_FT(stats.proj_4, rawProjection[4]);
|
||||
SETSTAT_FT(stats.proj_5, rawProjection[5]);
|
||||
break;
|
||||
|
||||
|
||||
default:
|
||||
ERROR_LOG(VIDEO, "unknown projection type: %d", xfregs.projection.type);
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public:
|
||||
static void Dirty();
|
||||
static void Shutdown();
|
||||
static void DoState(PointerWrap &p);
|
||||
;
|
||||
|
||||
// constant management
|
||||
static void SetConstants();
|
||||
|
||||
|
||||
@@ -90,8 +90,8 @@ struct TargetRectangle : public MathUtil::Rectangle<int>
|
||||
#define PRIM_LOG(...) DEBUG_LOG(VIDEO, ##__VA_ARGS__)
|
||||
#endif
|
||||
|
||||
|
||||
// #define LOG_VTX() DEBUG_LOG(VIDEO, "vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[0], ((float*)VertexManager::s_pCurBufferPointer)[1], ((float*)VertexManager::s_pCurBufferPointer)[2]);
|
||||
// warning: mapping buffer should be disabled to use this
|
||||
// #define LOG_VTX() DEBUG_LOG(VIDEO, "vtx: %f %f %f, ", ((float*)VertexManager::s_pCurBufferPointer)[-3], ((float*)VertexManager::s_pCurBufferPointer)[-2], ((float*)VertexManager::s_pCurBufferPointer)[-1]);
|
||||
|
||||
#define LOG_VTX()
|
||||
|
||||
@@ -102,8 +102,7 @@ typedef enum
|
||||
API_D3D9_SM20 = 4,
|
||||
API_D3D9 = 6,
|
||||
API_D3D11 = 8,
|
||||
API_GLSL = 16,
|
||||
API_NONE = 32
|
||||
API_NONE = 16
|
||||
} API_TYPE;
|
||||
|
||||
inline u32 RGBA8ToRGBA6ToRGBA8(u32 src)
|
||||
@@ -149,5 +148,11 @@ inline unsigned int GetPow2(unsigned int val)
|
||||
++ret;
|
||||
return ret;
|
||||
}
|
||||
struct s_svar
|
||||
{
|
||||
const char *name;
|
||||
const unsigned int reg;
|
||||
const unsigned int size;
|
||||
};
|
||||
|
||||
#endif // _VIDEOCOMMON_H
|
||||
|
||||
@@ -22,6 +22,7 @@
|
||||
#include "VideoConfig.h"
|
||||
#include "VideoCommon.h"
|
||||
#include "FileUtil.h"
|
||||
#include "Core.h"
|
||||
|
||||
VideoConfig g_Config;
|
||||
VideoConfig g_ActiveConfig;
|
||||
@@ -42,6 +43,7 @@ VideoConfig::VideoConfig()
|
||||
// disable all features by default
|
||||
backend_info.APIType = API_NONE;
|
||||
backend_info.bUseRGBATextures = false;
|
||||
backend_info.bUseMinimalMipCount = false;
|
||||
backend_info.bSupports3DVision = false;
|
||||
}
|
||||
|
||||
@@ -50,7 +52,7 @@ void VideoConfig::Load(const char *ini_file)
|
||||
std::string temp;
|
||||
IniFile iniFile;
|
||||
iniFile.Load(ini_file);
|
||||
|
||||
|
||||
iniFile.Get("Hardware", "VSync", &bVSync, 0); // Hardware
|
||||
iniFile.Get("Settings", "wideScreenHack", &bWidescreenHack, false);
|
||||
iniFile.Get("Settings", "AspectRatio", &iAspectRatio, (int)ASPECT_AUTO);
|
||||
@@ -75,17 +77,18 @@ void VideoConfig::Load(const char *ini_file)
|
||||
iniFile.Get("Settings", "AnaglyphStereoSeparation", &iAnaglyphStereoSeparation, 200);
|
||||
iniFile.Get("Settings", "AnaglyphFocalAngle", &iAnaglyphFocalAngle, 0);
|
||||
iniFile.Get("Settings", "EnablePixelLighting", &bEnablePixelLighting, 0);
|
||||
|
||||
iniFile.Get("Settings", "HackedBufferUpload", &bHackedBufferUpload, 0);
|
||||
|
||||
iniFile.Get("Settings", "MSAA", &iMultisampleMode, 0);
|
||||
iniFile.Get("Settings", "EFBScale", &iEFBScale, 2); // native
|
||||
|
||||
|
||||
iniFile.Get("Settings", "DstAlphaPass", &bDstAlphaPass, false);
|
||||
|
||||
|
||||
iniFile.Get("Settings", "TexFmtOverlayEnable", &bTexFmtOverlayEnable, 0);
|
||||
iniFile.Get("Settings", "TexFmtOverlayCenter", &bTexFmtOverlayCenter, 0);
|
||||
iniFile.Get("Settings", "WireFrame", &bWireFrame, 0);
|
||||
iniFile.Get("Settings", "DisableFog", &bDisableFog, 0);
|
||||
|
||||
|
||||
iniFile.Get("Settings", "EnableOpenCL", &bEnableOpenCL, false);
|
||||
iniFile.Get("Settings", "OMPDecoder", &bOMPDecoder, false);
|
||||
|
||||
@@ -95,7 +98,7 @@ void VideoConfig::Load(const char *ini_file)
|
||||
iniFile.Get("Enhancements", "MaxAnisotropy", &iMaxAnisotropy, 0); // NOTE - this is x in (1 << x)
|
||||
iniFile.Get("Enhancements", "PostProcessingShader", &sPostProcessingShader, "");
|
||||
iniFile.Get("Enhancements", "Enable3dVision", &b3DVision, false);
|
||||
|
||||
|
||||
iniFile.Get("Hacks", "EFBAccessEnable", &bEFBAccessEnable, true);
|
||||
iniFile.Get("Hacks", "DlistCachingEnable", &bDlistCachingEnable,false);
|
||||
iniFile.Get("Hacks", "EFBCopyEnable", &bEFBCopyEnable, true);
|
||||
@@ -133,6 +136,7 @@ void VideoConfig::GameIniLoad(const char *ini_file)
|
||||
iniFile.GetIfExists("Video_Settings", "AnaglyphStereoSeparation", &iAnaglyphStereoSeparation);
|
||||
iniFile.GetIfExists("Video_Settings", "AnaglyphFocalAngle", &iAnaglyphFocalAngle);
|
||||
iniFile.GetIfExists("Video_Settings", "EnablePixelLighting", &bEnablePixelLighting);
|
||||
iniFile.GetIfExists("Video_Settings", "HackedBufferUpload", &bHackedBufferUpload);
|
||||
iniFile.GetIfExists("Video_Settings", "MSAA", &iMultisampleMode);
|
||||
iniFile.GetIfExists("Video_Settings", "EFBScale", &iEFBScale); // integral
|
||||
iniFile.GetIfExists("Video_Settings", "DstAlphaPass", &bDstAlphaPass);
|
||||
@@ -171,6 +175,7 @@ void VideoConfig::VerifyValidity()
|
||||
if (!backend_info.bSupports3DVision) b3DVision = false;
|
||||
if (!backend_info.bSupportsFormatReinterpretation) bEFBEmulateFormatChanges = false;
|
||||
if (!backend_info.bSupportsPixelLighting) bEnablePixelLighting = false;
|
||||
if (backend_info.APIType != API_OPENGL) backend_info.bSupportsGLSLUBO = false;
|
||||
}
|
||||
|
||||
void VideoConfig::Save(const char *ini_file)
|
||||
@@ -201,7 +206,7 @@ void VideoConfig::Save(const char *ini_file)
|
||||
iniFile.Set("Settings", "AnaglyphStereoSeparation", iAnaglyphStereoSeparation);
|
||||
iniFile.Set("Settings", "AnaglyphFocalAngle", iAnaglyphFocalAngle);
|
||||
iniFile.Set("Settings", "EnablePixelLighting", bEnablePixelLighting);
|
||||
|
||||
iniFile.Set("Settings", "HackedBufferUpload", bHackedBufferUpload);
|
||||
|
||||
iniFile.Set("Settings", "ShowEFBCopyRegions", bShowEFBCopyRegions);
|
||||
iniFile.Set("Settings", "MSAA", iMultisampleMode);
|
||||
@@ -214,14 +219,14 @@ void VideoConfig::Save(const char *ini_file)
|
||||
|
||||
iniFile.Set("Settings", "EnableOpenCL", bEnableOpenCL);
|
||||
iniFile.Set("Settings", "OMPDecoder", bOMPDecoder);
|
||||
|
||||
|
||||
iniFile.Set("Settings", "EnableShaderDebugging", bEnableShaderDebugging);
|
||||
|
||||
iniFile.Set("Enhancements", "ForceFiltering", bForceFiltering);
|
||||
iniFile.Set("Enhancements", "MaxAnisotropy", iMaxAnisotropy);
|
||||
iniFile.Set("Enhancements", "PostProcessingShader", sPostProcessingShader);
|
||||
iniFile.Set("Enhancements", "Enable3dVision", b3DVision);
|
||||
|
||||
|
||||
iniFile.Set("Hacks", "EFBAccessEnable", bEFBAccessEnable);
|
||||
iniFile.Set("Hacks", "DlistCachingEnable", bDlistCachingEnable);
|
||||
iniFile.Set("Hacks", "EFBCopyEnable", bEFBCopyEnable);
|
||||
@@ -232,7 +237,7 @@ void VideoConfig::Save(const char *ini_file)
|
||||
iniFile.Set("Hacks", "EFBEmulateFormatChanges", bEFBEmulateFormatChanges);
|
||||
|
||||
iniFile.Set("Hardware", "Adapter", iAdapter);
|
||||
|
||||
|
||||
iniFile.Save(ini_file);
|
||||
}
|
||||
|
||||
@@ -288,3 +293,8 @@ void VideoConfig::GameIniSave(const char* default_ini, const char* game_ini)
|
||||
|
||||
iniFile.Save(game_ini);
|
||||
}
|
||||
|
||||
bool VideoConfig::IsVSync()
|
||||
{
|
||||
return Core::isTabPressed ? false : bVSync;
|
||||
}
|
||||
|
||||
@@ -37,17 +37,6 @@
|
||||
#define CONF_SAVETARGETS 8
|
||||
#define CONF_SAVESHADERS 16
|
||||
|
||||
enum MultisampleMode {
|
||||
MULTISAMPLE_OFF,
|
||||
MULTISAMPLE_2X,
|
||||
MULTISAMPLE_4X,
|
||||
MULTISAMPLE_8X,
|
||||
MULTISAMPLE_CSAA_8X,
|
||||
MULTISAMPLE_CSAA_8XQ,
|
||||
MULTISAMPLE_CSAA_16X,
|
||||
MULTISAMPLE_CSAA_16XQ,
|
||||
};
|
||||
|
||||
enum AspectMode {
|
||||
ASPECT_AUTO = 0,
|
||||
ASPECT_FORCE_16_9 = 1,
|
||||
@@ -67,6 +56,7 @@ struct VideoConfig
|
||||
void Save(const char *ini_file);
|
||||
void GameIniSave(const char* default_ini, const char* game_ini);
|
||||
void UpdateProjectionHack();
|
||||
bool IsVSync();
|
||||
|
||||
// General
|
||||
bool bVSync;
|
||||
@@ -98,12 +88,12 @@ struct VideoConfig
|
||||
bool bTexFmtOverlayCenter;
|
||||
bool bShowEFBCopyRegions;
|
||||
bool bLogFPSToFile;
|
||||
|
||||
|
||||
// Render
|
||||
bool bWireFrame;
|
||||
bool bDstAlphaPass;
|
||||
bool bDisableFog;
|
||||
|
||||
|
||||
// Utility
|
||||
bool bDumpTextures;
|
||||
bool bHiresTextures;
|
||||
@@ -115,7 +105,7 @@ struct VideoConfig
|
||||
int iAnaglyphStereoSeparation;
|
||||
int iAnaglyphFocalAngle;
|
||||
bool b3DVision;
|
||||
|
||||
|
||||
// Hacks
|
||||
bool bEFBAccessEnable;
|
||||
bool bDlistCachingEnable;
|
||||
@@ -133,6 +123,7 @@ struct VideoConfig
|
||||
bool bZTPSpeedHack; // The Legend of Zelda: Twilight Princess
|
||||
bool bUseBBox;
|
||||
bool bEnablePixelLighting;
|
||||
bool bHackedBufferUpload;
|
||||
|
||||
int iLog; // CONF_ bits
|
||||
int iSaveTargetId; // TODO: Should be dropped
|
||||
@@ -157,17 +148,20 @@ struct VideoConfig
|
||||
std::vector<std::string> PPShaders; // post-processing shaders
|
||||
|
||||
bool bUseRGBATextures; // used for D3D11 in TextureCache
|
||||
bool bUseMinimalMipCount;
|
||||
bool bSupports3DVision;
|
||||
bool bSupportsDualSourceBlend; // only supported by D3D11 and OpenGL
|
||||
bool bSupportsFormatReinterpretation;
|
||||
bool bSupportsPixelLighting;
|
||||
|
||||
bool bSupportsGLSLUBO; // needed by pixelShaderGen, so must stay in videoCommon
|
||||
} backend_info;
|
||||
|
||||
// Utility
|
||||
bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; }
|
||||
bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; }
|
||||
bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; }
|
||||
bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; }
|
||||
// Utility
|
||||
bool RealXFBEnabled() const { return bUseXFB && bUseRealXFB; }
|
||||
bool VirtualXFBEnabled() const { return bUseXFB && !bUseRealXFB; }
|
||||
bool EFBCopiesToTextureEnabled() const { return bEFBCopyEnable && bCopyEFBToTexture; }
|
||||
bool EFBCopiesToRamEnabled() const { return bEFBCopyEnable && !bCopyEFBToTexture; }
|
||||
};
|
||||
|
||||
extern VideoConfig g_Config;
|
||||
|
||||
@@ -30,33 +30,33 @@
|
||||
|
||||
static void DoState(PointerWrap &p)
|
||||
{
|
||||
// BP Memory
|
||||
p.Do(bpmem);
|
||||
// BP Memory
|
||||
p.Do(bpmem);
|
||||
p.DoMarker("BP Memory");
|
||||
|
||||
// CP Memory
|
||||
p.DoArray(arraybases, 16);
|
||||
p.DoArray(arraystrides, 16);
|
||||
p.Do(MatrixIndexA);
|
||||
p.Do(MatrixIndexB);
|
||||
p.Do(g_VtxDesc.Hex);
|
||||
p.DoArray(arraybases, 16);
|
||||
p.DoArray(arraystrides, 16);
|
||||
p.Do(MatrixIndexA);
|
||||
p.Do(MatrixIndexB);
|
||||
p.Do(g_VtxDesc.Hex);
|
||||
p.DoArray(g_VtxAttr, 8);
|
||||
p.DoMarker("CP Memory");
|
||||
|
||||
// XF Memory
|
||||
p.Do(xfregs);
|
||||
p.DoArray(xfmem, XFMEM_SIZE);
|
||||
// XF Memory
|
||||
p.Do(xfregs);
|
||||
p.DoArray(xfmem, XFMEM_SIZE);
|
||||
p.DoMarker("XF Memory");
|
||||
|
||||
// Texture decoder
|
||||
p.DoArray(texMem, TMEM_SIZE);
|
||||
p.DoArray(texMem, TMEM_SIZE);
|
||||
p.DoMarker("texMem");
|
||||
|
||||
// FIFO
|
||||
Fifo_DoState(p);
|
||||
// FIFO
|
||||
Fifo_DoState(p);
|
||||
p.DoMarker("Fifo");
|
||||
|
||||
CommandProcessor::DoState(p);
|
||||
CommandProcessor::DoState(p);
|
||||
p.DoMarker("CommandProcessor");
|
||||
|
||||
PixelEngine::DoState(p);
|
||||
@@ -77,7 +77,7 @@ static void DoState(PointerWrap &p)
|
||||
|
||||
void VideoCommon_DoState(PointerWrap &p)
|
||||
{
|
||||
DoState(p);
|
||||
DoState(p);
|
||||
}
|
||||
|
||||
void VideoCommon_RunLoop(bool enable)
|
||||
|
||||
@@ -110,70 +110,70 @@
|
||||
|
||||
union LitChannel
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 matsource : 1;
|
||||
u32 enablelighting : 1;
|
||||
u32 lightMask0_3 : 4;
|
||||
u32 ambsource : 1;
|
||||
u32 diffusefunc : 2; // LIGHTDIF_X
|
||||
u32 attnfunc : 2; // LIGHTATTN_X
|
||||
u32 lightMask4_7 : 4;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 hex : 15;
|
||||
u32 unused : 17;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 dummy0 : 7;
|
||||
u32 lightparams : 4;
|
||||
u32 dummy1 : 21;
|
||||
};
|
||||
unsigned int GetFullLightMask() const
|
||||
{
|
||||
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
|
||||
}
|
||||
struct
|
||||
{
|
||||
u32 matsource : 1;
|
||||
u32 enablelighting : 1;
|
||||
u32 lightMask0_3 : 4;
|
||||
u32 ambsource : 1;
|
||||
u32 diffusefunc : 2; // LIGHTDIF_X
|
||||
u32 attnfunc : 2; // LIGHTATTN_X
|
||||
u32 lightMask4_7 : 4;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 hex : 15;
|
||||
u32 unused : 17;
|
||||
};
|
||||
struct
|
||||
{
|
||||
u32 dummy0 : 7;
|
||||
u32 lightparams : 4;
|
||||
u32 dummy1 : 21;
|
||||
};
|
||||
unsigned int GetFullLightMask() const
|
||||
{
|
||||
return enablelighting ? (lightMask0_3 | (lightMask4_7 << 4)) : 0;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
union INVTXSPEC
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 numcolors : 2;
|
||||
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
|
||||
u32 numtextures : 4;
|
||||
u32 unused : 24;
|
||||
};
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
u32 numcolors : 2;
|
||||
u32 numnormals : 2; // 0 - nothing, 1 - just normal, 2 - normals and binormals
|
||||
u32 numtextures : 4;
|
||||
u32 unused : 24;
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union TexMtxInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 unknown : 1;
|
||||
u32 projection : 1; // XF_TEXPROJ_X
|
||||
u32 inputform : 2; // XF_TEXINPUT_X
|
||||
u32 texgentype : 3; // XF_TEXGEN_X
|
||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||
u32 embosslightshift : 3; // light index that is used
|
||||
};
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
u32 unknown : 1;
|
||||
u32 projection : 1; // XF_TEXPROJ_X
|
||||
u32 inputform : 2; // XF_TEXINPUT_X
|
||||
u32 texgentype : 3; // XF_TEXGEN_X
|
||||
u32 sourcerow : 5; // XF_SRCGEOM_X
|
||||
u32 embosssourceshift : 3; // what generated texcoord to use
|
||||
u32 embosslightshift : 3; // light index that is used
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union PostMtxInfo
|
||||
{
|
||||
struct
|
||||
{
|
||||
u32 index : 6; // base row of dual transform matrix
|
||||
u32 unused : 2;
|
||||
u32 normalize : 1; // normalize before send operation
|
||||
};
|
||||
u32 hex;
|
||||
struct
|
||||
{
|
||||
u32 index : 6; // base row of dual transform matrix
|
||||
u32 unused : 2;
|
||||
u32 normalize : 1; // normalize before send operation
|
||||
};
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
union NumColorChannel
|
||||
@@ -207,25 +207,25 @@ union DualTexInfo
|
||||
|
||||
struct Light
|
||||
{
|
||||
u32 useless[3];
|
||||
u32 color; //rgba
|
||||
float a0; //attenuation
|
||||
float a1;
|
||||
float a2;
|
||||
float k0; //k stuff
|
||||
float k1;
|
||||
float k2;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
u32 useless[3];
|
||||
u32 color; //rgba
|
||||
float a0; //attenuation
|
||||
float a1;
|
||||
float a2;
|
||||
float k0; //k stuff
|
||||
float k1;
|
||||
float k2;
|
||||
union
|
||||
{
|
||||
struct {
|
||||
float dpos[3];
|
||||
float ddir[3]; // specular lights only
|
||||
};
|
||||
struct {
|
||||
float sdir[3];
|
||||
float shalfangle[3]; // specular lights only
|
||||
};
|
||||
};
|
||||
float ddir[3]; // specular lights only
|
||||
};
|
||||
struct {
|
||||
float sdir[3];
|
||||
float shalfangle[3]; // specular lights only
|
||||
};
|
||||
};
|
||||
};
|
||||
|
||||
struct Viewport
|
||||
@@ -246,35 +246,35 @@ struct Projection
|
||||
|
||||
struct XFRegisters
|
||||
{
|
||||
u32 error; // 0x1000
|
||||
u32 diag; // 0x1001
|
||||
u32 state0; // 0x1002
|
||||
u32 state1; // 0x1003
|
||||
u32 xfClock; // 0x1004
|
||||
u32 clipDisable; // 0x1005
|
||||
u32 perf0; // 0x1006
|
||||
u32 perf1; // 0x1007
|
||||
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
|
||||
NumColorChannel numChan; // 0x1009
|
||||
u32 ambColor[2]; // 0x100a, 0x100b
|
||||
u32 matColor[2]; // 0x100c, 0x100d
|
||||
LitChannel color[2]; // 0x100e, 0x100f
|
||||
LitChannel alpha[2]; // 0x1010, 0x1011
|
||||
DualTexInfo dualTexTrans; // 0x1012
|
||||
u32 unk3; // 0x1013
|
||||
u32 unk4; // 0x1014
|
||||
u32 unk5; // 0x1015
|
||||
u32 unk6; // 0x1016
|
||||
u32 unk7; // 0x1017
|
||||
u32 MatrixIndexA; // 0x1018
|
||||
u32 MatrixIndexB; // 0x1019
|
||||
Viewport viewport; // 0x101a - 0x101f
|
||||
Projection projection; // 0x1020 - 0x1026
|
||||
u32 unk8[24]; // 0x1027 - 0x103e
|
||||
NumTexGen numTexGen; // 0x103f
|
||||
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
|
||||
u32 unk9[8]; // 0x1048 - 0x104f
|
||||
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
|
||||
u32 error; // 0x1000
|
||||
u32 diag; // 0x1001
|
||||
u32 state0; // 0x1002
|
||||
u32 state1; // 0x1003
|
||||
u32 xfClock; // 0x1004
|
||||
u32 clipDisable; // 0x1005
|
||||
u32 perf0; // 0x1006
|
||||
u32 perf1; // 0x1007
|
||||
INVTXSPEC hostinfo; // 0x1008 number of textures,colors,normals from vertex input
|
||||
NumColorChannel numChan; // 0x1009
|
||||
u32 ambColor[2]; // 0x100a, 0x100b
|
||||
u32 matColor[2]; // 0x100c, 0x100d
|
||||
LitChannel color[2]; // 0x100e, 0x100f
|
||||
LitChannel alpha[2]; // 0x1010, 0x1011
|
||||
DualTexInfo dualTexTrans; // 0x1012
|
||||
u32 unk3; // 0x1013
|
||||
u32 unk4; // 0x1014
|
||||
u32 unk5; // 0x1015
|
||||
u32 unk6; // 0x1016
|
||||
u32 unk7; // 0x1017
|
||||
u32 MatrixIndexA; // 0x1018
|
||||
u32 MatrixIndexB; // 0x1019
|
||||
Viewport viewport; // 0x101a - 0x101f
|
||||
Projection projection; // 0x1020 - 0x1026
|
||||
u32 unk8[24]; // 0x1027 - 0x103e
|
||||
NumTexGen numTexGen; // 0x103f
|
||||
TexMtxInfo texMtxInfo[8]; // 0x1040 - 0x1047
|
||||
u32 unk9[8]; // 0x1048 - 0x104f
|
||||
PostMtxInfo postMtxInfo[8]; // 0x1050 - 0x1057
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -36,37 +36,37 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
|
||||
u32 address = baseAddress;
|
||||
u32 dataIndex = 0;
|
||||
|
||||
while (transferSize > 0 && address < 0x1058)
|
||||
{
|
||||
u32 newValue = pData[dataIndex];
|
||||
while (transferSize > 0 && address < 0x1058)
|
||||
{
|
||||
u32 newValue = pData[dataIndex];
|
||||
u32 nextAddress = address + 1;
|
||||
|
||||
switch (address)
|
||||
{
|
||||
case XFMEM_ERROR:
|
||||
case XFMEM_DIAG:
|
||||
case XFMEM_STATE0: // internal state 0
|
||||
case XFMEM_STATE1: // internal state 1
|
||||
case XFMEM_CLOCK:
|
||||
switch (address)
|
||||
{
|
||||
case XFMEM_ERROR:
|
||||
case XFMEM_DIAG:
|
||||
case XFMEM_STATE0: // internal state 0
|
||||
case XFMEM_STATE1: // internal state 1
|
||||
case XFMEM_CLOCK:
|
||||
case XFMEM_SETGPMETRIC:
|
||||
nextAddress = 0x1007;
|
||||
break;
|
||||
break;
|
||||
|
||||
case XFMEM_CLIPDISABLE:
|
||||
case XFMEM_CLIPDISABLE:
|
||||
//if (data & 1) {} // disable clipping detection
|
||||
//if (data & 2) {} // disable trivial rejection
|
||||
//if (data & 4) {} // disable cpoly clipping acceleration
|
||||
break;
|
||||
break;
|
||||
|
||||
case XFMEM_VTXSPECS: //__GXXfVtxSpecs, wrote 0004
|
||||
break;
|
||||
case XFMEM_VTXSPECS: //__GXXfVtxSpecs, wrote 0004
|
||||
break;
|
||||
|
||||
case XFMEM_SETNUMCHAN:
|
||||
case XFMEM_SETNUMCHAN:
|
||||
if (xfregs.numChan.numColorChans != (newValue & 3))
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
|
||||
case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color
|
||||
case XFMEM_SETCHAN0_AMBCOLOR: // Channel Ambient Color
|
||||
case XFMEM_SETCHAN1_AMBCOLOR:
|
||||
{
|
||||
u8 chan = address - XFMEM_SETCHAN0_AMBCOLOR;
|
||||
@@ -75,11 +75,11 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
|
||||
VertexManager::Flush();
|
||||
VertexShaderManager::SetMaterialColorChanged(chan);
|
||||
PixelShaderManager::SetMaterialColorChanged(chan);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
case XFMEM_SETCHAN0_MATCOLOR: // Channel Material Color
|
||||
case XFMEM_SETCHAN0_MATCOLOR: // Channel Material Color
|
||||
case XFMEM_SETCHAN1_MATCOLOR:
|
||||
{
|
||||
u8 chan = address - XFMEM_SETCHAN0_MATCOLOR;
|
||||
@@ -92,28 +92,28 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
|
||||
break;
|
||||
}
|
||||
|
||||
case XFMEM_SETCHAN0_COLOR: // Channel Color
|
||||
case XFMEM_SETCHAN0_COLOR: // Channel Color
|
||||
case XFMEM_SETCHAN1_COLOR:
|
||||
case XFMEM_SETCHAN0_ALPHA: // Channel Alpha
|
||||
case XFMEM_SETCHAN1_ALPHA:
|
||||
case XFMEM_SETCHAN1_ALPHA:
|
||||
if (((u32*)&xfregs)[address - 0x1000] != (newValue & 0x7fff))
|
||||
VertexManager::Flush();
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
|
||||
case XFMEM_DUALTEX:
|
||||
case XFMEM_DUALTEX:
|
||||
if (xfregs.dualTexTrans.enabled != (newValue & 1))
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
|
||||
|
||||
case XFMEM_SETMATRIXINDA:
|
||||
//_assert_msg_(GX_XF, 0, "XF matrixindex0");
|
||||
case XFMEM_SETMATRIXINDA:
|
||||
//_assert_msg_(GX_XF, 0, "XF matrixindex0");
|
||||
VertexShaderManager::SetTexMatrixChangedA(newValue);
|
||||
break;
|
||||
case XFMEM_SETMATRIXINDB:
|
||||
//_assert_msg_(GX_XF, 0, "XF matrixindex1");
|
||||
VertexShaderManager::SetTexMatrixChangedB(newValue);
|
||||
break;
|
||||
break;
|
||||
case XFMEM_SETMATRIXINDB:
|
||||
//_assert_msg_(GX_XF, 0, "XF matrixindex1");
|
||||
VertexShaderManager::SetTexMatrixChangedB(newValue);
|
||||
break;
|
||||
|
||||
case XFMEM_SETVIEWPORT:
|
||||
case XFMEM_SETVIEWPORT+1:
|
||||
@@ -135,16 +135,16 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
|
||||
case XFMEM_SETPROJECTION+4:
|
||||
case XFMEM_SETPROJECTION+5:
|
||||
case XFMEM_SETPROJECTION+6:
|
||||
VertexManager::Flush();
|
||||
VertexManager::Flush();
|
||||
VertexShaderManager::SetProjectionChanged();
|
||||
|
||||
nextAddress = XFMEM_SETPROJECTION + 7;
|
||||
break;
|
||||
|
||||
case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens
|
||||
case XFMEM_SETNUMTEXGENS: // GXSetNumTexGens
|
||||
if (xfregs.numTexGen.numTexGens != (newValue & 15))
|
||||
VertexManager::Flush();
|
||||
break;
|
||||
break;
|
||||
|
||||
case XFMEM_SETTEXMTXINFO:
|
||||
case XFMEM_SETTEXMTXINFO+1:
|
||||
@@ -178,47 +178,47 @@ void XFRegWritten(int transferSize, u32 baseAddress, u32 *pData)
|
||||
|
||||
// Maybe these are for Normals?
|
||||
case 0x1048: //xfregs.texcoords[0].nrmmtxinfo.hex = data; break; ??
|
||||
case 0x1049:
|
||||
case 0x104a:
|
||||
case 0x104b:
|
||||
case 0x104c:
|
||||
case 0x104d:
|
||||
case 0x104e:
|
||||
case 0x104f:
|
||||
case 0x1049:
|
||||
case 0x104a:
|
||||
case 0x104b:
|
||||
case 0x104c:
|
||||
case 0x104d:
|
||||
case 0x104e:
|
||||
case 0x104f:
|
||||
DEBUG_LOG(VIDEO, "Possible Normal Mtx XF reg?: %x=%x\n", address, newValue);
|
||||
break;
|
||||
|
||||
case 0x1013:
|
||||
case 0x1014:
|
||||
case 0x1015:
|
||||
case 0x1016:
|
||||
case 0x1017:
|
||||
case 0x1014:
|
||||
case 0x1015:
|
||||
case 0x1016:
|
||||
case 0x1017:
|
||||
|
||||
default:
|
||||
WARN_LOG(VIDEO, "Unknown XF Reg: %x=%x\n", address, newValue);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
WARN_LOG(VIDEO, "Unknown XF Reg: %x=%x\n", address, newValue);
|
||||
break;
|
||||
}
|
||||
|
||||
int transferred = nextAddress - address;
|
||||
address = nextAddress;
|
||||
|
||||
transferSize -= transferred;
|
||||
dataIndex += transferred;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
{
|
||||
// do not allow writes past registers
|
||||
if (baseAddress + transferSize > 0x1058)
|
||||
{
|
||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||
// do not allow writes past registers
|
||||
if (baseAddress + transferSize > 0x1058)
|
||||
{
|
||||
INFO_LOG(VIDEO, "xf load exceeds address space: %x %d bytes\n", baseAddress, transferSize);
|
||||
|
||||
if (baseAddress >= 0x1058)
|
||||
transferSize = 0;
|
||||
else
|
||||
transferSize = 0x1058 - baseAddress;
|
||||
}
|
||||
if (baseAddress >= 0x1058)
|
||||
transferSize = 0;
|
||||
else
|
||||
transferSize = 0x1058 - baseAddress;
|
||||
}
|
||||
|
||||
// write to XF mem
|
||||
if (baseAddress < 0x1000 && transferSize > 0)
|
||||
@@ -247,11 +247,11 @@ void LoadXFReg(u32 transferSize, u32 baseAddress, u32 *pData)
|
||||
}
|
||||
|
||||
// write to XF regs
|
||||
if (transferSize > 0)
|
||||
if (transferSize > 0)
|
||||
{
|
||||
XFRegWritten(transferSize, baseAddress, pData);
|
||||
memcpy_gc((u32*)(&xfregs) + (baseAddress - 0x1000), pData, transferSize * 4);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// TODO - verify that it is correct. Seems to work, though.
|
||||
|
||||
@@ -465,8 +465,8 @@ End:
|
||||
|
||||
void * memcpy_amd(void *dest, const void *src, size_t n)
|
||||
{
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
||||
|
||||
+17
-21
@@ -35,7 +35,7 @@
|
||||
#include "VertexLoaderManager.h"
|
||||
#include "VertexManagerBase.h"
|
||||
#include "x64Emitter.h"
|
||||
#include "ABI.h"
|
||||
#include "x64ABI.h"
|
||||
|
||||
#include "DLCache.h"
|
||||
#include "VideoConfig.h"
|
||||
@@ -111,17 +111,17 @@ struct CachedDisplayList
|
||||
u32 num_cp_reg;
|
||||
u32 num_bp_reg;
|
||||
u32 num_index_xf;
|
||||
u32 num_draw_call;
|
||||
u32 num_draw_call;
|
||||
u32 pass;
|
||||
u32 check;
|
||||
int frame_count;
|
||||
int frame_count;
|
||||
u32 BufferCount;
|
||||
|
||||
void InsertRegion(ReferencedDataRegion* NewRegion)
|
||||
{
|
||||
if(LastRegion)
|
||||
{
|
||||
LastRegion->NextRegion = NewRegion;
|
||||
LastRegion->NextRegion = NewRegion;
|
||||
}
|
||||
LastRegion = NewRegion;
|
||||
if(!Regions)
|
||||
@@ -174,7 +174,7 @@ struct CachedDisplayList
|
||||
Current = Current->NextRegion;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
ReferencedDataRegion* FindOverlapingRegion(u8* RegionStart, u32 Regionsize)
|
||||
{
|
||||
@@ -182,7 +182,7 @@ struct CachedDisplayList
|
||||
while(Current)
|
||||
{
|
||||
if(!Current->IntersectsMemoryRange(RegionStart, Regionsize))
|
||||
return Current;
|
||||
return Current;
|
||||
Current = Current->NextRegion;
|
||||
}
|
||||
return Current;
|
||||
@@ -330,7 +330,7 @@ u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
u32 addr = DataReadU32();
|
||||
u32 count = DataReadU32();
|
||||
ExecuteDisplayList(addr, count);
|
||||
}
|
||||
}
|
||||
break;
|
||||
case GX_CMD_UNKNOWN_METRICS: // zelda 4 swords calls it and checks the metrics registers after that
|
||||
DEBUG_LOG(VIDEO, "GX 0x44: %08x", cmd_byte);
|
||||
@@ -392,7 +392,7 @@ u32 AnalyzeAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
dl->num_draw_call = num_draw_call;
|
||||
dl->num_index_xf = num_index_xf;
|
||||
dl->num_xf_reg = num_xf_reg;
|
||||
// reset to the old pointer
|
||||
// reset to the old pointer
|
||||
g_pVideoData = old_pVideoData;
|
||||
return result;
|
||||
}
|
||||
@@ -458,7 +458,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
NewRegion->MustClean = true;
|
||||
NewRegion->size = transfer_size * 4;
|
||||
NewRegion->start_address = (u8*) new u8[NewRegion->size+15+12]; // alignment and guaranteed space
|
||||
NewRegion->hash = 0;
|
||||
NewRegion->hash = 0;
|
||||
dl->InsertRegion(NewRegion);
|
||||
u32 *data_buffer = (u32*)(u8*)(((size_t)NewRegion->start_address+0xf)&~0xf);
|
||||
DataReadU32xFuncs[transfer_size-1](data_buffer);
|
||||
@@ -539,7 +539,6 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
if (cmd_byte & 0x80)
|
||||
{
|
||||
// load vertices (use computed vertex size from FifoCommandRunnable above)
|
||||
|
||||
u16 numVertices = DataReadU16();
|
||||
if(numVertices > 0)
|
||||
{
|
||||
@@ -550,8 +549,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
cmd_byte & GX_VAT_MASK, // Vertex loader index (0 - 7)
|
||||
(cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT,
|
||||
numVertices);
|
||||
u8* EndAddress = VertexManager::s_pCurBufferPointer;
|
||||
u32 Vdatasize = (u32)(EndAddress - StartAddress);
|
||||
u32 Vdatasize = (u32)(VertexManager::s_pCurBufferPointer - StartAddress);
|
||||
if (Vdatasize > 0)
|
||||
{
|
||||
// Compile
|
||||
@@ -559,7 +557,7 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
NewRegion->MustClean = true;
|
||||
NewRegion->size = Vdatasize;
|
||||
NewRegion->start_address = (u8*)new u8[Vdatasize];
|
||||
NewRegion->hash = 0;
|
||||
NewRegion->hash = 0;
|
||||
dl->InsertRegion(NewRegion);
|
||||
memcpy(NewRegion->start_address, StartAddress, Vdatasize);
|
||||
emitter.ABI_CallFunctionCCCP((void *)&VertexLoaderManager::RunCompiledVertices, cmd_byte & GX_VAT_MASK, (cmd_byte & GX_PRIMITIVE_MASK) >> GX_PRIMITIVE_SHIFT, numVertices, NewRegion->start_address);
|
||||
@@ -578,7 +576,6 @@ void CompileAndRunDisplayList(u32 address, u32 size, CachedDisplayList *dl)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -627,7 +624,7 @@ void Clear()
|
||||
}
|
||||
dl_map.clear();
|
||||
// Reset the cache pointers.
|
||||
emitter.SetCodePtr(dlcode_cache);
|
||||
emitter.SetCodePtr(dlcode_cache);
|
||||
}
|
||||
|
||||
void ProgressiveCleanup()
|
||||
@@ -685,14 +682,14 @@ bool HandleDisplayList(u32 address, u32 size)
|
||||
{
|
||||
vhash = DLCache::CreateVMapId(Parentiter->second.VATUsed);
|
||||
iter = Parentiter->second.dl_map.find(vhash);
|
||||
childexist = iter != Parentiter->second.dl_map.end();
|
||||
childexist = iter != Parentiter->second.dl_map.end();
|
||||
}
|
||||
if (Parentiter != DLCache::dl_map.end() && childexist)
|
||||
{
|
||||
DLCache::CachedDisplayList &dl = iter->second;
|
||||
if (dl.uncachable)
|
||||
{
|
||||
return false;
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (dl.pass)
|
||||
@@ -701,7 +698,7 @@ bool HandleDisplayList(u32 address, u32 size)
|
||||
// First, check that the hash is the same as the last time.
|
||||
if (dl.dl_hash != GetHash64(Memory::GetPointer(address), size, 0))
|
||||
{
|
||||
dl.uncachable = true;
|
||||
dl.uncachable = true;
|
||||
return false;
|
||||
}
|
||||
DLCache::CompileAndRunDisplayList(address, size, &dl);
|
||||
@@ -718,7 +715,7 @@ bool HandleDisplayList(u32 address, u32 size)
|
||||
if (DlistChanged)
|
||||
{
|
||||
dl.uncachable = true;
|
||||
dl.ClearRegions();
|
||||
dl.ClearRegions();
|
||||
return false;
|
||||
}
|
||||
dl.frame_count= frameCount;
|
||||
@@ -765,10 +762,9 @@ bool HandleDisplayList(u32 address, u32 size)
|
||||
vdl.VATUsed = dlvatused;
|
||||
vdl.count = 1;
|
||||
DLCache::dl_map[dl_id] = vdl;
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
|
||||
}
|
||||
|
||||
void IncrementCheckContextId()
|
||||
+19
-112
@@ -517,7 +517,7 @@ inline void decodebytesARGB8_4ToRgba(u32 *dst, const u16 *src, const u16 * src2)
|
||||
{
|
||||
#if 0
|
||||
for (int x = 0; x < 4; x++) {
|
||||
dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8);
|
||||
dst[x] = ((src[x] & 0xFF) << 24) | ((src[x] & 0xFF00)>>8) | (src2[x] << 8);
|
||||
}
|
||||
#else
|
||||
dst[0] = ((src[0] & 0xFF) << 24) | ((src[0] & 0xFF00)>>8) | (src2[0] << 8);
|
||||
@@ -556,7 +556,7 @@ void decodeDXTBlock(u32 *dst, const DXTBlock *src, int pitch)
|
||||
{
|
||||
int blue3 = ((blue2 - blue1) >> 1) - ((blue2 - blue1) >> 3);
|
||||
int green3 = ((green2 - green1) >> 1) - ((green2 - green1) >> 3);
|
||||
int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
|
||||
int red3 = ((red2 - red1) >> 1) - ((red2 - red1) >> 3);
|
||||
colors[2] = makecol(red1 + red3, green1 + green3, blue1 + blue3, 255);
|
||||
colors[3] = makecol(red2 - red3, green2 - green3, blue2 - blue3, 255);
|
||||
}
|
||||
@@ -692,7 +692,7 @@ inline void SetOpenMPThreadCount(int width, int height)
|
||||
if (g_ActiveConfig.bOMPDecoder && width > 127 && height > 127)
|
||||
{
|
||||
// don't span to many threads they will kill the rest of the emu :)
|
||||
omp_set_num_threads((cpu_info.num_cores + 2) / 3);
|
||||
omp_set_num_threads((omp_get_num_procs() + 2) / 3);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1119,20 +1119,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
_mm_storeu_si128( (__m128i*)( dst+(y + iy+1) * width + x + 4 ), o4 );
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Reference C implementation:
|
||||
for (int y = 0; y < height; y += 8)
|
||||
for (int x = 0; x < width; x += 8)
|
||||
for (int iy = 0; iy < 8; iy++, src += 4)
|
||||
for (int ix = 0; ix < 4; ix++)
|
||||
{
|
||||
int val = src[ix];
|
||||
u8 i1 = Convert4To8(val >> 4);
|
||||
u8 i2 = Convert4To8(val & 0xF);
|
||||
memset(dst+(y + iy) * width + x + ix * 2 , i1,4);
|
||||
memset(dst+(y + iy) * width + x + ix * 2 + 1 , i2,4);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case GX_TF_I8: // speed critical
|
||||
@@ -1248,26 +1234,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Reference C implementation
|
||||
for (int y = 0; y < height; y += 4)
|
||||
for (int x = 0; x < width; x += 8)
|
||||
for (int iy = 0; iy < 4; ++iy, src += 8)
|
||||
{
|
||||
u32 * newdst = dst + (y + iy)*width+x;
|
||||
const u8 * newsrc = src;
|
||||
u8 srcval;
|
||||
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = (newsrc++)[0]; (newdst++)[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
srcval = newsrc[0]; newdst[0] = srcval | (srcval << 8) | (srcval << 16) | (srcval << 24);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case GX_TF_C8:
|
||||
@@ -1380,20 +1346,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
_mm_storeu_si128( (__m128i*)(dst + (y + iy) * width + x), r1 );
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Reference C implementation:
|
||||
for (int y = 0; y < height; y += 4)
|
||||
for (int x = 0; x < width; x += 4)
|
||||
for (int iy = 0; iy < 4; iy++, src += 8)
|
||||
{
|
||||
u32 *ptr = dst + (y + iy) * width + x;
|
||||
u16 *s = (u16 *)src;
|
||||
ptr[0] = decodeIA8Swapped(s[0]);
|
||||
ptr[1] = decodeIA8Swapped(s[1]);
|
||||
ptr[2] = decodeIA8Swapped(s[2]);
|
||||
ptr[3] = decodeIA8Swapped(s[3]);
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case GX_TF_C14X2:
|
||||
@@ -1493,18 +1445,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
__m128i *ptr = (__m128i *)(dst + (y + iy) * width + x);
|
||||
_mm_storeu_si128(ptr, abgr888x4);
|
||||
}
|
||||
#if 0
|
||||
// Reference C implementation.
|
||||
for (int y = 0; y < height; y += 4)
|
||||
for (int x = 0; x < width; x += 4)
|
||||
for (int iy = 0; iy < 4; iy++, src += 8)
|
||||
{
|
||||
u32 *ptr = dst + (y + iy) * width + x;
|
||||
u16 *s = (u16 *)src;
|
||||
for(int j = 0; j < 4; j++)
|
||||
*ptr++ = decode565RGBA(Common::swap16(*s++));
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case GX_TF_RGB5A3:
|
||||
@@ -1718,13 +1658,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Reference C implementation:
|
||||
for (int y = 0; y < height; y += 4)
|
||||
for (int x = 0; x < width; x += 4)
|
||||
for (int iy = 0; iy < 4; iy++, src += 8)
|
||||
decodebytesRGB5A3rgba(dst+(y+iy)*width+x, (u16*)src);
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case GX_TF_RGBA8: // speed critical
|
||||
@@ -1860,16 +1793,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
_mm_storeu_si128(dst128, rgba11);
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
// Reference C implementation.
|
||||
for (int y = 0; y < height; y += 4)
|
||||
for (int x = 0; x < width; x += 4)
|
||||
{
|
||||
for (int iy = 0; iy < 4; iy++)
|
||||
decodebytesARGB8_4ToRgba(dst + (y+iy)*width + x, (u16*)src + 4 * iy, (u16*)src + 4 * iy + 16);
|
||||
src += 64;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
break;
|
||||
case GX_TF_CMPR: // speed critical
|
||||
@@ -2104,22 +2027,6 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he
|
||||
}
|
||||
}
|
||||
}
|
||||
#if 0
|
||||
for (int y = 0; y < height; y += 8)
|
||||
{
|
||||
for (int x = 0; x < width; x += 8)
|
||||
{
|
||||
decodeDXTBlockRGBA((u32*)dst + y * width + x, (DXTBlock*)src, width);
|
||||
src += sizeof(DXTBlock);
|
||||
decodeDXTBlockRGBA((u32*)dst + y * width + x + 4, (DXTBlock*)src, width);
|
||||
src += sizeof(DXTBlock);
|
||||
decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x, (DXTBlock*)src, width);
|
||||
src += sizeof(DXTBlock);
|
||||
decodeDXTBlockRGBA((u32*)dst + (y + 4) * width + x + 4, (DXTBlock*)src, width);
|
||||
src += sizeof(DXTBlock);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -2233,7 +2140,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u32 base = (tBlk * widthBlks + sBlk) * blockWidth * blockHeight;
|
||||
u16 blkS = s & (blockWidth - 1);
|
||||
u16 blkT = t & (blockHeight - 1);
|
||||
u32 blkOff = blkT * blockWidth + blkS;
|
||||
u32 blkOff = blkT * blockWidth + blkS;
|
||||
*/
|
||||
|
||||
switch (texformat)
|
||||
@@ -2247,9 +2154,9 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 7;
|
||||
u16 blkT = t & 7;
|
||||
u32 blkOff = (blkT << 3) + blkS;
|
||||
|
||||
|
||||
int rs = (blkOff & 1)?0:4;
|
||||
u32 offset = base + (blkOff >> 1);
|
||||
u32 offset = base + (blkOff >> 1);
|
||||
|
||||
u8 val = (*(src + offset) >> rs) & 0xF;
|
||||
u16 *tlut = (u16*)(texMem + tlutaddr);
|
||||
@@ -2259,7 +2166,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
case 0:
|
||||
*((u32*)dst) = decodeIA8Swapped(tlut[val]);
|
||||
break;
|
||||
case 1:
|
||||
case 1:
|
||||
*((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
|
||||
break;
|
||||
case 2:
|
||||
@@ -2277,9 +2184,9 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 7;
|
||||
u16 blkT = t & 7;
|
||||
u32 blkOff = (blkT << 3) + blkS;
|
||||
|
||||
|
||||
int rs = (blkOff & 1)?0:4;
|
||||
u32 offset = base + (blkOff >> 1);
|
||||
u32 offset = base + (blkOff >> 1);
|
||||
|
||||
u8 val = (*(src + offset) >> rs) & 0xF;
|
||||
val = Convert4To8(val);
|
||||
@@ -2298,7 +2205,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 7;
|
||||
u16 blkT = t & 3;
|
||||
u32 blkOff = (blkT << 3) + blkS;
|
||||
|
||||
|
||||
u8 val = *(src + base + blkOff);
|
||||
dst[0] = val;
|
||||
dst[1] = val;
|
||||
@@ -2315,7 +2222,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 7;
|
||||
u16 blkT = t & 3;
|
||||
u32 blkOff = (blkT << 3) + blkS;
|
||||
|
||||
|
||||
u8 val = *(src + base + blkOff);
|
||||
u16 *tlut = (u16*)(texMem + tlutaddr);
|
||||
|
||||
@@ -2324,7 +2231,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
case 0:
|
||||
*((u32*)dst) = decodeIA8Swapped(tlut[val]);
|
||||
break;
|
||||
case 1:
|
||||
case 1:
|
||||
*((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
|
||||
break;
|
||||
case 2:
|
||||
@@ -2342,7 +2249,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 7;
|
||||
u16 blkT = t & 3;
|
||||
u32 blkOff = (blkT << 3) + blkS;
|
||||
|
||||
|
||||
u8 val = *(src + base + blkOff);
|
||||
const u8 a = Convert4To8(val>>4);
|
||||
const u8 l = Convert4To8(val&0xF);
|
||||
@@ -2361,7 +2268,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 3;
|
||||
u16 blkT = t & 3;
|
||||
u32 blkOff = (blkT << 2) + blkS;
|
||||
|
||||
|
||||
u32 offset = (base + blkOff) << 1;
|
||||
const u16* valAddr = (u16*)(src + offset);
|
||||
|
||||
@@ -2377,7 +2284,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 3;
|
||||
u16 blkT = t & 3;
|
||||
u32 blkOff = (blkT << 2) + blkS;
|
||||
|
||||
|
||||
u32 offset = (base + blkOff) << 1;
|
||||
const u16* valAddr = (u16*)(src + offset);
|
||||
|
||||
@@ -2389,7 +2296,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
case 0:
|
||||
*((u32*)dst) = decodeIA8Swapped(tlut[val]);
|
||||
break;
|
||||
case 1:
|
||||
case 1:
|
||||
*((u32*)dst) = decode565RGBA(Common::swap16(tlut[val]));
|
||||
break;
|
||||
case 2:
|
||||
@@ -2407,7 +2314,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u16 blkS = s & 3;
|
||||
u16 blkT = t & 3;
|
||||
u32 blkOff = (blkT << 2) + blkS;
|
||||
|
||||
|
||||
u32 offset = (base + blkOff) << 1;
|
||||
const u16* valAddr = (u16*)(src + offset);
|
||||
|
||||
@@ -2465,7 +2372,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
u32 offset = (base + blkOff) << 3;
|
||||
|
||||
const DXTBlock* dxtBlock = (const DXTBlock*)(src + offset);
|
||||
|
||||
|
||||
u16 c1 = Common::swap16(dxtBlock->color1);
|
||||
u16 c2 = Common::swap16(dxtBlock->color2);
|
||||
int blue1 = Convert5To8(c1 & 0x1F);
|
||||
@@ -2484,7 +2391,7 @@ void TexDecoder_DecodeTexel(u8 *dst, const u8 *src, int s, int t, int imageWidth
|
||||
colorSel |= c1 > c2?0:4;
|
||||
|
||||
u32 color = 0;
|
||||
|
||||
|
||||
switch (colorSel)
|
||||
{
|
||||
case 0:
|
||||
Reference in New Issue
Block a user