mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-24 11:49:05 +02:00
Merge pull request #21151 from hrydgard/brave-story-performance-hack
Brave Story: Hack to make the bloom effect run much more efficiently
This commit is contained in:
8 files changed
+45
-1
No files matched your search
@@ -155,6 +155,7 @@ void Compatibility::CheckSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
CheckSetting(iniFile, gameID, "IgnoreEnqueue", &flags_.IgnoreEnqueue);
|
||||
CheckSetting(iniFile, gameID, "MsgDialogAutoStatus", &flags_.MsgDialogAutoStatus);
|
||||
CheckSetting(iniFile, gameID, "NullPageValid", &flags_.NullPageValid);
|
||||
CheckSetting(iniFile, gameID, "DetectDestBlendSquared", &flags_.DetectDestBlendSquared);
|
||||
}
|
||||
|
||||
void Compatibility::CheckVRSettings(IniFile &iniFile, const std::string &gameID) {
|
||||
|
||||
@@ -118,6 +118,7 @@ struct CompatFlags {
|
||||
bool IgnoreEnqueue;
|
||||
bool MsgDialogAutoStatus;
|
||||
bool NullPageValid;
|
||||
bool DetectDestBlendSquared;
|
||||
};
|
||||
|
||||
struct VRCompat {
|
||||
|
||||
+1
-1
@@ -149,7 +149,7 @@ static bool Memory_TryBase(MemMapSetupFlags flags) {
|
||||
}
|
||||
}
|
||||
|
||||
int i; // the final values is used in the next loop
|
||||
int i; // the final value of i is used in the next loop
|
||||
for (i = 0; i < ARRAY_SIZE(views); i++) {
|
||||
const MemoryView &view = views[i];
|
||||
if (view.size == 0)
|
||||
|
||||
@@ -1273,6 +1273,21 @@ bool FramebufferManagerCommon::BindFramebufferAsColorTexture(int stage, VirtualF
|
||||
return true;
|
||||
}
|
||||
|
||||
// There's a special case we can handle here, where the game is texturing from the same pixels being read, in order to
|
||||
// implement a DST*DST blending function, which the PSP can't do. However on the PC we can absolutely do this!
|
||||
// TODO: Add more checks here.
|
||||
if (PSP_CoreParameter().compat.flags().DetectDestBlendSquared &&
|
||||
gstate.isAlphaBlendEnabled() && gstate.getBlendEq() == GE_BLENDMODE_MUL_AND_ADD && gstate.getBlendFuncA() == GE_SRCBLEND_DSTCOLOR && gstate.getBlendFuncB() == GE_DSTBLEND_FIXB && gstate.getFixB() == 0x0 &&
|
||||
gstate.getMaterialAmbientRGBA() == 0xFFFFFFFF) {
|
||||
// This is the pure DST*DST case, the SRC color is ignored.
|
||||
// Used by Brave Story - New Traveller. This assumes that texture coordinates are set to match the framebuffer pixels - and to
|
||||
// be able to make that assumption reasonably safely we use a compat flag to restrict it to that game.
|
||||
// We can just override the blend mode. Let's set a state variable.
|
||||
// We also just leave the last texture bound, ideally we should bind a placeholder here.
|
||||
gstate_c.dstSquared = true;
|
||||
return true;
|
||||
}
|
||||
|
||||
Draw::Framebuffer *renderCopy = GetTempFBO(TempFBO::COPY, framebuffer->renderWidth, framebuffer->renderHeight);
|
||||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
|
||||
@@ -1154,6 +1154,19 @@ static void ConvertBlendState(GenericBlendState &blendState, FBReadSetting useFB
|
||||
//
|
||||
// If we can't apply blending, we make a copy of the framebuffer and do it manually.
|
||||
|
||||
if (gstate_c.dstSquared && useFBRead != FBReadSetting::Forced) {
|
||||
blendState.blendEnabled = true;
|
||||
blendState.applyFramebufferRead = false;
|
||||
blendState.dirtyShaderBlendFixValues = false;
|
||||
blendState.useBlendColor = false;
|
||||
blendState.replaceBlend = REPLACE_BLEND_NO;
|
||||
blendState.simulateLogicOpType = SimulateLogicOpShaderTypeIfNeeded();
|
||||
blendState.replaceAlphaWithStencil = REPLACE_ALPHA_NO;
|
||||
blendState.setEquation(BlendEq::ADD, BlendEq::ADD);
|
||||
blendState.setFactors(BlendFactor::ZERO, BlendFactor::DST_COLOR, BlendFactor::ZERO, BlendFactor::ONE);
|
||||
return;
|
||||
}
|
||||
|
||||
blendState.applyFramebufferRead = false;
|
||||
blendState.dirtyShaderBlendFixValues = false;
|
||||
blendState.useBlendColor = false;
|
||||
|
||||
@@ -656,6 +656,9 @@ public:
|
||||
// We detect this case and go into a special drawing mode.
|
||||
bool blueToAlpha;
|
||||
|
||||
// DST squared, used in Brave Story
|
||||
bool dstSquared;
|
||||
|
||||
// U/V is 1:1 to pixels. Can influence texture sampling.
|
||||
bool pixelMapped;
|
||||
|
||||
|
||||
@@ -470,6 +470,7 @@ void DrawEngineVulkan::Flush() {
|
||||
if (result.action == SW_DRAW_INDEXED) {
|
||||
if (textureNeedsApply) {
|
||||
gstate_c.pixelMapped = result.pixelMapped;
|
||||
gstate_c.dstSquared = false;
|
||||
textureCache_->ApplyTexture();
|
||||
gstate_c.pixelMapped = false;
|
||||
textureCache_->GetVulkanHandles(imageView, sampler);
|
||||
@@ -477,6 +478,9 @@ void DrawEngineVulkan::Flush() {
|
||||
imageView = (VkImageView)draw_->GetNativeObject(gstate_c.textureIsArray ? Draw::NativeObject::NULL_IMAGEVIEW_ARRAY : Draw::NativeObject::NULL_IMAGEVIEW);
|
||||
if (sampler == VK_NULL_HANDLE)
|
||||
sampler = nullSampler_;
|
||||
if (gstate_c.dstSquared) {
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE);
|
||||
}
|
||||
}
|
||||
if (!lastPipeline_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_FRAGMENTSHADER_STATE | DIRTY_GEOMETRYSHADER_STATE) || prim != lastPrim_) {
|
||||
if (prim != lastPrim_ || gstate_c.IsDirty(DIRTY_BLEND_STATE | DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_RASTER_STATE | DIRTY_DEPTHSTENCIL_STATE)) {
|
||||
|
||||
@@ -2106,3 +2106,10 @@ UCES01473 = true
|
||||
NPJG90095 = true
|
||||
NPEG90035 = true
|
||||
NPUG70125 = true
|
||||
|
||||
[DetectDestBlendSquared]
|
||||
# Fixes the problem in Brave Story where we had to copy the framebuffer to blend it with itself.
|
||||
# We can just do that blend natively on PC. See #19820
|
||||
ULUS10279 = true
|
||||
UCJS10024 = true
|
||||
UCAS40096 = true
|
||||
Reference in new issue
Block a user