GPU: Purify ConvertViewportAndScissor().

This makes it harder to misuse.  See #15856.
This commit is contained in:
Unknown W. Brackets 2022-08-20 14:16:55 -07:00
parent d61619db47
commit b5a4843c1f
10 changed files with 50 additions and 85 deletions

View file

@ -557,9 +557,7 @@ DepthScaleFactors GetDepthScaleFactors() {
}
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out) {
bool throughmode = gstate.isModeThrough();
out.dirtyProj = false;
out.dirtyDepth = false;
out.throughMode = gstate.isModeThrough();
float renderWidthFactor, renderHeightFactor;
float renderX = 0.0f, renderY = 0.0f;
@ -610,7 +608,7 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
float offsetX = gstate.getOffsetX();
float offsetY = gstate.getOffsetY();
if (throughmode) {
if (out.throughMode) {
out.viewportX = renderX * renderWidthFactor + displayOffsetX;
out.viewportY = renderY * renderHeightFactor + displayOffsetY;
out.viewportW = curRTWidth * renderWidthFactor;
@ -647,10 +645,10 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
float right = left + vpWidth;
float bottom = top + vpHeight;
float wScale = 1.0f;
float xOffset = 0.0f;
float hScale = 1.0f;
float yOffset = 0.0f;
out.widthScale = 1.0f;
out.xOffset = 0.0f;
out.heightScale = 1.0f;
out.yOffset = 0.0f;
// If we're within the bounds, we want clipping the viewport way. So leave it be.
{
@ -678,8 +676,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
right = left + 1.0f;
}
wScale = vpWidth / (right - left);
xOffset = drift / (right - left);
out.widthScale = vpWidth / (right - left);
out.xOffset = drift / (right - left);
}
}
@ -707,8 +705,8 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
bottom = top + 1.0f;
}
hScale = vpHeight / (bottom - top);
yOffset = drift / (bottom - top);
out.heightScale = vpHeight / (bottom - top);
out.yOffset = drift / (bottom - top);
}
}
@ -740,13 +738,13 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
}
// Okay. So, in our shader, -1 will map to minz, and +1 will map to maxz.
float halfActualZRange = (maxz - minz) * (1.0f / 2.0f);
float zScale = halfActualZRange < std::numeric_limits<float>::epsilon() ? 1.0f : vpZScale / halfActualZRange;
out.depthScale = halfActualZRange < std::numeric_limits<float>::epsilon() ? 1.0f : vpZScale / halfActualZRange;
// This adjusts the center from halfActualZRange to vpZCenter.
float zOffset = halfActualZRange < std::numeric_limits<float>::epsilon() ? 0.0f : (vpZCenter - (minz + halfActualZRange)) / halfActualZRange;
out.zOffset = halfActualZRange < std::numeric_limits<float>::epsilon() ? 0.0f : (vpZCenter - (minz + halfActualZRange)) / halfActualZRange;
if (!gstate_c.Supports(GPU_SUPPORTS_ACCURATE_DEPTH)) {
zScale = 1.0f;
zOffset = 0.0f;
out.depthScale = 1.0f;
out.zOffset = 0.0f;
out.depthRangeMin = ToScaledDepthFromIntegerScale(vpZCenter - vpZScale);
out.depthRangeMax = ToScaledDepthFromIntegerScale(vpZCenter + vpZScale);
} else {
@ -757,19 +755,27 @@ void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, flo
// OpenGL will clamp these for us anyway, and Direct3D will error if not clamped.
out.depthRangeMin = std::max(out.depthRangeMin, 0.0f);
out.depthRangeMax = std::min(out.depthRangeMax, 1.0f);
}
}
bool scaleChanged = gstate_c.vpWidthScale != wScale || gstate_c.vpHeightScale != hScale;
bool offsetChanged = gstate_c.vpXOffset != xOffset || gstate_c.vpYOffset != yOffset;
bool depthChanged = gstate_c.vpDepthScale != zScale || gstate_c.vpZOffset != zOffset;
if (scaleChanged || offsetChanged || depthChanged) {
gstate_c.vpWidthScale = wScale;
gstate_c.vpHeightScale = hScale;
gstate_c.vpDepthScale = zScale;
gstate_c.vpXOffset = xOffset;
gstate_c.vpYOffset = yOffset;
gstate_c.vpZOffset = zOffset;
out.dirtyProj = true;
out.dirtyDepth = depthChanged;
void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor) {
if (vpAndScissor.throughMode)
return;
bool scaleChanged = gstate_c.vpWidthScale != vpAndScissor.widthScale || gstate_c.vpHeightScale != vpAndScissor.heightScale;
bool offsetChanged = gstate_c.vpXOffset != vpAndScissor.xOffset || gstate_c.vpYOffset != vpAndScissor.yOffset;
bool depthChanged = gstate_c.vpDepthScale != vpAndScissor.depthScale || gstate_c.vpZOffset != vpAndScissor.zOffset;
if (scaleChanged || offsetChanged || depthChanged) {
gstate_c.vpWidthScale = vpAndScissor.widthScale;
gstate_c.vpHeightScale = vpAndScissor.heightScale;
gstate_c.vpDepthScale = vpAndScissor.depthScale;
gstate_c.vpXOffset = vpAndScissor.xOffset;
gstate_c.vpYOffset = vpAndScissor.yOffset;
gstate_c.vpZOffset = vpAndScissor.zOffset;
gstate_c.Dirty(DIRTY_PROJMATRIX);
if (depthChanged) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
}
}

View file

@ -75,10 +75,16 @@ struct ViewportAndScissor {
float viewportH;
float depthRangeMin;
float depthRangeMax;
bool dirtyProj;
bool dirtyDepth;
float widthScale;
float heightScale;
float depthScale;
float xOffset;
float yOffset;
float zOffset;
bool throughMode;
};
void ConvertViewportAndScissor(bool useBufferedRendering, float renderWidth, float renderHeight, int bufferWidth, int bufferHeight, ViewportAndScissor &out);
void UpdateCachedViewportState(const ViewportAndScissor &vpAndScissor);
float ToScaledDepthFromIntegerScale(float z);
struct DepthScaleFactors {

View file

@ -617,13 +617,7 @@ rotateVBO:
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
UpdateCachedViewportState(vpAndScissor);
}
int maxIndex = indexGen.MaxIndex();

View file

@ -374,15 +374,13 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
UpdateCachedViewportState(vpAndScissor);
float depthMin = vpAndScissor.depthRangeMin;
float depthMax = vpAndScissor.depthRangeMax;
if (depthMin < 0.0f) depthMin = 0.0f;
if (depthMax > 1.0f) depthMax = 1.0f;
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
Draw::Viewport &vp = dynState_.viewport;
vp.TopLeftX = vpAndScissor.viewportX;
@ -392,10 +390,6 @@ void DrawEngineD3D11::ApplyDrawState(int prim) {
vp.MinDepth = depthMin;
vp.MaxDepth = depthMax;
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
D3D11_RECT &scissor = dynState_.scissor;
scissor.left = vpAndScissor.scissorX;
scissor.top = vpAndScissor.scissorY;

View file

@ -582,13 +582,7 @@ rotateVBO:
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
UpdateCachedViewportState(vpAndScissor);
}
int maxIndex = indexGen.MaxIndex();

View file

@ -260,6 +260,7 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
UpdateCachedViewportState(vpAndScissor);
dxstate.scissorTest.enable();
dxstate.scissorRect.set(vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorX + vpAndScissor.scissorW, vpAndScissor.scissorY + vpAndScissor.scissorH);
@ -268,12 +269,6 @@ void DrawEngineDX9::ApplyDrawState(int prim) {
float depthMax = vpAndScissor.depthRangeMax;
dxstate.viewport.set(vpAndScissor.viewportX, vpAndScissor.viewportY, vpAndScissor.viewportW, vpAndScissor.viewportH, depthMin, depthMax);
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
}
gstate_c.Clean(DIRTY_VIEWPORTSCISSOR_STATE | DIRTY_DEPTHSTENCIL_STATE | DIRTY_RASTER_STATE | DIRTY_BLEND_STATE);

View file

@ -364,13 +364,7 @@ void DrawEngineGLES::DoFlush() {
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
UpdateCachedViewportState(vpAndScissor);
}
int maxIndex = indexGen.MaxIndex();

View file

@ -276,19 +276,13 @@ void DrawEngineGLES::ApplyDrawState(int prim) {
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
UpdateCachedViewportState(vpAndScissor);
renderManager->SetScissor(GLRect2D{ vpAndScissor.scissorX, vpAndScissor.scissorY, vpAndScissor.scissorW, vpAndScissor.scissorH });
renderManager->SetViewport({
vpAndScissor.viewportX, vpAndScissor.viewportY,
vpAndScissor.viewportW, vpAndScissor.viewportH,
vpAndScissor.depthRangeMin, vpAndScissor.depthRangeMax });
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
}
}

View file

@ -856,13 +856,7 @@ void DrawEngineVulkan::DoFlush() {
framebufferManager_->GetRenderWidth(), framebufferManager_->GetRenderHeight(),
framebufferManager_->GetTargetBufferWidth(), framebufferManager_->GetTargetBufferHeight(),
vpAndScissor);
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
UpdateCachedViewportState(vpAndScissor);
}
int maxIndex = indexGen.MaxIndex();

View file

@ -318,15 +318,13 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
fbManager.GetRenderWidth(), fbManager.GetRenderHeight(),
fbManager.GetTargetBufferWidth(), fbManager.GetTargetBufferHeight(),
vpAndScissor);
UpdateCachedViewportState(vpAndScissor);
float depthMin = vpAndScissor.depthRangeMin;
float depthMax = vpAndScissor.depthRangeMax;
if (depthMin < 0.0f) depthMin = 0.0f;
if (depthMax > 1.0f) depthMax = 1.0f;
if (vpAndScissor.dirtyDepth) {
gstate_c.Dirty(DIRTY_DEPTHRANGE);
}
VkViewport &vp = dynState.viewport;
vp.x = vpAndScissor.viewportX;
@ -336,10 +334,6 @@ void DrawEngineVulkan::ConvertStateToVulkanKey(FramebufferManagerVulkan &fbManag
vp.minDepth = vpAndScissor.depthRangeMin;
vp.maxDepth = vpAndScissor.depthRangeMax;
if (vpAndScissor.dirtyProj) {
gstate_c.Dirty(DIRTY_PROJMATRIX);
}
ScissorRect &scissor = dynState.scissor;
scissor.x = vpAndScissor.scissorX;
scissor.y = vpAndScissor.scissorY;