Skip to content

Commit

Permalink
GPU: Set projection matrix per backend.
Browse files Browse the repository at this point in the history
There's a bit of variance, so this keeps the central code clean.
  • Loading branch information
unknownbrackets committed Oct 31, 2021
1 parent f35c7d0 commit 159eab5
Show file tree
Hide file tree
Showing 6 changed files with 54 additions and 30 deletions.
47 changes: 21 additions & 26 deletions GPU/Common/SoftwareTransformCommon.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
6 changes: 4 additions & 2 deletions GPU/Common/SoftwareTransformCommon.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -64,10 +64,12 @@ class SoftwareTransform {
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_;
};
5 changes: 5 additions & 0 deletions GPU/D3D11/DrawEngineD3D11.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -599,6 +599,11 @@ void DrawEngineD3D11::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);
Expand Down
11 changes: 11 additions & 0 deletions GPU/Directx9/DrawEngineDX9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -568,6 +568,17 @@ void DrawEngineDX9::DoFlush() {

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);
Expand Down
8 changes: 7 additions & 1 deletion GPU/GLES/DrawEngineGLES.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)) {
Expand All @@ -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);
Expand Down
7 changes: 6 additions & 1 deletion GPU/Vulkan/DrawEngineVulkan.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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...
Expand All @@ -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);
Expand Down

0 comments on commit 159eab5

Please sign in to comment.