Files
ppsspp/GPU/Common/DepthRaster.h
T
Henrik RydgårdandClaude Opus 5 7a13881245 DepthRaster: fix host buffer overflows in the depth raster queue
CalculateDepthDraw guarded depthVertexCount_ with vertexCount, which is the
index count - but depthVertexCount_ grows by the number of decoded vertices,
which for an indexed draw can be far larger. Two draws with 6 indices spanning
40000 vertices each therefore passed the check and wrote ~700KB past the end of
depthTransformed_. It also never bounded depthIndexCount_ against depthIndices_
at all, which only has room for 3 indices per vertex slot while draws routinely
produce more. Pass the decoded count in separately and check both.

DepthRasterClipIndexedTriangles duplicated culling-disabled triangles twice: once
in the collect loop (added for Syphon Filter, #21498) and again in the output
stage, which was the older code and should have been removed then. So it emitted
four triangles per input triangle into buffers sized for one, and did twice the
rasterization work it needed to in that mode. Removed the output-stage copy, and
gave the function the output capacity so it stops when full - even at 2x, a
culling-disabled draw over ~32k indices doesn't fit.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01DCPmm7FoQUoqrbMdhfqhQ2
2026-08-30 22:33:01 +02:00

61 lines
2.0 KiB
C++

#pragma once
#include "Common/CommonTypes.h"
#include "GPU/ge_constants.h"
struct DepthScreenVertex {
int x;
int y;
int z;
};
// X11.h, sigh.
#ifdef Always
#undef Always
#endif
// We only need to support these three modes.
enum class ZCompareMode : u8 {
Greater, // Most common
Less, // Less common
Always, // Mostly used for clears
};
struct DepthScissor {
u16 x1;
u16 y1;
u16 x2;
u16 y2;
DepthScissor Tile(int tile, int numTiles) const;
};
struct DepthDraw {
u32 depthAddr;
u16 depthStride;
u8 cullMode;
GEPrimitiveType prim;
ZCompareMode compareMode;
bool cullEnabled;
DepthScissor scissor;
int vertexOffset;
int indexOffset;
int vertexCount;
};
// Specialized, very limited depth-only rasterizer.
// Meant to run in parallel with hardware rendering, in games that read back the depth buffer
// for effects like lens flare.
// So, we can be quite inaccurate without any issues, and skip a lot of functionality.
class VertexDecoder;
struct TransformedVertex;
// maxOutCount is the capacity of each of tx/ty/tz, in elements.
int DepthRasterClipIndexedTriangles(int *tx, int *ty, float *tz, const float *transformed, const uint16_t *indexBuffer, const DepthDraw &draw, const DepthScissor scissor, int maxOutCount);
int DepthRasterClipIndexedRectangles(int *tx, int *ty, float *tz, const float *transformed, const uint16_t *indexBuffer, const DepthDraw &draw, const DepthScissor scissor);
void DecodeAndTransformForDepthRaster(float *dest, const float *worldviewproj, const void *vertexData, int indexLowerBound, int indexUpperBound, const VertexDecoder *dec, u32 vertTypeID);
void TransformPredecodedForDepthRaster(float *dest, const float *worldviewproj, const void *decodedVertexData, const VertexDecoder *dec, int count);
void ConvertPredecodedThroughForDepthRaster(float *dest, const void *decodedVertexData, const VertexDecoder *dec, int count);
void DepthRasterScreenVerts(uint16_t *depth, int depthStride, const int *tx, const int *ty, const float *tz, int count, const DepthDraw &draw, const DepthScissor scissor, bool lowQ);