mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Merge pull request #15611 from hrydgard/mali-bug-workaround
Workaround old Mali driver bug with discard + stencil
This commit is contained in:
commit
d07c256a1d
9 changed files with 76 additions and 4 deletions
|
@ -823,6 +823,11 @@ VKContext::VKContext(VulkanContext *vulkan, bool splitSubmit)
|
|||
// corrupt the depth buffer. This is easily worked around by simply scaling Z down a tiny bit when this case
|
||||
// is detected. See: https://github.com/hrydgard/ppsspp/issues/11937
|
||||
bugs_.Infest(Bugs::EQUAL_WZ_CORRUPTS_DEPTH);
|
||||
|
||||
if (IsHashMaliDriverVersion(deviceProps) || VK_VERSION_MAJOR(deviceProps.driverVersion) <= 16) {
|
||||
// At least one driver at the upper end of the range is known to be likely to suffer from the bug causing issue #13833 (Midnight Club map broken).
|
||||
bugs_.Infest(Bugs::MALI_STENCIL_DISCARD_BUG);
|
||||
}
|
||||
}
|
||||
|
||||
caps_.deviceID = deviceProps.deviceID;
|
||||
|
|
|
@ -592,5 +592,18 @@ void ConvertToD32F(uint8_t *dst, const uint8_t *src, uint32_t dstStride, uint32_
|
|||
}
|
||||
}
|
||||
|
||||
const char *Bugs::GetBugName(uint32_t bug) {
|
||||
switch (bug) {
|
||||
case NO_DEPTH_CANNOT_DISCARD_STENCIL: return "NO_DEPTH_CANNOT_DISCARD_STENCIL";
|
||||
case DUAL_SOURCE_BLENDING_BROKEN: return "DUAL_SOURCE_BLENDING_BROKEN";
|
||||
case ANY_MAP_BUFFER_RANGE_SLOW: return "ANY_MAP_BUFFER_RANGE_SLOW";
|
||||
case PVR_GENMIPMAP_HEIGHT_GREATER: return "PVR_GENMIPMAP_HEIGHT_GREATER";
|
||||
case BROKEN_NAN_IN_CONDITIONAL: return "BROKEN_NAN_IN_CONDITIONAL";
|
||||
case COLORWRITEMASK_BROKEN_WITH_DEPTHTEST: return "COLORWRITEMASK_BROKEN_WITH_DEPTHTEST";
|
||||
case BROKEN_FLAT_IN_SHADER: return "BROKEN_FLAT_IN_SHADER";
|
||||
case EQUAL_WZ_CORRUPTS_DEPTH: return "EQUAL_WZ_CORRUPTS_DEPTH";
|
||||
case MALI_STENCIL_DISCARD_BUG: return "MALI_STENCIL_DISCARD_BUG";
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Draw
|
||||
|
|
|
@ -308,6 +308,10 @@ public:
|
|||
void Infest(uint32_t bug) {
|
||||
flags_ |= (1 << bug);
|
||||
}
|
||||
uint32_t MaxBugIndex() const {
|
||||
return (uint32_t)MAX_BUG;
|
||||
}
|
||||
const char *GetBugName(uint32_t bug);
|
||||
|
||||
enum : uint32_t {
|
||||
NO_DEPTH_CANNOT_DISCARD_STENCIL = 0,
|
||||
|
@ -318,6 +322,8 @@ public:
|
|||
COLORWRITEMASK_BROKEN_WITH_DEPTHTEST = 5,
|
||||
BROKEN_FLAT_IN_SHADER = 6,
|
||||
EQUAL_WZ_CORRUPTS_DEPTH = 7,
|
||||
MALI_STENCIL_DISCARD_BUG = 8,
|
||||
MAX_BUG,
|
||||
};
|
||||
|
||||
protected:
|
||||
|
|
|
@ -81,6 +81,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
|||
CheckSetting(iniFile, gameID, "MpegAvcWarmUp", &flags_.MpegAvcWarmUp);
|
||||
CheckSetting(iniFile, gameID, "BlueToAlpha", &flags_.BlueToAlpha);
|
||||
CheckSetting(iniFile, gameID, "CenteredLines", &flags_.CenteredLines);
|
||||
CheckSetting(iniFile, gameID, "MaliDepthStencilBugWorkaround", &flags_.MaliDepthStencilBugWorkaround);
|
||||
}
|
||||
|
||||
void Compatibility::CheckSetting(IniFile &iniFile, const std::string &gameID, const char *option, bool *flag) {
|
||||
|
|
|
@ -80,6 +80,7 @@ struct CompatFlags {
|
|||
bool MpegAvcWarmUp;
|
||||
bool BlueToAlpha;
|
||||
bool CenteredLines;
|
||||
bool MaliDepthStencilBugWorkaround;
|
||||
};
|
||||
|
||||
class IniFile;
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
|
||||
#include "Common/GPU/thin3d.h"
|
||||
#include "Common/StringUtils.h"
|
||||
#include "Core/System.h"
|
||||
#include "Core/Config.h"
|
||||
|
||||
#include "GPU/ge_constants.h"
|
||||
|
@ -341,6 +342,10 @@ void ComputeFragmentShaderID(FShaderID *id_out, const Draw::Bugs &bugs) {
|
|||
if (g_Config.bVendorBugChecksEnabled) {
|
||||
if (bugs.Has(Draw::Bugs::NO_DEPTH_CANNOT_DISCARD_STENCIL)) {
|
||||
id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, !IsStencilTestOutputDisabled() && !gstate.isDepthWriteEnabled());
|
||||
} else if (bugs.Has(Draw::Bugs::MALI_STENCIL_DISCARD_BUG) && PSP_CoreParameter().compat.flags().MaliDepthStencilBugWorkaround) {
|
||||
// Very similar driver bug to the Adreno one, with the same workaround (though might look into if there are cheaper ones!)
|
||||
// Keeping the conditions separate since it can probably be made tighter.
|
||||
id.SetBit(FS_BIT_NO_DEPTH_CANNOT_DISCARD_STENCIL, !IsStencilTestOutputDisabled() && !gstate.isDepthWriteEnabled());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -682,6 +682,26 @@ void SystemInfoScreen::CreateViews() {
|
|||
cpuExtensions->Add(new TextView(exts[i], new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
ViewGroup *driverBugsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
driverBugsScroll->SetTag("DevSystemInfoDriverBugs");
|
||||
LinearLayout *driverBugs = new LinearLayoutList(ORIENT_VERTICAL);
|
||||
driverBugs->SetSpacing(0);
|
||||
driverBugsScroll->Add(driverBugs);
|
||||
|
||||
tabHolder->AddTab(si->T("Driver bugs"), driverBugsScroll);
|
||||
|
||||
bool anyDriverBugs = false;
|
||||
for (int i = 0; i < (int)draw->GetBugs().MaxBugIndex(); i++) {
|
||||
if (draw->GetBugs().Has(i)) {
|
||||
anyDriverBugs = true;
|
||||
driverBugs->Add(new TextView(draw->GetBugs().GetBugName(i), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
}
|
||||
|
||||
if (!anyDriverBugs) {
|
||||
driverBugs->Add(new TextView(si->T("No GPU driver bugs detected"), new LayoutParams(FILL_PARENT, WRAP_CONTENT)))->SetFocusable(true);
|
||||
}
|
||||
|
||||
ViewGroup *gpuExtensionsScroll = new ScrollView(ORIENT_VERTICAL, new LinearLayoutParams(FILL_PARENT, FILL_PARENT));
|
||||
gpuExtensionsScroll->SetTag("DevSystemInfoOGLExt");
|
||||
LinearLayout *gpuExtensions = new LinearLayoutList(ORIENT_VERTICAL);
|
||||
|
|
|
@ -321,6 +321,7 @@ void GPUDriverTestScreen::DiscardTest() {
|
|||
|
||||
InputLayout *inputLayout = ui_draw2d.CreateInputLayout(draw);
|
||||
BlendState *blendOff = draw->CreateBlendState({ false, 0xF });
|
||||
BlendState *blendOffNoColor = draw->CreateBlendState({ false, 0x8 });
|
||||
|
||||
// Write depth, write stencil.
|
||||
DepthStencilStateDesc dsDesc{};
|
||||
|
@ -331,8 +332,8 @@ void GPUDriverTestScreen::DiscardTest() {
|
|||
dsDesc.front.compareMask = 0xFF;
|
||||
dsDesc.front.compareOp = Comparison::ALWAYS;
|
||||
dsDesc.front.passOp = StencilOp::REPLACE;
|
||||
dsDesc.front.failOp = StencilOp::ZERO;
|
||||
dsDesc.front.depthFailOp = StencilOp::ZERO;
|
||||
dsDesc.front.failOp = StencilOp::REPLACE; // These two shouldn't matter, because the test that fails is discard, not stencil.
|
||||
dsDesc.front.depthFailOp = StencilOp::REPLACE;
|
||||
dsDesc.front.writeMask = 0xFF;
|
||||
dsDesc.back = dsDesc.front;
|
||||
DepthStencilState *depthStencilWrite = draw->CreateDepthStencilState(dsDesc);
|
||||
|
@ -353,6 +354,9 @@ void GPUDriverTestScreen::DiscardTest() {
|
|||
dsDesc.stencilEnabled = true;
|
||||
dsDesc.depthCompare = Comparison::ALWAYS;
|
||||
dsDesc.front.compareOp = Comparison::EQUAL;
|
||||
dsDesc.front.failOp = StencilOp::KEEP;
|
||||
dsDesc.front.depthFailOp = StencilOp::KEEP;
|
||||
dsDesc.front.writeMask = 0x0;
|
||||
dsDesc.back = dsDesc.front;
|
||||
DepthStencilState *stencilEqualDepthAlways = draw->CreateDepthStencilState(dsDesc);
|
||||
|
||||
|
@ -393,7 +397,7 @@ void GPUDriverTestScreen::DiscardTest() {
|
|||
PipelineDesc discardDesc{
|
||||
Primitive::TRIANGLE_LIST,
|
||||
{ draw->GetVshaderPreset(VS_TEXTURE_COLOR_2D), discardFragShader_ },
|
||||
inputLayout, depthStencilWrite, blendOff, rasterNoCull, &vsColBufDesc,
|
||||
inputLayout, depthStencilWrite, blendOffNoColor, rasterNoCull, &vsColBufDesc,
|
||||
};
|
||||
discardWriteDepthStencil_ = draw->CreateGraphicsPipeline(discardDesc);
|
||||
discardDesc.depthStencil = depthWrite;
|
||||
|
@ -501,7 +505,7 @@ void GPUDriverTestScreen::DiscardTest() {
|
|||
dc.Flush();
|
||||
|
||||
dc.BeginPipeline(writePipelines[j], samplerNearest_);
|
||||
// Draw the rectangle with stencil value 0, depth 0.1f and the text with stencil 0xFF, depth 0.9. Then leave 0xFF as the stencil value and draw the rectangles at depth 0.5.
|
||||
// Draw the rectangle with stencil value 0, depth 0.1f and the text with stencil 0xFF, depth 0.9. Then set 0xFF as the stencil value and draw the rectangles at depth 0.5.
|
||||
draw->SetStencilRef(0x0);
|
||||
dc.SetCurZ(0.1f);
|
||||
dc.FillRect(UI::Drawable(bgColorBAD), bounds);
|
||||
|
|
|
@ -586,6 +586,23 @@ NPJH50304 = true
|
|||
ULES00703 = true
|
||||
ULAS42095 = true
|
||||
|
||||
[MaliDepthStencilBugWorkaround]
|
||||
# See issue #13833 where the map is supposed to be round but is not.
|
||||
|
||||
# Midnight Club: LA Remix
|
||||
ULUS10383 = true
|
||||
ULES01144 = true
|
||||
ULJS00180 = true
|
||||
ULJS00267 = true
|
||||
ULJM05904 = true
|
||||
NPJH50440 = true
|
||||
# Midnight Club 3 : DUB edition
|
||||
ULUS10021 = true
|
||||
ULES00108 = true
|
||||
|
||||
# Tales of Phantasia - Narikiri Dungeon X. See #15526
|
||||
ULJS00293 = true
|
||||
|
||||
[RequireDefaultCPUClock]
|
||||
# GOW : Ghost of Sparta
|
||||
UCUS98737 = true
|
||||
|
|
Loading…
Add table
Reference in a new issue