Skip to content

Commit

Permalink
GPU: Only load the relevant color components upon writes to the tev c…
Browse files Browse the repository at this point in the history
…olor registers.

The other two components need not be valid upon write, hence loading them results in glitches.

Fixes issue 6783.
  • Loading branch information
neobrain committed Sep 21, 2014
1 parent 6d4fd54 commit 1d23c2c
Show file tree
Hide file tree
Showing 6 changed files with 121 additions and 65 deletions.
2 changes: 1 addition & 1 deletion Source/Core/Core/State.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
{
Expand Down
16 changes: 8 additions & 8 deletions Source/Core/VideoBackends/Software/BPMemLoader.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand All @@ -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];
Expand Down
6 changes: 4 additions & 2 deletions Source/Core/VideoCommon/BPMemory.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;

Expand Down
92 changes: 59 additions & 33 deletions Source/Core/VideoCommon/BPStructs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;

Expand Down
53 changes: 34 additions & 19 deletions Source/Core/VideoCommon/PixelShaderManager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,21 @@
#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;

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();
}

Expand All @@ -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();
Expand Down Expand Up @@ -107,16 +114,22 @@ void PixelShaderManager::SetConstants()
}
}

void PixelShaderManager::SetColorChanged(int type, int num)
void PixelShaderManager::SetTevColor(int index, int component, s32 value)
{
auto& c = constants.colors[index];
c[component] = s_tev_color[index][component] = value;
dirty = true;

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)
{
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.kcolors[index];
c[component] = s_tev_konst_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 konst color%d: %d %d %d %d\n", index, c[0], c[1], c[2], c[3]);
}

void PixelShaderManager::SetAlpha()
Expand Down Expand Up @@ -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();
}
}
17 changes: 15 additions & 2 deletions Source/Core/VideoCommon/PixelShaderManager.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

#pragma once

#include <array>

#include "VideoCommon/BPMemory.h"
#include "VideoCommon/ConstantManager.h"
#include "VideoCommon/PixelShaderGen.h"
Expand All @@ -24,8 +26,11 @@ class PixelShaderManager

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);
Expand All @@ -42,4 +47,12 @@ class PixelShaderManager

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;
};

0 comments on commit 1d23c2c

Please sign in to comment.