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