mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-07-14 11:14:28 +02:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 38ee1e1e22 | |||
| 2b02a5dc78 | |||
| dead00eb62 | |||
| 4fa2b8e45d | |||
| fc90973509 | |||
| ff9176f83e | |||
| 63d3dd9978 | |||
| b704c6caaa | |||
| a64465681c | |||
| 539357436c | |||
| 22cb6b0c9c | |||
| 81df4e5def |
@@ -31969,6 +31969,9 @@ SLKA-25176:
|
||||
name: "펌프 잇 업 익시드"
|
||||
name-en: "Pump It Up - Exceed"
|
||||
region: "NTSC-K"
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 4 # Fixes graphical corruption in musical notes.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
SLKA-25180:
|
||||
name: "스플린터 셀 - 판도라 투머로우"
|
||||
name-en: "Tom Clancy's Splinter Cell - Pandora Tomorrow"
|
||||
@@ -44039,7 +44042,7 @@ SLPM-65495:
|
||||
SLPM-65496:
|
||||
name: "ハイパーストリートファイターⅡ アニバーサリーエディション"
|
||||
name-sort: "はいぱーすとりーとふぁいたー2 あにばーさりーえでぃしょん"
|
||||
name-en: "Hyper Street Fighter"
|
||||
name-en: "Hyper Street Fighter II - The Anniversary Edition"
|
||||
region: "NTSC-J"
|
||||
SLPM-65497:
|
||||
name: "ワールドサッカーウイニングイレブン7 インターナショナル プレミアムパッケージ supported by アディダス"
|
||||
@@ -54506,6 +54509,7 @@ SLPM-74405:
|
||||
region: "NTSC-J"
|
||||
gameFixes:
|
||||
- EETimingHack # Stops crash after intro movie.
|
||||
- InstantDMAHack # Stops hang when entering Sword Select screen.
|
||||
SLPM-74406:
|
||||
name: "WRC ~WORLD RALLY CHAMPIONSHIP~ [PlayStation2 the Best]"
|
||||
name-sort: "WRC ~わーるど らりー ちゃんぴおんしっぷ~ [PlayStation2 the Best]"
|
||||
@@ -70115,6 +70119,9 @@ SLUS-21131:
|
||||
name: "Pump It Up - Exceed"
|
||||
region: "NTSC-U"
|
||||
compat: 5
|
||||
gsHWFixes:
|
||||
cpuSpriteRenderBW: 4 # Fixes graphical corruption in musical notes.
|
||||
cpuSpriteRenderLevel: 2 # Needed for above.
|
||||
SLUS-21132:
|
||||
name: "Stella Deus - The Gate of Eternity"
|
||||
region: "NTSC-U"
|
||||
|
||||
@@ -1538,6 +1538,8 @@ xinput,XInput Controller,a:b0,b:b1,back:b6,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,
|
||||
05000000853200000503000000010000,Nacon MGX Pro,a:b0,b:b1,back:b10,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b6,leftstick:b13,lefttrigger:a5,leftx:a0,lefty:a1,rightshoulder:b7,rightstick:b14,righttrigger:a4,rightx:a2,righty:a3,start:b11,x:b3,y:b4,platform:Linux,
|
||||
0300000085320000170d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000190d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000180d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,x:b0,y:b3,platform:Linux,
|
||||
0300000085320000160d000011010000,Nacon Revolution 5 Pro,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:a3,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:a4,rightx:a2,righty:a5,start:b9,touchpad:b13,x:b0,y:b3,platform:Linux,
|
||||
030000000d0f00000900000010010000,Natec Genesis P44,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,leftstick:b10,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,rightstick:b11,righttrigger:b7,rightx:a2,righty:a3,start:b9,x:b0,y:b3,platform:Linux,
|
||||
030000004f1f00000800000011010000,NeoGeo PS3,a:b1,b:b2,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,guide:b12,leftshoulder:b4,lefttrigger:b6,leftx:a0,lefty:a1,rightshoulder:b5,righttrigger:b7,start:b9,x:b0,y:b3,platform:Linux,
|
||||
0300000092120000474e000000010000,NeoGeo X Arcade Stick,a:b0,b:b1,back:b8,dpdown:h0.4,dpleft:h0.8,dpright:h0.2,dpup:h0.1,start:b9,x:b3,y:b2,platform:Linux,
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -876,7 +876,7 @@ static __fi void rcntEndGate(bool isVblank, u64 sCycle)
|
||||
isVblank ? "vblank" : "hblank", counters[i].mode.GateMode, counters[i].count);
|
||||
counters[i].count = 0;
|
||||
counters[i].target &= 0xffff;
|
||||
counters[i].startCycle = sCycle & ~(counters[i].rate - 1);
|
||||
counters[i].startCycle = sCycle & ~(static_cast<u64>(counters[i].rate - 1));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,8 +91,8 @@ void GSDrawingContext::UpdateScissor()
|
||||
scissor.in = rscissor + GSVector4i::cxpr(0, 0, 1, 1);
|
||||
|
||||
// Fixed-point scissor min/max, used for rejecting primitives which are entirely outside.
|
||||
// Bottom-right end point should be exclusive for rectangle intersection test to work correctly.
|
||||
scissor.cull = rscissor.sll32<4>() + GSVector4i::cxpr(0, 0, 1, 1);
|
||||
// Add half a pixel around the edges for upscaling and lines/points.
|
||||
scissor.cull = rscissor.sll32<4>() + GSVector4i(-8, -8, 8, 8);
|
||||
|
||||
// Offset applied to vertices for culling.
|
||||
scissor.xyof = GSVector4i::loadl(&XYOFFSET.U64).xyxy();
|
||||
|
||||
+36
-31
@@ -1279,12 +1279,12 @@ void GSState::DumpTransferList(const std::string& filename)
|
||||
(*file) << std::endl;
|
||||
|
||||
// clear, EE->GS, or GS->GS
|
||||
(*file) << LIST_ITEM << "type: " << (transfer.zero_clear ? "clear" : ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) ? "EE_to_GS" : "GS_to_GS")) << std::endl;
|
||||
(*file) << LIST_ITEM << "type: " << ((transfer.transfer_type == EEGS_TransferType::Clear) ? "clear" : ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) ? "EE_to_GS" : "GS_to_GS")) << std::endl;
|
||||
|
||||
// Dump BITBLTBUF
|
||||
(*file) << INDENT << "BITBLTBUF: " << OPEN_MAP;
|
||||
|
||||
const bool gs_to_gs = (transfer.transfer_type == EEGS_TransferType::GS_to_GS) && !transfer.zero_clear;
|
||||
const bool gs_to_gs = (transfer.transfer_type == EEGS_TransferType::GS_to_GS) && transfer.transfer_type != EEGS_TransferType::Clear;
|
||||
|
||||
if (gs_to_gs)
|
||||
{
|
||||
@@ -1330,11 +1330,11 @@ void GSState::DumpTransferImages()
|
||||
const GSUploadQueue& transfer = m_draw_transfers[i];
|
||||
|
||||
std::string filename;
|
||||
if ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) || transfer.zero_clear)
|
||||
if ((transfer.transfer_type == EEGS_TransferType::EE_to_GS) || transfer.transfer_type == EEGS_TransferType::Clear)
|
||||
{
|
||||
// clear or EE->GS: only the destination info is relevant.
|
||||
filename = GetDrawDumpPath("%05lld_transfer%02d_%s_%04x_%d_%s_%d_%d_%d_%d.png",
|
||||
s_n, transfer_n++, (transfer.zero_clear ? "clear" : "EE_to_GS"), transfer.blit.DBP, transfer.blit.DBW,
|
||||
s_n, transfer_n++, ((transfer.transfer_type == EEGS_TransferType::Clear) ? "clear" : "EE_to_GS"), transfer.blit.DBP, transfer.blit.DBW,
|
||||
GSUtil::GetPSMName(transfer.blit.DPSM), transfer.rect.x, transfer.rect.y, transfer.rect.z, transfer.rect.w);
|
||||
}
|
||||
else
|
||||
@@ -2911,12 +2911,11 @@ void GSState::Write(const u8* mem, int len)
|
||||
m_draw_transfers.pop_back();
|
||||
transfer.rect = transfer.rect.runion(r);
|
||||
transfer.draw = s_n;
|
||||
transfer.zero_clear = false;
|
||||
m_draw_transfers.push_back(transfer);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GSUploadQueue new_transfer = {blit, r, s_n, false, EEGS_TransferType::EE_to_GS};
|
||||
const GSUploadQueue new_transfer = {blit, s_n, r, EEGS_TransferType::EE_to_GS};
|
||||
m_draw_transfers.push_back(new_transfer);
|
||||
}
|
||||
|
||||
@@ -3111,12 +3110,11 @@ void GSState::Move()
|
||||
m_draw_transfers.pop_back();
|
||||
transfer.rect = transfer.rect.runion(r);
|
||||
transfer.draw = s_n;
|
||||
transfer.zero_clear = false;
|
||||
m_draw_transfers.push_back(transfer);
|
||||
}
|
||||
else
|
||||
{
|
||||
const GSUploadQueue new_transfer = {m_env.BITBLTBUF, r, s_n, false, EEGS_TransferType::GS_to_GS};
|
||||
const GSUploadQueue new_transfer = {m_env.BITBLTBUF, s_n, r, EEGS_TransferType::GS_to_GS};
|
||||
m_draw_transfers.push_back(new_transfer);
|
||||
}
|
||||
|
||||
@@ -5932,39 +5930,46 @@ __forceinline void GSState::VertexKick(u32 skip)
|
||||
bbox = v0.runion(v1).runion(v2);
|
||||
}
|
||||
|
||||
if (m_nativeres && (primclass == GS_TRIANGLE_CLASS || primclass == GS_SPRITE_CLASS))
|
||||
if constexpr (primclass == GS_TRIANGLE_CLASS || primclass == GS_SPRITE_CLASS)
|
||||
{
|
||||
// For triangles and sprites at native res take the region strictly within the bounds
|
||||
// omitting the bottom/right.
|
||||
bbox = (bbox + GSVector4i(0xF, 0xF, -1, -1)) & GSVector4i(~0xF);
|
||||
if (m_nativeres)
|
||||
{
|
||||
// For triangles and sprites at native res take the interior pixel centers.
|
||||
const GSVector4i interior = (bbox + GSVector4i(0xF, 0xF, -1, -1)) & GSVector4i(~0xF);
|
||||
bbox = interior + GSVector4i(0, 0, 1, 1); // +1 to bottom/right so empty test works correctly.
|
||||
}
|
||||
else
|
||||
{
|
||||
// For upscaling, remove bottom/right subtexels.
|
||||
bbox -= ((bbox & GSVector4i(0xF)) == GSVector4i(0)) & GSVector4i(0, 0, 1, 1);
|
||||
}
|
||||
|
||||
// For AA1 triangles and lines, expand the bounds by 1 pixel on all sides.
|
||||
// Note: redundant check for the AA1 flag to avoid calling a function if not needed.
|
||||
if (PRIM->AA1 && IsCoverageAlphaSupported())
|
||||
{
|
||||
bbox += GSVector4i(-0x10, -0x10, 0x10, 0x10);
|
||||
}
|
||||
}
|
||||
|
||||
// For AA1 triangles and lines, expand the bounds by 1 pixel on all sides.
|
||||
// Note: redundant check for the AA1 flag to avoid calling a function if not needed.
|
||||
if ((primclass == GS_TRIANGLE_CLASS || primclass == GS_LINE_CLASS) && PRIM->AA1 && IsCoverageAlphaSupported())
|
||||
// Do scissor test.
|
||||
const GSVector4i bbox_ex = bbox + GSVector4i(0, 0, 1, 1); // Exclusive coords for the scissor test.
|
||||
const GSVector4i& scissor = m_context->scissor.cull;
|
||||
u32 test = static_cast<u32>(!bbox_ex.rintersects(scissor));
|
||||
|
||||
// Test for empty bbox.
|
||||
if constexpr (primclass == GS_TRIANGLE_CLASS || primclass == GS_SPRITE_CLASS)
|
||||
{
|
||||
bbox += GSVector4i(-0x10, -0x10, 0x10, 0x10);
|
||||
test |= static_cast<u32>(bbox.rempty());
|
||||
}
|
||||
|
||||
// Make the bottom-right endpoints exclusive for rectangle intersection to work correctly.
|
||||
bbox += GSVector4i::cxpr(0, 0, 1, 1);
|
||||
|
||||
// Do scissor test and empty bbox test.
|
||||
GSVector4i test = GSVector4i(bbox.rintersects(m_context->scissor.cull)) == GSVector4i::cxpr(0);
|
||||
|
||||
// Test for degenerate triangle.
|
||||
if (primclass == GS_TRIANGLE_CLASS)
|
||||
if constexpr (primclass == GS_TRIANGLE_CLASS)
|
||||
{
|
||||
test |= v0.eq64(v1) | v1.eq64(v2) | v0.eq64(v2);
|
||||
test |= static_cast<u32>(v0.eq(v1)) | static_cast<u32>(v1.eq(v2)) | static_cast<u32>(v0.eq(v2));
|
||||
}
|
||||
|
||||
#ifndef ARCH_ARM64
|
||||
// We only care about the xy passing the skip test.
|
||||
skip |= test.mask();
|
||||
#else
|
||||
// mask() is slow on ARM, so just pull the bits out instead, thankfully we only care about the first 4 bytes.
|
||||
skip |= (static_cast<u64>(test.extract64<0>()) & UINT64_C(0x8080808080808080)) != 0;
|
||||
#endif
|
||||
skip |= test;
|
||||
}
|
||||
|
||||
if (skip != 0)
|
||||
|
||||
+3
-3
@@ -258,15 +258,15 @@ public:
|
||||
{
|
||||
EE_to_GS,
|
||||
GS_to_GS,
|
||||
GS_to_EE
|
||||
GS_to_EE,
|
||||
Clear
|
||||
};
|
||||
|
||||
struct GSUploadQueue
|
||||
{
|
||||
GIFRegBITBLTBUF blit;
|
||||
GSVector4i rect;
|
||||
u64 draw;
|
||||
bool zero_clear;
|
||||
GSVector4i rect;
|
||||
EEGS_TransferType transfer_type;
|
||||
};
|
||||
|
||||
|
||||
@@ -466,28 +466,52 @@ GSRendererType D3D::GetPreferredRenderer()
|
||||
}
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D_FEATURE_LEVEL feature_level, bool debug,
|
||||
const char* D3D::ShaderModelToCacheString(D3D::ShaderModel shader_model)
|
||||
{
|
||||
switch (shader_model)
|
||||
{
|
||||
case ShaderModel::SM40:
|
||||
return "sm40";
|
||||
case ShaderModel::SM41:
|
||||
return "sm41";
|
||||
case ShaderModel::SM50:
|
||||
return "sm50";
|
||||
case ShaderModel::SM51:
|
||||
return "sm51";
|
||||
default:
|
||||
return "unk";
|
||||
}
|
||||
}
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> D3D::CompileShader(D3D::ShaderType type, D3D::ShaderModel shader_model, bool debug,
|
||||
const std::string_view code, const D3D_SHADER_MACRO* macros /* = nullptr */,
|
||||
const char* entry_point /* = "main" */)
|
||||
{
|
||||
const char* target;
|
||||
switch (feature_level)
|
||||
switch (shader_model)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
case ShaderModel::SM40:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_0", "ps_4_0", "cs_4_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
case ShaderModel::SM41:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_4_1", "ps_4_1", "cs_4_1"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case ShaderModel::SM50:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_0", "ps_5_0", "cs_5_0"}};
|
||||
target = targets[static_cast<int>(type)];
|
||||
}
|
||||
break;
|
||||
|
||||
case D3D_FEATURE_LEVEL_11_1:
|
||||
case ShaderModel::SM51:
|
||||
default:
|
||||
{
|
||||
static constexpr std::array<const char*, 4> targets = {{"vs_5_1", "ps_5_1", "cs_5_1"}};
|
||||
|
||||
@@ -63,6 +63,16 @@ namespace D3D
|
||||
Compute
|
||||
};
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> CompileShader(ShaderType type, D3D_FEATURE_LEVEL feature_level, bool debug,
|
||||
enum class ShaderModel
|
||||
{
|
||||
SM40 = 0x40, // DX11 FL 10_0
|
||||
SM41 = 0x41, // DX11 FL 10_1
|
||||
SM50 = 0x50, // DX11 FL 11_0
|
||||
SM51 = 0x51, // DX12
|
||||
};
|
||||
|
||||
const char* ShaderModelToCacheString(ShaderModel shader_model);
|
||||
|
||||
wil::com_ptr_nothrow<ID3DBlob> CompileShader(ShaderType type, ShaderModel shader_model, bool debug,
|
||||
const std::string_view code, const D3D_SHADER_MACRO* macros = nullptr, const char* entry_point = "main");
|
||||
}; // namespace D3D
|
||||
|
||||
@@ -56,12 +56,27 @@ bool D3D11ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
|
||||
|
||||
bool D3D11ShaderCache::Open(D3D_FEATURE_LEVEL feature_level, bool debug)
|
||||
{
|
||||
m_feature_level = feature_level;
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_10_0:
|
||||
m_shader_model = D3D::ShaderModel::SM40;
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_10_1:
|
||||
m_shader_model = D3D::ShaderModel::SM41;
|
||||
break;
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
m_shader_model = D3D::ShaderModel::SM50;
|
||||
break;
|
||||
default:
|
||||
pxAssert(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
m_debug = debug;
|
||||
|
||||
if (!GSConfig.DisableShaderCache)
|
||||
{
|
||||
const std::string base_filename = GetCacheBaseFileName(feature_level, debug);
|
||||
const std::string base_filename = GetCacheBaseFileName(m_shader_model, debug);
|
||||
const std::string index_filename = base_filename + ".idx";
|
||||
const std::string blob_filename = base_filename + ".bin";
|
||||
|
||||
@@ -198,19 +213,10 @@ bool D3D11ShaderCache::ReadExisting(const std::string& index_filename, const std
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string D3D11ShaderCache::GetCacheBaseFileName(D3D_FEATURE_LEVEL feature_level, bool debug)
|
||||
std::string D3D11ShaderCache::GetCacheBaseFileName(D3D::ShaderModel shader_model, bool debug)
|
||||
{
|
||||
std::string base_filename = "d3d_shaders_";
|
||||
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
base_filename += "sm50";
|
||||
break;
|
||||
default:
|
||||
base_filename += "unk";
|
||||
break;
|
||||
}
|
||||
base_filename += D3D::ShaderModelToCacheString(shader_model);
|
||||
|
||||
if (debug)
|
||||
base_filename += "_debug";
|
||||
@@ -400,7 +406,7 @@ wil::com_ptr_nothrow<ID3DBlob> D3D11ShaderCache::CompileAndAddShaderBlob(const C
|
||||
const std::string_view shader_code, const D3D_SHADER_MACRO* macros, const char* entry_point)
|
||||
{
|
||||
wil::com_ptr_nothrow<ID3DBlob> blob =
|
||||
D3D::CompileShader(key.shader_type, m_feature_level, m_debug, shader_code, macros, entry_point);
|
||||
D3D::CompileShader(key.shader_type, m_shader_model, m_debug, shader_code, macros, entry_point);
|
||||
if (!blob)
|
||||
return {};
|
||||
|
||||
|
||||
@@ -16,7 +16,6 @@ public:
|
||||
D3D11ShaderCache();
|
||||
~D3D11ShaderCache();
|
||||
|
||||
D3D_FEATURE_LEVEL GetFeatureLevel() const { return m_feature_level; }
|
||||
bool UsingDebugShaders() const { return m_debug; }
|
||||
|
||||
bool Open(D3D_FEATURE_LEVEL feature_level, bool debug);
|
||||
@@ -74,7 +73,7 @@ private:
|
||||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static std::string GetCacheBaseFileName(D3D_FEATURE_LEVEL feature_level, bool debug);
|
||||
static std::string GetCacheBaseFileName(D3D::ShaderModel shader_mode, bool debug);
|
||||
static CacheIndexKey GetCacheKey(D3D::ShaderType type, const std::string_view shader_code,
|
||||
const D3D_SHADER_MACRO* macros, const char* entry_point);
|
||||
|
||||
@@ -89,6 +88,6 @@ private:
|
||||
|
||||
CacheIndex m_index;
|
||||
|
||||
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
D3D::ShaderModel m_shader_model = D3D::ShaderModel::SM50;
|
||||
bool m_debug = false;
|
||||
};
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#include "GS/Renderers/DX12/D3D12ShaderCache.h"
|
||||
#include "GS/Renderers/DX11/D3D.h"
|
||||
#include "GS/GS.h"
|
||||
|
||||
#include "Config.h"
|
||||
@@ -54,16 +53,18 @@ bool D3D12ShaderCache::CacheIndexKey::operator!=(const CacheIndexKey& key) const
|
||||
source_length != key.source_length);
|
||||
}
|
||||
|
||||
bool D3D12ShaderCache::Open(D3D_FEATURE_LEVEL feature_level, bool debug)
|
||||
bool D3D12ShaderCache::Open(D3D::ShaderModel shader_model, bool debug)
|
||||
{
|
||||
m_feature_level = feature_level;
|
||||
// Only support SM5.1 for now, which is the minimum for D3D12.
|
||||
pxAssert(shader_model >= D3D::ShaderModel::SM51);
|
||||
m_shader_model = shader_model;
|
||||
m_debug = debug;
|
||||
|
||||
bool result = true;
|
||||
|
||||
if (!GSConfig.DisableShaderCache)
|
||||
{
|
||||
const std::string base_shader_filename = GetCacheBaseFileName("shaders", feature_level, debug);
|
||||
const std::string base_shader_filename = GetCacheBaseFileName("shaders", m_shader_model, debug);
|
||||
const std::string shader_index_filename = base_shader_filename + ".idx";
|
||||
const std::string shader_blob_filename = base_shader_filename + ".bin";
|
||||
|
||||
@@ -75,7 +76,7 @@ bool D3D12ShaderCache::Open(D3D_FEATURE_LEVEL feature_level, bool debug)
|
||||
|
||||
if (result)
|
||||
{
|
||||
const std::string base_pipelines_filename = GetCacheBaseFileName("pipelines", feature_level, debug);
|
||||
const std::string base_pipelines_filename = GetCacheBaseFileName("pipelines", m_shader_model, debug);
|
||||
const std::string pipelines_index_filename = base_pipelines_filename + ".idx";
|
||||
const std::string pipelines_blob_filename = base_pipelines_filename + ".bin";
|
||||
|
||||
@@ -133,7 +134,7 @@ void D3D12ShaderCache::InvalidatePipelineCache()
|
||||
if (GSConfig.DisableShaderCache)
|
||||
return;
|
||||
|
||||
const std::string base_pipelines_filename = GetCacheBaseFileName("pipelines", m_feature_level, m_debug);
|
||||
const std::string base_pipelines_filename = GetCacheBaseFileName("pipelines", m_shader_model, m_debug);
|
||||
const std::string pipelines_index_filename = base_pipelines_filename + ".idx";
|
||||
const std::string pipelines_blob_filename = base_pipelines_filename + ".bin";
|
||||
CreateNew(pipelines_index_filename, pipelines_blob_filename, m_pipeline_index_file, m_pipeline_blob_file);
|
||||
@@ -253,21 +254,12 @@ bool D3D12ShaderCache::ReadExisting(const std::string& index_filename, const std
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string D3D12ShaderCache::GetCacheBaseFileName(const std::string_view type, D3D_FEATURE_LEVEL feature_level, bool debug)
|
||||
std::string D3D12ShaderCache::GetCacheBaseFileName(const std::string_view type, D3D::ShaderModel shader_model, bool debug)
|
||||
{
|
||||
std::string base_filename = "d3d12_";
|
||||
base_filename += type;
|
||||
base_filename += "_";
|
||||
|
||||
switch (feature_level)
|
||||
{
|
||||
case D3D_FEATURE_LEVEL_11_0:
|
||||
base_filename += "sm50";
|
||||
break;
|
||||
default:
|
||||
base_filename += "unk";
|
||||
break;
|
||||
}
|
||||
base_filename += D3D::ShaderModelToCacheString(shader_model);
|
||||
|
||||
if (debug)
|
||||
base_filename += "_debug";
|
||||
@@ -497,15 +489,15 @@ D3D12ShaderCache::ComPtr<ID3DBlob> D3D12ShaderCache::CompileAndAddShaderBlob(
|
||||
{
|
||||
case EntryType::VertexShader:
|
||||
blob =
|
||||
D3D::CompileShader(D3D::ShaderType::Vertex, m_feature_level, m_debug, shader_code, macros, entry_point);
|
||||
D3D::CompileShader(D3D::ShaderType::Vertex, m_shader_model, m_debug, shader_code, macros, entry_point);
|
||||
break;
|
||||
case EntryType::PixelShader:
|
||||
blob =
|
||||
D3D::CompileShader(D3D::ShaderType::Pixel, m_feature_level, m_debug, shader_code, macros, entry_point);
|
||||
D3D::CompileShader(D3D::ShaderType::Pixel, m_shader_model, m_debug, shader_code, macros, entry_point);
|
||||
break;
|
||||
case EntryType::ComputeShader:
|
||||
blob = D3D::CompileShader(
|
||||
D3D::ShaderType::Compute, m_feature_level, m_debug, shader_code, macros, entry_point);
|
||||
blob =
|
||||
D3D::CompileShader(D3D::ShaderType::Compute, m_shader_model, m_debug, shader_code, macros, entry_point);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
// SPDX-License-Identifier: GPL-3.0+
|
||||
|
||||
#pragma once
|
||||
#include "GS/Renderers/DX11/D3D.h"
|
||||
|
||||
#include "common/Pcsx2Defs.h"
|
||||
#include "common/HashCombine.h"
|
||||
@@ -32,10 +33,9 @@ public:
|
||||
D3D12ShaderCache();
|
||||
~D3D12ShaderCache();
|
||||
|
||||
__fi D3D_FEATURE_LEVEL GetFeatureLevel() const { return m_feature_level; }
|
||||
__fi bool UsingDebugShaders() const { return m_debug; }
|
||||
|
||||
bool Open(D3D_FEATURE_LEVEL feature_level, bool debug);
|
||||
bool Open(D3D::ShaderModel shader_model, bool debug);
|
||||
void Close();
|
||||
|
||||
__fi ComPtr<ID3DBlob> GetVertexShader(
|
||||
@@ -95,7 +95,7 @@ private:
|
||||
|
||||
using CacheIndex = std::unordered_map<CacheIndexKey, CacheIndexData, CacheIndexEntryHasher>;
|
||||
|
||||
static std::string GetCacheBaseFileName(const std::string_view type, D3D_FEATURE_LEVEL feature_level, bool debug);
|
||||
static std::string GetCacheBaseFileName(const std::string_view type, D3D::ShaderModel shader_model, bool debug);
|
||||
static CacheIndexKey GetShaderCacheKey(
|
||||
EntryType type, const std::string_view shader_code, const D3D_SHADER_MACRO* macros, const char* entry_point);
|
||||
static CacheIndexKey GetPipelineCacheKey(const D3D12_GRAPHICS_PIPELINE_STATE_DESC& gpdesc);
|
||||
@@ -123,6 +123,6 @@ private:
|
||||
std::FILE* m_pipeline_blob_file = nullptr;
|
||||
CacheIndex m_pipeline_index;
|
||||
|
||||
D3D_FEATURE_LEVEL m_feature_level = D3D_FEATURE_LEVEL_11_0;
|
||||
D3D::ShaderModel m_shader_model = D3D::ShaderModel::SM51;
|
||||
bool m_debug = false;
|
||||
};
|
||||
|
||||
@@ -892,7 +892,7 @@ bool GSDevice12::Create(GSVSyncMode vsync_mode, bool allow_present_throttle)
|
||||
m_tfx_source = std::move(*shader);
|
||||
}
|
||||
|
||||
if (!m_shader_cache.Open(m_feature_level, GSConfig.UseDebugDevice))
|
||||
if (!m_shader_cache.Open(D3D::ShaderModel::SM51, GSConfig.UseDebugDevice))
|
||||
Console.Warning("D3D12: Shader cache failed to open.");
|
||||
|
||||
if (!CreateRootSignatures())
|
||||
|
||||
@@ -790,11 +790,14 @@ void GSRendererHW::DetectTextureShuffle()
|
||||
|
||||
void GSRendererHW::DetectTextureShuffleSecondPass(GSTextureCache::Target* rt, GSTextureCache::Source* tex)
|
||||
{
|
||||
const auto HasLowerOnes = [&](u32 x) { return x != 0 && (x & (x + 1)) == 0; };
|
||||
if (!m_process_texture || !rt)
|
||||
{
|
||||
GL_INS("HW: Texture shuffle detection (2): Not detected.");
|
||||
m_texture_shuffle.Disable();
|
||||
return;
|
||||
}
|
||||
|
||||
const GSLocalMemory::psm_t& tex_psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];
|
||||
const GSLocalMemory::psm_t& frame_psm = GSLocalMemory::m_psm[m_cached_ctx.FRAME.PSM];
|
||||
|
||||
if (frame_psm.bpp != 16)
|
||||
{
|
||||
GL_INS("HW: Texture shuffle detection (2): Failed (not 16 bit RT).");
|
||||
@@ -804,7 +807,7 @@ void GSRendererHW::DetectTextureShuffleSecondPass(GSTextureCache::Target* rt, GS
|
||||
|
||||
if (m_texture_shuffle)
|
||||
{
|
||||
if (tex->m_32_bits_fmt)
|
||||
if (tex && tex->m_32_bits_fmt)
|
||||
{
|
||||
GL_INS("HW: Texture shuffle detection (2): Passed.");
|
||||
}
|
||||
@@ -812,9 +815,9 @@ void GSRendererHW::DetectTextureShuffleSecondPass(GSTextureCache::Target* rt, GS
|
||||
{
|
||||
// Detects when the source texture is really a 16 bit texture instead of 32 bit being reinterpreted as 16 bit.
|
||||
// Make sure it's opaque and not bilinear to reduce false positives.
|
||||
|
||||
const auto HasLowerOnes = [&](u32 x) { return x != 0 && (x & (x + 1)) == 0; };
|
||||
if (m_cached_ctx.TEX0.TBP0 != m_cached_ctx.FRAME.Block() &&
|
||||
rt->m_32_bits_fmt == true && IsOpaque() && !m_vt.IsRealLinear() &&
|
||||
rt && rt->m_32_bits_fmt == true && IsOpaque() && !m_vt.IsRealLinear() &&
|
||||
HasLowerOnes(m_cached_ctx.FRAME.FBMSK))
|
||||
{
|
||||
GL_INS("HW: Texture shuffle detection (2): Passed (real 16 bit source).");
|
||||
@@ -832,10 +835,10 @@ void GSRendererHW::DetectTextureShuffleSecondPass(GSTextureCache::Target* rt, GS
|
||||
// Last ditch check for reinterpreting a 32 bit source and RT as 16 bits.
|
||||
// These "shuffles" appear to not do anything useful for games, but using the texture shuffle
|
||||
// path helps to maintain correct sizes in the texture cache. Occurs in NFS Most Wanted.
|
||||
|
||||
const GSLocalMemory::psm_t& tex_psm = GSLocalMemory::m_psm[m_cached_ctx.TEX0.PSM];
|
||||
if (PRIM->TME &&
|
||||
((m_vt.m_primclass == GS_SPRITE_CLASS || m_vt.m_primclass == GS_TRIANGLE_CLASS) && TrianglesAreQuads(true)) &&
|
||||
(tex_psm.bpp == 16) && (frame_psm.bpp == 16) && rt->m_32_bits_fmt && tex->m_32_bits_fmt)
|
||||
(tex_psm.bpp == 16) && (frame_psm.bpp == 16) && rt && rt->m_32_bits_fmt && tex && tex->m_32_bits_fmt)
|
||||
{
|
||||
GL_INS("HW: Texture shuffle detection (2): Passed (HACK: reinterpreting both source/RT as 16 bit).");
|
||||
m_texture_shuffle.type = TextureShuffleType::HackShuffle;
|
||||
@@ -2918,7 +2921,7 @@ void GSRendererHW::Draw()
|
||||
}
|
||||
|
||||
// Test if we can optimize Alpha Test as a NOP
|
||||
m_cached_ctx.TEST.ATE = m_cached_ctx.TEST.ATE && !GSRenderer::TryAlphaTest(fm, zm);
|
||||
m_cached_ctx.TEST.ATE = !!m_cached_ctx.TEST.ATE && !GSRenderer::TryAlphaTest(fm, zm);
|
||||
|
||||
// Need to fix the alpha test, since the alpha will be fixed to 1.0 if ABE is disabled and AA1 is enabled
|
||||
// So if it doesn't meet the condition, always fail, if it does, always pass (turn off the test).
|
||||
@@ -2992,7 +2995,7 @@ void GSRendererHW::Draw()
|
||||
// I hate that I have to do this, but some games (like Pac-Man World Rally) troll us by causing a flush with degenerate triangles, so we don't have all available information about the next draw.
|
||||
// So we have to check when the next draw happens if our frame has changed or if it's become recursive.
|
||||
const bool has_colclip_texture = g_gs_device->GetColorClipTexture() != nullptr;
|
||||
if (!no_rt && has_colclip_texture && (m_conf.colclip_frame.FBP != m_cached_ctx.FRAME.FBP || m_conf.colclip_frame.Block() == m_cached_ctx.TEX0.TBP0))
|
||||
if (!no_rt && has_colclip_texture && (m_conf.colclip_frame.FBP != m_cached_ctx.FRAME.FBP || (PRIM->TME && m_conf.colclip_frame.Block() == m_cached_ctx.TEX0.TBP0)))
|
||||
{
|
||||
GIFRegTEX0 FRAME;
|
||||
FRAME.TBP0 = m_conf.colclip_frame.Block();
|
||||
@@ -4388,15 +4391,15 @@ void GSRendererHW::Draw()
|
||||
}
|
||||
}
|
||||
|
||||
// Second pass texture shuffle detection using RT and source.
|
||||
DetectTextureShuffleSecondPass(rt, src);
|
||||
|
||||
if (m_process_texture)
|
||||
{
|
||||
GIFRegCLAMP MIP_CLAMP = m_cached_ctx.CLAMP;
|
||||
|
||||
if (rt)
|
||||
{
|
||||
// Second pass texture shuffle detection using RT and source.
|
||||
DetectTextureShuffleSecondPass(rt, src);
|
||||
|
||||
if (m_texture_shuffle)
|
||||
{
|
||||
if (IsSplitTextureShuffle(rt->m_TEX0, rt->m_valid))
|
||||
@@ -6261,7 +6264,7 @@ void GSRendererHW::EmulateTextureShuffleAndFbmask(GSTextureCache::Target* rt, GS
|
||||
|
||||
// If date is enabled you need to test the green channel instead of the alpha channel.
|
||||
// Only enable this code in DATE mode to reduce the number of shaders.
|
||||
m_conf.ps.write_rg = (process_rg & SHUFFLE_WRITE) && m_cached_ctx.TEST.DATE;
|
||||
m_conf.ps.write_rg = !!(process_rg & SHUFFLE_WRITE) && !!m_cached_ctx.TEST.DATE;
|
||||
|
||||
m_conf.ps.real16src = m_texture_shuffle.real_16_bit_source;
|
||||
|
||||
@@ -8804,7 +8807,7 @@ __ri void GSRendererHW::DrawPrims(GSTextureCache::Target* rt, GSTextureCache::Ta
|
||||
EmulateDATESelectMethod(date_options, rt, blend_alpha_min, blend_alpha_max);
|
||||
|
||||
// Before emulateblending, dither will be used
|
||||
m_conf.ps.dither = GSConfig.Dithering > 0 && m_conf.ps.dst_fmt == GSLocalMemory::PSM_FMT_16 && env.DTHE.DTHE;
|
||||
m_conf.ps.dither = GSConfig.Dithering > 0 && m_conf.ps.dst_fmt == GSLocalMemory::PSM_FMT_16 && !!env.DTHE.DTHE;
|
||||
|
||||
if (m_conf.ps.dst_fmt == GSLocalMemory::PSM_FMT_24)
|
||||
{
|
||||
@@ -9761,12 +9764,12 @@ bool GSRendererHW::TryGSMemClear(bool no_rt, bool preserve_rt, bool invalidate_r
|
||||
rt_end_bp, m_cached_ctx.FRAME.PSM, m_cached_ctx.FRAME.FBW, m_cached_ctx.FRAME.FBMSK);
|
||||
|
||||
GSUploadQueue clear_queue;
|
||||
clear_queue.transfer_type = EEGS_TransferType::Clear;
|
||||
clear_queue.draw = s_n;
|
||||
clear_queue.rect = m_r;
|
||||
clear_queue.blit.DBP = m_cached_ctx.FRAME.Block();
|
||||
clear_queue.blit.DBW = m_cached_ctx.FRAME.FBW;
|
||||
clear_queue.blit.DPSM = m_cached_ctx.FRAME.PSM;
|
||||
clear_queue.zero_clear = true;
|
||||
m_draw_transfers.push_back(clear_queue);
|
||||
}
|
||||
else
|
||||
@@ -9791,12 +9794,12 @@ bool GSRendererHW::TryGSMemClear(bool no_rt, bool preserve_rt, bool invalidate_r
|
||||
ds_end_bp, m_cached_ctx.ZBUF.PSM, m_cached_ctx.FRAME.FBW);
|
||||
|
||||
GSUploadQueue clear_queue;
|
||||
clear_queue.transfer_type = EEGS_TransferType::Clear;
|
||||
clear_queue.draw = s_n;
|
||||
clear_queue.rect = m_r;
|
||||
clear_queue.blit.DBP = m_cached_ctx.ZBUF.Block();
|
||||
clear_queue.blit.DBW = m_cached_ctx.FRAME.FBW;
|
||||
clear_queue.blit.DPSM = m_cached_ctx.ZBUF.PSM;
|
||||
clear_queue.zero_clear = true;
|
||||
m_draw_transfers.push_back(clear_queue);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -551,13 +551,13 @@ bool GSRendererHWFunctions::SwPrimRender(GSRendererHW& hw, bool invalidate_tc, b
|
||||
if (add_ee_transfer)
|
||||
{
|
||||
GSRendererHW::GSUploadQueue uq;
|
||||
uq.transfer_type = GSRendererHW::GetInstance()->EEGS_TransferType::EE_to_GS;
|
||||
uq.blit.U64 = 0;
|
||||
uq.blit.DBP = hw.m_cached_ctx.FRAME.Block();
|
||||
uq.blit.DBW = hw.m_cached_ctx.FRAME.FBW;
|
||||
uq.blit.DPSM = hw.m_cached_ctx.FRAME.PSM;
|
||||
uq.draw = GSState::s_n;
|
||||
uq.rect = bbox;
|
||||
uq.zero_clear = false;
|
||||
hw.m_draw_transfers.push_back(uq);
|
||||
}
|
||||
|
||||
|
||||
@@ -2261,20 +2261,34 @@ GSTextureCache::Source* GSTextureCache::LookupSource(const bool is_color, const
|
||||
}
|
||||
}
|
||||
|
||||
if (src->m_from_target && src->m_target_direct && src->m_region.HasEither())
|
||||
if (src->m_from_target && src->m_target_direct)
|
||||
{
|
||||
if (src->m_from_target->m_TEX0.TBP0 == src->m_TEX0.TBP0)
|
||||
GSVector4i req_rect = r;
|
||||
|
||||
// The read area might be offset but the start of the texture is at the beginning of the space.
|
||||
req_rect.x = region.HasX() ? region.GetMinX() : 0;
|
||||
req_rect.y = region.HasY() ? region.GetMinY() : 0;
|
||||
|
||||
const bool dirty_overlap = !src->m_from_target->m_dirty.GetTotalRect(src->m_from_target->m_TEX0, src->m_from_target->m_unscaled_size).rintersect(req_rect).rempty();
|
||||
|
||||
if (dirty_overlap)
|
||||
src->m_from_target->Update();
|
||||
|
||||
if (src->m_region.HasEither())
|
||||
{
|
||||
src->m_region.bits = 0;
|
||||
src->m_region.SetX(0, region.HasX() ? region.GetMaxX() : (1 << TEX0.TW));
|
||||
src->m_region.SetY(0, region.HasY() ? region.GetMaxY() : (1 << TEX0.TH));
|
||||
}
|
||||
else if (src->m_TEX0.TBP0 > src->m_from_target->m_TEX0.TBP0)
|
||||
{
|
||||
GSVector4i dst_offset = TranslateAlignedRectByPage(src->m_from_target, src->m_TEX0.TBP0, src->m_TEX0.PSM, src->m_TEX0.TBW, GSVector4i(0, 0, 1, 1), false);
|
||||
src->m_region.bits = 0;
|
||||
src->m_region.SetX(dst_offset.x, dst_offset.x + (region.HasX() ? std::min(region.GetMaxX(), (1 << TEX0.TW)) : (1 << TEX0.TW)));
|
||||
src->m_region.SetY(dst_offset.y, dst_offset.y + (region.HasY() ? std::min(region.GetMaxY(), (1 << TEX0.TH)) : (1 << TEX0.TH)));
|
||||
if (src->m_from_target->m_TEX0.TBP0 == src->m_TEX0.TBP0)
|
||||
{
|
||||
src->m_region.bits = 0;
|
||||
src->m_region.SetX(0, region.HasX() ? region.GetMaxX() : (1 << TEX0.TW));
|
||||
src->m_region.SetY(0, region.HasY() ? region.GetMaxY() : (1 << TEX0.TH));
|
||||
}
|
||||
else if (src->m_TEX0.TBP0 > src->m_from_target->m_TEX0.TBP0)
|
||||
{
|
||||
GSVector4i dst_offset = TranslateAlignedRectByPage(src->m_from_target, src->m_TEX0.TBP0, src->m_TEX0.PSM, src->m_TEX0.TBW, GSVector4i(0, 0, 1, 1), false);
|
||||
src->m_region.bits = 0;
|
||||
src->m_region.SetX(dst_offset.x, dst_offset.x + (region.HasX() ? std::min(region.GetMaxX(), (1 << TEX0.TW)) : (1 << TEX0.TW)));
|
||||
src->m_region.SetY(dst_offset.y, dst_offset.y + (region.HasY() ? std::min(region.GetMaxY(), (1 << TEX0.TH)) : (1 << TEX0.TH)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2349,7 +2363,7 @@ void GSTextureCache::CombineAlignedInsideTargets(Target* target, GSTextureCache:
|
||||
const GSVector4 target_drect = GSVector4(target_drect_unscaled) * target->m_scale;
|
||||
|
||||
const bool valid_color = t->m_valid_rgb;
|
||||
const bool valid_alpha = (t->m_valid_alpha_high | t->m_valid_alpha_low) && (GSUtil::GetChannelMask(t->m_TEX0.PSM) & 0x8);
|
||||
const bool valid_alpha = (t->m_valid_alpha_high || t->m_valid_alpha_low) && (GSUtil::GetChannelMask(t->m_TEX0.PSM) & 0x8);
|
||||
|
||||
target->m_valid_alpha_high |= t->m_valid_alpha_high;
|
||||
target->m_valid_alpha_low |= t->m_valid_alpha_low;
|
||||
@@ -3482,14 +3496,15 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
else
|
||||
eerect = eerect.runion(targetr);
|
||||
|
||||
const bool transfer_is_clear = iter->transfer_type == GSRendererHW::GetInstance()->EEGS_TransferType::Clear;
|
||||
// Later writes might be partial over a previously cleared area. We want to upload in these cases.
|
||||
hw_clear = hw_clear.has_value() ? (hw_clear.value() && iter->zero_clear) : iter->zero_clear;
|
||||
hw_clear = hw_clear.has_value() ? (hw_clear.value() && transfer_is_clear) : transfer_is_clear;
|
||||
|
||||
// When the write covers the entire target, don't bother checking any earlier writes.
|
||||
if (iter->blit.DBP <= TEX0.TBP0 && transfer_end >= rect_end)
|
||||
{
|
||||
// If it was a clear draw then we can use that as our target size.
|
||||
if (iter->zero_clear && iter->blit.DBP == TEX0.TBP0 && iter->blit.DPSM == TEX0.PSM)
|
||||
if (iter->transfer_type == GSRendererHW::GetInstance()->EEGS_TransferType::Clear && iter->blit.DBP == TEX0.TBP0 && iter->blit.DPSM == TEX0.PSM)
|
||||
dst->UpdateValidity(iter->rect);
|
||||
|
||||
// Some games clear RT and Z at the same time, only erase if it's specifically this target.
|
||||
@@ -3528,7 +3543,7 @@ bool GSTextureCache::PreloadTarget(GIFRegTEX0 TEX0, const GSVector2i& size, cons
|
||||
if (iter->draw < (GSState::s_n - 1))
|
||||
break;
|
||||
|
||||
if (iter->zero_clear && iter->blit.DBP == TEX0.TBP0 && iter->blit.DBW == TEX0.TBW)
|
||||
if (iter->transfer_type == GSRendererHW::GetInstance()->EEGS_TransferType::Clear && iter->blit.DBP == TEX0.TBP0 && iter->blit.DBW == TEX0.TBW)
|
||||
{
|
||||
hw_clear = true;
|
||||
transfers.erase(std::next(iter).base());
|
||||
@@ -3863,7 +3878,6 @@ GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, con
|
||||
const u32 bp = TEX0.TBP0;
|
||||
|
||||
Target* dst = nullptr;
|
||||
Target* dst_match = nullptr;
|
||||
auto* list = &m_dst[RenderTarget];
|
||||
|
||||
// Let's try to find a perfect frame that contains valid data
|
||||
@@ -4019,7 +4033,7 @@ GSTextureCache::Target* GSTextureCache::LookupDisplayTarget(GIFRegTEX0 TEX0, con
|
||||
else
|
||||
eerect = eerect.runion(targetr);
|
||||
|
||||
if (iter->zero_clear && iter->draw == last_draw)
|
||||
if (iter->transfer_type == GSRendererHW::GetInstance()->EEGS_TransferType::Clear && iter->draw == last_draw)
|
||||
{
|
||||
can_create = false;
|
||||
break;
|
||||
|
||||
@@ -263,7 +263,7 @@ public:
|
||||
|
||||
bool OverlapsValid(u32 bp, u32 bw, u32 psm, const GSVector4i& rect) const;
|
||||
|
||||
__fi bool HasValidAlpha() const { return (m_valid_alpha_low | m_valid_alpha_high); }
|
||||
__fi bool HasValidAlpha() const { return (m_valid_alpha_low || m_valid_alpha_high); }
|
||||
bool HasValidBitsForFormat(u32 psm, bool req_color, bool req_alpha, bool width_match);
|
||||
|
||||
void ResizeDrawn(const GSVector4i& rect);
|
||||
|
||||
@@ -4217,6 +4217,7 @@ TRANSLATE_NOOP("FullscreenUI", "Please enter your user name and password for ret
|
||||
TRANSLATE_NOOP("FullscreenUI", "Username");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Password");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Logging in...");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Dismiss");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Login");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Cancel");
|
||||
TRANSLATE_NOOP("FullscreenUI", "When enabled and logged in, PCSX2 will scan for achievements on startup.");
|
||||
@@ -4255,6 +4256,7 @@ TRANSLATE_NOOP("FullscreenUI", "Last Played: {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Size: {:.2f} MB");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Are you sure you want to reset the play time for '{}' ({})?\n\nYour current play time is {}.\n\nThis action cannot be undone.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Version: {}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Successfully logged in as {}.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Login failed.\nError: {}\n\nPlease check your username and password, and try again.");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to preview sound:\n{}");
|
||||
TRANSLATE_NOOP("FullscreenUI", "Failed to Load State From Backup Slot {}");
|
||||
|
||||
@@ -709,7 +709,7 @@ __fi void psxRcntWmode32(int index, u32 value)
|
||||
|
||||
// Current counter *always* resets on mode write.
|
||||
counter.count = 0;
|
||||
counter.startCycle = psxRegs.cycle & ~(counter.rate - 1);
|
||||
counter.startCycle = psxRegs.cycle & ~(static_cast<u64>(counter.rate - 1));
|
||||
counter.target &= 0xffffffff;
|
||||
_rcntSet(index);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user