Merge pull request #7196 from unknownbrackets/gpu-minor

dx9: Compensate for viewport w/h adjustments
This commit is contained in:
Henrik Rydgård 2014-12-19 12:57:38 +01:00
commit 4b053efe8a
5 changed files with 77 additions and 17 deletions

View File

@ -853,7 +853,7 @@ namespace DX9 {
// We maintain a separate vector of framebuffer objects for blitting.
for (size_t i = 0; i < bvfbs_.size(); ++i) {
VirtualFramebuffer *v = bvfbs_[i];
if (MaskedEqual(v->fb_address, vfb->fb_address) && v->format == vfb->format) {
if (v->fb_address == vfb->fb_address && v->format == vfb->format) {
if (v->bufferWidth == vfb->bufferWidth && v->bufferHeight == vfb->bufferHeight) {
nvfb = v;
v->fb_stride = vfb->fb_stride;
@ -874,8 +874,8 @@ namespace DX9 {
nvfb->z_stride = vfb->z_stride;
nvfb->width = vfb->width;
nvfb->height = vfb->height;
nvfb->renderWidth = vfb->width;
nvfb->renderHeight = vfb->height;
nvfb->renderWidth = vfb->bufferWidth;
nvfb->renderHeight = vfb->bufferHeight;
nvfb->bufferWidth = vfb->bufferWidth;
nvfb->bufferHeight = vfb->bufferHeight;
nvfb->format = vfb->format;

View File

@ -222,13 +222,27 @@ void ShaderManagerDX9::VSSetMatrix(int creg, const float* pMatrix) {
}
// Depth in ogl is between -1;1 we need between 0;1 and optionally reverse it
static void ConvertProjMatrixToD3D(Matrix4x4 & in, bool invertedX, bool invertedY, bool invertedZ) {
static void ConvertProjMatrixToD3D(Matrix4x4 &in, bool invertedX, bool invertedY, bool invertedZ) {
Matrix4x4 s;
Matrix4x4 t;
s.setScaling(Vec3(1, 1, invertedZ ? -0.5 : 0.5f));
s.setScaling(Vec3(gstate_c.vpWidthScale, gstate_c.vpHeightScale, invertedZ ? -0.5 : 0.5f));
float xoff = 0.5f / gstate_c.curRTRenderWidth;
xoff = gstate_c.vpXOffset + (invertedX ? xoff : -xoff);
float yoff = 0.5f / gstate_c.curRTRenderHeight;
t.setTranslation(Vec3(invertedX ? xoff : -xoff, invertedY ? -yoff : yoff, 0.5f));
yoff = gstate_c.vpYOffset + (invertedY ? yoff : -yoff);
t.setTranslation(Vec3(xoff, yoff, 0.5f));
in = in * s * t;
}
static void ConvertProjMatrixToD3DThrough(Matrix4x4 &in) {
Matrix4x4 s;
Matrix4x4 t;
s.setScaling(Vec3(1.0f, 1.0f, 0.5f));
float xoff = -0.5f / gstate_c.curRTRenderWidth;
float yoff = -0.5f / gstate_c.curRTRenderHeight;
t.setTranslation(Vec3(xoff, yoff, 0.5f));
in = in * s * t;
}
@ -310,7 +324,7 @@ void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) {
Matrix4x4 proj_through;
proj_through.setOrtho(0.0f, gstate_c.curRTWidth, gstate_c.curRTHeight, 0, 0, 1);
ConvertProjMatrixToD3D(proj_through, false, false, false);
ConvertProjMatrixToD3DThrough(proj_through);
VSSetMatrix(CONST_VS_PROJ_THROUGH, proj_through.getReadPtr());
}

View File

@ -713,7 +713,6 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) {
(regionY2 - regionY1) * renderHeightFactor,
0.f, 1.f);
} else {
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
float vpXScale = getFloat24(gstate.viewportx1);
float vpXCenter = getFloat24(gstate.viewportx2);
float vpYScale = getFloat24(gstate.viewporty1);
@ -737,8 +736,6 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) {
vpY0 *= renderHeightFactor;
vpWidth *= renderWidthFactor;
vpHeight *= renderHeightFactor;
// shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
float zScale = getFloat24(gstate.viewportz1) / 65535.0f;
float zOff = getFloat24(gstate.viewportz2) / 65535.0f;
@ -748,15 +745,59 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) {
gstate_c.vpDepth = zScale * 2;
// D3D doesn't like viewports partially outside the target. Clamp the viewport for now. Should also adjust
// the projection matrix to compensate, really.
float left = std::max(0.0f, vpX0 + renderX);
float top = std::max(0.0f, vpY0 + renderY);
float right = std::min(left + vpWidth, renderWidth);
float bottom = std::min(top + vpHeight, renderHeight);
// D3D doesn't like viewports partially outside the target, so we
// apply the viewport partially in the shader.
float left = renderX + vpX0;
float top = renderY + vpY0;
float right = left + vpWidth;
float bottom = top + vpHeight;
float wScale = 1.0f;
float xOffset = 0.0f;
float hScale = 1.0f;
float yOffset = 0.0f;
// 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;
left += overageLeft;
right -= overageRight;
wScale = vpWidth / (right - left);
xOffset = drift / (right - left);
}
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;
top += overageTop;
bottom -= overageBottom;
hScale = vpHeight / (bottom - top);
yOffset = -drift / (bottom - top);
}
depthRangeMin = std::max(0.0f, depthRangeMin);
depthRangeMax = std::min(1.0f, depthRangeMax);
bool scaleChanged = gstate_c.vpWidthScale != wScale || gstate_c.vpHeightScale != hScale;
bool offsetChanged = gstate_c.vpXOffset != xOffset || gstate_c.vpYOffset != yOffset;
if (scaleChanged || offsetChanged)
{
gstate_c.vpWidthScale = wScale;
gstate_c.vpHeightScale = hScale;
gstate_c.vpXOffset = xOffset;
gstate_c.vpYOffset = yOffset;
shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
}
dxstate.viewport.set(left, top, right - left, bottom - top, depthRangeMin, depthRangeMax);
}
}

View File

@ -1652,7 +1652,7 @@ void TextureCacheDX9::LoadTextureLevel(TexCacheEntry &entry, int level, int maxL
entry.SetAlphaStatus(TexCacheEntry::STATUS_ALPHA_UNKNOWN);
}
if (level == 0 && !replaceImages) {
if (level == 0 && (!replaceImages || entry.texture == nullptr)) {
// Create texture
D3DPOOL pool = D3DPOOL_MANAGED;
int usage = 0;

View File

@ -476,6 +476,11 @@ struct GPUStateCache
float vpWidth;
float vpHeight;
float vpDepth;
// Only used by Direct3D, not saved.
float vpXOffset;
float vpYOffset;
float vpWidthScale;
float vpHeightScale;
u32 curRTWidth;
u32 curRTHeight;