Skip to content

Commit

Permalink
Merge pull request #12952 from unknownbrackets/vulkan-safesize
Browse files Browse the repository at this point in the history
Vulkan: Match safe size behavior on all backends
  • Loading branch information
hrydgard authored Jul 13, 2020
2 parents 4537b80 + 1432cc9 commit 6009bf7
Show file tree
Hide file tree
Showing 6 changed files with 48 additions and 18 deletions.
25 changes: 23 additions & 2 deletions GPU/Common/SoftwareTransformCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -441,12 +441,17 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
// TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not.
// TODO: Allow creating a depth clear and a color draw.
bool reallyAClear = false;
if (maxIndex > 1 && prim == GE_PRIM_RECTANGLES && gstate.isModeClear() && params_.allowClear) {
if (maxIndex > 1 && prim == GE_PRIM_RECTANGLES && gstate.isModeClear()) {
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
reallyAClear = IsReallyAClear(transformed, maxIndex, scissorX2, scissorY2);
if (reallyAClear && gstate.getColorMask() != 0 && gstate.getClearModeColorMask() != 0) {
result->setSafeSize = true;
result->safeWidth = scissorX2;
result->safeHeight = scissorY2;
}
}
if (reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_IMGTEC) {
if (params_.allowClear && reallyAClear && gl_extensions.gpuVendor != GPU_VENDOR_IMGTEC) {
// If alpha is not allowed to be separate, it must match for both depth/stencil and color. Vulkan requires this.
bool alphaMatchesColor = gstate.isClearModeColorMask() == gstate.isClearModeAlphaMask();
bool depthMatchesStencil = gstate.isClearModeAlphaMask() == gstate.isClearModeDepthMask();
Expand All @@ -461,6 +466,22 @@ void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVt
return;
}
}

// Detect full screen "clears" that might not be so obvious, to set the safe size if possible.
if (!result->setSafeSize && prim == GE_PRIM_RECTANGLES && maxIndex == 2) {
bool clearingColor = gstate.isModeClear() && gstate.getClearModeColorMask() != 0;
bool writingColor = gstate.getColorMask() != 0;
bool startsZeroX = transformed[0].x <= 0.0f && transformed[1].x > transformed[0].x;
bool startsZeroY = transformed[0].y <= 0.0f && transformed[1].y > transformed[0].y;

if (startsZeroX && startsZeroY && (clearingColor || writingColor)) {
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
result->setSafeSize = true;
result->safeWidth = std::min(scissorX2, (int)transformed[1].x);
result->safeHeight = std::min(scissorY2, (int)transformed[1].y);
}
}
}

// Also, this assumes SetTexture() has already figured out the actual texture height.
Expand Down
4 changes: 4 additions & 0 deletions GPU/Common/SoftwareTransformCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,10 @@ struct SoftwareTransformResult {
bool setStencil;
u8 stencilValue;

bool setSafeSize;
u32 safeWidth;
u32 safeHeight;

TransformedVertex *drawBuffer;
int drawNumTrans;
bool drawIndexed;
Expand Down
8 changes: 5 additions & 3 deletions GPU/D3D11/DrawEngineD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -600,6 +600,9 @@ void DrawEngineD3D11::DoFlush() {
swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result);
}

if (result.setSafeSize)
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);

if (result.action == SW_DRAW_PRIMITIVES) {
const int vertexSize = sizeof(transformed[0]);

Expand Down Expand Up @@ -663,12 +666,11 @@ void DrawEngineD3D11::DoFlush() {
uint8_t clearStencil = clearColor >> 24;
draw_->Clear(clearFlag, clearColor, clearDepth, clearStencil);

int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
if ((gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
}
}
Expand Down
8 changes: 5 additions & 3 deletions GPU/Directx9/DrawEngineDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -563,6 +563,9 @@ void DrawEngineDX9::DoFlush() {
swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result);
}

if (result.setSafeSize)
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);

ApplyDrawStateLate();
vshader = shaderManager_->ApplyShader(false, false, lastVType_);

Expand Down Expand Up @@ -601,12 +604,11 @@ void DrawEngineDX9::DoFlush() {
dxstate.colorMask.set((mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_TARGET) != 0, (mask & D3DCLEAR_STENCIL) != 0);
device_->Clear(0, NULL, mask, SwapRB(clearColor), clearDepth, clearColor >> 24);

int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);
if ((gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
}
}
Expand Down
8 changes: 4 additions & 4 deletions GPU/GLES/DrawEngineGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -588,6 +588,8 @@ void DrawEngineGLES::DoFlush() {

if (result.action == SW_NOT_READY)
swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, maxIndex, &result);
if (result.setSafeSize)
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);

ApplyDrawStateLate(result.setStencil, result.stencilValue);

Expand Down Expand Up @@ -627,16 +629,14 @@ void DrawEngineGLES::DoFlush() {
if (alphaMask) target |= GL_STENCIL_BUFFER_BIT;
if (depthMask) target |= GL_DEPTH_BUFFER_BIT;

int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;

render_->Clear(clearColor, clearDepth, clearColor >> 24, target, rgbaMask, vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH);
framebufferManager_->SetColorUpdated(gstate_c.skipDrawReason);
framebufferManager_->SetSafeSize(scissorX2, scissorY2);

if ((gstate_c.featureFlags & GPU_USE_CLEAR_RAM_HACK) && colorMask && (alphaMask || gstate.FrameBufFormat() == GE_FORMAT_565)) {
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
}
gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied.
Expand Down
13 changes: 7 additions & 6 deletions GPU/Vulkan/DrawEngineVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -930,6 +930,9 @@ void DrawEngineVulkan::DoFlush() {
swTransform.BuildDrawingParams(prim, indexGen.VertexCount(), dec_->VertexType(), inds, maxIndex, &result);
}

if (result.setSafeSize)
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);

// Only here, where we know whether to clear or to draw primitives, should we actually set the current framebuffer! Because that gives use the opportunity
// to use a "pre-clear" render pass, for high efficiency on tilers.
if (result.action == SW_DRAW_PRIMITIVES) {
Expand Down Expand Up @@ -1014,13 +1017,11 @@ void DrawEngineVulkan::DoFlush() {
// If non-buffered though, it'll just do a plain clear.
framebufferManager_->NotifyClear(gstate.isClearModeColorMask(), gstate.isClearModeAlphaMask(), gstate.isClearModeDepthMask(), result.color, result.depth);

int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->SetSafeSize(scissorX2, scissorY2);

if (gstate_c.Supports(GPU_USE_CLEAR_RAM_HACK) && gstate.isClearModeColorMask() && (gstate.isClearModeAlphaMask() || gstate.FrameBufFormat() == GE_FORMAT_565)) {
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color);
}
}
Expand Down

0 comments on commit 6009bf7

Please sign in to comment.