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:
Henrik Rydgård authored and GitHub committed 2026-01-24 00:55:57 +01:00
commit 3a330889db
8 files changed
+45 -1

No files matched your search

+1
View File
@@ -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) {
+1
View File
@@ -118,6 +118,7 @@ struct CompatFlags {
bool IgnoreEnqueue;
bool MsgDialogAutoStatus;
bool NullPageValid;
bool DetectDestBlendSquared;
};
struct VRCompat {
+1 -1
View File
@@ -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)
+15
View File
@@ -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;
+13
View File
@@ -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;
+3
View File
@@ -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;
+4
View File
@@ -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)) {
+7
View File
@@ -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