Merge pull request #1102 from neobrain/tevreg_loading

GPU: Only load the relevant color components upon writes to the tev color registers
This commit is contained in:
Tony Wasserka 2014-09-21 10:51:27 +02:00
commit 124df2e134
7 changed files with 128 additions and 65 deletions

View File

@ -13,6 +13,7 @@
// - Zero backwards/forwards compatibility
// - Serialization code for anything complex has to be manually written.
#include <array>
#include <cstddef>
#include <deque>
#include <list>
@ -159,6 +160,12 @@ public:
Do(x.second);
}
template <typename T, std::size_t N>
void DoArray(std::array<T,N>& x)
{
DoArray(x.data(), (u32)x.size());
}
template <typename T>
void DoArray(T* x, u32 count)
{

View File

@ -63,7 +63,7 @@ static Common::Event g_compressAndDumpStateSyncEvent;
static std::thread g_save_thread;
// Don't forget to increase this after doing changes on the savestate system
static const u32 STATE_VERSION = 31;
static const u32 STATE_VERSION = 32;
enum
{

View File

@ -145,10 +145,10 @@ void SWBPWritten(int address, int newvalue)
}
break;
case BPMEM_TEV_REGISTER_L: // Reg 1
case BPMEM_TEV_REGISTER_L+2: // Reg 2
case BPMEM_TEV_REGISTER_L+4: // Reg 3
case BPMEM_TEV_REGISTER_L+6: // Reg 4
case BPMEM_TEV_COLOR_RA:
case BPMEM_TEV_COLOR_RA + 2:
case BPMEM_TEV_COLOR_RA + 4:
case BPMEM_TEV_COLOR_RA + 6:
{
int regNum = (address >> 1 ) & 0x3;
TevReg& reg = bpmem.tevregs[regNum];
@ -160,10 +160,10 @@ void SWBPWritten(int address, int newvalue)
break;
}
case BPMEM_TEV_REGISTER_H: // Reg 1
case BPMEM_TEV_REGISTER_H+2: // Reg 2
case BPMEM_TEV_REGISTER_H+4: // Reg 3
case BPMEM_TEV_REGISTER_H+6: // Reg 4
case BPMEM_TEV_COLOR_BG:
case BPMEM_TEV_COLOR_BG + 2:
case BPMEM_TEV_COLOR_BG + 4:
case BPMEM_TEV_COLOR_BG + 6:
{
int regNum = (address >> 1 ) & 0x3;
TevReg& reg = bpmem.tevregs[regNum];

View File

@ -80,8 +80,8 @@
#define BPMEM_TX_SETTLUT_4 0xB8 // 0xB8 + 4
#define BPMEM_TEV_COLOR_ENV 0xC0 // 0xC0 + (2 * 16)
#define BPMEM_TEV_ALPHA_ENV 0xC1 // 0xC1 + (2 * 16)
#define BPMEM_TEV_REGISTER_L 0xE0 // 0xE0 + (2 * 4)
#define BPMEM_TEV_REGISTER_H 0xE1 // 0xE1 + (2 * 4)
#define BPMEM_TEV_COLOR_RA 0xE0 // 0xE0 + (2 * 4)
#define BPMEM_TEV_COLOR_BG 0xE1 // 0xE1 + (2 * 4)
#define BPMEM_FOGRANGE 0xE8 // 0xE8 + 6
#define BPMEM_FOGPARAM0 0xEE
#define BPMEM_FOGBMAGNITUDE 0xEF
@ -853,6 +853,8 @@ union TevReg
BitField< 0, 32,u64> low;
BitField<32, 32,u64> high;
// TODO: Check if Konst uses all 11 bits or just 8
// Low register
BitField< 0,11,s64> red;

View File

@ -480,6 +480,55 @@ static void BPWritten(const BPCmd& bp)
}
}
return;
// ---------------------------------------------------
// Set the TEV Color
// ---------------------------------------------------
//
// NOTE: Each of these registers actually maps to two variables internally.
// There's a bit that specifies which one is currently written to.
//
// NOTE: Some games write only to the RA register (or only to the BG register).
// We may not assume that the unwritten register holds a valid value, hence
// both component pairs need to be loaded individually.
case BPMEM_TEV_COLOR_RA:
case BPMEM_TEV_COLOR_RA + 2:
case BPMEM_TEV_COLOR_RA + 4:
case BPMEM_TEV_COLOR_RA + 6:
{
int num = (bp.address >> 1) & 0x3;
if (bpmem.tevregs[num].type_ra)
{
PixelShaderManager::SetTevKonstColor(num, 0, (s32)bpmem.tevregs[num].red);
PixelShaderManager::SetTevKonstColor(num, 3, (s32)bpmem.tevregs[num].alpha);
}
else
{
PixelShaderManager::SetTevColor(num, 0, (s32)bpmem.tevregs[num].red);
PixelShaderManager::SetTevColor(num, 3, (s32)bpmem.tevregs[num].alpha);
}
return;
}
case BPMEM_TEV_COLOR_BG:
case BPMEM_TEV_COLOR_BG + 2:
case BPMEM_TEV_COLOR_BG + 4:
case BPMEM_TEV_COLOR_BG + 6:
{
int num = (bp.address >> 1) & 0x3;
if (bpmem.tevregs[num].type_bg)
{
PixelShaderManager::SetTevKonstColor(num, 1, (s32)bpmem.tevregs[num].green);
PixelShaderManager::SetTevKonstColor(num, 2, (s32)bpmem.tevregs[num].blue);
}
else
{
PixelShaderManager::SetTevColor(num, 1, (s32)bpmem.tevregs[num].green);
PixelShaderManager::SetTevColor(num, 2, (s32)bpmem.tevregs[num].blue);
}
return;
}
default:
break;
}
@ -548,29 +597,6 @@ static void BPWritten(const BPCmd& bp)
case BPMEM_TX_SETTLUT_4:
return;
// ---------------------------------------------------
// Set the TEV Color
// ---------------------------------------------------
case BPMEM_TEV_REGISTER_L: // Reg 1
case BPMEM_TEV_REGISTER_H:
case BPMEM_TEV_REGISTER_L+2: // Reg 2
case BPMEM_TEV_REGISTER_H+2:
case BPMEM_TEV_REGISTER_L+4: // Reg 3
case BPMEM_TEV_REGISTER_H+4:
case BPMEM_TEV_REGISTER_L+6: // Reg 4
case BPMEM_TEV_REGISTER_H+6:
// some games only send the _L part, so always update
// there actually are 2 register behind each of these
// addresses, selected by the type bit.
{
// don't compare with changes!
int num = (bp.address >> 1) & 0x3;
if ((bp.address & 1) == 0)
PixelShaderManager::SetColorChanged(static_cast<int>(bpmem.tevregs[num].type_ra), num);
else
PixelShaderManager::SetColorChanged(static_cast<int>(bpmem.tevregs[num].type_bg), num);
}
return;
default:
break;
}
@ -1213,19 +1239,19 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
break;
}
case BPMEM_TEV_REGISTER_L: // 0xE0
case BPMEM_TEV_REGISTER_L+2:
case BPMEM_TEV_REGISTER_L+4:
case BPMEM_TEV_REGISTER_L+6:
SetRegName(BPMEM_TEV_REGISTER_L);
case BPMEM_TEV_COLOR_RA: // 0xE0
case BPMEM_TEV_COLOR_RA + 2: // 0xE2
case BPMEM_TEV_COLOR_RA + 4: // 0xE4
case BPMEM_TEV_COLOR_RA + 6: // 0xE6
SetRegName(BPMEM_TEV_COLOR_RA);
// TODO: Description
break;
case BPMEM_TEV_REGISTER_H: // 0xE1
case BPMEM_TEV_REGISTER_H+2:
case BPMEM_TEV_REGISTER_H+4:
case BPMEM_TEV_REGISTER_H+6:
SetRegName(BPMEM_TEV_REGISTER_H);
case BPMEM_TEV_COLOR_BG: // 0xE1
case BPMEM_TEV_COLOR_BG + 2: // 0xE3
case BPMEM_TEV_COLOR_BG + 4: // 0xE5
case BPMEM_TEV_COLOR_BG + 6: // 0xE7
SetRegName(BPMEM_TEV_COLOR_BG);
// TODO: Description
break;

View File

@ -12,8 +12,11 @@
#include "VideoCommon/VideoCommon.h"
#include "VideoCommon/VideoConfig.h"
static bool s_bFogRangeAdjustChanged;
static bool s_bViewPortChanged;
bool PixelShaderManager::s_bFogRangeAdjustChanged;
bool PixelShaderManager::s_bViewPortChanged;
std::array<int4,4> PixelShaderManager::s_tev_color;
std::array<int4,4> PixelShaderManager::s_tev_konst_color;
PixelShaderConstants PixelShaderManager::constants;
bool PixelShaderManager::dirty;
@ -21,6 +24,9 @@ bool PixelShaderManager::dirty;
void PixelShaderManager::Init()
{
memset(&constants, 0, sizeof(constants));
memset(s_tev_color.data(), 0, sizeof(s_tev_color));
memset(s_tev_konst_color.data(), 0, sizeof(s_tev_konst_color));
Dirty();
}
@ -29,14 +35,15 @@ void PixelShaderManager::Dirty()
s_bFogRangeAdjustChanged = true;
s_bViewPortChanged = true;
SetColorChanged(0, 0);
SetColorChanged(0, 1);
SetColorChanged(0, 2);
SetColorChanged(0, 3);
SetColorChanged(1, 0);
SetColorChanged(1, 1);
SetColorChanged(1, 2);
SetColorChanged(1, 3);
for (unsigned index = 0; index < s_tev_color.size(); ++index)
{
for (int comp = 0; comp < 4; ++comp)
{
SetTevColor(index, comp, s_tev_color[index][comp]);
SetTevKonstColor(index, comp, s_tev_konst_color[index][comp]);
}
}
SetAlpha();
SetDestAlpha();
SetZTextureBias();
@ -107,16 +114,22 @@ void PixelShaderManager::SetConstants()
}
}
void PixelShaderManager::SetColorChanged(int type, int num)
void PixelShaderManager::SetTevColor(int index, int component, s32 value)
{
int4* c = type ? constants.kcolors : constants.colors;
c[num][0] = static_cast<s32>(bpmem.tevregs[num].red);
c[num][3] = static_cast<s32>(bpmem.tevregs[num].alpha);
c[num][2] = static_cast<s32>(bpmem.tevregs[num].blue);
c[num][1] = static_cast<s32>(bpmem.tevregs[num].green);
auto& c = constants.colors[index];
c[component] = s_tev_color[index][component] = value;
dirty = true;
PRIM_LOG("pixel %scolor%d: %d %d %d %d\n", type?"k":"", num, c[num][0], c[num][1], c[num][2], c[num][3]);
PRIM_LOG("tev color%d: %d %d %d %d\n", index, c[0], c[1], c[2], c[3]);
}
void PixelShaderManager::SetTevKonstColor(int index, int component, s32 value)
{
auto& c = constants.kcolors[index];
c[component] = s_tev_konst_color[index][component] = value;
dirty = true;
PRIM_LOG("tev konst color%d: %d %d %d %d\n", index, c[0], c[1], c[2], c[3]);
}
void PixelShaderManager::SetAlpha()
@ -265,11 +278,13 @@ void PixelShaderManager::SetFogRangeAdjustChanged()
void PixelShaderManager::DoState(PointerWrap &p)
{
p.Do(constants);
p.Do(dirty);
p.DoArray(s_tev_color);
p.DoArray(s_tev_konst_color);
if (p.GetMode() == PointerWrap::MODE_READ)
{
// Reload current state from global GPU state
// NOTE: This requires that all GPU memory has been loaded already.
Dirty();
}
}

View File

@ -4,6 +4,8 @@
#pragma once
#include <array>
#include "VideoCommon/BPMemory.h"
#include "VideoCommon/ConstantManager.h"
#include "VideoCommon/PixelShaderGen.h"
@ -24,8 +26,11 @@ public:
static void SetConstants(); // sets pixel shader constants
// constant management, should be called after memory is committed
static void SetColorChanged(int type, int index);
// constant management
// Some of these functions grab the constant values from global state,
// so make sure to call them after memory is committed
static void SetTevColor(int index, int component, s32 value);
static void SetTevKonstColor(int index, int component, s32 value);
static void SetAlpha();
static void SetDestAlpha();
static void SetTexDims(int texmapid, u32 width, u32 height, u32 wraps, u32 wrapt);
@ -42,4 +47,12 @@ public:
static PixelShaderConstants constants;
static bool dirty;
static bool s_bFogRangeAdjustChanged;
static bool s_bViewPortChanged;
// These colors aren't available from global BP state,
// hence we keep a copy of them around.
static std::array<int4,4> s_tev_color;
static std::array<int4,4> s_tev_konst_color;
};