Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
hrydgard
GitHub Repository: hrydgard/ppsspp
Path: blob/master/GPU/Common/FramebufferManagerCommon.h
5658 views
1
// Copyright (c) 2012- PPSSPP Project.
2
3
// This program is free software: you can redistribute it and/or modify
4
// it under the terms of the GNU General Public License as published by
5
// the Free Software Foundation, version 2.0 or later versions.
6
7
// This program is distributed in the hope that it will be useful,
8
// but WITHOUT ANY WARRANTY; without even the implied warranty of
9
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
// GNU General Public License 2.0 for more details.
11
12
// A copy of the GPL 2.0 should have been included with the program.
13
// If not, see http://www.gnu.org/licenses/
14
15
// Official git repository and contact information can be found at
16
// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17
18
// TODO: We now have the tools in thin3d to nearly eliminate the backend-specific framebuffer managers.
19
// Here's a list of functionality to unify into FramebufferManagerCommon:
20
// * DrawActiveTexture
21
// * BlitFramebuffer
22
//
23
// Also, in TextureCache we should be able to unify texture-based depal.
24
25
#pragma once
26
27
#include <vector>
28
#include <unordered_map>
29
30
#include "Common/CommonTypes.h"
31
#include "Common/Log.h"
32
#include "Common/GPU/thin3d.h"
33
#include "Core/Config.h"
34
#include "Core/ConfigValues.h"
35
#include "GPU/GPU.h"
36
#include "GPU/GPUDefinitions.h"
37
#include "GPU/ge_constants.h"
38
#include "GPU/Common/Draw2D.h"
39
40
enum {
41
FB_USAGE_DISPLAYED_FRAMEBUFFER = 1,
42
FB_USAGE_RENDER_COLOR = 2,
43
FB_USAGE_TEXTURE = 4,
44
FB_USAGE_CLUT = 8,
45
FB_USAGE_DOWNLOAD = 16,
46
FB_USAGE_DOWNLOAD_CLEAR = 32,
47
FB_USAGE_BLUE_TO_ALPHA = 64,
48
FB_USAGE_FIRST_FRAME_SAVED = 128,
49
FB_USAGE_RENDER_DEPTH = 256,
50
FB_USAGE_COLOR_MIXED_DEPTH = 512,
51
FB_USAGE_INVALIDATE_DEPTH = 1024, // used to clear depth buffers.
52
};
53
54
enum {
55
FB_NON_BUFFERED_MODE = 0,
56
FB_BUFFERED_MODE = 1,
57
};
58
59
namespace Draw {
60
class Framebuffer;
61
}
62
63
class VulkanFBO;
64
class ShaderWriter;
65
66
// We have to track VFBs and depth buffers together, since bits are shared between the color alpha channel
67
// and the stencil buffer on the PSP.
68
// Sometimes, virtual framebuffers need to share a Z buffer. We emulate this by copying from on to the next
69
// when such a situation is detected. In order to reliably detect this, we separately track depth buffers,
70
// and they know which color buffer they were used with last.
71
// Two VirtualFramebuffer can occupy the same address range as long as they have different fb_format.
72
// In that case, the one with the highest colorBindSeq number is the valid one.
73
struct VirtualFramebuffer {
74
u32 fb_address;
75
u32 z_address; // If 0, it's a "RAM" framebuffer.
76
u16 fb_stride;
77
u16 z_stride;
78
79
// The original PSP format of the framebuffer.
80
// In reality they are all RGBA8888 for better quality but this is what the PSP thinks it is. This is necessary
81
// when we need to interpret the bits directly (depal or buffer aliasing).
82
// NOTE: CANNOT be changed after creation anymore!
83
GEBufferFormat fb_format;
84
85
Draw::Framebuffer *fbo;
86
87
// width/height: The detected size of the current framebuffer, in original PSP pixels.
88
u16 width;
89
u16 height;
90
91
// bufferWidth/bufferHeight: The pre-scaling size of the buffer itself. May only be bigger than or equal to width/height.
92
// In original PSP pixels - actual framebuffer is this size times the render resolution multiplier.
93
// The buffer may be used to render a width or height from 0 to these values without being recreated.
94
u16 bufferWidth;
95
u16 bufferHeight;
96
97
// renderWidth/renderHeight: The scaled size we render at. May be scaled to render at higher resolutions.
98
// These are simply bufferWidth/Height * renderScaleFactor and are thus redundant.
99
u16 renderWidth;
100
u16 renderHeight;
101
102
// Attempt to keep track of a bounding rectangle of what's been actually drawn. Coarse, but might be smaller
103
// than width/height if framebuffer has been enlarged. In PSP pixels.
104
u16 drawnWidth;
105
u16 drawnHeight;
106
107
// The dimensions at which we are confident that we can read back this buffer without stomping on irrelevant memory.
108
u16 safeWidth;
109
u16 safeHeight;
110
111
// The scale factor at which we are rendering (to achieve higher resolution).
112
u8 renderScaleFactor;
113
114
u16 usageFlags;
115
116
// These are used to track state to try to avoid buffer size shifting back and forth.
117
// You might think that doesn't happen since we mostly grow framebuffers, but we do resize down,
118
// if the size has shrunk for a while and the framebuffer is also larger than the stride.
119
// At this point, the "safe" size is probably a lie, and we have had various issues with readbacks, so this resizes down to avoid them.
120
// An example would be a game that always uses the address 0x00154000 for temp buffers, and uses it for a full-screen effect for 3 frames, then goes back to using it for character shadows or something much smaller.
121
u16 newWidth;
122
u16 newHeight;
123
124
// The frame number at which this was last resized.
125
int lastFrameNewSize;
126
127
// Tracking for downloads-to-CLUT.
128
u16 clutUpdatedBytes;
129
130
// Means that the whole image has already been read back to memory - used when combining small readbacks (gameUsesSequentialCopies_).
131
bool memoryUpdated;
132
133
// TODO: Fold into usageFlags?
134
bool dirtyAfterDisplay;
135
bool reallyDirtyAfterDisplay; // takes frame skipping into account
136
137
// Global sequence numbers for the last time these were bound.
138
// Not based on frames at all. Can be used to determine new-ness of one framebuffer over another,
139
// can even be within a frame.
140
int colorBindSeq;
141
int depthBindSeq;
142
143
// These are mainly used for garbage collection purposes and similar.
144
// Cannot be used to determine new-ness against a similar other buffer, since they are
145
// only at frame granularity.
146
int last_frame_used;
147
int last_frame_attached;
148
int last_frame_render;
149
int last_frame_displayed;
150
int last_frame_clut;
151
int last_frame_failed;
152
int last_frame_depth_updated;
153
int last_frame_depth_render;
154
155
// Convenience methods
156
inline int WidthInBytes() const { return width * BufferFormatBytesPerPixel(fb_format); }
157
inline int BufferWidthInBytes() const { return bufferWidth * BufferFormatBytesPerPixel(fb_format); }
158
inline int FbStrideInBytes() const { return fb_stride * BufferFormatBytesPerPixel(fb_format); }
159
inline int ZStrideInBytes() const { return z_stride * 2; }
160
161
inline int Stride(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_stride : z_stride; }
162
inline u32 Address(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_address : z_address; }
163
inline GEBufferFormat Format(RasterChannel channel) const { return channel == RASTER_COLOR ? fb_format : GE_FORMAT_DEPTH16; }
164
inline int BindSeq(RasterChannel channel) const { return channel == RASTER_COLOR ? colorBindSeq : depthBindSeq; }
165
166
// Computed from stride.
167
int BufferByteSize(RasterChannel channel) const { return BufferByteStride(channel) * height; }
168
int BufferByteStride(RasterChannel channel) const {
169
return channel == RASTER_COLOR ? fb_stride * (fb_format == GE_FORMAT_8888 ? 4 : 2) : z_stride * 2;
170
}
171
int BufferByteWidth(RasterChannel channel) const {
172
return channel == RASTER_COLOR ? width * (fb_format == GE_FORMAT_8888 ? 4 : 2) : width * 2;
173
}
174
};
175
176
struct FramebufferHeuristicParams {
177
u32 fb_address;
178
u32 z_address;
179
u16 fb_stride;
180
u16 z_stride;
181
GEBufferFormat fb_format;
182
bool isClearingDepth;
183
bool isWritingDepth;
184
bool isDrawing;
185
bool isModeThrough;
186
bool isBlending;
187
int viewportWidth;
188
int viewportHeight;
189
int16_t regionWidth;
190
int16_t regionHeight;
191
int16_t scissorLeft;
192
int16_t scissorTop;
193
int16_t scissorRight;
194
int16_t scissorBottom;
195
};
196
197
struct GPUgstate;
198
extern GPUgstate gstate;
199
200
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate);
201
202
enum BindFramebufferColorFlags {
203
BINDFBCOLOR_SKIP_COPY = 0,
204
BINDFBCOLOR_MAY_COPY = 1,
205
BINDFBCOLOR_MAY_COPY_WITH_UV = 3, // includes BINDFBCOLOR_MAY_COPY
206
BINDFBCOLOR_APPLY_TEX_OFFSET = 4,
207
// Used when rendering to a temporary surface (e.g. not the current render target.)
208
BINDFBCOLOR_FORCE_SELF = 8,
209
BINDFBCOLOR_UNCACHED = 16,
210
};
211
212
enum DrawTextureFlags {
213
DRAWTEX_NEAREST = 0,
214
DRAWTEX_LINEAR = 1,
215
DRAWTEX_TO_BACKBUFFER = 8,
216
DRAWTEX_DEPTH = 16,
217
};
218
219
inline DrawTextureFlags operator | (const DrawTextureFlags &lhs, const DrawTextureFlags &rhs) {
220
return DrawTextureFlags((u32)lhs | (u32)rhs);
221
}
222
223
enum class TempFBO {
224
DEPAL,
225
BLIT,
226
// For copies of framebuffers (e.g. shader blending.)
227
COPY,
228
// Used for copies when setting color to depth.
229
Z_COPY,
230
// Used to copy stencil data, means we need a stencil backing.
231
STENCIL,
232
};
233
234
inline Draw::DataFormat GEFormatToThin3D(GEBufferFormat geFormat) {
235
switch (geFormat) {
236
case GE_FORMAT_4444:
237
return Draw::DataFormat::A4R4G4B4_UNORM_PACK16;
238
case GE_FORMAT_5551:
239
return Draw::DataFormat::A1R5G5B5_UNORM_PACK16;
240
case GE_FORMAT_565:
241
return Draw::DataFormat::R5G6B5_UNORM_PACK16;
242
case GE_FORMAT_8888:
243
return Draw::DataFormat::R8G8B8A8_UNORM;
244
case GE_FORMAT_DEPTH16:
245
return Draw::DataFormat::D16;
246
default:
247
// TODO: Assert?
248
return Draw::DataFormat::UNDEFINED;
249
}
250
}
251
252
// Dimensions are in bytes, later steps get to convert back into real coordinates as appropriate.
253
// Makes it easy to see if blits match etc.
254
struct BlockTransferRect {
255
VirtualFramebuffer *vfb;
256
RasterChannel channel; // We usually only deal with color, but we have limited depth block transfer support now.
257
258
int x_bytes;
259
int y;
260
int w_bytes;
261
int h;
262
263
std::string ToString() const;
264
265
int w_pixels() const {
266
return w_bytes / BufferFormatBytesPerPixel(vfb->fb_format);
267
}
268
int x_pixels() const {
269
return x_bytes / BufferFormatBytesPerPixel(vfb->fb_format);
270
}
271
};
272
273
namespace Draw {
274
class DrawContext;
275
}
276
277
struct DrawPixelsEntry {
278
Draw::Texture *tex;
279
uint64_t contentsHash;
280
int frameNumber;
281
};
282
283
struct GPUDebugBuffer;
284
class DrawEngineCommon;
285
class PresentationCommon;
286
class ShaderManagerCommon;
287
class TextureCacheCommon;
288
struct DisplayLayoutConfig;
289
290
class FramebufferManagerCommon {
291
public:
292
FramebufferManagerCommon(Draw::DrawContext *draw);
293
virtual ~FramebufferManagerCommon();
294
295
void SetTextureCache(TextureCacheCommon *tc) {
296
textureCache_ = tc;
297
}
298
void SetShaderManager(ShaderManagerCommon * sm) {
299
shaderManager_ = sm;
300
}
301
void SetDrawEngine(DrawEngineCommon *td) {
302
drawEngine_ = td;
303
}
304
305
void Init(int msaaLevel);
306
virtual void BeginFrame(const DisplayLayoutConfig &config);
307
void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format);
308
void DestroyFramebuf(VirtualFramebuffer *v);
309
310
VirtualFramebuffer *DoSetRenderFrameBuffer(FramebufferHeuristicParams &params, u32 skipDrawReason);
311
VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason, bool *changed) {
312
// Inlining this part since it's so frequent.
313
if (!framebufChanged && currentRenderVfb_) {
314
currentRenderVfb_->last_frame_render = gpuStats.numFlips;
315
currentRenderVfb_->dirtyAfterDisplay = true;
316
if (!skipDrawReason)
317
currentRenderVfb_->reallyDirtyAfterDisplay = true;
318
*changed = false;
319
return currentRenderVfb_;
320
} else {
321
// This is so that we will be able to drive DoSetRenderFramebuffer with inputs
322
// that come from elsewhere than gstate.
323
FramebufferHeuristicParams inputs;
324
GetFramebufferHeuristicInputs(&inputs, gstate);
325
VirtualFramebuffer *vfb = DoSetRenderFrameBuffer(inputs, skipDrawReason);
326
_dbg_assert_msg_(vfb, "DoSetRenderFramebuffer must return a valid framebuffer.");
327
_dbg_assert_msg_(currentRenderVfb_, "DoSetRenderFramebuffer must set a valid framebuffer.");
328
*changed = true;
329
return vfb;
330
}
331
}
332
void SetDepthFrameBuffer(bool isClearingDepth);
333
334
void RebindFramebuffer(const char *tag);
335
std::vector<const VirtualFramebuffer *> GetFramebufferList() const;
336
337
void CopyDisplayToOutput(const DisplayLayoutConfig &config, bool reallyDirty);
338
339
bool NotifyFramebufferCopy(u32 src, u32 dest, int size, GPUCopyFlag flags, u32 skipDrawReason);
340
void PerformWriteFormattedFromMemory(u32 addr, int size, int width, GEBufferFormat fmt);
341
void UpdateFromMemory(u32 addr, int size);
342
void ApplyClearToMemory(int x1, int y1, int x2, int y2, u32 clearColor);
343
bool PerformWriteStencilFromMemory(u32 addr, int size, WriteStencil flags);
344
345
// We changed our depth mode, gotta start over.
346
// Ideally, we should convert depth buffers here, not just clear them.
347
void ClearAllDepthBuffers();
348
349
// Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it.
350
// In that case we hardly need to actually copy the bytes in VRAM, they will be wrong anyway (unless
351
// read framebuffers is on, in which case this should always return false).
352
// If this returns false, a memory copy will happen and NotifyBlockTransferAfter will be called.
353
bool NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason);
354
355
// This gets called after the memory copy, in case NotifyBlockTransferBefore returned false.
356
// Otherwise it doesn't get called.
357
void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason);
358
359
bool BindFramebufferAsColorTexture(int stage, VirtualFramebuffer *framebuffer, int flags, int layer);
360
void ReadFramebufferToMemory(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
361
362
void DownloadFramebufferForClut(u32 fb_address, u32 loadBytes);
363
bool DrawFramebufferToOutput(const DisplayLayoutConfig &config, const u8 *srcPixels, int srcStride, GEBufferFormat srcPixelFormat);
364
365
// TODO: Should split into one that uses config, and one that doesn't.
366
void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height, RasterChannel channel, const char *tag);
367
368
size_t NumVFBs() const { return vfbs_.size(); }
369
370
u32 PrevDisplayFramebufAddr() const {
371
return prevDisplayFramebuf_ ? prevDisplayFramebuf_->fb_address : 0;
372
}
373
u32 CurrentDisplayFramebufAddr() const {
374
return displayFramebuf_ ? displayFramebuf_->fb_address : 0;
375
}
376
377
u32 DisplayFramebufAddr() const {
378
return displayFramebufPtr_;
379
}
380
u32 DisplayFramebufStride() const {
381
return displayStride_;
382
}
383
GEBufferFormat DisplayFramebufFormat() const {
384
return displayFormat_;
385
}
386
387
bool UseBufferedRendering() const {
388
return useBufferedRendering_;
389
}
390
391
void ForceUseBufferedRendering(bool buf) {
392
useBufferedRendering_ = true;
393
}
394
395
// TODO: Maybe just include the last depth buffer address in this, too.
396
bool MayIntersectFramebufferColor(u32 start) const {
397
// Clear the cache/kernel bits.
398
start &= 0x3FFFFFFF;
399
if (Memory::IsVRAMAddress(start))
400
start &= 0x041FFFFF;
401
// Most games only have two framebuffers at the start.
402
if (start >= framebufColorRangeEnd_ || start < PSP_GetVidMemBase()) {
403
return false;
404
}
405
return true;
406
}
407
408
VirtualFramebuffer *GetCurrentRenderVFB() const {
409
return currentRenderVfb_;
410
}
411
412
// This only checks for the color channel, and if there are multiple overlapping ones
413
// with different color depth, this might get things wrong.
414
// DEPRECATED FOR NEW USES - avoid whenever possible.
415
VirtualFramebuffer *GetVFBAt(u32 addr) const;
416
417
// This will only return exact matches of addr+stride+format.
418
VirtualFramebuffer *GetExactVFB(u32 addr, int stride, GEBufferFormat format) const;
419
420
// If this doesn't find the exact VFB, but one with a different color format with matching stride,
421
// it'll resolve the newest one at address to the format requested, and return that.
422
VirtualFramebuffer *ResolveVFB(u32 addr, int stride, GEBufferFormat format);
423
424
// Utility to get the display VFB.
425
VirtualFramebuffer *GetDisplayVFB();
426
427
int GetRenderWidth() const { return currentRenderVfb_ ? currentRenderVfb_->renderWidth : 480; }
428
int GetRenderHeight() const { return currentRenderVfb_ ? currentRenderVfb_->renderHeight : 272; }
429
int GetTargetWidth() const { return currentRenderVfb_ ? currentRenderVfb_->width : 480; }
430
int GetTargetHeight() const { return currentRenderVfb_ ? currentRenderVfb_->height : 272; }
431
int GetTargetBufferWidth() const { return currentRenderVfb_ ? currentRenderVfb_->bufferWidth : 480; }
432
int GetTargetBufferHeight() const { return currentRenderVfb_ ? currentRenderVfb_->bufferHeight : 272; }
433
int GetTargetStride() const { return currentRenderVfb_ ? currentRenderVfb_->fb_stride : 512; }
434
GEBufferFormat GetTargetFormat() const { return currentRenderVfb_ ? currentRenderVfb_->fb_format : displayFormat_; }
435
436
void SetColorUpdated(int skipDrawReason) {
437
if (currentRenderVfb_) {
438
SetColorUpdated(currentRenderVfb_, skipDrawReason);
439
}
440
}
441
void SetSafeSize(u16 w, u16 h);
442
443
void NotifyRenderResized(const DisplayLayoutConfig &config, int msaaLevel);
444
virtual void NotifyDisplayResized();
445
void NotifyConfigChanged();
446
447
void CheckPostShaders(const DisplayLayoutConfig &config);
448
449
virtual void DestroyAllFBOs();
450
451
virtual void DeviceLost();
452
virtual void DeviceRestore(Draw::DrawContext *draw);
453
454
Draw::Framebuffer *GetTempFBO(TempFBO reason, u16 w, u16 h);
455
456
// Debug features
457
virtual bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes);
458
virtual bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer);
459
virtual bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer);
460
virtual bool GetOutputFramebuffer(GPUDebugBuffer &buffer);
461
462
const std::vector<VirtualFramebuffer *> &Framebuffers() const {
463
return vfbs_;
464
}
465
466
Draw2D *GetDraw2D() {
467
return &draw2D_;
468
}
469
470
// If a vfb with the target format exists, resolve it (run CopyToColorFromOverlappingFramebuffers).
471
// If it doesn't exist, create it and do the same.
472
// Returns the resolved framebuffer.
473
VirtualFramebuffer *ResolveFramebufferColorToFormat(VirtualFramebuffer *vfb, GEBufferFormat newFormat);
474
475
Draw2DPipeline *Get2DPipeline(Draw2DShader shader);
476
477
// If from==to, returns a copy pipeline.
478
Draw2DPipeline *GetReinterpretPipeline(GEBufferFormat from, GEBufferFormat to, float *scaleFactorX);
479
480
// Public to be used from the texture cache's depal shenanigans.
481
void BlitUsingRaster(
482
Draw::Framebuffer *src, float srcX1, float srcY1, float srcX2, float srcY2,
483
Draw::Framebuffer *dest, float destX1, float destY1, float destX2, float destY2,
484
bool linearFilter,
485
int scaleFactor, // usually unused, except for swizzle...
486
Draw2DPipeline *pipeline, const char *tag);
487
488
void ReleasePipelines();
489
490
int GetMSAALevel() const {
491
return msaaLevel_;
492
}
493
494
void DiscardFramebufferCopy() {
495
currentFramebufferCopy_ = nullptr;
496
}
497
498
bool PresentedThisFrame() const;
499
500
const std::vector<VirtualFramebuffer *> &GetVFBs() const {
501
return vfbs_;
502
}
503
504
// Hack, only needed for non-buffered rendering.
505
const DisplayLayoutConfig &GetDisplayLayoutConfigCopy() const {
506
return displayLayoutConfigCopy_;
507
}
508
509
protected:
510
virtual void ReadbackFramebuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h, RasterChannel channel, Draw::ReadbackMode mode);
511
// Used for when a shader is required, such as GLES.
512
virtual bool ReadbackDepthbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint16_t *pixels, int pixelsStride, int destW, int destH, Draw::ReadbackMode mode);
513
virtual bool ReadbackStencilbuffer(Draw::Framebuffer *fbo, int x, int y, int w, int h, uint8_t *pixels, int pixelsStride, Draw::ReadbackMode mode);
514
void SetViewport2D(int x, int y, int w, int h);
515
Draw::Texture *MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height);
516
void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation, int flags);
517
518
void CopyToColorFromOverlappingFramebuffers(VirtualFramebuffer *dest);
519
void CopyToDepthFromOverlappingFramebuffers(VirtualFramebuffer *dest);
520
521
bool UpdateRenderSize(int msaaLevel);
522
523
void FlushBeforeCopy();
524
virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra
525
526
// Used by ReadFramebufferToMemory and later framebuffer block copies
527
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp, RasterChannel channel, const char *tag);
528
529
void CopyFramebufferForColorTexture(VirtualFramebuffer *dst, VirtualFramebuffer *src, int flags, int layer, bool *partial);
530
531
void EstimateDrawingSize(u32 fb_address, int fb_stride, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int &drawing_width, int &drawing_height);
532
533
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb);
534
static void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb);
535
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth);
536
537
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst, bool allowSizeMismatch = false);
538
539
void ResizeFramebufFBO(VirtualFramebuffer *vfb, int w, int h, bool force = false, bool skipCopy = false);
540
541
static bool ShouldDownloadFramebufferColor(const VirtualFramebuffer *vfb);
542
static bool ShouldDownloadFramebufferDepth(const VirtualFramebuffer *vfb);
543
void DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb);
544
545
bool FindTransferFramebuffer(u32 basePtr, int stride, int x, int y, int w, int h, int bpp, bool destination, BlockTransferRect *rect);
546
547
VirtualFramebuffer *FindDownloadTempBuffer(VirtualFramebuffer *vfb, RasterChannel channel);
548
virtual void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) {}
549
550
VirtualFramebuffer *CreateRAMFramebuffer(uint32_t fbAddress, int width, int height, int stride, GEBufferFormat format);
551
552
void UpdateFramebufUsage(VirtualFramebuffer *vfb) const;
553
554
int GetFramebufferLayers() const;
555
556
static void SetColorUpdated(VirtualFramebuffer *dstBuffer, int skipDrawReason) {
557
dstBuffer->memoryUpdated = false;
558
dstBuffer->clutUpdatedBytes = 0;
559
dstBuffer->dirtyAfterDisplay = true;
560
dstBuffer->drawnWidth = dstBuffer->width;
561
dstBuffer->drawnHeight = dstBuffer->height;
562
if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0)
563
dstBuffer->reallyDirtyAfterDisplay = true;
564
}
565
566
inline int GetBindSeqCount() {
567
return fbBindSeqCount_++;
568
}
569
570
static SkipGPUReadbackMode GetSkipGPUReadbackMode();
571
572
PresentationCommon *presentation_ = nullptr;
573
574
Draw::DrawContext *draw_ = nullptr;
575
576
TextureCacheCommon *textureCache_ = nullptr;
577
ShaderManagerCommon *shaderManager_ = nullptr;
578
DrawEngineCommon *drawEngine_ = nullptr;
579
580
bool needBackBufferYSwap_ = false;
581
582
u32 displayFramebufPtr_ = 0;
583
u32 displayStride_ = 0;
584
GEBufferFormat displayFormat_ = GE_FORMAT_565;
585
u32 prevDisplayFramebufPtr_ = 0;
586
587
int fbBindSeqCount_ = 0;
588
589
VirtualFramebuffer *displayFramebuf_ = nullptr;
590
VirtualFramebuffer *prevDisplayFramebuf_ = nullptr;
591
VirtualFramebuffer *prevPrevDisplayFramebuf_ = nullptr;
592
int frameLastFramebufUsed_ = 0;
593
594
VirtualFramebuffer *currentRenderVfb_ = nullptr;
595
596
Draw::Framebuffer *currentFramebufferCopy_ = nullptr;
597
598
// The range of PSP memory that may contain FBOs. So we can skip iterating.
599
u32 framebufColorRangeEnd_ = 0;
600
601
bool useBufferedRendering_ = false;
602
bool postShaderIsUpscalingFilter_ = false;
603
bool postShaderIsSupersampling_ = false;
604
605
std::vector<VirtualFramebuffer *> vfbs_;
606
std::vector<VirtualFramebuffer *> bvfbs_; // blitting framebuffers (for download)
607
608
std::vector<DrawPixelsEntry> drawPixelsCache_;
609
610
bool gameUsesSequentialCopies_ = false;
611
612
// Sampled in BeginFrame/UpdateSize for safety.
613
float renderWidth_ = 0.0f;
614
float renderHeight_ = 0.0f;
615
616
int msaaLevel_ = 0;
617
int renderScaleFactor_ = 1;
618
int pixelWidth_ = 0;
619
int pixelHeight_ = 0;
620
int bloomHack_ = 0;
621
bool updatePostShaders_ = false;
622
623
Draw::DataFormat preferredPixelsFormat_ = Draw::DataFormat::R8G8B8A8_UNORM;
624
625
struct TempFBOInfo {
626
Draw::Framebuffer *fbo;
627
int last_frame_used;
628
};
629
630
std::unordered_map<u64, TempFBOInfo> tempFBOs_;
631
632
std::vector<Draw::Framebuffer *> fbosToDelete_;
633
634
// Aggressively delete unused FBOs to save gpu memory.
635
enum {
636
FBO_OLD_AGE = 5,
637
FBO_OLD_USAGE_FLAG = 15,
638
};
639
640
// Thin3D stuff for reinterpreting image data between the various 16-bit color formats.
641
// Safe, not optimal - there might be input attachment tricks, etc, but we can't use them
642
// since we don't want N different implementations.
643
Draw2DPipeline *reinterpretFromTo_[4][4]{};
644
645
// Common implementation of stencil buffer upload. Also not 100% optimal, but not performance
646
// critical either.
647
Draw::Pipeline *stencilWritePipeline_ = nullptr;
648
Draw::SamplerState *stencilWriteSampler_ = nullptr;
649
650
// Used on GLES where we can't directly readback depth or stencil, but here for simplicity.
651
Draw::Pipeline *stencilReadbackPipeline_ = nullptr;
652
Draw::SamplerState *stencilReadbackSampler_ = nullptr;
653
Draw::Pipeline *depthReadbackPipeline_ = nullptr;
654
Draw::SamplerState *depthReadbackSampler_ = nullptr;
655
656
// Draw2D pipelines
657
Draw2DPipeline *draw2DPipelineCopyColor_ = nullptr;
658
Draw2DPipeline *draw2DPipelineColorRect2Lin_ = nullptr;
659
Draw2DPipeline *draw2DPipelineCopyDepth_ = nullptr;
660
Draw2DPipeline *draw2DPipelineEncodeDepth_ = nullptr;
661
Draw2DPipeline *draw2DPipeline565ToDepth_ = nullptr;
662
Draw2DPipeline *draw2DPipeline565ToDepthDeswizzle_ = nullptr;
663
664
Draw2D draw2D_;
665
// The fragment shaders are "owned" by the pipelines since they're 1:1.
666
667
// Depth readback helper state
668
u8 *convBuf_ = nullptr;
669
u32 convBufSize_ = 0;
670
671
DisplayLayoutConfig displayLayoutConfigCopy_{};
672
};
673
674
// Should probably live elsewhere.
675
bool GetOutputFramebuffer(Draw::DrawContext *draw, GPUDebugBuffer &buffer);
676
677