mirror of
https://github.com/hrydgard/ppsspp.git
synced 2025-04-02 11:01:50 -04:00
Use texture UV range to optimize framebuf copies.
This commit is contained in:
parent
f4df7f076e
commit
62de281e35
9 changed files with 161 additions and 30 deletions
|
@ -115,6 +115,12 @@ extern GPUgstate gstate;
|
|||
|
||||
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate);
|
||||
|
||||
enum BindFramebufferColorFlags {
|
||||
BINDFBCOLOR_SKIP_COPY = 0,
|
||||
BINDFBCOLOR_MAY_COPY = 1,
|
||||
BINDFBCOLOR_MAY_COPY_WITH_UV = 3,
|
||||
};
|
||||
|
||||
class FramebufferManagerCommon {
|
||||
public:
|
||||
FramebufferManagerCommon();
|
||||
|
|
|
@ -608,7 +608,7 @@ namespace DX9 {
|
|||
return offscreen;
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, bool skipCopy) {
|
||||
void FramebufferManagerDX9::BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (framebuffer == NULL) {
|
||||
framebuffer = currentRenderVfb_;
|
||||
}
|
||||
|
@ -621,6 +621,7 @@ namespace DX9 {
|
|||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping() || g_Config.bDisableSlowFramebufEffects) {
|
||||
skipCopy = true;
|
||||
}
|
||||
|
@ -630,7 +631,22 @@ namespace DX9 {
|
|||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
BlitFramebuffer(©Info, 0, 0, framebuffer, 0, 0, framebuffer->drawnWidth, framebuffer->drawnHeight, 0, false);
|
||||
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = framebuffer->drawnWidth;
|
||||
int h = framebuffer->drawnHeight;
|
||||
|
||||
// If max is not > min, we probably could not detect it. Skip.
|
||||
// See the vertex decoder, where this is updated.
|
||||
if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) != 0 && gstate_c.vertMaxU > gstate_c.vertMinU) {
|
||||
x = gstate_c.vertMinU;
|
||||
y = gstate_c.vertMinV;
|
||||
w = gstate_c.vertMaxU - x;
|
||||
h = gstate_c.vertMaxV - y;
|
||||
}
|
||||
|
||||
BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0, false);
|
||||
|
||||
RebindFramebuffer();
|
||||
pD3Ddevice->SetTexture(stage, fbo_get_color_texture(renderCopy));
|
||||
|
|
|
@ -71,7 +71,7 @@ public:
|
|||
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
|
||||
|
||||
void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, bool skipCopy = false);
|
||||
void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override;
|
||||
|
||||
|
|
|
@ -815,7 +815,7 @@ void TransformDrawEngineDX9::ApplyDrawStateLate() {
|
|||
textureCache_->ApplyTexture();
|
||||
|
||||
if (fboTexNeedBind_) {
|
||||
framebufferManager_->BindFramebufferColor(1, nullptr, false);
|
||||
framebufferManager_->BindFramebufferColor(1, nullptr, BINDFBCOLOR_MAY_COPY_WITH_UV);
|
||||
// If we are rendering at a higher resolution, linear is probably best for the dest color.
|
||||
pD3Ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR);
|
||||
pD3Ddevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR);
|
||||
|
|
|
@ -960,12 +960,60 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
|
|||
float xoff = -0.5f / framebuffer->renderWidth;
|
||||
float yoff = 0.5f / framebuffer->renderHeight;
|
||||
|
||||
const float pos[12 + 8] = {
|
||||
-1 + xoff, 1 + yoff, 0, 0, 0,
|
||||
1 + xoff, 1 + yoff, 0, 1, 0,
|
||||
1 + xoff, -1 + yoff, 0, 1, 1,
|
||||
-1 + xoff, -1 + yoff, 0, 0, 1,
|
||||
struct Pos {
|
||||
Pos(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {
|
||||
}
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
struct UV {
|
||||
UV(float u_, float v_) : u(u_), v(v_) {
|
||||
}
|
||||
float u;
|
||||
float v;
|
||||
};
|
||||
|
||||
struct PosUV {
|
||||
Pos pos;
|
||||
UV uv;
|
||||
};
|
||||
|
||||
PosUV verts[4] = {
|
||||
{ { -1 + xoff, 1 + yoff, -1 }, { 0, 0 } },
|
||||
{ { 1 + xoff, 1 + yoff, -1 }, { 1, 0 } },
|
||||
{ { 1 + xoff, -1 + yoff, -1 }, { 1, 1 } },
|
||||
{ { -1 + xoff, -1 + yoff, -1 }, { 0, 1 } },
|
||||
};
|
||||
|
||||
// If min is not < max, then we don't have values (wasn't set during decode.)
|
||||
if (gstate_c.vertMinV < gstate_c.vertMaxV) {
|
||||
const float invWidth = 1.0f / (float)framebuffer->bufferWidth;
|
||||
const float invHeight = 1.0f / (float)framebuffer->bufferHeight;
|
||||
// Inverse of half = double.
|
||||
const float invHalfWidth = invWidth * 2.0f;
|
||||
const float invHalfHeight = invHeight * 2.0f;
|
||||
|
||||
const float left = gstate_c.vertMinU * invHalfWidth - 1.0f + xoff;
|
||||
const float right = gstate_c.vertMaxU * invHalfWidth - 1.0f + xoff;
|
||||
const float top = gstate_c.vertMinV * invHalfHeight - 1.0f + yoff;
|
||||
const float bottom = gstate_c.vertMaxV * invHalfHeight - 1.0f + yoff;
|
||||
// Points are: BL, BR, TR, TL.
|
||||
verts[0].pos = Pos(left, bottom, -1.0f);
|
||||
verts[1].pos = Pos(right, bottom, -1.0f);
|
||||
verts[2].pos = Pos(right, top, -1.0f);
|
||||
verts[3].pos = Pos(left, top, -1.0f);
|
||||
|
||||
// And also the UVs, same order.
|
||||
const float uvleft = gstate_c.vertMinU * invWidth;
|
||||
const float uvright = gstate_c.vertMaxU * invWidth;
|
||||
const float uvtop = 1.0f - gstate_c.vertMinV * invHeight;
|
||||
const float uvbottom = 1.0f - gstate_c.vertMaxV * invHeight;
|
||||
verts[0].uv = UV(uvleft, uvbottom);
|
||||
verts[1].uv = UV(uvright, uvbottom);
|
||||
verts[2].uv = UV(uvright, uvtop);
|
||||
verts[3].uv = UV(uvleft, uvtop);
|
||||
}
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
|
@ -977,7 +1025,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
|
|||
pD3Ddevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
pD3Ddevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
||||
|
||||
framebufferManager_->BindFramebufferColor(0, framebuffer, true);
|
||||
framebufferManager_->BindFramebufferColor(0, framebuffer, BINDFBCOLOR_SKIP_COPY);
|
||||
pD3Ddevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_POINT);
|
||||
pD3Ddevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_POINT);
|
||||
pD3Ddevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_NONE);
|
||||
|
@ -999,7 +1047,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
|
|||
vp.Height = framebuffer->renderHeight;
|
||||
pD3Ddevice->SetViewport(&vp);
|
||||
|
||||
HRESULT hr = pD3Ddevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, pos, (3 + 2) * sizeof(float));
|
||||
HRESULT hr = pD3Ddevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, verts, (3 + 2) * sizeof(float));
|
||||
if (FAILED(hr)) {
|
||||
ERROR_LOG_REPORT(G3D, "Depal render failed: %08x", hr);
|
||||
}
|
||||
|
@ -1011,7 +1059,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame
|
|||
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
} else {
|
||||
framebufferManager_->BindFramebufferColor(0, framebuffer);
|
||||
framebufferManager_->BindFramebufferColor(0, framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV);
|
||||
}
|
||||
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
|
|
|
@ -838,7 +838,7 @@ FBO *FramebufferManager::GetTempFBO(u16 w, u16 h, FBOColorDepth depth) {
|
|||
return fbo;
|
||||
}
|
||||
|
||||
void FramebufferManager::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, bool skipCopy) {
|
||||
void FramebufferManager::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags) {
|
||||
if (framebuffer == NULL) {
|
||||
framebuffer = currentRenderVfb_;
|
||||
}
|
||||
|
@ -856,6 +856,7 @@ void FramebufferManager::BindFramebufferColor(int stage, u32 fbRawAddress, Virtu
|
|||
|
||||
// currentRenderVfb_ will always be set when this is called, except from the GE debugger.
|
||||
// Let's just not bother with the copy in that case.
|
||||
bool skipCopy = (flags & BINDFBCOLOR_MAY_COPY) == 0;
|
||||
if (GPUStepping::IsStepping() || g_Config.bDisableSlowFramebufEffects) {
|
||||
skipCopy = true;
|
||||
}
|
||||
|
@ -865,9 +866,23 @@ void FramebufferManager::BindFramebufferColor(int stage, u32 fbRawAddress, Virtu
|
|||
if (renderCopy) {
|
||||
VirtualFramebuffer copyInfo = *framebuffer;
|
||||
copyInfo.fbo = renderCopy;
|
||||
BlitFramebuffer(©Info, 0, 0, framebuffer, 0, 0, framebuffer->drawnWidth, framebuffer->drawnHeight, 0, false);
|
||||
|
||||
RebindFramebuffer();
|
||||
int x = 0;
|
||||
int y = 0;
|
||||
int w = framebuffer->drawnWidth;
|
||||
int h = framebuffer->drawnHeight;
|
||||
|
||||
// If max is not > min, we probably could not detect it. Skip.
|
||||
// See the vertex decoder, where this is updated.
|
||||
if ((flags & BINDFBCOLOR_MAY_COPY_WITH_UV) != 0 && gstate_c.vertMaxU > gstate_c.vertMinU) {
|
||||
x = gstate_c.vertMinU;
|
||||
y = gstate_c.vertMinV;
|
||||
w = gstate_c.vertMaxU - x;
|
||||
h = gstate_c.vertMaxV - y;
|
||||
}
|
||||
|
||||
BlitFramebuffer(©Info, x, y, framebuffer, x, y, w, h, 0, false);
|
||||
|
||||
fbo_bind_color_as_texture(renderCopy, 0);
|
||||
} else {
|
||||
fbo_bind_color_as_texture(framebuffer->fbo, 0);
|
||||
|
|
|
@ -98,7 +98,7 @@ public:
|
|||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
|
||||
|
||||
// For use when texturing from a framebuffer. May create a duplicate if target.
|
||||
void BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, bool skipCopy = false);
|
||||
void BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
// Reads a rectangular subregion of a framebuffer to the right position in its backing memory.
|
||||
virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override;
|
||||
|
|
|
@ -904,7 +904,9 @@ void TransformDrawEngine::ApplyDrawStateLate() {
|
|||
textureCache_->ApplyTexture();
|
||||
|
||||
if (fboTexNeedBind_) {
|
||||
framebufferManager_->BindFramebufferColor(GL_TEXTURE1, gstate.getFrameBufRawAddress(), nullptr);
|
||||
framebufferManager_->BindFramebufferColor(GL_TEXTURE1, gstate.getFrameBufRawAddress(), nullptr, BINDFBCOLOR_MAY_COPY_WITH_UV);
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
|
||||
glActiveTexture(GL_TEXTURE1);
|
||||
// If we are rendering at a higher resolution, linear is probably best for the dest color.
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
|
||||
|
|
|
@ -1023,20 +1023,64 @@ void TextureCache::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuf
|
|||
GLuint clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_);
|
||||
FBO *depalFBO = framebufferManager_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, FBO_8888);
|
||||
fbo_bind_as_render_target(depalFBO);
|
||||
static const float pos[12] = {
|
||||
-1, -1, -1,
|
||||
1, -1, -1,
|
||||
1, 1, -1,
|
||||
-1, 1, -1
|
||||
|
||||
struct Pos {
|
||||
Pos(float x_, float y_, float z_) : x(x_), y(y_), z(z_) {
|
||||
}
|
||||
float x;
|
||||
float y;
|
||||
float z;
|
||||
};
|
||||
static const float uv[8] = {
|
||||
0, 0,
|
||||
1, 0,
|
||||
1, 1,
|
||||
0, 1,
|
||||
struct UV {
|
||||
UV(float u_, float v_) : u(u_), v(v_) {
|
||||
}
|
||||
float u;
|
||||
float v;
|
||||
};
|
||||
|
||||
Pos pos[4] = {
|
||||
{-1, -1, -1},
|
||||
{ 1, -1, -1},
|
||||
{ 1, 1, -1},
|
||||
{-1, 1, -1},
|
||||
};
|
||||
UV uv[4] = {
|
||||
{0, 0},
|
||||
{1, 0},
|
||||
{1, 1},
|
||||
{0, 1},
|
||||
};
|
||||
static const GLubyte indices[4] = { 0, 1, 3, 2 };
|
||||
|
||||
// If min is not < max, then we don't have values (wasn't set during decode.)
|
||||
if (gstate_c.vertMinV < gstate_c.vertMaxV) {
|
||||
const float invWidth = 1.0f / (float)framebuffer->bufferWidth;
|
||||
const float invHeight = 1.0f / (float)framebuffer->bufferHeight;
|
||||
// Inverse of half = double.
|
||||
const float invHalfWidth = invWidth * 2.0f;
|
||||
const float invHalfHeight = invHeight * 2.0f;
|
||||
|
||||
const float left = gstate_c.vertMinU * invHalfWidth - 1.0f;
|
||||
const float right = gstate_c.vertMaxU * invHalfWidth - 1.0f;
|
||||
const float top = -(gstate_c.vertMinV * invHalfHeight - 1.0f);
|
||||
const float bottom = -(gstate_c.vertMaxV * invHalfHeight - 1.0f);
|
||||
// Points are: BL, BR, TR, TL.
|
||||
pos[0] = Pos(left, bottom, -1.0f);
|
||||
pos[1] = Pos(right, bottom, -1.0f);
|
||||
pos[2] = Pos(right, top, -1.0f);
|
||||
pos[3] = Pos(left, top, -1.0f);
|
||||
|
||||
// And also the UVs, same order.
|
||||
const float uvleft = gstate_c.vertMinU * invWidth;
|
||||
const float uvright = gstate_c.vertMaxU * invWidth;
|
||||
const float uvtop = 1.0f - gstate_c.vertMinV * invHeight;
|
||||
const float uvbottom = 1.0f - gstate_c.vertMaxV * invHeight;
|
||||
uv[0] = UV(uvleft, uvbottom);
|
||||
uv[1] = UV(uvright, uvbottom);
|
||||
uv[2] = UV(uvright, uvtop);
|
||||
uv[3] = UV(uvleft, uvtop);
|
||||
}
|
||||
|
||||
shaderManager_->DirtyLastShader();
|
||||
|
||||
glUseProgram(depal->program);
|
||||
|
@ -1050,7 +1094,7 @@ void TextureCache::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuf
|
|||
glBindTexture(GL_TEXTURE_2D, clutTexture);
|
||||
glActiveTexture(GL_TEXTURE0);
|
||||
|
||||
framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, true);
|
||||
framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, BINDFBCOLOR_SKIP_COPY);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
|
||||
|
||||
|
@ -1073,11 +1117,11 @@ void TextureCache::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuf
|
|||
|
||||
fbo_bind_color_as_texture(depalFBO, 0);
|
||||
glstate.Restore();
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
} else {
|
||||
framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer);
|
||||
framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, BINDFBCOLOR_MAY_COPY_WITH_UV);
|
||||
}
|
||||
|
||||
framebufferManager_->RebindFramebuffer();
|
||||
SetFramebufferSamplingParams(framebuffer->bufferWidth, framebuffer->bufferHeight);
|
||||
|
||||
lastBoundTexture = -1;
|
||||
|
|
Loading…
Add table
Reference in a new issue