PixelEngine: Convert to BitField and enum class

This commit is contained in:
Pokechu22 2022-01-29 13:28:17 -08:00
parent 45b8ebeb25
commit 8882eb040a
3 changed files with 134 additions and 85 deletions

View File

@ -5,6 +5,7 @@
#include <mutex> #include <mutex>
#include "Common/BitField.h"
#include "Common/ChunkFile.h" #include "Common/ChunkFile.h"
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
#include "Common/Logging/Log.h" #include "Common/Logging/Log.h"
@ -24,70 +25,115 @@
namespace PixelEngine namespace PixelEngine
{ {
// Note: These enums are (assumed to be) identical to the one in BPMemory, but the base type is set
// to u16 instead of u32 for BitField
enum class CompareMode : u16
{
Never = 0,
Less = 1,
Equal = 2,
LEqual = 3,
Greater = 4,
NEqual = 5,
GEqual = 6,
Always = 7
};
union UPEZConfReg union UPEZConfReg
{ {
u16 Hex; u16 hex;
struct BitField<0, 1, bool, u16> z_comparator_enable;
{ BitField<1, 3, CompareMode, u16> function;
u16 ZCompEnable : 1; // Z Comparator Enable BitField<4, 1, bool, u16> z_update_enable;
u16 Function : 3;
u16 ZUpdEnable : 1;
u16 : 11;
}; };
enum class SrcBlendFactor : u16
{
Zero = 0,
One = 1,
DstClr = 2,
InvDstClr = 3,
SrcAlpha = 4,
InvSrcAlpha = 5,
DstAlpha = 6,
InvDstAlpha = 7
};
enum class DstBlendFactor : u16
{
Zero = 0,
One = 1,
SrcClr = 2,
InvSrcClr = 3,
SrcAlpha = 4,
InvSrcAlpha = 5,
DstAlpha = 6,
InvDstAlpha = 7
};
enum class LogicOp : u16
{
Clear = 0,
And = 1,
AndReverse = 2,
Copy = 3,
AndInverted = 4,
NoOp = 5,
Xor = 6,
Or = 7,
Nor = 8,
Equiv = 9,
Invert = 10,
OrReverse = 11,
CopyInverted = 12,
OrInverted = 13,
Nand = 14,
Set = 15
}; };
union UPEAlphaConfReg union UPEAlphaConfReg
{ {
u16 Hex; u16 hex;
struct BitField<0, 1, bool, u16> blend; // Set for GX_BM_BLEND or GX_BM_SUBTRACT
{ BitField<1, 1, bool, u16> logic; // Set for GX_BM_LOGIC
u16 BMMath : 1; // GX_BM_BLEND || GX_BM_SUBSTRACT BitField<2, 1, bool, u16> dither;
u16 BMLogic : 1; // GX_BM_LOGIC BitField<3, 1, bool, u16> color_update_enable;
u16 Dither : 1; BitField<4, 1, bool, u16> alpha_update_enable;
u16 ColorUpdEnable : 1; BitField<5, 3, DstBlendFactor, u16> dst_factor;
u16 AlphaUpdEnable : 1; BitField<8, 3, SrcBlendFactor, u16> src_factor;
u16 DstFactor : 3; BitField<11, 1, bool, u16> subtract; // Set for GX_BM_SUBTRACT
u16 SrcFactor : 3; BitField<12, 4, LogicOp, u16> logic_op;
u16 Substract : 1; // Additive mode by default
u16 BlendOperator : 4;
};
}; };
union UPEDstAlphaConfReg union UPEDstAlphaConfReg
{ {
u16 Hex; u16 hex;
struct BitField<0, 8, u8, u16> alpha;
{ BitField<8, 1, bool, u16> enable;
u16 DstAlpha : 8;
u16 Enable : 1;
u16 : 7;
};
}; };
union UPEAlphaModeConfReg union UPEAlphaModeConfReg
{ {
u16 Hex; u16 hex;
struct BitField<0, 8, u8, u16> threshold;
{ // Yagcd and libogc use 8 bits for this, but the enum only needs 3
u16 Threshold : 8; BitField<8, 3, CompareMode, u16> compare_mode;
u16 CompareMode : 8;
}; };
union UPEAlphaReadReg
{
u16 hex;
BitField<0, 2, AlphaReadMode, u16> read_mode;
}; };
// fifo Control Register // fifo Control Register
union UPECtrlReg union UPECtrlReg
{ {
struct u16 hex;
{ BitField<0, 1, bool, u16> pe_token_enable;
u16 PETokenEnable : 1; BitField<1, 1, bool, u16> pe_finish_enable;
u16 PEFinishEnable : 1; BitField<2, 1, bool, u16> pe_token; // Write only
u16 PEToken : 1; // write only BitField<3, 1, bool, u16> pe_finish; // Write only
u16 PEFinish : 1; // write only
u16 : 12;
};
u16 Hex;
UPECtrlReg() { Hex = 0; }
UPECtrlReg(u16 _hex) { Hex = _hex; }
}; };
// STATE_TO_SAVE // STATE_TO_SAVE
@ -140,12 +186,12 @@ static void SetTokenFinish_OnMainThread(u64 userdata, s64 cyclesLate);
void Init() void Init()
{ {
m_Control.Hex = 0; m_Control.hex = 0;
m_ZConf.Hex = 0; m_ZConf.hex = 0;
m_AlphaConf.Hex = 0; m_AlphaConf.hex = 0;
m_DstAlphaConf.Hex = 0; m_DstAlphaConf.hex = 0;
m_AlphaModeConf.Hex = 0; m_AlphaModeConf.hex = 0;
m_AlphaRead.Hex = 0; m_AlphaRead.hex = 0;
s_token = 0; s_token = 0;
s_token_pending = 0; s_token_pending = 0;
@ -168,11 +214,11 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
u32 addr; u32 addr;
u16* ptr; u16* ptr;
} directly_mapped_vars[] = { } directly_mapped_vars[] = {
{PE_ZCONF, &m_ZConf.Hex}, {PE_ZCONF, &m_ZConf.hex},
{PE_ALPHACONF, &m_AlphaConf.Hex}, {PE_ALPHACONF, &m_AlphaConf.hex},
{PE_DSTALPHACONF, &m_DstAlphaConf.Hex}, {PE_DSTALPHACONF, &m_DstAlphaConf.hex},
{PE_ALPHAMODE, &m_AlphaModeConf.Hex}, {PE_ALPHAMODE, &m_AlphaModeConf.hex},
{PE_ALPHAREAD, &m_AlphaRead.Hex}, {PE_ALPHAREAD, &m_AlphaRead.hex},
}; };
for (auto& mapped_var : directly_mapped_vars) for (auto& mapped_var : directly_mapped_vars)
{ {
@ -207,20 +253,20 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base)
} }
// Control register // Control register
mmio->Register(base | PE_CTRL_REGISTER, MMIO::DirectRead<u16>(&m_Control.Hex), mmio->Register(base | PE_CTRL_REGISTER, MMIO::DirectRead<u16>(&m_Control.hex),
MMIO::ComplexWrite<u16>([](u32, u16 val) { MMIO::ComplexWrite<u16>([](u32, u16 val) {
UPECtrlReg tmpCtrl(val); UPECtrlReg tmpCtrl{.hex = val};
if (tmpCtrl.PEToken) if (tmpCtrl.pe_token)
s_signal_token_interrupt = false; s_signal_token_interrupt = false;
if (tmpCtrl.PEFinish) if (tmpCtrl.pe_finish)
s_signal_finish_interrupt = false; s_signal_finish_interrupt = false;
m_Control.PETokenEnable = tmpCtrl.PETokenEnable; m_Control.pe_token_enable = tmpCtrl.pe_token_enable.Value();
m_Control.PEFinishEnable = tmpCtrl.PEFinishEnable; m_Control.pe_finish_enable = tmpCtrl.pe_finish_enable.Value();
m_Control.PEToken = 0; // this flag is write only m_Control.pe_token = false; // this flag is write only
m_Control.PEFinish = 0; // this flag is write only m_Control.pe_finish = false; // this flag is write only
DEBUG_LOG_FMT(PIXELENGINE, "(w16) CTRL_REGISTER: {:#06x}", val); DEBUG_LOG_FMT(PIXELENGINE, "(w16) CTRL_REGISTER: {:#06x}", val);
UpdateInterrupts(); UpdateInterrupts();
@ -244,11 +290,11 @@ static void UpdateInterrupts()
{ {
// check if there is a token-interrupt // check if there is a token-interrupt
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN, ProcessorInterface::SetInterrupt(INT_CAUSE_PE_TOKEN,
s_signal_token_interrupt && m_Control.PETokenEnable); s_signal_token_interrupt && m_Control.pe_token_enable);
// check if there is a finish-interrupt // check if there is a finish-interrupt
ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH, ProcessorInterface::SetInterrupt(INT_CAUSE_PE_FINISH,
s_signal_finish_interrupt && m_Control.PEFinishEnable); s_signal_finish_interrupt && m_Control.pe_finish_enable);
} }
static void SetTokenFinish_OnMainThread(u64 userdata, s64 cyclesLate) static void SetTokenFinish_OnMainThread(u64 userdata, s64 cyclesLate)
@ -325,9 +371,9 @@ void SetFinish(int cycles_into_future)
RaiseEvent(cycles_into_future); RaiseEvent(cycles_into_future);
} }
UPEAlphaReadReg GetAlphaReadMode() AlphaReadMode GetAlphaReadMode()
{ {
return m_AlphaRead; return m_AlphaRead.read_mode;
} }
} // namespace PixelEngine } // namespace PixelEngine

View File

@ -4,7 +4,9 @@
#pragma once #pragma once
#include "Common/CommonTypes.h" #include "Common/CommonTypes.h"
class PointerWrap; class PointerWrap;
namespace MMIO namespace MMIO
{ {
class Mapping; class Mapping;
@ -45,14 +47,11 @@ enum
}; };
// ReadMode specifies the returned alpha channel for EFB peeks // ReadMode specifies the returned alpha channel for EFB peeks
union UPEAlphaReadReg enum class AlphaReadMode : u16
{ {
u16 Hex; Read00 = 0, // Always read 0x00
struct ReadFF = 1, // Always read 0xFF
{ ReadNone = 2, // Always read the real alpha value
u16 ReadMode : 2;
u16 : 14;
};
}; };
void Init(); void Init();
@ -63,6 +62,6 @@ void RegisterMMIO(MMIO::Mapping* mmio, u32 base);
// gfx backend support // gfx backend support
void SetToken(const u16 token, const bool interrupt, int cycle_delay); void SetToken(const u16 token, const bool interrupt, int cycle_delay);
void SetFinish(int cycle_delay); void SetFinish(int cycle_delay);
UPEAlphaReadReg GetAlphaReadMode(); AlphaReadMode GetAlphaReadMode();
} // namespace PixelEngine } // namespace PixelEngine

View File

@ -247,9 +247,6 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
// a little-endian value is expected to be returned // a little-endian value is expected to be returned
color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000)); color = ((color & 0xFF00FF00) | ((color >> 16) & 0xFF) | ((color << 16) & 0xFF0000));
// check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine::UPEAlphaReadReg alpha_read_mode = PixelEngine::GetAlphaReadMode();
if (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24) if (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24)
{ {
color = RGBA8ToRGBA6ToRGBA8(color); color = RGBA8ToRGBA6ToRGBA8(color);
@ -263,17 +260,24 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
color |= 0xFF000000; color |= 0xFF000000;
} }
if (alpha_read_mode.ReadMode == 2) // check what to do with the alpha channel (GX_PokeAlphaRead)
PixelEngine::AlphaReadMode alpha_read_mode = PixelEngine::GetAlphaReadMode();
if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadNone)
{ {
return color; // GX_READ_NONE return color;
} }
else if (alpha_read_mode.ReadMode == 1) else if (alpha_read_mode == PixelEngine::AlphaReadMode::ReadFF)
{ {
return color | 0xFF000000; // GX_READ_FF return color | 0xFF000000;
} }
else /*if(alpha_read_mode.ReadMode == 0)*/ else
{ {
return color & 0x00FFFFFF; // GX_READ_00 if (alpha_read_mode != PixelEngine::AlphaReadMode::Read00)
{
PanicAlertFmt("Invalid PE alpha read mode: {}", static_cast<u16>(alpha_read_mode));
}
return color & 0x00FFFFFF;
} }
} }
else // if (type == EFBAccessType::PeekZ) else // if (type == EFBAccessType::PeekZ)