Files
ppsspp/GPU/GPU.h
T
Henrik RydgårdandClaude Opus 5.5 b9b1a29c42 Read CLUT8 from 16-bit framebuffers in the shader, replacing the SOCOM hack
The shader depal CLUT8 mode now handles 565, 5551 and 4444 framebuffers
(the format goes in the depal format bits, which this mode didn't fill
before), rebuilding the 16-bit pixel and taking its low or high byte.
This replaces SOCOMClut8Replacement, which assumed the high byte.

- The GE samples a pixel at its corner, the GPU at its center. With u
  stepping two bytes per pixel (SOCOM and Bend's games use u = 1 + 2x)
  that's a whole byte, so the shader steps back to the corner.
- The CLUT index shift, mask and start are applied, as in the other
  depal modes.
- The self-render copy region counted CLUT8's U in pixels, not bytes.

SOCOM, Star Wars: The Force Unleashed and the NPJG90068 dumps improve a
lot. Syphon Filter and Resistance: Retribution now read the right bytes,
which exposes a 16-bit precision difference in their bright pass.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
2026-10-10 01:04:23 +02:00

181 lines
4.5 KiB
C++

// Copyright (c) 2015- PPSSPP Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0 or later versions.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official git repository and contact information can be found at
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
#pragma once
#include <cstring>
#include <cstdint>
enum GPUCore : int;
class GPUCommon;
class GPUCommon;
class GraphicsContext;
// PSP rasterization has two outputs, color and depth. Stencil is packed
// into the alpha channel of color (if exists), so possibly RASTER_COLOR
// should be named RASTER_COLOR_STENCIL but it gets kinda hard to read.
enum RasterChannel : uint8_t {
RASTER_COLOR = 0,
RASTER_DEPTH = 1,
};
enum SkipDrawReasonFlags {
SKIPDRAW_SKIPFRAME = 1,
SKIPDRAW_NON_DISPLAYED_FB = 2, // Skip drawing to FBO:s that have not been displayed.
SKIPDRAW_BAD_FB_TEXTURE = 4,
SKIPDRAW_WINDOW_MINIMIZED = 8, // Don't draw when the host window is minimized.
};
enum class ShaderDepalMode {
OFF = 0,
NORMAL = 1,
SMOOTHED = 2,
CLUT8 = 3, // Read a color framebuffer as 8-bit CLUT (the depal format bits say which format).
};
// Global GPU-related utility functions.
// Nothing directly Ge-related in here.
// PSP uses a curious 24-bit float - it's the top 24 bits of a regular IEEE754 32-bit float.
// This is used for light positions, transform matrices, you name it.
inline float getFloat24(unsigned int data) {
data <<= 8;
float f;
memcpy(&f, &data, 4);
return f;
}
// in case we ever want to generate PSP display lists...
inline unsigned int toFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
return i >> 8;
}
// TODO: Not completely sure about the exact mechanics here, or where we need to use this.
// Useful to experiment with.
inline float roundToFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
i &= 0xFFFFFF00;
i += 0x80; // TODO: Subtract for negative numbers?
float retval;
memcpy(&retval, &i, 4);
return retval;
}
inline float truncateToFloat24(float f) {
unsigned int i;
memcpy(&i, &f, 4);
i &= 0xFFFFFF00;
float retval;
memcpy(&retval, &i, 4);
return retval;
}
// TODO: Possibly use macros to disable expensive parts of stats tracking in release builds.
struct GPUStatsPerFrame {
int numEnqueue;
int numUpdateStall;
int numDrawSyncs;
int numListSyncs;
int numGEInterrupts;
int numDrawCalls;
int numVertexDecodes;
int numCulledDraws;
int numFlushes;
int numSoftTransformedDraws;
int numSoftClippedTriangles;
int numBBOXJumps;
int numVertsSubmitted;
int numVertsDecoded;
int numVertsDrawn;
int numTextureInvalidations;
int numTexturesChanged;
int numTextureInvalidationsByFramebuffer;
int numTexturesHashed;
int numTextureDataBytesHashed;
int numTexturesDecoded;
int numVideoTextures;
int numFramebufferEvaluations;
int numFBOsCreated;
int numBlockingReadbacks;
int numReadbacks;
int numUploads;
int numCachedUploads;
int numDepal;
int numClears;
int numDepthCopies;
int numReinterpretCopies;
int numColorCopies;
int numCopiesForShaderBlend;
int numCopiesForSelfTex;
int numBlockTransfers;
int numReplacerTrackedTex;
int numCachedReplacedTextures;
int numClutTextures;
double msProcessingDisplayLists;
double msPrepareDepth;
double msCullDepth;
double msRasterizeDepth;
double msRasterTimeAvailable;
int vertexGPUCycles;
int otherGPUCycles;
int numDepthRasterPrims;
int numDepthRasterEarlySize;
int numDepthRasterNoPixels;
int numDepthRasterTooSmall;
int numDepthRasterZCulled;
int numDepthEarlyBoxCulled;
};
struct GPUStatsTotals {
// Flip count. Doesn't really belong here.
int numFlips;
};
// The ToString function lives in GPUCommonHW.cpp.
struct GPUStatistics {
void Reset() {
ResetFrame();
totals = {};
}
void ResetFrame() {
perFrame = {};
}
// Flip count. Doesn't really belong here.
GPUStatsPerFrame perFrame;
GPUStatsTotals totals;
};
extern GPUStatistics gpuStats;
extern GPUCommon *gpu;
extern GPUCommon *gpu;
namespace Draw {
class DrawContext;
}
bool GPU_Init(GPUCore gpuCore, GraphicsContext *ctx, Draw::DrawContext *draw);
void GPU_Shutdown();
const char *RasterChannelToString(RasterChannel channel);