Skip to content

Commit

Permalink
Merge pull request #13251 from hrydgard/fit-viewport-to-scissor
Browse files Browse the repository at this point in the history
Fit viewport to scissor
  • Loading branch information
hrydgard committed Aug 5, 2020
2 parents c2255fd + fd3a9d4 commit 937042b
Show file tree
Hide file tree
Showing 5 changed files with 43 additions and 34 deletions.
69 changes: 40 additions & 29 deletions GPU/Common/GPUStateUtils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,25 +568,23 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
renderHeightFactor = renderHeight / 272.0f;
}

renderX += gstate_c.curRTOffsetX * renderWidthFactor;
renderX = gstate_c.curRTOffsetX;

// Scissor
int scissorX1 = gstate.getScissorX1();
int scissorY1 = gstate.getScissorY1();
int scissorX2 = gstate.getScissorX2() + 1;
int scissorY2 = gstate.getScissorY2() + 1;

// This is a bit of a hack as the render buffer isn't always that size
// We always scissor on non-buffered so that clears don't spill outside the frame.
out.scissorEnable = true;
if (scissorX2 < scissorX1 || scissorY2 < scissorY1) {
out.scissorX = 0;
out.scissorY = 0;
out.scissorW = 0;
out.scissorH = 0;
} else {
out.scissorX = renderX + displayOffsetX + scissorX1 * renderWidthFactor;
out.scissorY = renderY + displayOffsetY + scissorY1 * renderHeightFactor;
out.scissorX = (renderX * renderWidthFactor) + displayOffsetX + scissorX1 * renderWidthFactor;
out.scissorY = (renderY * renderHeightFactor) + displayOffsetY + scissorY1 * renderHeightFactor;
out.scissorW = (scissorX2 - scissorX1) * renderWidthFactor;
out.scissorH = (scissorY2 - scissorY1) * renderHeightFactor;
}
Expand All @@ -598,8 +596,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
float offsetY = gstate.getOffsetY();

if (throughmode) {
out.viewportX = renderX + displayOffsetX;
out.viewportY = renderY + displayOffsetY;
out.viewportX = renderX * renderWidthFactor + displayOffsetX;
out.viewportY = renderY * renderHeightFactor + displayOffsetY;
out.viewportW = curRTWidth * renderWidthFactor;
out.viewportH = curRTHeight * renderHeightFactor;
out.depthRangeMin = ToScaledDepthFromIntegerScale(0);
Expand Down Expand Up @@ -629,12 +627,6 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
float vpWidth = fabsf(gstate_c.vpWidth);
float vpHeight = fabsf(gstate_c.vpHeight);

// This multiplication should probably be done after viewport clipping. Would let us very slightly simplify the clipping logic?
vpX0 *= renderWidthFactor;
vpY0 *= renderHeightFactor;
vpWidth *= renderWidthFactor;
vpHeight *= renderHeightFactor;

// We used to apply the viewport here via glstate, but there are limits which vary by driver.
// This may mean some games won't work, or at least won't work at higher render resolutions.
// So we apply it in the shader instead.
Expand All @@ -648,27 +640,46 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
float hScale = 1.0f;
float yOffset = 0.0f;

if (!gstate_c.Supports(GPU_SUPPORTS_LARGE_VIEWPORTS)) {
// If we're within the bounds, we want clipping the viewport way. So leave it be.
if (left < 0.0f || right > renderWidth) {
float overageLeft = std::max(-left, 0.0f);
float overageRight = std::max(right - renderWidth, 0.0f);
// Our center drifted by the difference in overages.
float drift = overageRight - overageLeft;
// If we're within the bounds, we want clipping the viewport way. So leave it be.
{
float overageLeft = std::max(-left, 0.0f);
float overageRight = std::max(right - bufferWidth, 0.0f);

// Expand viewport to cover scissor region. The viewport doesn't clip on the PSP.
if (right < scissorX2) {
overageRight -= scissorX2 - right;
}
if (left > scissorX1) {
overageLeft += scissorX1 - left;
}

// Our center drifted by the difference in overages.
float drift = overageRight - overageLeft;

if (overageLeft != 0.0f || overageRight != 0.0f) {
left += overageLeft;
right -= overageRight;

wScale = vpWidth / (right - left);
xOffset = drift / (right - left);
}
}

{
float overageTop = std::max(-top, 0.0f);
float overageBottom = std::max(bottom - bufferHeight, 0.0f);

if (top < 0.0f || bottom > renderHeight) {
float overageTop = std::max(-top, 0.0f);
float overageBottom = std::max(bottom - renderHeight, 0.0f);
// Our center drifted by the difference in overages.
float drift = overageBottom - overageTop;
// Expand viewport to cover scissor region. The viewport doesn't clip on the PSP.
if (bottom < scissorY2) {
overageBottom -= scissorY2 - bottom;
}
if (top > scissorY1) {
overageTop += scissorY1 - top;
}
// Our center drifted by the difference in overages.
float drift = overageBottom - overageTop;

if (overageTop != 0.0f || overageBottom != 0.0f) {
top += overageTop;
bottom -= overageBottom;

Expand All @@ -677,10 +688,10 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
}
}

out.viewportX = left + displayOffsetX;
out.viewportY = top + displayOffsetY;
out.viewportW = right - left;
out.viewportH = bottom - top;
out.viewportX = left * renderWidthFactor + displayOffsetX;
out.viewportY = top * renderHeightFactor + displayOffsetY;
out.viewportW = (right - left) * renderWidthFactor;
out.viewportH = (bottom - top) * renderHeightFactor;

// The depth viewport parameters are the same, but we handle it a bit differently.
// When clipping is enabled, depth is clamped to [0, 65535]. And minz/maxz discard.
Expand Down
4 changes: 2 additions & 2 deletions GPU/Common/ShaderUniforms.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@
using namespace Lin;

static void ConvertProjMatrixToVulkan(Matrix4x4 &in) {
const Vec3 trans(0, 0, gstate_c.vpZOffset * 0.5f + 0.5f);
const Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
const Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
in.translateAndScale(trans, scale);
}

static void ConvertProjMatrixToD3D11(Matrix4x4 &in) {
const Vec3 trans(0, 0, gstate_c.vpZOffset * 0.5f + 0.5f);
const Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
const Vec3 scale(gstate_c.vpWidthScale, -gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
in.translateAndScale(trans, scale);
}
Expand Down
1 change: 0 additions & 1 deletion GPU/D3D11/GPU_D3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,6 @@ void GPU_D3D11::CheckGPUFeatures() {
#endif

features |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
features |= GPU_SUPPORTS_LARGE_VIEWPORTS;
if (draw_->GetDeviceCaps().dualSourceBlend)
features |= GPU_SUPPORTS_DUALSOURCE_BLEND;
if (draw_->GetDeviceCaps().depthClampSupported)
Expand Down
2 changes: 1 addition & 1 deletion GPU/GPUState.h
Original file line number Diff line number Diff line change
Expand Up @@ -482,7 +482,7 @@ enum {
GPU_SUPPORTS_16BIT_FORMATS = FLAG_BIT(13),
GPU_SUPPORTS_DEPTH_CLAMP = FLAG_BIT(14),
GPU_SUPPORTS_32BIT_INT_FSHADER = FLAG_BIT(15),
GPU_SUPPORTS_LARGE_VIEWPORTS = FLAG_BIT(16),
// Free bit: 16
GPU_SUPPORTS_ACCURATE_DEPTH = FLAG_BIT(17),
GPU_SUPPORTS_VAO = FLAG_BIT(18),
GPU_SUPPORTS_ANY_COPY_IMAGE = FLAG_BIT(19),
Expand Down
1 change: 0 additions & 1 deletion GPU/Vulkan/GPU_Vulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,6 @@ void GPU_Vulkan::CheckGPUFeatures() {
features |= GPU_SUPPORTS_BLEND_MINMAX;
features |= GPU_SUPPORTS_ANY_COPY_IMAGE;
features |= GPU_SUPPORTS_OES_TEXTURE_NPOT;
features |= GPU_SUPPORTS_LARGE_VIEWPORTS;
features |= GPU_SUPPORTS_INSTANCE_RENDERING;
features |= GPU_SUPPORTS_VERTEX_TEXTURE_FETCH;
features |= GPU_SUPPORTS_TEXTURE_FLOAT;
Expand Down

0 comments on commit 937042b

Please sign in to comment.