mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2026-04-24 13:29:15 -05:00
Convert BPMemory to BitField and enum class
Additional changes: - For TevStageCombiner's ColorCombiner and AlphaCombiner, op/comparison and scale/compare_mode have been split as there are different meanings and enums if bias is set to compare. (Shift has also been renamed to scale) - In TexMode0, min_filter has been split into min_mip and min_filter. - In TexImage1, image_type is now cache_manually_managed. - The unused bit in GenMode is now exposed. - LPSize's lineaspect is now named adjust_for_aspect_ratio.
This commit is contained in:
@@ -184,8 +184,8 @@ void ClearScreen(const MathUtil::Rectangle<int>& rc)
|
||||
auto pixel_format = bpmem.zcontrol.pixel_format;
|
||||
|
||||
// (1): Disable unused color channels
|
||||
if (pixel_format == PEControl::RGB8_Z24 || pixel_format == PEControl::RGB565_Z16 ||
|
||||
pixel_format == PEControl::Z24)
|
||||
if (pixel_format == PixelFormat::RGB8_Z24 || pixel_format == PixelFormat::RGB565_Z16 ||
|
||||
pixel_format == PixelFormat::Z24)
|
||||
{
|
||||
alphaEnable = false;
|
||||
}
|
||||
@@ -196,11 +196,11 @@ void ClearScreen(const MathUtil::Rectangle<int>& rc)
|
||||
u32 z = bpmem.clearZValue;
|
||||
|
||||
// (2) drop additional accuracy
|
||||
if (pixel_format == PEControl::RGBA6_Z24)
|
||||
if (pixel_format == PixelFormat::RGBA6_Z24)
|
||||
{
|
||||
color = RGBA8ToRGBA6ToRGBA8(color);
|
||||
}
|
||||
else if (pixel_format == PEControl::RGB565_Z16)
|
||||
else if (pixel_format == PixelFormat::RGB565_Z16)
|
||||
{
|
||||
color = RGBA8ToRGB565ToRGBA8(color);
|
||||
z = Z24ToZ16ToZ24(z);
|
||||
@@ -228,29 +228,28 @@ void OnPixelFormatChange()
|
||||
const auto new_format = bpmem.zcontrol.pixel_format;
|
||||
g_renderer->StorePixelFormat(new_format);
|
||||
|
||||
DEBUG_LOG_FMT(VIDEO, "pixelfmt: pixel={}, zc={}", static_cast<int>(new_format),
|
||||
static_cast<int>(bpmem.zcontrol.zformat));
|
||||
DEBUG_LOG_FMT(VIDEO, "pixelfmt: pixel={}, zc={}", new_format, bpmem.zcontrol.zformat);
|
||||
|
||||
// no need to reinterpret pixel data in these cases
|
||||
if (new_format == old_format || old_format == PEControl::INVALID_FMT)
|
||||
if (new_format == old_format || old_format == PixelFormat::INVALID_FMT)
|
||||
return;
|
||||
|
||||
// Check for pixel format changes
|
||||
switch (old_format)
|
||||
{
|
||||
case PEControl::RGB8_Z24:
|
||||
case PEControl::Z24:
|
||||
case PixelFormat::RGB8_Z24:
|
||||
case PixelFormat::Z24:
|
||||
{
|
||||
// Z24 and RGB8_Z24 are treated equal, so just return in this case
|
||||
if (new_format == PEControl::RGB8_Z24 || new_format == PEControl::Z24)
|
||||
if (new_format == PixelFormat::RGB8_Z24 || new_format == PixelFormat::Z24)
|
||||
return;
|
||||
|
||||
if (new_format == PEControl::RGBA6_Z24)
|
||||
if (new_format == PixelFormat::RGBA6_Z24)
|
||||
{
|
||||
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB8ToRGBA6);
|
||||
return;
|
||||
}
|
||||
else if (new_format == PEControl::RGB565_Z16)
|
||||
else if (new_format == PixelFormat::RGB565_Z16)
|
||||
{
|
||||
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB8ToRGB565);
|
||||
return;
|
||||
@@ -258,14 +257,14 @@ void OnPixelFormatChange()
|
||||
}
|
||||
break;
|
||||
|
||||
case PEControl::RGBA6_Z24:
|
||||
case PixelFormat::RGBA6_Z24:
|
||||
{
|
||||
if (new_format == PEControl::RGB8_Z24 || new_format == PEControl::Z24)
|
||||
if (new_format == PixelFormat::RGB8_Z24 || new_format == PixelFormat::Z24)
|
||||
{
|
||||
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGBA6ToRGB8);
|
||||
return;
|
||||
}
|
||||
else if (new_format == PEControl::RGB565_Z16)
|
||||
else if (new_format == PixelFormat::RGB565_Z16)
|
||||
{
|
||||
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGBA6ToRGB565);
|
||||
return;
|
||||
@@ -273,14 +272,14 @@ void OnPixelFormatChange()
|
||||
}
|
||||
break;
|
||||
|
||||
case PEControl::RGB565_Z16:
|
||||
case PixelFormat::RGB565_Z16:
|
||||
{
|
||||
if (new_format == PEControl::RGB8_Z24 || new_format == PEControl::Z24)
|
||||
if (new_format == PixelFormat::RGB8_Z24 || new_format == PixelFormat::Z24)
|
||||
{
|
||||
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB565ToRGB8);
|
||||
return;
|
||||
}
|
||||
else if (new_format == PEControl::RGBA6_Z24)
|
||||
else if (new_format == PixelFormat::RGBA6_Z24)
|
||||
{
|
||||
g_renderer->ReinterpretPixelData(EFBReinterpretType::RGB565ToRGBA6);
|
||||
return;
|
||||
@@ -292,8 +291,7 @@ void OnPixelFormatChange()
|
||||
break;
|
||||
}
|
||||
|
||||
ERROR_LOG_FMT(VIDEO, "Unhandled EFB format change: {} to {}", static_cast<int>(old_format),
|
||||
static_cast<int>(new_format));
|
||||
ERROR_LOG_FMT(VIDEO, "Unhandled EFB format change: {} to {}", old_format, new_format);
|
||||
}
|
||||
|
||||
void SetInterlacingMode(const BPCmd& bp)
|
||||
@@ -305,17 +303,15 @@ void SetInterlacingMode(const BPCmd& bp)
|
||||
{
|
||||
// SDK always sets bpmem.lineptwidth.lineaspect via BPMEM_LINEPTWIDTH
|
||||
// just before this cmd
|
||||
static constexpr std::string_view action[] = {"don't adjust", "adjust"};
|
||||
DEBUG_LOG_FMT(VIDEO, "BPMEM_FIELDMODE texLOD:{} lineaspect:{}", action[bpmem.fieldmode.texLOD],
|
||||
action[bpmem.lineptwidth.lineaspect]);
|
||||
DEBUG_LOG_FMT(VIDEO, "BPMEM_FIELDMODE texLOD:{} lineaspect:{}", bpmem.fieldmode.texLOD,
|
||||
bpmem.lineptwidth.adjust_for_aspect_ratio);
|
||||
}
|
||||
break;
|
||||
case BPMEM_FIELDMASK:
|
||||
{
|
||||
// Determines if fields will be written to EFB (always computed)
|
||||
static constexpr std::string_view action[] = {"skip", "write"};
|
||||
DEBUG_LOG_FMT(VIDEO, "BPMEM_FIELDMASK even:{} odd:{}", action[bpmem.fieldmask.even],
|
||||
action[bpmem.fieldmask.odd]);
|
||||
DEBUG_LOG_FMT(VIDEO, "BPMEM_FIELDMASK even:{} odd:{}", bpmem.fieldmask.even,
|
||||
bpmem.fieldmask.odd);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -17,7 +17,7 @@ bool BlendMode::UseLogicOp() const
|
||||
return false;
|
||||
|
||||
// Fast path for Kirby's Return to Dreamland, they use it with dstAlpha.
|
||||
if (logicmode == BlendMode::NOOP)
|
||||
if (logicmode == LogicOp::NoOp)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
|
||||
+767
-454
File diff suppressed because it is too large
Load Diff
@@ -91,10 +91,9 @@ static void BPWritten(const BPCmd& bp)
|
||||
{
|
||||
case BPMEM_GENMODE: // Set the Generation Mode
|
||||
PRIM_LOG("genmode: texgen={}, col={}, multisampling={}, tev={}, cullmode={}, ind={}, zfeeze={}",
|
||||
bpmem.genMode.numtexgens.Value(), bpmem.genMode.numcolchans.Value(),
|
||||
bpmem.genMode.multisampling.Value(), bpmem.genMode.numtevstages.Value() + 1,
|
||||
static_cast<u32>(bpmem.genMode.cullmode), bpmem.genMode.numindstages.Value(),
|
||||
bpmem.genMode.zfreeze.Value());
|
||||
bpmem.genMode.numtexgens, bpmem.genMode.numcolchans, bpmem.genMode.multisampling,
|
||||
bpmem.genMode.numtevstages + 1, bpmem.genMode.cullmode, bpmem.genMode.numindstages,
|
||||
bpmem.genMode.zfreeze);
|
||||
|
||||
if (bp.changes)
|
||||
PixelShaderManager::SetGenModeChanged();
|
||||
@@ -138,8 +137,8 @@ static void BPWritten(const BPCmd& bp)
|
||||
GeometryShaderManager::SetLinePtWidthChanged();
|
||||
return;
|
||||
case BPMEM_ZMODE: // Depth Control
|
||||
PRIM_LOG("zmode: test={}, func={}, upd={}", bpmem.zmode.testenable.Value(),
|
||||
bpmem.zmode.func.Value(), bpmem.zmode.updateenable.Value());
|
||||
PRIM_LOG("zmode: test={}, func={}, upd={}", bpmem.zmode.testenable, bpmem.zmode.func,
|
||||
bpmem.zmode.updateenable);
|
||||
SetDepthMode();
|
||||
PixelShaderManager::SetZModeControl();
|
||||
return;
|
||||
@@ -147,10 +146,9 @@ static void BPWritten(const BPCmd& bp)
|
||||
if (bp.changes & 0xFFFF)
|
||||
{
|
||||
PRIM_LOG("blendmode: en={}, open={}, colupd={}, alphaupd={}, dst={}, src={}, sub={}, mode={}",
|
||||
bpmem.blendmode.blendenable.Value(), bpmem.blendmode.logicopenable.Value(),
|
||||
bpmem.blendmode.colorupdate.Value(), bpmem.blendmode.alphaupdate.Value(),
|
||||
bpmem.blendmode.dstfactor.Value(), bpmem.blendmode.srcfactor.Value(),
|
||||
bpmem.blendmode.subtract.Value(), bpmem.blendmode.logicmode.Value());
|
||||
bpmem.blendmode.blendenable, bpmem.blendmode.logicopenable,
|
||||
bpmem.blendmode.colorupdate, bpmem.blendmode.alphaupdate, bpmem.blendmode.dstfactor,
|
||||
bpmem.blendmode.srcfactor, bpmem.blendmode.subtract, bpmem.blendmode.logicmode);
|
||||
|
||||
SetBlendMode();
|
||||
|
||||
@@ -158,8 +156,7 @@ static void BPWritten(const BPCmd& bp)
|
||||
}
|
||||
return;
|
||||
case BPMEM_CONSTANTALPHA: // Set Destination Alpha
|
||||
PRIM_LOG("constalpha: alp={}, en={}", bpmem.dstalpha.alpha.Value(),
|
||||
bpmem.dstalpha.enable.Value());
|
||||
PRIM_LOG("constalpha: alp={}, en={}", bpmem.dstalpha.alpha, bpmem.dstalpha.enable);
|
||||
if (bp.changes)
|
||||
{
|
||||
PixelShaderManager::SetAlpha();
|
||||
@@ -264,14 +261,14 @@ static void BPWritten(const BPCmd& bp)
|
||||
const UPE_Copy PE_copy = bpmem.triggerEFBCopy;
|
||||
if (PE_copy.copy_to_xfb == 0)
|
||||
{
|
||||
// bpmem.zcontrol.pixel_format to PEControl::Z24 is when the game wants to copy from ZBuffer
|
||||
// bpmem.zcontrol.pixel_format to PixelFormat::Z24 is when the game wants to copy from ZBuffer
|
||||
// (Zbuffer uses 24-bit Format)
|
||||
static constexpr CopyFilterCoefficients::Values filter_coefficients = {
|
||||
{0, 0, 21, 22, 21, 0, 0}};
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24;
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PixelFormat::Z24;
|
||||
g_texture_cache->CopyRenderTargetToTexture(
|
||||
destAddr, PE_copy.tp_realFormat(), copy_width, copy_height, destStride, is_depth_copy,
|
||||
srcRect, !!PE_copy.intensity_fmt, !!PE_copy.half_scale, 1.0f, 1.0f,
|
||||
srcRect, PE_copy.intensity_fmt, PE_copy.half_scale, 1.0f, 1.0f,
|
||||
bpmem.triggerEFBCopy.clamp_top, bpmem.triggerEFBCopy.clamp_bottom, filter_coefficients);
|
||||
}
|
||||
else
|
||||
@@ -297,7 +294,7 @@ static void BPWritten(const BPCmd& bp)
|
||||
destAddr, srcRect.left, srcRect.top, srcRect.right, srcRect.bottom,
|
||||
bpmem.copyTexSrcWH.x + 1, destStride, height, yScale);
|
||||
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PEControl::Z24;
|
||||
bool is_depth_copy = bpmem.zcontrol.pixel_format == PixelFormat::Z24;
|
||||
g_texture_cache->CopyRenderTargetToTexture(
|
||||
destAddr, EFBCopyFormat::XFB, copy_width, height, destStride, is_depth_copy, srcRect,
|
||||
false, false, yScale, s_gammaLUT[PE_copy.gamma], bpmem.triggerEFBCopy.clamp_top,
|
||||
@@ -370,10 +367,9 @@ static void BPWritten(const BPCmd& bp)
|
||||
PixelShaderManager::SetFogColorChanged();
|
||||
return;
|
||||
case BPMEM_ALPHACOMPARE: // Compare Alpha Values
|
||||
PRIM_LOG("alphacmp: ref0={}, ref1={}, comp0={}, comp1={}, logic={}",
|
||||
bpmem.alpha_test.ref0.Value(), bpmem.alpha_test.ref1.Value(),
|
||||
static_cast<int>(bpmem.alpha_test.comp0), static_cast<int>(bpmem.alpha_test.comp1),
|
||||
static_cast<int>(bpmem.alpha_test.logic));
|
||||
PRIM_LOG("alphacmp: ref0={}, ref1={}, comp0={}, comp1={}, logic={}", bpmem.alpha_test.ref0,
|
||||
bpmem.alpha_test.ref1, bpmem.alpha_test.comp0, bpmem.alpha_test.comp1,
|
||||
bpmem.alpha_test.logic);
|
||||
if (bp.changes & 0xFFFF)
|
||||
PixelShaderManager::SetAlpha();
|
||||
if (bp.changes)
|
||||
@@ -383,7 +379,7 @@ static void BPWritten(const BPCmd& bp)
|
||||
}
|
||||
return;
|
||||
case BPMEM_BIAS: // BIAS
|
||||
PRIM_LOG("ztex bias={:#x}", bpmem.ztex1.bias.Value());
|
||||
PRIM_LOG("ztex bias={:#x}", bpmem.ztex1.bias);
|
||||
if (bp.changes)
|
||||
PixelShaderManager::SetZTextureBias();
|
||||
return;
|
||||
@@ -393,11 +389,7 @@ static void BPWritten(const BPCmd& bp)
|
||||
PixelShaderManager::SetZTextureTypeChanged();
|
||||
if (bp.changes & 12)
|
||||
PixelShaderManager::SetZTextureOpChanged();
|
||||
#if defined(_DEBUG) || defined(DEBUGFAST)
|
||||
static constexpr std::string_view pzop[] = {"DISABLE", "ADD", "REPLACE", "?"};
|
||||
static constexpr std::string_view pztype[] = {"Z8", "Z16", "Z24", "?"};
|
||||
PRIM_LOG("ztex op={}, type={}", pzop[bpmem.ztex2.op], pztype[bpmem.ztex2.type]);
|
||||
#endif
|
||||
PRIM_LOG("ztex op={}, type={}", bpmem.ztex2.op, bpmem.ztex2.type);
|
||||
}
|
||||
return;
|
||||
// ----------------------------------
|
||||
@@ -588,15 +580,15 @@ static void BPWritten(const BPCmd& bp)
|
||||
case BPMEM_TEV_COLOR_RA + 6:
|
||||
{
|
||||
int num = (bp.address >> 1) & 0x3;
|
||||
if (bpmem.tevregs[num].type_ra)
|
||||
if (bpmem.tevregs[num].ra.type == TevRegType::Constant)
|
||||
{
|
||||
PixelShaderManager::SetTevKonstColor(num, 0, (s32)bpmem.tevregs[num].red);
|
||||
PixelShaderManager::SetTevKonstColor(num, 3, (s32)bpmem.tevregs[num].alpha);
|
||||
PixelShaderManager::SetTevKonstColor(num, 0, bpmem.tevregs[num].ra.red);
|
||||
PixelShaderManager::SetTevKonstColor(num, 3, bpmem.tevregs[num].ra.alpha);
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelShaderManager::SetTevColor(num, 0, (s32)bpmem.tevregs[num].red);
|
||||
PixelShaderManager::SetTevColor(num, 3, (s32)bpmem.tevregs[num].alpha);
|
||||
PixelShaderManager::SetTevColor(num, 0, bpmem.tevregs[num].ra.red);
|
||||
PixelShaderManager::SetTevColor(num, 3, bpmem.tevregs[num].ra.alpha);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -607,15 +599,15 @@ static void BPWritten(const BPCmd& bp)
|
||||
case BPMEM_TEV_COLOR_BG + 6:
|
||||
{
|
||||
int num = (bp.address >> 1) & 0x3;
|
||||
if (bpmem.tevregs[num].type_bg)
|
||||
if (bpmem.tevregs[num].bg.type == TevRegType::Constant)
|
||||
{
|
||||
PixelShaderManager::SetTevKonstColor(num, 1, (s32)bpmem.tevregs[num].green);
|
||||
PixelShaderManager::SetTevKonstColor(num, 2, (s32)bpmem.tevregs[num].blue);
|
||||
PixelShaderManager::SetTevKonstColor(num, 1, bpmem.tevregs[num].bg.green);
|
||||
PixelShaderManager::SetTevKonstColor(num, 2, bpmem.tevregs[num].bg.blue);
|
||||
}
|
||||
else
|
||||
{
|
||||
PixelShaderManager::SetTevColor(num, 1, (s32)bpmem.tevregs[num].green);
|
||||
PixelShaderManager::SetTevColor(num, 2, (s32)bpmem.tevregs[num].blue);
|
||||
PixelShaderManager::SetTevColor(num, 1, bpmem.tevregs[num].bg.green);
|
||||
PixelShaderManager::SetTevColor(num, 2, bpmem.tevregs[num].bg.blue);
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -915,26 +907,18 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
SetRegName(BPMEM_BLENDMODE);
|
||||
BlendMode mode;
|
||||
mode.hex = cmddata;
|
||||
const char* dstfactors[] = {"0", "1", "src_color", "1-src_color",
|
||||
"src_alpha", "1-src_alpha", "dst_alpha", "1-dst_alpha"};
|
||||
const char* srcfactors[] = {"0", "1", "dst_color", "1-dst_color",
|
||||
"src_alpha", "1-src_alpha", "dst_alpha", "1-dst_alpha"};
|
||||
const char* logicmodes[] = {"0", "s & d", "s & ~d", "s", "~s & d", "d",
|
||||
"s ^ d", "s | d", "~(s | d)", "~(s ^ d)", "~d", "s | ~d",
|
||||
"~s", "~s | d", "~(s & d)", "1"};
|
||||
*desc =
|
||||
fmt::format("Enable: {}\n"
|
||||
"Logic ops: {}\n"
|
||||
"Dither: {}\n"
|
||||
"Color write: {}\n"
|
||||
"Alpha write: {}\n"
|
||||
"Dest factor: {}\n"
|
||||
"Source factor: {}\n"
|
||||
"Subtract: {}\n"
|
||||
"Logic mode: {}\n",
|
||||
no_yes[mode.blendenable], no_yes[mode.logicopenable], no_yes[mode.dither],
|
||||
no_yes[mode.colorupdate], no_yes[mode.alphaupdate], dstfactors[mode.dstfactor],
|
||||
srcfactors[mode.srcfactor], no_yes[mode.subtract], logicmodes[mode.logicmode]);
|
||||
*desc = fmt::format("Enable: {}\n"
|
||||
"Logic ops: {}\n"
|
||||
"Dither: {}\n"
|
||||
"Color write: {}\n"
|
||||
"Alpha write: {}\n"
|
||||
"Dest factor: {}\n"
|
||||
"Source factor: {}\n"
|
||||
"Subtract: {}\n"
|
||||
"Logic mode: {}\n",
|
||||
no_yes[mode.blendenable], no_yes[mode.logicopenable], no_yes[mode.dither],
|
||||
no_yes[mode.colorupdate], no_yes[mode.alphaupdate], mode.dstfactor,
|
||||
mode.srcfactor, no_yes[mode.subtract], mode.logicmode);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -948,16 +932,10 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
SetRegName(BPMEM_ZCOMPARE);
|
||||
PEControl config;
|
||||
config.hex = cmddata;
|
||||
const char* pixel_formats[] = {"RGB8_Z24", "RGBA6_Z24", "RGB565_Z16", "Z24",
|
||||
"Y8", "U8", "V8", "YUV420"};
|
||||
const char* zformats[] = {
|
||||
"linear", "compressed (near)", "compressed (mid)", "compressed (far)",
|
||||
"inv linear", "compressed (inv near)", "compressed (inv mid)", "compressed (inv far)"};
|
||||
*desc = fmt::format("EFB pixel format: {}\n"
|
||||
"Depth format: {}\n"
|
||||
"Early depth test: {}\n",
|
||||
pixel_formats[config.pixel_format], zformats[config.zformat],
|
||||
no_yes[config.early_ztest]);
|
||||
config.pixel_format, config.zformat, no_yes[config.early_ztest]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1048,7 +1026,7 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
"Mipmap filter: {}\n"
|
||||
"Vertical scaling: {}\n"
|
||||
"Clear: {}\n"
|
||||
"Frame to field: 0x{:01X}\n"
|
||||
"Frame to field: {}\n"
|
||||
"Copy to XFB: {}\n"
|
||||
"Intensity format: {}\n"
|
||||
"Automatic color conversion: {}",
|
||||
@@ -1059,9 +1037,8 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
(copy.gamma == 0) ?
|
||||
"1.0" :
|
||||
(copy.gamma == 1) ? "1.7" : (copy.gamma == 2) ? "2.2" : "Invalid value 0x3?",
|
||||
no_yes[copy.half_scale], no_yes[copy.scale_invert], no_yes[copy.clear],
|
||||
static_cast<u32>(copy.frame_to_field), no_yes[copy.copy_to_xfb], no_yes[copy.intensity_fmt],
|
||||
no_yes[copy.auto_conv]);
|
||||
no_yes[copy.half_scale], no_yes[copy.scale_invert], no_yes[copy.clear], copy.frame_to_field,
|
||||
no_yes[copy.copy_to_xfb], no_yes[copy.intensity_fmt], no_yes[copy.auto_conv]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1183,8 +1160,8 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
*desc = fmt::format("Texture Unit: {}\n"
|
||||
"Width: {}\n"
|
||||
"Height: {}\n"
|
||||
"Format: {:x}\n",
|
||||
texnum, u32(teximg.width) + 1, u32(teximg.height) + 1, u32(teximg.format));
|
||||
"Format: {}\n",
|
||||
texnum, u32(teximg.width) + 1, u32(teximg.height) + 1, teximg.format);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1208,7 +1185,7 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
"Even TMEM Height: {}\n"
|
||||
"Cache is manually managed: {}\n",
|
||||
texnum, u32(teximg.tmem_even), u32(teximg.cache_width),
|
||||
u32(teximg.cache_height), no_yes[teximg.image_type]);
|
||||
u32(teximg.cache_height), no_yes[teximg.cache_manually_managed]);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -1285,14 +1262,6 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
SetRegName(BPMEM_TEV_COLOR_ENV);
|
||||
TevStageCombiner::ColorCombiner cc;
|
||||
cc.hex = cmddata;
|
||||
const char* tevin[] = {
|
||||
"prev.rgb", "prev.aaa", "c0.rgb", "c0.aaa", "c1.rgb", "c1.aaa", "c2.rgb", "c2.aaa",
|
||||
"tex.rgb", "tex.aaa", "ras.rgb", "ras.aaa", "ONE", "HALF", "konst.rgb", "ZERO",
|
||||
};
|
||||
const char* tevbias[] = {"0", "+0.5", "-0.5", "compare"};
|
||||
const char* tevop[] = {"add", "sub"};
|
||||
const char* tevscale[] = {"1", "2", "4", "0.5"};
|
||||
const char* tevout[] = {"prev.rgb", "c0.rgb", "c1.rgb", "c2.rgb"};
|
||||
*desc = fmt::format("Tev stage: {}\n"
|
||||
"a: {}\n"
|
||||
"b: {}\n"
|
||||
@@ -1303,9 +1272,8 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
"Clamp: {}\n"
|
||||
"Scale factor: {}\n"
|
||||
"Dest: {}\n",
|
||||
(data[0] - BPMEM_TEV_COLOR_ENV) / 2, tevin[cc.a], tevin[cc.b], tevin[cc.c],
|
||||
tevin[cc.d], tevbias[cc.bias], tevop[cc.op], no_yes[cc.clamp],
|
||||
tevscale[cc.shift], tevout[cc.dest]);
|
||||
(data[0] - BPMEM_TEV_COLOR_ENV) / 2, cc.a, cc.b, cc.c, cc.d, cc.bias, cc.op,
|
||||
no_yes[cc.clamp], cc.scale, cc.dest);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1329,13 +1297,6 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
SetRegName(BPMEM_TEV_ALPHA_ENV);
|
||||
TevStageCombiner::AlphaCombiner ac;
|
||||
ac.hex = cmddata;
|
||||
const char* tevin[] = {
|
||||
"prev", "c0", "c1", "c2", "tex", "ras", "konst", "ZERO",
|
||||
};
|
||||
const char* tevbias[] = {"0", "+0.5", "-0.5", "compare"};
|
||||
const char* tevop[] = {"add", "sub"};
|
||||
const char* tevscale[] = {"1", "2", "4", "0.5"};
|
||||
const char* tevout[] = {"prev", "c0", "c1", "c2"};
|
||||
*desc = fmt::format("Tev stage: {}\n"
|
||||
"a: {}\n"
|
||||
"b: {}\n"
|
||||
@@ -1348,9 +1309,8 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
"Dest: {}\n"
|
||||
"Ras sel: {}\n"
|
||||
"Tex sel: {}\n",
|
||||
(data[0] - BPMEM_TEV_ALPHA_ENV) / 2, tevin[ac.a], tevin[ac.b], tevin[ac.c],
|
||||
tevin[ac.d], tevbias[ac.bias], tevop[ac.op], no_yes[ac.clamp],
|
||||
tevscale[ac.shift], tevout[ac.dest], ac.rswap.Value(), ac.tswap.Value());
|
||||
(data[0] - BPMEM_TEV_ALPHA_ENV) / 2, ac.a, ac.b, ac.c, ac.d, ac.bias, ac.op,
|
||||
no_yes[ac.clamp], ac.scale, ac.dest, ac.rswap.Value(), ac.tswap.Value());
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -1410,14 +1370,10 @@ void GetBPRegInfo(const u8* data, std::string* name, std::string* desc)
|
||||
SetRegName(BPMEM_ALPHACOMPARE);
|
||||
AlphaTest test;
|
||||
test.hex = cmddata;
|
||||
const char* functions[] = {"NEVER", "LESS", "EQUAL", "LEQUAL",
|
||||
"GREATER", "NEQUAL", "GEQUAL", "ALWAYS"};
|
||||
const char* logic[] = {"AND", "OR", "XOR", "XNOR"};
|
||||
*desc = fmt::format("Test 1: {} (ref: 0x{:02x})\n"
|
||||
"Test 2: {} (ref: 0x{:02x})\n"
|
||||
"Logic: {}\n",
|
||||
functions[test.comp0], test.ref0.Value(), functions[test.comp1],
|
||||
test.ref1.Value(), logic[test.logic]);
|
||||
test.comp0, test.ref0.Value(), test.comp1, test.ref1.Value(), test.logic);
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@ using float4 = std::array<float, 4>;
|
||||
using uint4 = std::array<u32, 4>;
|
||||
using int4 = std::array<s32, 4>;
|
||||
|
||||
enum class SrcBlendFactor : u32;
|
||||
enum class DstBlendFactor : u32;
|
||||
|
||||
struct PixelShaderConstants
|
||||
{
|
||||
std::array<int4, 4> colors;
|
||||
@@ -45,10 +48,10 @@ struct PixelShaderConstants
|
||||
std::array<int4, 32> konst; // .rgba
|
||||
// The following are used in ubershaders when using shader_framebuffer_fetch blending
|
||||
u32 blend_enable;
|
||||
u32 blend_src_factor;
|
||||
u32 blend_src_factor_alpha;
|
||||
u32 blend_dst_factor;
|
||||
u32 blend_dst_factor_alpha;
|
||||
SrcBlendFactor blend_src_factor;
|
||||
SrcBlendFactor blend_src_factor_alpha;
|
||||
DstBlendFactor blend_dst_factor;
|
||||
DstBlendFactor blend_dst_factor_alpha;
|
||||
u32 blend_subtract;
|
||||
u32 blend_subtract_alpha;
|
||||
};
|
||||
|
||||
@@ -174,14 +174,14 @@ PixelShaderUid GetPixelShaderUid()
|
||||
|
||||
pixel_shader_uid_data* const uid_data = out.GetUidData();
|
||||
uid_data->useDstAlpha = bpmem.dstalpha.enable && bpmem.blendmode.alphaupdate &&
|
||||
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
|
||||
bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24;
|
||||
|
||||
uid_data->genMode_numindstages = bpmem.genMode.numindstages;
|
||||
uid_data->genMode_numtevstages = bpmem.genMode.numtevstages;
|
||||
uid_data->genMode_numtexgens = bpmem.genMode.numtexgens;
|
||||
uid_data->bounding_box = g_ActiveConfig.bBBoxEnable && BoundingBox::IsEnabled();
|
||||
uid_data->rgba6_format =
|
||||
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor;
|
||||
bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor;
|
||||
uid_data->dither = bpmem.blendmode.dither && uid_data->rgba6_format;
|
||||
uid_data->uint_output = bpmem.blendmode.UseLogicOp();
|
||||
|
||||
@@ -189,12 +189,13 @@ PixelShaderUid GetPixelShaderUid()
|
||||
|
||||
const bool forced_early_z =
|
||||
bpmem.UseEarlyDepthTest() &&
|
||||
(g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED)
|
||||
(g_ActiveConfig.bFastDepthCalc ||
|
||||
bpmem.alpha_test.TestResult() == AlphaTestResult::Undetermined)
|
||||
// We can't allow early_ztest for zfreeze because depth is overridden per-pixel.
|
||||
// This means it's impossible for zcomploc to be emulated on a zfrozen polygon.
|
||||
&& !(bpmem.zmode.testenable && bpmem.genMode.zfreeze);
|
||||
const bool per_pixel_depth =
|
||||
(bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) ||
|
||||
(bpmem.ztex2.op != ZTexOp::Disabled && bpmem.UseLateDepthTest()) ||
|
||||
(!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !forced_early_z) ||
|
||||
(bpmem.zmode.testenable && bpmem.genMode.zfreeze);
|
||||
|
||||
@@ -253,10 +254,12 @@ PixelShaderUid GetPixelShaderUid()
|
||||
uid_data->stagehash[n].cc = cc.hex & 0xFFFFFF;
|
||||
uid_data->stagehash[n].ac = ac.hex & 0xFFFFF0; // Storing rswap and tswap later
|
||||
|
||||
if (cc.a == TEVCOLORARG_RASA || cc.a == TEVCOLORARG_RASC || cc.b == TEVCOLORARG_RASA ||
|
||||
cc.b == TEVCOLORARG_RASC || cc.c == TEVCOLORARG_RASA || cc.c == TEVCOLORARG_RASC ||
|
||||
cc.d == TEVCOLORARG_RASA || cc.d == TEVCOLORARG_RASC || ac.a == TEVALPHAARG_RASA ||
|
||||
ac.b == TEVALPHAARG_RASA || ac.c == TEVALPHAARG_RASA || ac.d == TEVALPHAARG_RASA)
|
||||
if (cc.a == TevColorArg::RasAlpha || cc.a == TevColorArg::RasColor ||
|
||||
cc.b == TevColorArg::RasAlpha || cc.b == TevColorArg::RasColor ||
|
||||
cc.c == TevColorArg::RasAlpha || cc.c == TevColorArg::RasColor ||
|
||||
cc.d == TevColorArg::RasAlpha || cc.d == TevColorArg::RasColor ||
|
||||
ac.a == TevAlphaArg::RasAlpha || ac.b == TevAlphaArg::RasAlpha ||
|
||||
ac.c == TevAlphaArg::RasAlpha || ac.d == TevAlphaArg::RasAlpha)
|
||||
{
|
||||
const int i = bpmem.combiners[n].alphaC.rswap;
|
||||
uid_data->stagehash[n].tevksel_swap1a = bpmem.tevksel[i * 2].swap1;
|
||||
@@ -277,9 +280,9 @@ PixelShaderUid GetPixelShaderUid()
|
||||
uid_data->stagehash[n].tevorders_texmap = bpmem.tevorders[n / 2].getTexMap(n & 1);
|
||||
}
|
||||
|
||||
if (cc.a == TEVCOLORARG_KONST || cc.b == TEVCOLORARG_KONST || cc.c == TEVCOLORARG_KONST ||
|
||||
cc.d == TEVCOLORARG_KONST || ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST ||
|
||||
ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST)
|
||||
if (cc.a == TevColorArg::Konst || cc.b == TevColorArg::Konst || cc.c == TevColorArg::Konst ||
|
||||
cc.d == TevColorArg::Konst || ac.a == TevAlphaArg::Konst || ac.b == TevAlphaArg::Konst ||
|
||||
ac.c == TevAlphaArg::Konst || ac.d == TevAlphaArg::Konst)
|
||||
{
|
||||
uid_data->stagehash[n].tevksel_kc = bpmem.tevksel[n / 2].getKC(n & 1);
|
||||
uid_data->stagehash[n].tevksel_ka = bpmem.tevksel[n / 2].getKA(n & 1);
|
||||
@@ -291,15 +294,14 @@ PixelShaderUid GetPixelShaderUid()
|
||||
sizeof(*uid_data) :
|
||||
MY_STRUCT_OFFSET(*uid_data, stagehash[numStages]);
|
||||
|
||||
AlphaTest::TEST_RESULT Pretest = bpmem.alpha_test.TestResult();
|
||||
uid_data->Pretest = Pretest;
|
||||
uid_data->Pretest = bpmem.alpha_test.TestResult();
|
||||
uid_data->late_ztest = bpmem.UseLateDepthTest();
|
||||
|
||||
// NOTE: Fragment may not be discarded if alpha test always fails and early depth test is enabled
|
||||
// (in this case we need to write a depth value if depth test passes regardless of the alpha
|
||||
// testing result)
|
||||
if (uid_data->Pretest == AlphaTest::UNDETERMINED ||
|
||||
(uid_data->Pretest == AlphaTest::FAIL && uid_data->late_ztest))
|
||||
if (uid_data->Pretest == AlphaTestResult::Undetermined ||
|
||||
(uid_data->Pretest == AlphaTestResult::Fail && uid_data->late_ztest))
|
||||
{
|
||||
uid_data->alpha_test_comp0 = bpmem.alpha_test.comp0;
|
||||
uid_data->alpha_test_comp1 = bpmem.alpha_test.comp1;
|
||||
@@ -320,7 +322,7 @@ PixelShaderUid GetPixelShaderUid()
|
||||
uid_data->zfreeze = bpmem.genMode.zfreeze;
|
||||
uid_data->ztex_op = bpmem.ztex2.op;
|
||||
uid_data->early_ztest = bpmem.UseEarlyDepthTest();
|
||||
uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel;
|
||||
|
||||
uid_data->fog_fsel = bpmem.fog.c_proj_fsel.fsel;
|
||||
uid_data->fog_proj = bpmem.fog.c_proj_fsel.proj;
|
||||
uid_data->fog_RangeBaseEnabled = bpmem.fogRange.Base.Enabled;
|
||||
@@ -517,8 +519,8 @@ void UpdateBoundingBox(float2 rawpos) {{
|
||||
|
||||
static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, int n,
|
||||
APIType api_type, bool stereo);
|
||||
static void WriteTevRegular(ShaderCode& out, std::string_view components, int bias, int op,
|
||||
int clamp, int shift, bool alpha);
|
||||
static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBias bias, TevOp op,
|
||||
bool clamp, TevScale scale, bool alpha);
|
||||
static void SampleTexture(ShaderCode& out, std::string_view texcoords, std::string_view texswap,
|
||||
int texmap, bool stereo, APIType api_type);
|
||||
static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_data, APIType api_type,
|
||||
@@ -826,13 +828,13 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
||||
TevStageCombiner::AlphaCombiner last_ac;
|
||||
last_cc.hex = uid_data->stagehash[uid_data->genMode_numtevstages].cc;
|
||||
last_ac.hex = uid_data->stagehash[uid_data->genMode_numtevstages].ac;
|
||||
if (last_cc.dest != 0)
|
||||
if (last_cc.dest != TevOutput::Prev)
|
||||
{
|
||||
out.Write("\tprev.rgb = {};\n", tev_c_output_table[last_cc.dest]);
|
||||
out.Write("\tprev.rgb = {};\n", tev_c_output_table[u32(last_cc.dest.Value())]);
|
||||
}
|
||||
if (last_ac.dest != 0)
|
||||
if (last_ac.dest != TevOutput::Prev)
|
||||
{
|
||||
out.Write("\tprev.a = {};\n", tev_a_output_table[last_ac.dest]);
|
||||
out.Write("\tprev.a = {};\n", tev_a_output_table[u32(last_ac.dest.Value())]);
|
||||
}
|
||||
}
|
||||
out.Write("\tprev = prev & 255;\n");
|
||||
@@ -840,8 +842,8 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
||||
// NOTE: Fragment may not be discarded if alpha test always fails and early depth test is enabled
|
||||
// (in this case we need to write a depth value if depth test passes regardless of the alpha
|
||||
// testing result)
|
||||
if (uid_data->Pretest == AlphaTest::UNDETERMINED ||
|
||||
(uid_data->Pretest == AlphaTest::FAIL && uid_data->late_ztest))
|
||||
if (uid_data->Pretest == AlphaTestResult::Undetermined ||
|
||||
(uid_data->Pretest == AlphaTestResult::Fail && uid_data->late_ztest))
|
||||
{
|
||||
WriteAlphaTest(out, uid_data, api_type, uid_data->per_pixel_depth,
|
||||
use_dual_source || use_shader_blend);
|
||||
@@ -884,7 +886,7 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
||||
|
||||
// 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
|
||||
const bool skip_ztexture = !uid_data->per_pixel_depth && !uid_data->fog_fsel;
|
||||
const bool skip_ztexture = !uid_data->per_pixel_depth && uid_data->fog_fsel == FogType::Off;
|
||||
|
||||
// Note: z-textures are not written to depth buffer if early depth test is used
|
||||
if (uid_data->per_pixel_depth && uid_data->early_ztest)
|
||||
@@ -898,13 +900,13 @@ ShaderCode GeneratePixelShaderCode(APIType api_type, const ShaderHostConfig& hos
|
||||
// Note: depth texture output is only written to depth buffer if late depth test is used
|
||||
// theoretical final depth value is used for fog calculation, though, so we have to emulate
|
||||
// ztextures anyway
|
||||
if (uid_data->ztex_op != ZTEXTURE_DISABLE && !skip_ztexture)
|
||||
if (uid_data->ztex_op != ZTexOp::Disabled && !skip_ztexture)
|
||||
{
|
||||
// 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("\tzCoord = idot(" I_ZBIAS "[0].xyzw, textemp.xyzw) + " I_ZBIAS "[1].w {};\n",
|
||||
(uid_data->ztex_op == ZTEXTURE_ADD) ? "+ zCoord" : "");
|
||||
(uid_data->ztex_op == ZTexOp::Add) ? "+ zCoord" : "");
|
||||
out.Write("\tzCoord = zCoord & 0xFFFFFF;\n");
|
||||
}
|
||||
|
||||
@@ -963,7 +965,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
|
||||
// Perform the indirect op on the incoming regular coordinates
|
||||
// using iindtex{} as the offset coords
|
||||
if (tevind.bs != ITBA_OFF)
|
||||
if (tevind.bs != IndTexBumpAlpha::Off)
|
||||
{
|
||||
static constexpr std::array<const char*, 4> tev_ind_alpha_sel{
|
||||
"",
|
||||
@@ -980,8 +982,9 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
"248",
|
||||
};
|
||||
|
||||
out.Write("alphabump = iindtex{}.{} & {};\n", tevind.bt.Value(), tev_ind_alpha_sel[tevind.bs],
|
||||
tev_ind_alpha_mask[tevind.fmt]);
|
||||
out.Write("alphabump = iindtex{}.{} & {};\n", tevind.bt.Value(),
|
||||
tev_ind_alpha_sel[u32(tevind.bs.Value())],
|
||||
tev_ind_alpha_mask[u32(tevind.fmt.Value())]);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -998,7 +1001,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
"7",
|
||||
};
|
||||
out.Write("\tint3 iindtevcrd{} = iindtex{} & {};\n", n, tevind.bt.Value(),
|
||||
tev_ind_fmt_mask[tevind.fmt]);
|
||||
tev_ind_fmt_mask[u32(tevind.fmt.Value())]);
|
||||
|
||||
// bias - TODO: Check if this needs to be this complicated...
|
||||
// indexed by bias
|
||||
@@ -1014,21 +1017,25 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
"1",
|
||||
};
|
||||
|
||||
if (tevind.bias == ITB_S || tevind.bias == ITB_T || tevind.bias == ITB_U)
|
||||
if (tevind.bias == IndTexBias::S || tevind.bias == IndTexBias::T ||
|
||||
tevind.bias == IndTexBias::U)
|
||||
{
|
||||
out.Write("\tiindtevcrd{}.{} += int({});\n", n, tev_ind_bias_field[tevind.bias],
|
||||
tev_ind_bias_add[tevind.fmt]);
|
||||
out.Write("\tiindtevcrd{}.{} += int({});\n", n,
|
||||
tev_ind_bias_field[u32(tevind.bias.Value())],
|
||||
tev_ind_bias_add[u32(tevind.fmt.Value())]);
|
||||
}
|
||||
else if (tevind.bias == ITB_ST || tevind.bias == ITB_SU || tevind.bias == ITB_TU)
|
||||
else if (tevind.bias == IndTexBias::ST || tevind.bias == IndTexBias::SU ||
|
||||
tevind.bias == IndTexBias::TU_)
|
||||
{
|
||||
out.Write("\tiindtevcrd{}.{} += int2({}, {});\n", n, tev_ind_bias_field[tevind.bias],
|
||||
tev_ind_bias_add[tevind.fmt], tev_ind_bias_add[tevind.fmt]);
|
||||
out.Write("\tiindtevcrd{0}.{1} += int2({2}, {2});\n", n,
|
||||
tev_ind_bias_field[u32(tevind.bias.Value())],
|
||||
tev_ind_bias_add[u32(tevind.fmt.Value())]);
|
||||
}
|
||||
else if (tevind.bias == ITB_STU)
|
||||
else if (tevind.bias == IndTexBias::STU)
|
||||
{
|
||||
out.Write("\tiindtevcrd{}.{} += int3({}, {}, {});\n", n, tev_ind_bias_field[tevind.bias],
|
||||
tev_ind_bias_add[tevind.fmt], tev_ind_bias_add[tevind.fmt],
|
||||
tev_ind_bias_add[tevind.fmt]);
|
||||
out.Write("\tiindtevcrd{0}.{1} += int3({2}, {2}, {2});\n", n,
|
||||
tev_ind_bias_field[u32(tevind.bias.Value())],
|
||||
tev_ind_bias_add[u32(tevind.fmt.Value())]);
|
||||
}
|
||||
|
||||
// multiply by offset matrix and scale - calculations are likely to overflow badly,
|
||||
@@ -1122,33 +1129,33 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
};
|
||||
|
||||
// wrap S
|
||||
if (tevind.sw == ITW_OFF)
|
||||
if (tevind.sw == IndTexWrap::ITW_OFF)
|
||||
{
|
||||
out.Write("\twrappedcoord.x = fixpoint_uv{}.x;\n", texcoord);
|
||||
}
|
||||
else if (tevind.sw == ITW_0)
|
||||
else if (tevind.sw == IndTexWrap::ITW_0)
|
||||
{
|
||||
out.Write("\twrappedcoord.x = 0;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("\twrappedcoord.x = fixpoint_uv{}.x & ({} - 1);\n", texcoord,
|
||||
tev_ind_wrap_start[tevind.sw]);
|
||||
tev_ind_wrap_start[u32(tevind.sw.Value())]);
|
||||
}
|
||||
|
||||
// wrap T
|
||||
if (tevind.tw == ITW_OFF)
|
||||
if (tevind.tw == IndTexWrap::ITW_OFF)
|
||||
{
|
||||
out.Write("\twrappedcoord.y = fixpoint_uv{}.y;\n", texcoord);
|
||||
}
|
||||
else if (tevind.tw == ITW_0)
|
||||
else if (tevind.tw == IndTexWrap::ITW_0)
|
||||
{
|
||||
out.Write("\twrappedcoord.y = 0;\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
out.Write("\twrappedcoord.y = fixpoint_uv{}.y & ({} - 1);\n", texcoord,
|
||||
tev_ind_wrap_start[tevind.tw]);
|
||||
tev_ind_wrap_start[u32(tevind.tw.Value())]);
|
||||
}
|
||||
|
||||
if (tevind.fb_addprev) // add previous tevcoord
|
||||
@@ -1165,10 +1172,12 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
cc.hex = stage.cc;
|
||||
ac.hex = stage.ac;
|
||||
|
||||
if (cc.a == TEVCOLORARG_RASA || cc.a == TEVCOLORARG_RASC || cc.b == TEVCOLORARG_RASA ||
|
||||
cc.b == TEVCOLORARG_RASC || cc.c == TEVCOLORARG_RASA || cc.c == TEVCOLORARG_RASC ||
|
||||
cc.d == TEVCOLORARG_RASA || cc.d == TEVCOLORARG_RASC || ac.a == TEVALPHAARG_RASA ||
|
||||
ac.b == TEVALPHAARG_RASA || ac.c == TEVALPHAARG_RASA || ac.d == TEVALPHAARG_RASA)
|
||||
if (cc.a == TevColorArg::RasAlpha || cc.a == TevColorArg::RasColor ||
|
||||
cc.b == TevColorArg::RasAlpha || cc.b == TevColorArg::RasColor ||
|
||||
cc.c == TevColorArg::RasAlpha || cc.c == TevColorArg::RasColor ||
|
||||
cc.d == TevColorArg::RasAlpha || cc.d == TevColorArg::RasColor ||
|
||||
ac.a == TevAlphaArg::RasAlpha || ac.b == TevAlphaArg::RasAlpha ||
|
||||
ac.c == TevAlphaArg::RasAlpha || ac.d == TevAlphaArg::RasAlpha)
|
||||
{
|
||||
// Generate swizzle string to represent the Ras color channel swapping
|
||||
const char rasswap[5] = {
|
||||
@@ -1179,7 +1188,7 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
'\0',
|
||||
};
|
||||
|
||||
out.Write("\trastemp = {}.{};\n", tev_ras_table[stage.tevorders_colorchan], rasswap);
|
||||
out.Write("\trastemp = {}.{};\n", tev_ras_table[u32(stage.tevorders_colorchan)], rasswap);
|
||||
}
|
||||
|
||||
if (stage.tevorders_enable)
|
||||
@@ -1209,72 +1218,73 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
out.Write("\ttextemp = int4(255, 255, 255, 255);\n");
|
||||
}
|
||||
|
||||
if (cc.a == TEVCOLORARG_KONST || cc.b == TEVCOLORARG_KONST || cc.c == TEVCOLORARG_KONST ||
|
||||
cc.d == TEVCOLORARG_KONST || ac.a == TEVALPHAARG_KONST || ac.b == TEVALPHAARG_KONST ||
|
||||
ac.c == TEVALPHAARG_KONST || ac.d == TEVALPHAARG_KONST)
|
||||
if (cc.a == TevColorArg::Konst || cc.b == TevColorArg::Konst || cc.c == TevColorArg::Konst ||
|
||||
cc.d == TevColorArg::Konst || ac.a == TevAlphaArg::Konst || ac.b == TevAlphaArg::Konst ||
|
||||
ac.c == TevAlphaArg::Konst || ac.d == TevAlphaArg::Konst)
|
||||
{
|
||||
out.Write("\tkonsttemp = int4({}, {});\n", tev_ksel_table_c[stage.tevksel_kc],
|
||||
tev_ksel_table_a[stage.tevksel_ka]);
|
||||
out.Write("\tkonsttemp = int4({}, {});\n", tev_ksel_table_c[u32(stage.tevksel_kc)],
|
||||
tev_ksel_table_a[u32(stage.tevksel_ka)]);
|
||||
|
||||
if (stage.tevksel_kc > 7)
|
||||
if (u32(stage.tevksel_kc) > 7)
|
||||
{
|
||||
out.SetConstantsUsed(C_KCOLORS + ((stage.tevksel_kc - 0xc) % 4),
|
||||
C_KCOLORS + ((stage.tevksel_kc - 0xc) % 4));
|
||||
out.SetConstantsUsed(C_KCOLORS + ((u32(stage.tevksel_kc) - 0xc) % 4),
|
||||
C_KCOLORS + ((u32(stage.tevksel_kc) - 0xc) % 4));
|
||||
}
|
||||
if (stage.tevksel_ka > 7)
|
||||
if (u32(stage.tevksel_ka) > 7)
|
||||
{
|
||||
out.SetConstantsUsed(C_KCOLORS + ((stage.tevksel_ka - 0xc) % 4),
|
||||
C_KCOLORS + ((stage.tevksel_ka - 0xc) % 4));
|
||||
out.SetConstantsUsed(C_KCOLORS + ((u32(stage.tevksel_ka) - 0xc) % 4),
|
||||
C_KCOLORS + ((u32(stage.tevksel_ka) - 0xc) % 4));
|
||||
}
|
||||
}
|
||||
|
||||
if (cc.d == TEVCOLORARG_C0 || cc.d == TEVCOLORARG_A0 || ac.d == TEVALPHAARG_A0)
|
||||
if (cc.d == TevColorArg::Color0 || cc.d == TevColorArg::Alpha0 || ac.d == TevAlphaArg::Alpha0)
|
||||
out.SetConstantsUsed(C_COLORS + 1, C_COLORS + 1);
|
||||
|
||||
if (cc.d == TEVCOLORARG_C1 || cc.d == TEVCOLORARG_A1 || ac.d == TEVALPHAARG_A1)
|
||||
if (cc.d == TevColorArg::Color1 || cc.d == TevColorArg::Alpha1 || ac.d == TevAlphaArg::Alpha1)
|
||||
out.SetConstantsUsed(C_COLORS + 2, C_COLORS + 2);
|
||||
|
||||
if (cc.d == TEVCOLORARG_C2 || cc.d == TEVCOLORARG_A2 || ac.d == TEVALPHAARG_A2)
|
||||
if (cc.d == TevColorArg::Color2 || cc.d == TevColorArg::Alpha2 || ac.d == TevAlphaArg::Alpha2)
|
||||
out.SetConstantsUsed(C_COLORS + 3, C_COLORS + 3);
|
||||
|
||||
if (cc.dest >= GX_TEVREG0)
|
||||
out.SetConstantsUsed(C_COLORS + cc.dest, C_COLORS + cc.dest);
|
||||
if (cc.dest >= TevOutput::Color0)
|
||||
out.SetConstantsUsed(C_COLORS + u32(cc.dest.Value()), C_COLORS + u32(cc.dest.Value()));
|
||||
|
||||
if (ac.dest >= GX_TEVREG0)
|
||||
out.SetConstantsUsed(C_COLORS + ac.dest, C_COLORS + ac.dest);
|
||||
if (ac.dest >= TevOutput::Color0)
|
||||
out.SetConstantsUsed(C_COLORS + u32(ac.dest.Value()), C_COLORS + u32(ac.dest.Value()));
|
||||
|
||||
out.Write("\ttevin_a = int4({}, {})&int4(255, 255, 255, 255);\n", tev_c_input_table[cc.a],
|
||||
tev_a_input_table[ac.a]);
|
||||
out.Write("\ttevin_b = int4({}, {})&int4(255, 255, 255, 255);\n", tev_c_input_table[cc.b],
|
||||
tev_a_input_table[ac.b]);
|
||||
out.Write("\ttevin_c = int4({}, {})&int4(255, 255, 255, 255);\n", tev_c_input_table[cc.c],
|
||||
tev_a_input_table[ac.c]);
|
||||
out.Write("\ttevin_d = int4({}, {});\n", tev_c_input_table[cc.d], tev_a_input_table[ac.d]);
|
||||
out.Write("\ttevin_a = int4({}, {})&int4(255, 255, 255, 255);\n",
|
||||
tev_c_input_table[u32(cc.a.Value())], tev_a_input_table[u32(ac.a.Value())]);
|
||||
out.Write("\ttevin_b = int4({}, {})&int4(255, 255, 255, 255);\n",
|
||||
tev_c_input_table[u32(cc.b.Value())], tev_a_input_table[u32(ac.b.Value())]);
|
||||
out.Write("\ttevin_c = int4({}, {})&int4(255, 255, 255, 255);\n",
|
||||
tev_c_input_table[u32(cc.c.Value())], tev_a_input_table[u32(ac.c.Value())]);
|
||||
out.Write("\ttevin_d = int4({}, {});\n", tev_c_input_table[u32(cc.d.Value())],
|
||||
tev_a_input_table[u32(ac.d.Value())]);
|
||||
|
||||
out.Write("\t// color combine\n");
|
||||
out.Write("\t{} = clamp(", tev_c_output_table[cc.dest]);
|
||||
if (cc.bias != TEVBIAS_COMPARE)
|
||||
out.Write("\t{} = clamp(", tev_c_output_table[u32(cc.dest.Value())]);
|
||||
if (cc.bias != TevBias::Compare)
|
||||
{
|
||||
WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.shift, false);
|
||||
WriteTevRegular(out, "rgb", cc.bias, cc.op, cc.clamp, cc.scale, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr std::array<const char*, 8> function_table{
|
||||
"((tevin_a.r > tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_R8_GT
|
||||
"((tevin_a.r == tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // TEVCMP_R8_EQ
|
||||
"((tevin_a.r > tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // TevCompareMode::R8, GT
|
||||
"((tevin_a.r == tevin_b.r) ? tevin_c.rgb : int3(0,0,0))", // R8, TevComparison::EQ
|
||||
"((idot(tevin_a.rgb, comp16) > idot(tevin_b.rgb, comp16)) ? tevin_c.rgb : "
|
||||
"int3(0,0,0))", // TEVCMP_GR16_GT
|
||||
"int3(0,0,0))", // GR16, GT
|
||||
"((idot(tevin_a.rgb, comp16) == idot(tevin_b.rgb, comp16)) ? tevin_c.rgb : "
|
||||
"int3(0,0,0))", // TEVCMP_GR16_EQ
|
||||
"int3(0,0,0))", // GR16, EQ
|
||||
"((idot(tevin_a.rgb, comp24) > idot(tevin_b.rgb, comp24)) ? tevin_c.rgb : "
|
||||
"int3(0,0,0))", // TEVCMP_BGR24_GT
|
||||
"int3(0,0,0))", // BGR24, GT
|
||||
"((idot(tevin_a.rgb, comp24) == idot(tevin_b.rgb, comp24)) ? tevin_c.rgb : "
|
||||
"int3(0,0,0))", // TEVCMP_BGR24_EQ
|
||||
"(max(sign(tevin_a.rgb - tevin_b.rgb), int3(0,0,0)) * tevin_c.rgb)", // TEVCMP_RGB8_GT
|
||||
"((int3(1,1,1) - sign(abs(tevin_a.rgb - tevin_b.rgb))) * tevin_c.rgb)" // TEVCMP_RGB8_EQ
|
||||
"int3(0,0,0))", // BGR24, EQ
|
||||
"(max(sign(tevin_a.rgb - tevin_b.rgb), int3(0,0,0)) * tevin_c.rgb)", // RGB8, GT
|
||||
"((int3(1,1,1) - sign(abs(tevin_a.rgb - tevin_b.rgb))) * tevin_c.rgb)" // RGB8, EQ
|
||||
};
|
||||
|
||||
const u32 mode = (cc.shift << 1) | cc.op;
|
||||
const u32 mode = (u32(cc.compare_mode.Value()) << 1) | u32(cc.comparison.Value());
|
||||
out.Write(" tevin_d.rgb + ");
|
||||
out.Write("{}", function_table[mode]);
|
||||
}
|
||||
@@ -1285,25 +1295,25 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
out.Write(";\n");
|
||||
|
||||
out.Write("\t// alpha combine\n");
|
||||
out.Write("\t{} = clamp(", tev_a_output_table[ac.dest]);
|
||||
if (ac.bias != TEVBIAS_COMPARE)
|
||||
out.Write("\t{} = clamp(", tev_a_output_table[u32(ac.dest.Value())]);
|
||||
if (ac.bias != TevBias::Compare)
|
||||
{
|
||||
WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.shift, true);
|
||||
WriteTevRegular(out, "a", ac.bias, ac.op, ac.clamp, ac.scale, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
static constexpr std::array<const char*, 8> function_table{
|
||||
"((tevin_a.r > tevin_b.r) ? tevin_c.a : 0)", // TEVCMP_R8_GT
|
||||
"((tevin_a.r == tevin_b.r) ? tevin_c.a : 0)", // TEVCMP_R8_EQ
|
||||
"((idot(tevin_a.rgb, comp16) > idot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // TEVCMP_GR16_GT
|
||||
"((idot(tevin_a.rgb, comp16) == idot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // TEVCMP_GR16_EQ
|
||||
"((idot(tevin_a.rgb, comp24) > idot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // TEVCMP_BGR24_GT
|
||||
"((idot(tevin_a.rgb, comp24) == idot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // TEVCMP_BGR24_EQ
|
||||
"((tevin_a.a > tevin_b.a) ? tevin_c.a : 0)", // TEVCMP_A8_GT
|
||||
"((tevin_a.a == tevin_b.a) ? tevin_c.a : 0)" // TEVCMP_A8_EQ
|
||||
"((tevin_a.r > tevin_b.r) ? tevin_c.a : 0)", // TevCompareMode::R8, GT
|
||||
"((tevin_a.r == tevin_b.r) ? tevin_c.a : 0)", // R8, TevComparison::EQ
|
||||
"((idot(tevin_a.rgb, comp16) > idot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // GR16, GT
|
||||
"((idot(tevin_a.rgb, comp16) == idot(tevin_b.rgb, comp16)) ? tevin_c.a : 0)", // GR16, EQ
|
||||
"((idot(tevin_a.rgb, comp24) > idot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // BGR24, GT
|
||||
"((idot(tevin_a.rgb, comp24) == idot(tevin_b.rgb, comp24)) ? tevin_c.a : 0)", // BGR24, EQ
|
||||
"((tevin_a.a > tevin_b.a) ? tevin_c.a : 0)", // A8, GT
|
||||
"((tevin_a.a == tevin_b.a) ? tevin_c.a : 0)" // A8, EQ
|
||||
};
|
||||
|
||||
const u32 mode = (ac.shift << 1) | ac.op;
|
||||
const u32 mode = (u32(ac.compare_mode.Value()) << 1) | u32(ac.comparison.Value());
|
||||
out.Write(" tevin_d.a + ");
|
||||
out.Write("{}", function_table[mode]);
|
||||
}
|
||||
@@ -1315,24 +1325,24 @@ static void WriteStage(ShaderCode& out, const pixel_shader_uid_data* uid_data, i
|
||||
out.Write(";\n");
|
||||
}
|
||||
|
||||
static void WriteTevRegular(ShaderCode& out, std::string_view components, int bias, int op,
|
||||
int clamp, int shift, bool alpha)
|
||||
static void WriteTevRegular(ShaderCode& out, std::string_view components, TevBias bias, TevOp op,
|
||||
bool clamp, TevScale scale, bool alpha)
|
||||
{
|
||||
static constexpr std::array<const char*, 4> tev_scale_table_left{
|
||||
"", // SCALE_1
|
||||
" << 1", // SCALE_2
|
||||
" << 2", // SCALE_4
|
||||
"", // DIVIDE_2
|
||||
"", // Scale1
|
||||
" << 1", // Scale2
|
||||
" << 2", // Scale4
|
||||
"", // Divide2
|
||||
};
|
||||
|
||||
static constexpr std::array<const char*, 4> tev_scale_table_right{
|
||||
"", // SCALE_1
|
||||
"", // SCALE_2
|
||||
"", // SCALE_4
|
||||
" >> 1", // DIVIDE_2
|
||||
"", // Scale1
|
||||
"", // Scale2
|
||||
"", // Scale4
|
||||
" >> 1", // Divide2
|
||||
};
|
||||
|
||||
// indexed by 2*op+(shift==3)
|
||||
// indexed by 2*op+(scale==Divide2)
|
||||
static constexpr std::array<const char*, 4> tev_lerp_bias{
|
||||
"",
|
||||
" + 128",
|
||||
@@ -1341,15 +1351,15 @@ static void WriteTevRegular(ShaderCode& out, std::string_view components, int bi
|
||||
};
|
||||
|
||||
static constexpr std::array<const char*, 4> tev_bias_table{
|
||||
"", // ZERO,
|
||||
" + 128", // ADDHALF,
|
||||
" - 128", // SUBHALF,
|
||||
"", // Zero,
|
||||
" + 128", // AddHalf,
|
||||
" - 128", // SubHalf,
|
||||
"",
|
||||
};
|
||||
|
||||
static constexpr std::array<char, 2> tev_op_table{
|
||||
'+', // TEVOP_ADD = 0,
|
||||
'-', // TEVOP_SUB = 1,
|
||||
'+', // TevOp::Add = 0,
|
||||
'-', // TevOp::Sub = 1,
|
||||
};
|
||||
|
||||
// Regular TEV stage: (d + bias + lerp(a,b,c)) * scale
|
||||
@@ -1357,12 +1367,14 @@ static void WriteTevRegular(ShaderCode& out, std::string_view components, int bi
|
||||
// - c is scaled from 0..255 to 0..256, which allows dividing the result by 256 instead of 255
|
||||
// - if scale is bigger than one, it is moved inside the lerp calculation for increased accuracy
|
||||
// - a rounding bias is added before dividing by 256
|
||||
out.Write("(((tevin_d.{}{}){})", components, tev_bias_table[bias], tev_scale_table_left[shift]);
|
||||
out.Write(" {} ", tev_op_table[op]);
|
||||
out.Write("(((tevin_d.{}{}){})", components, tev_bias_table[u32(bias)],
|
||||
tev_scale_table_left[u32(scale)]);
|
||||
out.Write(" {} ", tev_op_table[u32(op)]);
|
||||
out.Write("(((((tevin_a.{}<<8) + (tevin_b.{}-tevin_a.{})*(tevin_c.{}+(tevin_c.{}>>7))){}){})>>8)",
|
||||
components, components, components, components, components, tev_scale_table_left[shift],
|
||||
tev_lerp_bias[2 * op + ((shift == 3) == alpha)]);
|
||||
out.Write("){}", tev_scale_table_right[shift]);
|
||||
components, components, components, components, components,
|
||||
tev_scale_table_left[u32(scale)],
|
||||
tev_lerp_bias[2 * u32(op) + ((scale == TevScale::Divide2) == alpha)]);
|
||||
out.Write("){}", tev_scale_table_right[u32(scale)]);
|
||||
}
|
||||
|
||||
static void SampleTexture(ShaderCode& out, std::string_view texcoords, std::string_view texswap,
|
||||
@@ -1384,14 +1396,14 @@ static void SampleTexture(ShaderCode& out, std::string_view texcoords, std::stri
|
||||
}
|
||||
|
||||
constexpr std::array<const char*, 8> tev_alpha_funcs_table{
|
||||
"(false)", // NEVER
|
||||
"(prev.a < {})", // LESS
|
||||
"(prev.a == {})", // EQUAL
|
||||
"(prev.a <= {})", // LEQUAL
|
||||
"(prev.a > {})", // GREATER
|
||||
"(prev.a != {})", // NEQUAL
|
||||
"(prev.a >= {})", // GEQUAL
|
||||
"(true)" // ALWAYS
|
||||
"(false)", // CompareMode::Never
|
||||
"(prev.a < {})", // CompareMode::Less
|
||||
"(prev.a == {})", // CompareMode::Equal
|
||||
"(prev.a <= {})", // CompareMode::LEqual
|
||||
"(prev.a > {})", // CompareMode::Greater
|
||||
"(prev.a != {})", // CompareMode::NEqual
|
||||
"(prev.a >= {})", // CompareMode::GEqual
|
||||
"(true)" // CompareMode::Always
|
||||
};
|
||||
|
||||
constexpr std::array<const char*, 4> tev_alpha_funclogic_table{
|
||||
@@ -1409,12 +1421,12 @@ static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_dat
|
||||
I_ALPHA ".g",
|
||||
};
|
||||
|
||||
const auto write_alpha_func = [&out](int index, std::string_view ref) {
|
||||
const bool has_no_arguments = index == 0 || index == tev_alpha_funcs_table.size() - 1;
|
||||
const auto write_alpha_func = [&out](CompareMode mode, std::string_view ref) {
|
||||
const bool has_no_arguments = mode == CompareMode::Never || mode == CompareMode::Always;
|
||||
if (has_no_arguments)
|
||||
out.Write("{}", tev_alpha_funcs_table[index]);
|
||||
out.Write("{}", tev_alpha_funcs_table[u32(mode)]);
|
||||
else
|
||||
out.Write(tev_alpha_funcs_table[index], ref);
|
||||
out.Write(tev_alpha_funcs_table[u32(mode)], ref);
|
||||
};
|
||||
|
||||
out.SetConstantsUsed(C_ALPHA, C_ALPHA);
|
||||
@@ -1425,15 +1437,13 @@ static void WriteAlphaTest(ShaderCode& out, const pixel_shader_uid_data* uid_dat
|
||||
out.Write("\tif(!( ");
|
||||
|
||||
// Lookup the first component from the alpha function table
|
||||
const int comp0_index = uid_data->alpha_test_comp0;
|
||||
write_alpha_func(comp0_index, alpha_ref[0]);
|
||||
write_alpha_func(uid_data->alpha_test_comp0, alpha_ref[0]);
|
||||
|
||||
// Lookup the logic op
|
||||
out.Write("{}", tev_alpha_funclogic_table[uid_data->alpha_test_logic]);
|
||||
out.Write("{}", tev_alpha_funclogic_table[u32(uid_data->alpha_test_logic)]);
|
||||
|
||||
// Lookup the second component from the alpha function table
|
||||
const int comp1_index = uid_data->alpha_test_comp1;
|
||||
write_alpha_func(comp1_index, alpha_ref[1]);
|
||||
write_alpha_func(uid_data->alpha_test_comp1, alpha_ref[1]);
|
||||
|
||||
if (DriverDetails::HasBug(DriverDetails::BUG_BROKEN_NEGATED_BOOLEAN))
|
||||
out.Write(") == false) {{\n");
|
||||
@@ -1473,13 +1483,13 @@ constexpr std::array<const char*, 8> tev_fog_funcs_table{
|
||||
|
||||
static void WriteFog(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||
{
|
||||
if (uid_data->fog_fsel == 0)
|
||||
if (uid_data->fog_fsel == FogType::Off)
|
||||
return; // no Fog
|
||||
|
||||
out.SetConstantsUsed(C_FOGCOLOR, C_FOGCOLOR);
|
||||
out.SetConstantsUsed(C_FOGI, C_FOGI);
|
||||
out.SetConstantsUsed(C_FOGF, C_FOGF + 1);
|
||||
if (uid_data->fog_proj == 0)
|
||||
if (uid_data->fog_proj == FogProjection::Perspective)
|
||||
{
|
||||
// perspective
|
||||
// ze = A/(B - (Zs >> B_SHF)
|
||||
@@ -1515,14 +1525,14 @@ static void WriteFog(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||
|
||||
out.Write("\tfloat fog = clamp(ze - " I_FOGF ".y, 0.0, 1.0);\n");
|
||||
|
||||
if (uid_data->fog_fsel > 3)
|
||||
if (uid_data->fog_fsel >= FogType::Exp)
|
||||
{
|
||||
out.Write("{}", tev_fog_funcs_table[uid_data->fog_fsel]);
|
||||
out.Write("{}", tev_fog_funcs_table[u32(uid_data->fog_fsel)]);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (uid_data->fog_fsel != 2)
|
||||
WARN_LOG_FMT(VIDEO, "Unknown Fog Type! {:08x}", uid_data->fog_fsel);
|
||||
if (uid_data->fog_fsel != FogType::Linear)
|
||||
WARN_LOG_FMT(VIDEO, "Unknown Fog Type! {}", uid_data->fog_fsel);
|
||||
}
|
||||
|
||||
out.Write("\tint ifog = iround(fog * 256.0);\n");
|
||||
@@ -1611,11 +1621,13 @@ static void WriteBlend(ShaderCode& out, const pixel_shader_uid_data* uid_data)
|
||||
"1.0 - initial_ocol0.a;", // INVDSTALPHA
|
||||
};
|
||||
out.Write("\tfloat4 blend_src;\n");
|
||||
out.Write("\tblend_src.rgb = {}\n", blend_src_factor[uid_data->blend_src_factor]);
|
||||
out.Write("\tblend_src.a = {}\n", blend_src_factor_alpha[uid_data->blend_src_factor_alpha]);
|
||||
out.Write("\tblend_src.rgb = {}\n", blend_src_factor[u32(uid_data->blend_src_factor)]);
|
||||
out.Write("\tblend_src.a = {}\n",
|
||||
blend_src_factor_alpha[u32(uid_data->blend_src_factor_alpha)]);
|
||||
out.Write("\tfloat4 blend_dst;\n");
|
||||
out.Write("\tblend_dst.rgb = {}\n", blend_dst_factor[uid_data->blend_dst_factor]);
|
||||
out.Write("\tblend_dst.a = {}\n", blend_dst_factor_alpha[uid_data->blend_dst_factor_alpha]);
|
||||
out.Write("\tblend_dst.rgb = {}\n", blend_dst_factor[u32(uid_data->blend_dst_factor)]);
|
||||
out.Write("\tblend_dst.a = {}\n",
|
||||
blend_dst_factor_alpha[u32(uid_data->blend_dst_factor_alpha)]);
|
||||
|
||||
out.Write("\tfloat4 blend_result;\n");
|
||||
if (uid_data->blend_subtract)
|
||||
|
||||
@@ -9,6 +9,15 @@
|
||||
#include "VideoCommon/ShaderGenCommon.h"
|
||||
|
||||
enum class APIType;
|
||||
enum class AlphaTestResult;
|
||||
enum class SrcBlendFactor : u32;
|
||||
enum class DstBlendFactor : u32;
|
||||
enum class CompareMode : u32;
|
||||
enum class AlphaTestOp : u32;
|
||||
enum class RasColorChan : u32;
|
||||
enum class KonstSel : u32;
|
||||
enum class FogProjection : u32;
|
||||
enum class FogType : u32;
|
||||
|
||||
#pragma pack(1)
|
||||
struct pixel_shader_uid_data
|
||||
@@ -19,18 +28,18 @@ struct pixel_shader_uid_data
|
||||
u32 NumValues() const { return num_values; }
|
||||
u32 pad0 : 4;
|
||||
u32 useDstAlpha : 1;
|
||||
u32 Pretest : 2;
|
||||
AlphaTestResult Pretest : 2;
|
||||
u32 nIndirectStagesUsed : 4;
|
||||
u32 genMode_numtexgens : 4;
|
||||
u32 genMode_numtevstages : 4;
|
||||
u32 genMode_numindstages : 3;
|
||||
u32 alpha_test_comp0 : 3;
|
||||
u32 alpha_test_comp1 : 3;
|
||||
u32 alpha_test_logic : 2;
|
||||
CompareMode alpha_test_comp0 : 3;
|
||||
CompareMode alpha_test_comp1 : 3;
|
||||
AlphaTestOp alpha_test_logic : 2;
|
||||
u32 alpha_test_use_zcomploc_hack : 1;
|
||||
u32 fog_proj : 1;
|
||||
FogProjection fog_proj : 1;
|
||||
|
||||
u32 fog_fsel : 3;
|
||||
FogType fog_fsel : 3;
|
||||
u32 fog_RangeBaseEnabled : 1;
|
||||
u32 ztex_op : 2;
|
||||
u32 per_pixel_depth : 1;
|
||||
@@ -43,13 +52,13 @@ struct pixel_shader_uid_data
|
||||
u32 rgba6_format : 1;
|
||||
u32 dither : 1;
|
||||
u32 uint_output : 1;
|
||||
u32 blend_enable : 1; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_src_factor : 3; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_src_factor_alpha : 3; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_dst_factor : 3; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_dst_factor_alpha : 3; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_subtract : 1; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_subtract_alpha : 1; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_enable : 1; // Only used with shader_framebuffer_fetch blend
|
||||
SrcBlendFactor blend_src_factor : 3; // Only used with shader_framebuffer_fetch blend
|
||||
SrcBlendFactor blend_src_factor_alpha : 3; // Only used with shader_framebuffer_fetch blend
|
||||
DstBlendFactor blend_dst_factor : 3; // Only used with shader_framebuffer_fetch blend
|
||||
DstBlendFactor blend_dst_factor_alpha : 3; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_subtract : 1; // Only used with shader_framebuffer_fetch blend
|
||||
u32 blend_subtract_alpha : 1; // Only used with shader_framebuffer_fetch blend
|
||||
|
||||
u32 texMtxInfo_n_projection : 8; // 8x1 bit
|
||||
u32 tevindref_bi0 : 3;
|
||||
@@ -136,7 +145,7 @@ struct pixel_shader_uid_data
|
||||
u32 tevorders_texmap : 3;
|
||||
u32 tevorders_texcoord : 3;
|
||||
u32 tevorders_enable : 1;
|
||||
u32 tevorders_colorchan : 3;
|
||||
RasColorChan tevorders_colorchan : 3;
|
||||
u32 pad1 : 6;
|
||||
|
||||
// TODO: Clean up the swapXY mess
|
||||
@@ -152,8 +161,8 @@ struct pixel_shader_uid_data
|
||||
u32 tevksel_swap2c : 2;
|
||||
u32 tevksel_swap1d : 2;
|
||||
u32 tevksel_swap2d : 2;
|
||||
u32 tevksel_kc : 5;
|
||||
u32 tevksel_ka : 5;
|
||||
KonstSel tevksel_kc : 5;
|
||||
KonstSel tevksel_ka : 5;
|
||||
u32 pad3 : 14;
|
||||
} stagehash[16];
|
||||
|
||||
|
||||
@@ -182,7 +182,7 @@ void PixelShaderManager::SetConstants()
|
||||
// Destination alpha is only enabled if alpha writes are enabled. Force entire uniform to zero
|
||||
// when disabled.
|
||||
u32 dstalpha = bpmem.blendmode.alphaupdate && bpmem.dstalpha.enable &&
|
||||
bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24 ?
|
||||
bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24 ?
|
||||
bpmem.dstalpha.hex :
|
||||
0;
|
||||
|
||||
@@ -270,7 +270,7 @@ void PixelShaderManager::SetAlphaTestChanged()
|
||||
// TODO: we could optimize this further and check the actual constants,
|
||||
// i.e. "a <= 0" and "a >= 255" will always pass.
|
||||
u32 alpha_test =
|
||||
bpmem.alpha_test.TestResult() != AlphaTest::PASS ? bpmem.alpha_test.hex | 1 << 31 : 0;
|
||||
bpmem.alpha_test.TestResult() != AlphaTestResult::Pass ? bpmem.alpha_test.hex | 1 << 31 : 0;
|
||||
if (constants.alphaTest != alpha_test)
|
||||
{
|
||||
constants.alphaTest = alpha_test;
|
||||
@@ -362,25 +362,26 @@ void PixelShaderManager::SetZTextureTypeChanged()
|
||||
{
|
||||
switch (bpmem.ztex2.type)
|
||||
{
|
||||
case TEV_ZTEX_TYPE_U8:
|
||||
case ZTexFormat::U8:
|
||||
constants.zbias[0][0] = 0;
|
||||
constants.zbias[0][1] = 0;
|
||||
constants.zbias[0][2] = 0;
|
||||
constants.zbias[0][3] = 1;
|
||||
break;
|
||||
case TEV_ZTEX_TYPE_U16:
|
||||
case ZTexFormat::U16:
|
||||
constants.zbias[0][0] = 1;
|
||||
constants.zbias[0][1] = 0;
|
||||
constants.zbias[0][2] = 0;
|
||||
constants.zbias[0][3] = 256;
|
||||
break;
|
||||
case TEV_ZTEX_TYPE_U24:
|
||||
case ZTexFormat::U24:
|
||||
constants.zbias[0][0] = 65536;
|
||||
constants.zbias[0][1] = 256;
|
||||
constants.zbias[0][2] = 1;
|
||||
constants.zbias[0][3] = 0;
|
||||
break;
|
||||
default:
|
||||
PanicAlertFmt("Invalid ztex format {}", bpmem.ztex2.type);
|
||||
break;
|
||||
}
|
||||
dirty = true;
|
||||
@@ -457,8 +458,9 @@ void PixelShaderManager::SetZModeControl()
|
||||
{
|
||||
u32 late_ztest = bpmem.UseLateDepthTest();
|
||||
u32 rgba6_format =
|
||||
(bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor) ? 1 :
|
||||
0;
|
||||
(bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24 && !g_ActiveConfig.bForceTrueColor) ?
|
||||
1 :
|
||||
0;
|
||||
u32 dither = rgba6_format && bpmem.blendmode.dither;
|
||||
if (constants.late_ztest != late_ztest || constants.rgba6_format != rgba6_format ||
|
||||
constants.dither != dither)
|
||||
|
||||
@@ -171,7 +171,7 @@ void Renderer::SetAndClearFramebuffer(AbstractFramebuffer* framebuffer,
|
||||
|
||||
bool Renderer::EFBHasAlphaChannel() const
|
||||
{
|
||||
return m_prev_efb_format == PEControl::RGBA6_Z24;
|
||||
return m_prev_efb_format == PixelFormat::RGBA6_Z24;
|
||||
}
|
||||
|
||||
void Renderer::ClearScreen(const MathUtil::Rectangle<int>& rc, bool colorEnable, bool alphaEnable,
|
||||
@@ -197,15 +197,15 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||
// check what to do with the alpha channel (GX_PokeAlphaRead)
|
||||
PixelEngine::UPEAlphaReadReg alpha_read_mode = PixelEngine::GetAlphaReadMode();
|
||||
|
||||
if (bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24)
|
||||
if (bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24)
|
||||
{
|
||||
color = RGBA8ToRGBA6ToRGBA8(color);
|
||||
}
|
||||
else if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16)
|
||||
else if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
|
||||
{
|
||||
color = RGBA8ToRGB565ToRGBA8(color);
|
||||
}
|
||||
if (bpmem.zcontrol.pixel_format != PEControl::RGBA6_Z24)
|
||||
if (bpmem.zcontrol.pixel_format != PixelFormat::RGBA6_Z24)
|
||||
{
|
||||
color |= 0xFF000000;
|
||||
}
|
||||
@@ -231,7 +231,7 @@ u32 Renderer::AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data)
|
||||
depth = 1.0f - depth;
|
||||
|
||||
u32 ret = 0;
|
||||
if (bpmem.zcontrol.pixel_format == PEControl::RGB565_Z16)
|
||||
if (bpmem.zcontrol.pixel_format == PixelFormat::RGB565_Z16)
|
||||
{
|
||||
// if Z is in 16 bit format you must return a 16 bit integer
|
||||
ret = std::clamp<u32>(static_cast<u32>(depth * 65536.0f), 0, 0xFFFF);
|
||||
@@ -994,10 +994,10 @@ bool Renderer::RecompileImGuiPipeline()
|
||||
pconfig.depth_state = RenderState::GetNoDepthTestingDepthState();
|
||||
pconfig.blending_state = RenderState::GetNoBlendingBlendState();
|
||||
pconfig.blending_state.blendenable = true;
|
||||
pconfig.blending_state.srcfactor = BlendMode::SRCALPHA;
|
||||
pconfig.blending_state.dstfactor = BlendMode::INVSRCALPHA;
|
||||
pconfig.blending_state.srcfactoralpha = BlendMode::ZERO;
|
||||
pconfig.blending_state.dstfactoralpha = BlendMode::ONE;
|
||||
pconfig.blending_state.srcfactor = SrcBlendFactor::SrcAlpha;
|
||||
pconfig.blending_state.dstfactor = DstBlendFactor::InvSrcAlpha;
|
||||
pconfig.blending_state.srcfactoralpha = SrcBlendFactor::Zero;
|
||||
pconfig.blending_state.dstfactoralpha = DstBlendFactor::One;
|
||||
pconfig.framebuffer_state.color_texture_format = m_backbuffer_format;
|
||||
pconfig.framebuffer_state.depth_texture_format = AbstractTextureFormat::Undefined;
|
||||
pconfig.framebuffer_state.samples = 1;
|
||||
@@ -1697,7 +1697,7 @@ bool Renderer::UseVertexDepthRange() const
|
||||
return false;
|
||||
|
||||
// We need a full depth range if a ztexture is used.
|
||||
if (bpmem.ztex2.op != ZTEXTURE_DISABLE && !bpmem.zcontrol.early_ztest)
|
||||
if (bpmem.ztex2.op != ZTexOp::Disabled && !bpmem.zcontrol.early_ztest)
|
||||
return true;
|
||||
|
||||
// If an inverted depth range is unsupported, we also need to check if the range is inverted.
|
||||
|
||||
@@ -232,8 +232,8 @@ public:
|
||||
// Called when the configuration changes, and backend structures need to be updated.
|
||||
virtual void OnConfigChanged(u32 bits) {}
|
||||
|
||||
PEControl::PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; }
|
||||
void StorePixelFormat(PEControl::PixelFormat new_format) { m_prev_efb_format = new_format; }
|
||||
PixelFormat GetPrevPixelFormat() const { return m_prev_efb_format; }
|
||||
void StorePixelFormat(PixelFormat new_format) { m_prev_efb_format = new_format; }
|
||||
bool EFBHasAlphaChannel() const;
|
||||
VideoCommon::PostProcessing* GetPostProcessor() const { return m_post_processor.get(); }
|
||||
// Final surface changing
|
||||
@@ -343,7 +343,7 @@ protected:
|
||||
private:
|
||||
std::tuple<int, int> CalculateOutputDimensions(int width, int height) const;
|
||||
|
||||
PEControl::PixelFormat m_prev_efb_format = PEControl::INVALID_FMT;
|
||||
PixelFormat m_prev_efb_format = PixelFormat::INVALID_FMT;
|
||||
unsigned int m_efb_scale = 1;
|
||||
|
||||
// These will be set on the first call to SetWindowSize.
|
||||
|
||||
@@ -15,7 +15,7 @@ void RasterizationState::Generate(const BPMemory& bp, PrimitiveType primitive_ty
|
||||
|
||||
// Back-face culling should be disabled for points/lines.
|
||||
if (primitive_type != PrimitiveType::Triangles && primitive_type != PrimitiveType::TriangleStrip)
|
||||
cullmode = GenMode::CULL_NONE;
|
||||
cullmode = CullMode::None;
|
||||
}
|
||||
|
||||
RasterizationState& RasterizationState::operator=(const RasterizationState& rhs)
|
||||
@@ -47,14 +47,27 @@ DepthState& DepthState::operator=(const DepthState& rhs)
|
||||
// ONE on blending. As the backends may emulate this framebuffer
|
||||
// configuration with an alpha channel, we just drop all references
|
||||
// to the destination alpha channel.
|
||||
static BlendMode::BlendFactor RemoveDstAlphaUsage(BlendMode::BlendFactor factor)
|
||||
static SrcBlendFactor RemoveDstAlphaUsage(SrcBlendFactor factor)
|
||||
{
|
||||
switch (factor)
|
||||
{
|
||||
case BlendMode::DSTALPHA:
|
||||
return BlendMode::ONE;
|
||||
case BlendMode::INVDSTALPHA:
|
||||
return BlendMode::ZERO;
|
||||
case SrcBlendFactor::DstAlpha:
|
||||
return SrcBlendFactor::One;
|
||||
case SrcBlendFactor::InvDstAlpha:
|
||||
return SrcBlendFactor::Zero;
|
||||
default:
|
||||
return factor;
|
||||
}
|
||||
}
|
||||
|
||||
static DstBlendFactor RemoveDstAlphaUsage(DstBlendFactor factor)
|
||||
{
|
||||
switch (factor)
|
||||
{
|
||||
case DstBlendFactor::DstAlpha:
|
||||
return DstBlendFactor::One;
|
||||
case DstBlendFactor::InvDstAlpha:
|
||||
return DstBlendFactor::Zero;
|
||||
default:
|
||||
return factor;
|
||||
}
|
||||
@@ -64,14 +77,14 @@ static BlendMode::BlendFactor RemoveDstAlphaUsage(BlendMode::BlendFactor factor)
|
||||
// the alpha component, CLR and ALPHA are indentical. So just always
|
||||
// use ALPHA as this makes it easier for the backends to use the second
|
||||
// alpha value of dual source blending.
|
||||
static BlendMode::BlendFactor RemoveSrcColorUsage(BlendMode::BlendFactor factor)
|
||||
static DstBlendFactor RemoveSrcColorUsage(DstBlendFactor factor)
|
||||
{
|
||||
switch (factor)
|
||||
{
|
||||
case BlendMode::SRCCLR:
|
||||
return BlendMode::SRCALPHA;
|
||||
case BlendMode::INVSRCCLR:
|
||||
return BlendMode::INVSRCALPHA;
|
||||
case DstBlendFactor::SrcClr:
|
||||
return DstBlendFactor::SrcAlpha;
|
||||
case DstBlendFactor::InvSrcClr:
|
||||
return DstBlendFactor::InvSrcAlpha;
|
||||
default:
|
||||
return factor;
|
||||
}
|
||||
@@ -79,14 +92,14 @@ static BlendMode::BlendFactor RemoveSrcColorUsage(BlendMode::BlendFactor factor)
|
||||
|
||||
// Same as RemoveSrcColorUsage, but because of the overlapping enum,
|
||||
// this must be written as another function.
|
||||
static BlendMode::BlendFactor RemoveDstColorUsage(BlendMode::BlendFactor factor)
|
||||
static SrcBlendFactor RemoveDstColorUsage(SrcBlendFactor factor)
|
||||
{
|
||||
switch (factor)
|
||||
{
|
||||
case BlendMode::DSTCLR:
|
||||
return BlendMode::DSTALPHA;
|
||||
case BlendMode::INVDSTCLR:
|
||||
return BlendMode::INVDSTALPHA;
|
||||
case SrcBlendFactor::DstClr:
|
||||
return SrcBlendFactor::DstAlpha;
|
||||
case SrcBlendFactor::InvDstClr:
|
||||
return SrcBlendFactor::InvDstAlpha;
|
||||
default:
|
||||
return factor;
|
||||
}
|
||||
@@ -97,11 +110,11 @@ void BlendingState::Generate(const BPMemory& bp)
|
||||
// Start with everything disabled.
|
||||
hex = 0;
|
||||
|
||||
bool target_has_alpha = bp.zcontrol.pixel_format == PEControl::RGBA6_Z24;
|
||||
bool alpha_test_may_success = bp.alpha_test.TestResult() != AlphaTest::FAIL;
|
||||
bool target_has_alpha = bp.zcontrol.pixel_format == PixelFormat::RGBA6_Z24;
|
||||
bool alpha_test_may_succeed = bp.alpha_test.TestResult() != AlphaTestResult::Fail;
|
||||
|
||||
colorupdate = bp.blendmode.colorupdate && alpha_test_may_success;
|
||||
alphaupdate = bp.blendmode.alphaupdate && target_has_alpha && alpha_test_may_success;
|
||||
colorupdate = bp.blendmode.colorupdate && alpha_test_may_succeed;
|
||||
alphaupdate = bp.blendmode.alphaupdate && target_has_alpha && alpha_test_may_succeed;
|
||||
dstalpha = bp.dstalpha.enable && alphaupdate;
|
||||
usedualsrc = true;
|
||||
|
||||
@@ -110,14 +123,14 @@ void BlendingState::Generate(const BPMemory& bp)
|
||||
{
|
||||
blendenable = true;
|
||||
subtractAlpha = subtract = true;
|
||||
srcfactoralpha = srcfactor = BlendMode::ONE;
|
||||
dstfactoralpha = dstfactor = BlendMode::ONE;
|
||||
srcfactoralpha = srcfactor = SrcBlendFactor::One;
|
||||
dstfactoralpha = dstfactor = DstBlendFactor::One;
|
||||
|
||||
if (dstalpha)
|
||||
{
|
||||
subtractAlpha = false;
|
||||
srcfactoralpha = BlendMode::ONE;
|
||||
dstfactoralpha = BlendMode::ZERO;
|
||||
srcfactoralpha = SrcBlendFactor::One;
|
||||
dstfactoralpha = DstBlendFactor::Zero;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -133,22 +146,22 @@ void BlendingState::Generate(const BPMemory& bp)
|
||||
srcfactor = RemoveDstAlphaUsage(srcfactor);
|
||||
dstfactor = RemoveDstAlphaUsage(dstfactor);
|
||||
}
|
||||
// replaces SRCCLR with SRCALPHA and DSTCLR with DSTALPHA, it is important to
|
||||
// replaces SrcClr with SrcAlpha and DstClr with DstAlpha, it is important to
|
||||
// use the dst function for the src factor and vice versa
|
||||
srcfactoralpha = RemoveDstColorUsage(srcfactor);
|
||||
dstfactoralpha = RemoveSrcColorUsage(dstfactor);
|
||||
|
||||
if (dstalpha)
|
||||
{
|
||||
srcfactoralpha = BlendMode::ONE;
|
||||
dstfactoralpha = BlendMode::ZERO;
|
||||
srcfactoralpha = SrcBlendFactor::One;
|
||||
dstfactoralpha = DstBlendFactor::Zero;
|
||||
}
|
||||
}
|
||||
|
||||
// The logicop bit has the lowest priority
|
||||
else if (bp.blendmode.logicopenable)
|
||||
{
|
||||
if (bp.blendmode.logicmode == BlendMode::NOOP)
|
||||
if (bp.blendmode.logicmode == LogicOp::NoOp)
|
||||
{
|
||||
// Fast path for Kirby's Return to Dreamland, they use it with dstAlpha.
|
||||
colorupdate = false;
|
||||
@@ -169,38 +182,39 @@ void BlendingState::Generate(const BPMemory& bp)
|
||||
|
||||
void BlendingState::ApproximateLogicOpWithBlending()
|
||||
{
|
||||
// Any of these which use SRC as srcFactor or DST as dstFactor won't be correct.
|
||||
// This is because the two are aliased to one another (see the enum).
|
||||
struct LogicOpApproximation
|
||||
{
|
||||
bool subtract;
|
||||
BlendMode::BlendFactor srcfactor;
|
||||
BlendMode::BlendFactor dstfactor;
|
||||
SrcBlendFactor srcfactor;
|
||||
DstBlendFactor dstfactor;
|
||||
};
|
||||
// TODO: This previously had a warning about SRC and DST being aliased and not to mix them,
|
||||
// but INVSRCCLR and INVDSTCLR were also aliased and were mixed.
|
||||
// Thus, NOR, EQUIV, INVERT, COPY_INVERTED, and OR_INVERTED duplicate(d) other values.
|
||||
static constexpr std::array<LogicOpApproximation, 16> approximations = {{
|
||||
{false, BlendMode::ZERO, BlendMode::ZERO}, // CLEAR
|
||||
{false, BlendMode::DSTCLR, BlendMode::ZERO}, // AND
|
||||
{true, BlendMode::ONE, BlendMode::INVSRCCLR}, // AND_REVERSE
|
||||
{false, BlendMode::ONE, BlendMode::ZERO}, // COPY
|
||||
{true, BlendMode::DSTCLR, BlendMode::ONE}, // AND_INVERTED
|
||||
{false, BlendMode::ZERO, BlendMode::ONE}, // NOOP
|
||||
{false, BlendMode::INVDSTCLR, BlendMode::INVSRCCLR}, // XOR
|
||||
{false, BlendMode::INVDSTCLR, BlendMode::ONE}, // OR
|
||||
{false, BlendMode::INVSRCCLR, BlendMode::INVDSTCLR}, // NOR
|
||||
{false, BlendMode::INVSRCCLR, BlendMode::ZERO}, // EQUIV
|
||||
{false, BlendMode::INVDSTCLR, BlendMode::INVDSTCLR}, // INVERT
|
||||
{false, BlendMode::ONE, BlendMode::INVDSTALPHA}, // OR_REVERSE
|
||||
{false, BlendMode::INVSRCCLR, BlendMode::INVSRCCLR}, // COPY_INVERTED
|
||||
{false, BlendMode::INVSRCCLR, BlendMode::ONE}, // OR_INVERTED
|
||||
{false, BlendMode::INVDSTCLR, BlendMode::INVSRCCLR}, // NAND
|
||||
{false, BlendMode::ONE, BlendMode::ONE}, // SET
|
||||
{false, SrcBlendFactor::Zero, DstBlendFactor::Zero}, // CLEAR
|
||||
{false, SrcBlendFactor::DstClr, DstBlendFactor::Zero}, // AND
|
||||
{true, SrcBlendFactor::One, DstBlendFactor::InvSrcClr}, // AND_REVERSE
|
||||
{false, SrcBlendFactor::One, DstBlendFactor::Zero}, // COPY
|
||||
{true, SrcBlendFactor::DstClr, DstBlendFactor::One}, // AND_INVERTED
|
||||
{false, SrcBlendFactor::Zero, DstBlendFactor::One}, // NOOP
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::InvSrcClr}, // XOR
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::One}, // OR
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::InvSrcClr}, // NOR
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::Zero}, // EQUIV
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::InvSrcClr}, // INVERT
|
||||
{false, SrcBlendFactor::One, DstBlendFactor::InvDstAlpha}, // OR_REVERSE
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::InvSrcClr}, // COPY_INVERTED
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::One}, // OR_INVERTED
|
||||
{false, SrcBlendFactor::InvDstClr, DstBlendFactor::InvSrcClr}, // NAND
|
||||
{false, SrcBlendFactor::One, DstBlendFactor::One}, // SET
|
||||
}};
|
||||
|
||||
logicopenable = false;
|
||||
blendenable = true;
|
||||
subtract = approximations[logicmode].subtract;
|
||||
srcfactor = approximations[logicmode].srcfactor;
|
||||
dstfactor = approximations[logicmode].dstfactor;
|
||||
subtract = approximations[u32(logicmode.Value())].subtract;
|
||||
srcfactor = approximations[u32(logicmode.Value())].srcfactor;
|
||||
dstfactor = approximations[u32(logicmode.Value())].dstfactor;
|
||||
}
|
||||
|
||||
BlendingState& BlendingState::operator=(const BlendingState& rhs)
|
||||
@@ -217,20 +231,20 @@ void SamplerState::Generate(const BPMemory& bp, u32 index)
|
||||
|
||||
// GX can configure the mip filter to none. However, D3D and Vulkan can't express this in their
|
||||
// sampler states. Therefore, we set the min/max LOD to zero if this option is used.
|
||||
min_filter = (tm0.min_filter & 4) != 0 ? Filter::Linear : Filter::Point;
|
||||
mipmap_filter = (tm0.min_filter & 3) == TexMode0::TEXF_LINEAR ? Filter::Linear : Filter::Point;
|
||||
mag_filter = tm0.mag_filter != 0 ? Filter::Linear : Filter::Point;
|
||||
min_filter = tm0.min_filter == FilterMode::Linear ? Filter::Linear : Filter::Point;
|
||||
mipmap_filter = tm0.mipmap_filter == MipMode::Linear ? Filter::Linear : Filter::Point;
|
||||
mag_filter = tm0.mag_filter == FilterMode::Linear ? Filter::Linear : Filter::Point;
|
||||
|
||||
// If mipmaps are disabled, clamp min/max lod
|
||||
max_lod = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm1.max_lod : 0;
|
||||
max_lod = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm1.max_lod.Value() : 0;
|
||||
min_lod = std::min(max_lod.Value(), static_cast<u64>(tm1.min_lod));
|
||||
lod_bias = SamplerCommon::AreBpTexMode0MipmapsEnabled(tm0) ? tm0.lod_bias * (256 / 32) : 0;
|
||||
|
||||
// Address modes
|
||||
static constexpr std::array<AddressMode, 4> address_modes = {
|
||||
{AddressMode::Clamp, AddressMode::Repeat, AddressMode::MirroredRepeat, AddressMode::Repeat}};
|
||||
wrap_u = address_modes[tm0.wrap_s];
|
||||
wrap_v = address_modes[tm0.wrap_t];
|
||||
wrap_u = address_modes[u32(tm0.wrap_s.Value())];
|
||||
wrap_v = address_modes[u32(tm0.wrap_t.Value())];
|
||||
anisotropic_filtering = 0;
|
||||
}
|
||||
|
||||
@@ -252,7 +266,7 @@ RasterizationState GetInvalidRasterizationState()
|
||||
RasterizationState GetNoCullRasterizationState(PrimitiveType primitive)
|
||||
{
|
||||
RasterizationState state = {};
|
||||
state.cullmode = GenMode::CULL_NONE;
|
||||
state.cullmode = CullMode::None;
|
||||
state.primitive = primitive;
|
||||
return state;
|
||||
}
|
||||
@@ -260,7 +274,7 @@ RasterizationState GetNoCullRasterizationState(PrimitiveType primitive)
|
||||
RasterizationState GetCullBackFaceRasterizationState(PrimitiveType primitive)
|
||||
{
|
||||
RasterizationState state = {};
|
||||
state.cullmode = GenMode::CULL_BACK;
|
||||
state.cullmode = CullMode::Back;
|
||||
state.primitive = primitive;
|
||||
return state;
|
||||
}
|
||||
@@ -277,7 +291,7 @@ DepthState GetNoDepthTestingDepthState()
|
||||
DepthState state = {};
|
||||
state.testenable = false;
|
||||
state.updateenable = false;
|
||||
state.func = ZMode::ALWAYS;
|
||||
state.func = CompareMode::Always;
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -286,7 +300,7 @@ DepthState GetAlwaysWriteDepthState()
|
||||
DepthState state = {};
|
||||
state.testenable = true;
|
||||
state.updateenable = true;
|
||||
state.func = ZMode::ALWAYS;
|
||||
state.func = CompareMode::Always;
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -302,10 +316,10 @@ BlendingState GetNoBlendingBlendState()
|
||||
BlendingState state = {};
|
||||
state.usedualsrc = false;
|
||||
state.blendenable = false;
|
||||
state.srcfactor = BlendMode::ONE;
|
||||
state.srcfactoralpha = BlendMode::ONE;
|
||||
state.dstfactor = BlendMode::ZERO;
|
||||
state.dstfactoralpha = BlendMode::ZERO;
|
||||
state.srcfactor = SrcBlendFactor::One;
|
||||
state.srcfactoralpha = SrcBlendFactor::One;
|
||||
state.dstfactor = DstBlendFactor::Zero;
|
||||
state.dstfactoralpha = DstBlendFactor::Zero;
|
||||
state.logicopenable = false;
|
||||
state.colorupdate = true;
|
||||
state.alphaupdate = true;
|
||||
@@ -317,10 +331,10 @@ BlendingState GetNoColorWriteBlendState()
|
||||
BlendingState state = {};
|
||||
state.usedualsrc = false;
|
||||
state.blendenable = false;
|
||||
state.srcfactor = BlendMode::ONE;
|
||||
state.srcfactoralpha = BlendMode::ONE;
|
||||
state.dstfactor = BlendMode::ZERO;
|
||||
state.dstfactoralpha = BlendMode::ZERO;
|
||||
state.srcfactor = SrcBlendFactor::One;
|
||||
state.srcfactoralpha = SrcBlendFactor::One;
|
||||
state.dstfactor = DstBlendFactor::Zero;
|
||||
state.dstfactoralpha = DstBlendFactor::Zero;
|
||||
state.logicopenable = false;
|
||||
state.colorupdate = false;
|
||||
state.alphaupdate = false;
|
||||
|
||||
@@ -28,7 +28,7 @@ union RasterizationState
|
||||
bool operator==(const RasterizationState& rhs) const { return hex == rhs.hex; }
|
||||
bool operator!=(const RasterizationState& rhs) const { return hex != rhs.hex; }
|
||||
bool operator<(const RasterizationState& rhs) const { return hex < rhs.hex; }
|
||||
BitField<0, 2, GenMode::CullMode> cullmode;
|
||||
BitField<0, 2, CullMode> cullmode;
|
||||
BitField<3, 2, PrimitiveType> primitive;
|
||||
|
||||
u32 hex;
|
||||
@@ -59,7 +59,7 @@ union DepthState
|
||||
bool operator<(const DepthState& rhs) const { return hex < rhs.hex; }
|
||||
BitField<0, 1, u32> testenable;
|
||||
BitField<1, 1, u32> updateenable;
|
||||
BitField<2, 3, ZMode::CompareMode> func;
|
||||
BitField<2, 3, CompareMode> func;
|
||||
|
||||
u32 hex;
|
||||
};
|
||||
@@ -85,11 +85,11 @@ union BlendingState
|
||||
BitField<5, 1, u32> subtract;
|
||||
BitField<6, 1, u32> subtractAlpha;
|
||||
BitField<7, 1, u32> usedualsrc;
|
||||
BitField<8, 3, BlendMode::BlendFactor> dstfactor;
|
||||
BitField<11, 3, BlendMode::BlendFactor> srcfactor;
|
||||
BitField<14, 3, BlendMode::BlendFactor> dstfactoralpha;
|
||||
BitField<17, 3, BlendMode::BlendFactor> srcfactoralpha;
|
||||
BitField<20, 4, BlendMode::LogicOp> logicmode;
|
||||
BitField<8, 3, DstBlendFactor> dstfactor;
|
||||
BitField<11, 3, SrcBlendFactor> srcfactor;
|
||||
BitField<14, 3, DstBlendFactor> dstfactoralpha;
|
||||
BitField<17, 3, SrcBlendFactor> srcfactoralpha;
|
||||
BitField<20, 4, LogicOp> logicmode;
|
||||
|
||||
u32 hex;
|
||||
};
|
||||
|
||||
@@ -16,13 +16,13 @@ namespace SamplerCommon
|
||||
template <class T>
|
||||
constexpr bool IsBpTexMode0PointFiltering(const T& tm0)
|
||||
{
|
||||
return tm0.min_filter < 4 && !tm0.mag_filter;
|
||||
return tm0.min_filter == FilterMode::Near && tm0.mag_filter == FilterMode::Near;
|
||||
}
|
||||
|
||||
// Check if the minification filter has mipmap based filtering modes enabled.
|
||||
template <class T>
|
||||
constexpr bool AreBpTexMode0MipmapsEnabled(const T& tm0)
|
||||
{
|
||||
return (tm0.min_filter & 3) != 0;
|
||||
return tm0.mipmap_filter != MipMode::None;
|
||||
}
|
||||
} // namespace SamplerCommon
|
||||
|
||||
@@ -1115,7 +1115,7 @@ void ShaderCache::QueueUberShaderPipelines()
|
||||
{
|
||||
// uint_output is only ever enabled when logic ops are enabled.
|
||||
config.blending_state.logicopenable = true;
|
||||
config.blending_state.logicmode = BlendMode::AND;
|
||||
config.blending_state.logicmode = LogicOp::And;
|
||||
}
|
||||
|
||||
auto iter = m_gx_uber_pipeline_cache.find(config);
|
||||
|
||||
@@ -1187,12 +1187,12 @@ TextureCacheBase::TCacheEntry* TextureCacheBase::Load(const u32 stage)
|
||||
const u32 address = (tex.texImage3[id].image_base /* & 0x1FFFFF*/) << 5;
|
||||
u32 width = tex.texImage0[id].width + 1;
|
||||
u32 height = tex.texImage0[id].height + 1;
|
||||
const TextureFormat texformat = static_cast<TextureFormat>(tex.texImage0[id].format);
|
||||
const TextureFormat texformat = tex.texImage0[id].format;
|
||||
const u32 tlutaddr = tex.texTlut[id].tmem_offset << 9;
|
||||
const TLUTFormat tlutfmt = static_cast<TLUTFormat>(tex.texTlut[id].tlut_format);
|
||||
const TLUTFormat tlutfmt = tex.texTlut[id].tlut_format;
|
||||
const bool use_mipmaps = SamplerCommon::AreBpTexMode0MipmapsEnabled(tex.texMode0[id]);
|
||||
u32 tex_levels = use_mipmaps ? ((tex.texMode1[id].max_lod + 0xf) / 0x10 + 1) : 1;
|
||||
const bool from_tmem = tex.texImage1[id].image_type != 0;
|
||||
const bool from_tmem = tex.texImage1[id].cache_manually_managed != 0;
|
||||
const u32 tmem_address_even = from_tmem ? tex.texImage1[id].tmem_even * TMEM_LINE_SIZE : 0;
|
||||
const u32 tmem_address_odd = from_tmem ? tex.texImage2[id].tmem_odd * TMEM_LINE_SIZE : 0;
|
||||
|
||||
@@ -2204,7 +2204,7 @@ void TextureCacheBase::CopyRenderTargetToTexture(
|
||||
if (copy_to_ram)
|
||||
{
|
||||
EFBCopyFilterCoefficients coefficients = GetRAMCopyFilterCoefficients(filter_coefficients);
|
||||
PEControl::PixelFormat srcFormat = bpmem.zcontrol.pixel_format;
|
||||
PixelFormat srcFormat = bpmem.zcontrol.pixel_format;
|
||||
EFBCopyParams format(srcFormat, dstFormat, is_depth_copy, isIntensity,
|
||||
NeedsCopyFilterInShader(coefficients));
|
||||
|
||||
|
||||
@@ -50,8 +50,8 @@ struct TextureAndTLUTFormat
|
||||
|
||||
struct EFBCopyParams
|
||||
{
|
||||
EFBCopyParams(PEControl::PixelFormat efb_format_, EFBCopyFormat copy_format_, bool depth_,
|
||||
bool yuv_, bool copy_filter_)
|
||||
EFBCopyParams(PixelFormat efb_format_, EFBCopyFormat copy_format_, bool depth_, bool yuv_,
|
||||
bool copy_filter_)
|
||||
: efb_format(efb_format_), copy_format(copy_format_), depth(depth_), yuv(yuv_),
|
||||
copy_filter(copy_filter_)
|
||||
{
|
||||
@@ -63,7 +63,7 @@ struct EFBCopyParams
|
||||
std::tie(rhs.efb_format, rhs.copy_format, rhs.depth, rhs.yuv, rhs.copy_filter);
|
||||
}
|
||||
|
||||
PEControl::PixelFormat efb_format;
|
||||
PixelFormat efb_format;
|
||||
EFBCopyFormat copy_format;
|
||||
bool depth;
|
||||
bool yuv;
|
||||
|
||||
@@ -127,13 +127,13 @@ static void WriteSampleFunction(ShaderCode& code, const EFBCopyParams& params, A
|
||||
{
|
||||
switch (params.efb_format)
|
||||
{
|
||||
case PEControl::RGB8_Z24:
|
||||
case PixelFormat::RGB8_Z24:
|
||||
code.Write("RGBA8ToRGB8(");
|
||||
break;
|
||||
case PEControl::RGBA6_Z24:
|
||||
case PixelFormat::RGBA6_Z24:
|
||||
code.Write("RGBA8ToRGBA6(");
|
||||
break;
|
||||
case PEControl::RGB565_Z16:
|
||||
case PixelFormat::RGB565_Z16:
|
||||
code.Write("RGBA8ToRGB565(");
|
||||
break;
|
||||
default:
|
||||
|
||||
@@ -19,7 +19,7 @@ TCShaderUid GetShaderUid(EFBCopyFormat dst_format, bool is_depth_copy, bool is_i
|
||||
|
||||
UidData* const uid_data = out.GetUidData();
|
||||
uid_data->dst_format = dst_format;
|
||||
uid_data->efb_has_alpha = bpmem.zcontrol.pixel_format == PEControl::RGBA6_Z24;
|
||||
uid_data->efb_has_alpha = bpmem.zcontrol.pixel_format == PixelFormat::RGBA6_Z24;
|
||||
uid_data->is_depth_copy = is_depth_copy;
|
||||
uid_data->is_intensity = is_intensity;
|
||||
uid_data->scale_by_half = scale_by_half;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include <tuple>
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/EnumFormatter.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@@ -32,8 +33,17 @@ enum class TextureFormat
|
||||
// Special texture format used to represent YUVY xfb copies.
|
||||
// They aren't really textures, but they share so much hardware and usecases that it makes sense
|
||||
// to emulate them as part of texture cache.
|
||||
// This isn't a real value that can be used on console; it only exists for ease of implementation.
|
||||
XFB = 0xF,
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<TextureFormat> : EnumFormatter<TextureFormat::CMPR>
|
||||
{
|
||||
static constexpr array_type names = {"I4", "I8", "IA4", "IA8", "RGB565",
|
||||
"RGB5A3", "RGBA8", nullptr, "C4", "C8",
|
||||
"C14X2", nullptr, nullptr, nullptr, "CMPR"};
|
||||
formatter() : EnumFormatter(names) {}
|
||||
};
|
||||
|
||||
static inline bool IsColorIndexed(TextureFormat format)
|
||||
{
|
||||
@@ -82,8 +92,20 @@ enum class EFBCopyFormat
|
||||
// Special texture format used to represent YUVY xfb copies.
|
||||
// They aren't really textures, but they share so much hardware and usecases that it makes sense
|
||||
// to emulate them as part of texture cache.
|
||||
// This isn't a real value that can be used on console; it only exists for ease of implementation.
|
||||
XFB = 0xF,
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<EFBCopyFormat> : EnumFormatter<EFBCopyFormat::GB8>
|
||||
{
|
||||
static constexpr array_type names = {
|
||||
"R4/I4/Z4", "R8/I8/Z8H (?)", "RA4/IA4", "RA8/IA8 (Z16 too?)",
|
||||
"RGB565", "RGB5A3", "RGBA8", "A8",
|
||||
"R8/I8/Z8H", "G8/Z8M", "B8/Z8L", "RG8/Z16R (Note: G and R are reversed)",
|
||||
"GB8/Z16L",
|
||||
};
|
||||
formatter() : EnumFormatter(names) {}
|
||||
};
|
||||
|
||||
enum class TLUTFormat
|
||||
{
|
||||
@@ -92,6 +114,11 @@ enum class TLUTFormat
|
||||
RGB565 = 0x1,
|
||||
RGB5A3 = 0x2,
|
||||
};
|
||||
template <>
|
||||
struct fmt::formatter<TLUTFormat> : EnumFormatter<TLUTFormat::RGB5A3>
|
||||
{
|
||||
formatter() : EnumFormatter({"IA8", "RGB565", "RGB5A3"}) {}
|
||||
};
|
||||
|
||||
static inline bool IsValidTLUTFormat(TLUTFormat tlutfmt)
|
||||
{
|
||||
|
||||
@@ -22,12 +22,12 @@ PixelShaderUid GetPixelShaderUid()
|
||||
|
||||
pixel_ubershader_uid_data* const uid_data = out.GetUidData();
|
||||
uid_data->num_texgens = xfmem.numTexGen.numTexGens;
|
||||
uid_data->early_depth =
|
||||
bpmem.UseEarlyDepthTest() &&
|
||||
(g_ActiveConfig.bFastDepthCalc || bpmem.alpha_test.TestResult() == AlphaTest::UNDETERMINED) &&
|
||||
!(bpmem.zmode.testenable && bpmem.genMode.zfreeze);
|
||||
uid_data->early_depth = bpmem.UseEarlyDepthTest() &&
|
||||
(g_ActiveConfig.bFastDepthCalc ||
|
||||
bpmem.alpha_test.TestResult() == AlphaTestResult::Undetermined) &&
|
||||
!(bpmem.zmode.testenable && bpmem.genMode.zfreeze);
|
||||
uid_data->per_pixel_depth =
|
||||
(bpmem.ztex2.op != ZTEXTURE_DISABLE && bpmem.UseLateDepthTest()) ||
|
||||
(bpmem.ztex2.op != ZTexOp::Disabled && bpmem.UseLateDepthTest()) ||
|
||||
(!g_ActiveConfig.bFastDepthCalc && bpmem.zmode.testenable && !uid_data->early_depth) ||
|
||||
(bpmem.zmode.testenable && bpmem.genMode.zfreeze);
|
||||
uid_data->uint_output = bpmem.blendmode.UseLogicOp();
|
||||
@@ -367,21 +367,21 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
"// which are common to both color and alpha channels\n"
|
||||
"bool tevCompare(uint op, int3 color_A, int3 color_B) {{\n"
|
||||
" switch (op) {{\n"
|
||||
" case 0u: // TEVCMP_R8_GT\n"
|
||||
" case 0u: // TevCompareMode::R8, TevComparison::GT\n"
|
||||
" return (color_A.r > color_B.r);\n"
|
||||
" case 1u: // TEVCMP_R8_EQ\n"
|
||||
" case 1u: // TevCompareMode::R8, TevComparison::EQ\n"
|
||||
" return (color_A.r == color_B.r);\n"
|
||||
" case 2u: // TEVCMP_GR16_GT\n"
|
||||
" case 2u: // TevCompareMode::GR16, TevComparison::GT\n"
|
||||
" int A_16 = (color_A.r | (color_A.g << 8));\n"
|
||||
" int B_16 = (color_B.r | (color_B.g << 8));\n"
|
||||
" return A_16 > B_16;\n"
|
||||
" case 3u: // TEVCMP_GR16_EQ\n"
|
||||
" case 3u: // TevCompareMode::GR16, TevComparison::EQ\n"
|
||||
" return (color_A.r == color_B.r && color_A.g == color_B.g);\n"
|
||||
" case 4u: // TEVCMP_BGR24_GT\n"
|
||||
" case 4u: // TevCompareMode::BGR24, TevComparison::GT\n"
|
||||
" int A_24 = (color_A.r | (color_A.g << 8) | (color_A.b << 16));\n"
|
||||
" int B_24 = (color_B.r | (color_B.g << 8) | (color_B.b << 16));\n"
|
||||
" return A_24 > B_24;\n"
|
||||
" case 5u: // TEVCMP_BGR24_EQ\n"
|
||||
" case 5u: // TevCompareMode::BGR24, TevComparison::EQ\n"
|
||||
" return (color_A.r == color_B.r && color_A.g == color_B.g && color_A.b == color_B.b);\n"
|
||||
" default:\n"
|
||||
" return false;\n"
|
||||
@@ -814,29 +814,29 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
" s.AlphaBump = indcoord[bs - 1u];\n"
|
||||
" switch(fmt)\n"
|
||||
" {{\n"
|
||||
" case {}u:\n",
|
||||
ITF_8);
|
||||
" case {:s}:\n",
|
||||
IndTexFormat::ITF_8);
|
||||
out.Write(" indcoord.x = indcoord.x + ((bias & 1u) != 0u ? -128 : 0);\n"
|
||||
" indcoord.y = indcoord.y + ((bias & 2u) != 0u ? -128 : 0);\n"
|
||||
" indcoord.z = indcoord.z + ((bias & 4u) != 0u ? -128 : 0);\n"
|
||||
" s.AlphaBump = s.AlphaBump & 0xf8;\n"
|
||||
" break;\n"
|
||||
" case {}u:\n",
|
||||
ITF_5);
|
||||
" case {:s}:\n",
|
||||
IndTexFormat::ITF_5);
|
||||
out.Write(" indcoord.x = (indcoord.x & 0x1f) + ((bias & 1u) != 0u ? 1 : 0);\n"
|
||||
" indcoord.y = (indcoord.y & 0x1f) + ((bias & 2u) != 0u ? 1 : 0);\n"
|
||||
" indcoord.z = (indcoord.z & 0x1f) + ((bias & 4u) != 0u ? 1 : 0);\n"
|
||||
" s.AlphaBump = s.AlphaBump & 0xe0;\n"
|
||||
" break;\n"
|
||||
" case {}u:\n",
|
||||
ITF_4);
|
||||
" case {:s}:\n",
|
||||
IndTexFormat::ITF_4);
|
||||
out.Write(" indcoord.x = (indcoord.x & 0x0f) + ((bias & 1u) != 0u ? 1 : 0);\n"
|
||||
" indcoord.y = (indcoord.y & 0x0f) + ((bias & 2u) != 0u ? 1 : 0);\n"
|
||||
" indcoord.z = (indcoord.z & 0x0f) + ((bias & 4u) != 0u ? 1 : 0);\n"
|
||||
" s.AlphaBump = s.AlphaBump & 0xf0;\n"
|
||||
" break;\n"
|
||||
" case {}u:\n",
|
||||
ITF_3);
|
||||
" case {:s}:\n",
|
||||
IndTexFormat::ITF_3);
|
||||
out.Write(" indcoord.x = (indcoord.x & 0x07) + ((bias & 1u) != 0u ? 1 : 0);\n"
|
||||
" indcoord.y = (indcoord.y & 0x07) + ((bias & 2u) != 0u ? 1 : 0);\n"
|
||||
" indcoord.z = (indcoord.z & 0x07) + ((bias & 4u) != 0u ? 1 : 0);\n"
|
||||
@@ -924,7 +924,7 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
out.Write(" bool color_clamp = bool({});\n",
|
||||
BitfieldExtract("ss.cc", TevStageCombiner().colorC.clamp));
|
||||
out.Write(" uint color_shift = {};\n",
|
||||
BitfieldExtract("ss.cc", TevStageCombiner().colorC.shift));
|
||||
BitfieldExtract("ss.cc", TevStageCombiner().colorC.scale));
|
||||
out.Write(" uint color_dest = {};\n",
|
||||
BitfieldExtract("ss.cc", TevStageCombiner().colorC.dest));
|
||||
|
||||
@@ -949,12 +949,12 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
" }} else {{ // Compare mode\n"
|
||||
" // op 6 and 7 do a select per color channel\n"
|
||||
" if (color_compare_op == 6u) {{\n"
|
||||
" // TEVCMP_RGB8_GT\n"
|
||||
" // TevCompareMode::RGB8, TevComparison::GT\n"
|
||||
" color.r = (color_A.r > color_B.r) ? color_C.r : 0;\n"
|
||||
" color.g = (color_A.g > color_B.g) ? color_C.g : 0;\n"
|
||||
" color.b = (color_A.b > color_B.b) ? color_C.b : 0;\n"
|
||||
" }} else if (color_compare_op == 7u) {{\n"
|
||||
" // TEVCMP_RGB8_EQ\n"
|
||||
" // TevCompareMode::RGB8, TevComparison::EQ\n"
|
||||
" color.r = (color_A.r == color_B.r) ? color_C.r : 0;\n"
|
||||
" color.g = (color_A.g == color_B.g) ? color_C.g : 0;\n"
|
||||
" color.b = (color_A.b == color_B.b) ? color_C.b : 0;\n"
|
||||
@@ -990,7 +990,7 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
out.Write(" bool alpha_clamp = bool({});\n",
|
||||
BitfieldExtract("ss.ac", TevStageCombiner().alphaC.clamp));
|
||||
out.Write(" uint alpha_shift = {};\n",
|
||||
BitfieldExtract("ss.ac", TevStageCombiner().alphaC.shift));
|
||||
BitfieldExtract("ss.ac", TevStageCombiner().alphaC.scale));
|
||||
out.Write(" uint alpha_dest = {};\n",
|
||||
BitfieldExtract("ss.ac", TevStageCombiner().alphaC.dest));
|
||||
|
||||
@@ -1016,10 +1016,10 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
"true, alpha_shift);\n"
|
||||
" }} else {{ // Compare mode\n"
|
||||
" if (alpha_compare_op == 6u) {{\n"
|
||||
" // TEVCMP_A8_GT\n"
|
||||
" // TevCompareMode::A8, TevComparison::GT\n"
|
||||
" alpha = (alpha_A > alpha_B) ? alpha_C : 0;\n"
|
||||
" }} else if (alpha_compare_op == 7u) {{\n"
|
||||
" // TEVCMP_A8_EQ\n"
|
||||
" // TevCompareMode::A8, TevComparison::EQ\n"
|
||||
" alpha = (alpha_A == alpha_B) ? alpha_C : 0;\n"
|
||||
" }} else {{\n"
|
||||
" // All remaining alpha compare ops actually compare the color channels\n"
|
||||
@@ -1157,8 +1157,8 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
out.Write(" // Fog\n"
|
||||
" uint fog_function = {};\n",
|
||||
BitfieldExtract("bpmem_fogParam3", FogParam3().fsel));
|
||||
out.Write(" if (fog_function != 0u) {{\n"
|
||||
" // TODO: This all needs to be converted from float to fixed point\n"
|
||||
out.Write(" if (fog_function != {:s}) {{\n", FogType::Off);
|
||||
out.Write(" // TODO: This all needs to be converted from float to fixed point\n"
|
||||
" float ze;\n"
|
||||
" if ({} == 0u) {{\n",
|
||||
BitfieldExtract("bpmem_fogParam3", FogParam3().proj));
|
||||
@@ -1188,23 +1188,27 @@ ShaderCode GenPixelShader(APIType ApiType, const ShaderHostConfig& host_config,
|
||||
" }}\n"
|
||||
"\n"
|
||||
" float fog = clamp(ze - " I_FOGF ".y, 0.0, 1.0);\n"
|
||||
"\n"
|
||||
" if (fog_function > 3u) {{\n"
|
||||
" switch (fog_function) {{\n"
|
||||
" case 4u:\n"
|
||||
"\n");
|
||||
out.Write(" if (fog_function >= {:s}) {{\n", FogType::Exp);
|
||||
out.Write(" switch (fog_function) {{\n"
|
||||
" case {:s}:\n"
|
||||
" fog = 1.0 - exp2(-8.0 * fog);\n"
|
||||
" break;\n"
|
||||
" case 5u:\n"
|
||||
" break;\n",
|
||||
FogType::Exp);
|
||||
out.Write(" case {:s}:\n"
|
||||
" fog = 1.0 - exp2(-8.0 * fog * fog);\n"
|
||||
" break;\n"
|
||||
" case 6u:\n"
|
||||
" break;\n",
|
||||
FogType::ExpSq);
|
||||
out.Write(" case {:s}:\n"
|
||||
" fog = exp2(-8.0 * (1.0 - fog));\n"
|
||||
" break;\n"
|
||||
" case 7u:\n"
|
||||
" break;\n",
|
||||
FogType::BackwardsExp);
|
||||
out.Write(" case {:s}:\n"
|
||||
" fog = 1.0 - fog;\n"
|
||||
" fog = exp2(-8.0 * fog * fog);\n"
|
||||
" break;\n"
|
||||
" }}\n"
|
||||
" break;\n",
|
||||
FogType::BackwardsExpSq);
|
||||
out.Write(" }}\n"
|
||||
" }}\n"
|
||||
"\n"
|
||||
" int ifog = iround(fog * 256.0);\n"
|
||||
|
||||
@@ -293,7 +293,7 @@ int RunVertices(int vtx_attr_group, int primitive, int count, DataReader src, bo
|
||||
// if cull mode is CULL_ALL, tell VertexManager to skip triangles and quads.
|
||||
// They still need to go through vertex loading, because we need to calculate a zfreeze refrence
|
||||
// slope.
|
||||
bool cullall = (bpmem.genMode.cullmode == GenMode::CULL_ALL && primitive < 5);
|
||||
bool cullall = (bpmem.genMode.cullmode == CullMode::All && primitive < 5);
|
||||
|
||||
DataReader dst = g_vertex_manager->PrepareForAdditionalData(
|
||||
primitive, count, loader->m_native_vtx_decl.stride, cullall);
|
||||
|
||||
Reference in New Issue
Block a user