GPU: Set projection matrix per backend.

There's a bit of variance, so this keeps the central code clean.
This commit is contained in:
Unknown W. Brackets 2021-10-23 11:59:34 -07:00
parent f35c7d04bd
commit 159eab5141
6 changed files with 54 additions and 30 deletions

View File

@ -151,6 +151,25 @@ static int ColorIndexOffset(int prim, GEShadeMode shadeMode, bool clearMode) {
return 0;
}
void SoftwareTransform::SetProjMatrix(float mtx[14], bool invertedX, bool invertedY, const Lin::Vec3 &trans, const Lin::Vec3 &scale) {
memcpy(&projMatrix_.m, mtx, 16 * sizeof(float));
if (invertedY) {
projMatrix_.xy = -projMatrix_.xy;
projMatrix_.yy = -projMatrix_.yy;
projMatrix_.zy = -projMatrix_.zy;
projMatrix_.wy = -projMatrix_.wy;
}
if (invertedX) {
projMatrix_.xx = -projMatrix_.xx;
projMatrix_.yx = -projMatrix_.yx;
projMatrix_.zx = -projMatrix_.zx;
projMatrix_.wx = -projMatrix_.wx;
}
projMatrix_.translateAndScale(trans, scale);
}
void SoftwareTransform::Decode(int prim, u32 vertType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result) {
u8 *decoded = params_.decoded;
TransformedVertex *transformed = params_.transformed;
@ -560,30 +579,6 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
numTrans = vertexCount;
result->drawIndexed = true;
} else {
// Pretty bad hackery where we re-do the transform (in RotateUV) to see if the vertices are flipped in screen space.
// Since we've already got API-specific assumptions (Y direction, etc) baked into the projMatrix (which we arguably shouldn't),
// this gets nasty and very hard to understand.
float flippedMatrix[16];
if (!throughmode) {
memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float));
const bool invertedY = params_.flippedY ? (gstate_c.vpHeight < 0) : (gstate_c.vpHeight > 0);
if (invertedY) {
flippedMatrix[1] = -flippedMatrix[1];
flippedMatrix[5] = -flippedMatrix[5];
flippedMatrix[9] = -flippedMatrix[9];
flippedMatrix[13] = -flippedMatrix[13];
}
const bool invertedX = gstate_c.vpWidth < 0;
if (invertedX) {
flippedMatrix[0] = -flippedMatrix[0];
flippedMatrix[4] = -flippedMatrix[4];
flippedMatrix[8] = -flippedMatrix[8];
flippedMatrix[12] = -flippedMatrix[12];
}
}
//rectangles always need 2 vertices, disregard the last one if there's an odd number
vertexCount = vertexCount & ~1;
numTrans = 0;
@ -625,9 +620,9 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
RotateUVThrough(trans);
} else {
Vec4f tl;
Vec3ByMatrix44(tl.AsArray(), transVtxTL.pos, flippedMatrix);
Vec3ByMatrix44(tl.AsArray(), transVtxTL.pos, projMatrix_.m);
Vec4f br;
Vec3ByMatrix44(br.AsArray(), transVtxBR.pos, flippedMatrix);
Vec3ByMatrix44(br.AsArray(), transVtxBR.pos, projMatrix_.m);
// If both transformed verts are outside Z, cull this rectangle entirely.
constexpr float outsideValue = 1.000030517578125f;

View File

@ -18,8 +18,8 @@
#pragma once
#include "Common/CommonTypes.h"
#include "VertexDecoderCommon.h"
#include "Common/Math/lin/matrix4x4.h"
#include "GPU/Common/VertexDecoderCommon.h"
class FramebufferManagerCommon;
class TextureCacheCommon;
@ -64,10 +64,12 @@ public:
SoftwareTransform(SoftwareTransformParams &params) : params_(params) {
}
void SetProjMatrix(float mtx[14], bool invertedX, bool invertedY, const Lin::Vec3 &trans, const Lin::Vec3 &scale);
void Decode(int prim, u32 vertexType, const DecVtxFormat &decVtxFormat, int maxIndex, SoftwareTransformResult *result);
void DetectOffsetTexture(int maxIndex);
void BuildDrawingParams(int prim, int vertexCount, u32 vertType, u16 *&inds, int &maxIndex, SoftwareTransformResult *result);
protected:
const SoftwareTransformParams &params_;
Lin::Matrix4x4 projMatrix_;
};

View File

@ -599,6 +599,11 @@ rotateVBO:
int maxIndex = indexGen.MaxIndex();
SoftwareTransform swTransform(params);
const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
const Lin::Vec3 scale(gstate_c.vpWidthScale, -gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight < 0, trans, scale);
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
if (result.action == SW_NOT_READY) {
swTransform.DetectOffsetTexture(maxIndex);

View File

@ -568,6 +568,17 @@ rotateVBO:
int maxIndex = indexGen.MaxIndex();
SoftwareTransform swTransform(params);
// Half pixel offset hack.
float xScale = gstate_c.vpWidth < 0 ? -1.0f : 1.0f;
float xOffset = -1.0f / gstate_c.curRTRenderWidth;
float yScale = gstate_c.vpHeight > 0 ? -1.0f : 1.0f;
float yOffset = 1.0f / gstate_c.curRTRenderHeight;
const Lin::Vec3 trans(gstate_c.vpXOffset * xScale + xOffset, gstate_c.vpYOffset * yScale + yOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight > 0, trans, scale);
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
if (result.action == SW_NOT_READY) {
swTransform.DetectOffsetTexture(maxIndex);

View File

@ -563,7 +563,7 @@ void DrawEngineGLES::DoFlush() {
params.allowClear = true;
params.allowSeparateAlphaClear = true;
params.provokeFlatFirst = false;
params.flippedY = !framebufferManager_->UseBufferedRendering();
params.flippedY = framebufferManager_->UseBufferedRendering();
// We need correct viewport values in gstate_c already.
if (gstate_c.IsDirty(DIRTY_VIEWPORTSCISSOR_STATE)) {
@ -583,6 +583,12 @@ void DrawEngineGLES::DoFlush() {
#endif
SoftwareTransform swTransform(params);
const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset);
const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale * (params.flippedY ? 1.0 : -1.0f), gstate_c.vpDepthScale);
const bool invertedY = gstate_c.vpHeight * (params.flippedY ? 1.0 : -1.0f) < 0;
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, invertedY, trans, scale);
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
if (result.action == SW_NOT_READY)
swTransform.DetectOffsetTexture(maxIndex);

View File

@ -909,7 +909,7 @@ void DrawEngineVulkan::DoFlush() {
params.allowClear = framebufferManager_->UseBufferedRendering();
params.allowSeparateAlphaClear = false;
params.provokeFlatFirst = true;
params.flippedY = false;
params.flippedY = true;
// We need to update the viewport early because it's checked for flipping in SoftwareTransform.
// We don't have a "DrawStateEarly" in vulkan, so...
@ -924,6 +924,11 @@ void DrawEngineVulkan::DoFlush() {
int maxIndex = indexGen.MaxIndex();
SoftwareTransform swTransform(params);
const Lin::Vec3 trans(gstate_c.vpXOffset, gstate_c.vpYOffset, gstate_c.vpZOffset * 0.5f + 0.5f);
const Lin::Vec3 scale(gstate_c.vpWidthScale, gstate_c.vpHeightScale, gstate_c.vpDepthScale * 0.5f);
swTransform.SetProjMatrix(gstate.projMatrix, gstate_c.vpWidth < 0, gstate_c.vpHeight < 0, trans, scale);
swTransform.Decode(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), maxIndex, &result);
if (result.action == SW_NOT_READY) {
swTransform.DetectOffsetTexture(maxIndex);