GPU: Refactor out rectangle expansion.

Just so it's cleaner when the same is done for lines.
This commit is contained in:
Unknown W. Brackets 2021-10-31 11:09:04 -07:00
parent 9fc94a3494
commit 4fb09859fd
2 changed files with 126 additions and 106 deletions

View file

@ -567,36 +567,42 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
// Step 2: expand and process primitives.
result->drawBuffer = transformed;
int numTrans = 0;
const u16 *indsIn = (const u16 *)inds;
u16 *newInds = inds + vertexCount;
u16 *indsOut = newInds;
FramebufferManagerCommon *fbman = params_.fbman;
bool useBufferedRendering = fbman->UseBufferedRendering();
// The projected Z can be up to 0x3F8000FF, which is where this constant is from.
// It seems like it may only maintain 15 mantissa bits (excluding implied.)
float maxZValue = 1.000030517578125f * gstate_c.vpDepthScale;
float minZValue = -maxZValue;
// Scale and offset the Z appropriately, since we baked that into a projection transform.
if (params_.usesHalfZ) {
maxZValue = maxZValue * 0.5f + 0.5f + gstate_c.vpZOffset * 0.5f;
minZValue = minZValue * 0.5f + 0.5f + gstate_c.vpZOffset * 0.5f;
} else {
maxZValue += gstate_c.vpZOffset;
minZValue += gstate_c.vpZOffset;
}
// In case scale was negative, flip.
if (minZValue > maxZValue)
std::swap(minZValue, maxZValue);
if (prim == GE_PRIM_RECTANGLES) {
ExpandRectangles(vertexCount, maxIndex, inds, transformed, transformedExpanded, numTrans, throughmode);
result->drawBuffer = transformedExpanded;
result->drawIndexed = true;
if (prim != GE_PRIM_RECTANGLES) {
// We don't know the color until here, so we have to do it now, instead of in StateMapping.
// Might want to reconsider the order of things later...
if (gstate.isModeClear() && gstate.isClearModeAlphaMask()) {
result->setStencil = true;
if (vertexCount > 1) {
// Take the bottom right alpha value of the first rect as the stencil value.
// Technically, each rect could individually fill its stencil, but most of the
// time they use the same one.
result->stencilValue = transformed[inds[1]].color0[3];
} else {
result->stencilValue = 0;
}
}
} else {
// We can simply draw the unexpanded buffer.
numTrans = vertexCount;
result->drawIndexed = true;
// If we don't support custom cull in the shader, process it here.
if (!gstate_c.Supports(GPU_SUPPORTS_CULL_DISTANCE) && vertexCount > 0 && !throughmode) {
const u16 *indsIn = (const u16 *)inds;
u16 *newInds = inds + vertexCount;
u16 *indsOut = newInds;
float minZValue, maxZValue;
CalcCullParams(minZValue, maxZValue);
std::vector<int> outsideZ;
outsideZ.resize(vertexCount);
@ -674,13 +680,47 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
inds = newInds;
}
}
}
if (gstate.isModeClear()) {
gpuStats.numClears++;
}
result->action = SW_DRAW_PRIMITIVES;
result->drawNumTrans = numTrans;
}
void SoftwareTransform::CalcCullParams(float &minZValue, float &maxZValue) {
// The projected Z can be up to 0x3F8000FF, which is where this constant is from.
// It seems like it may only maintain 15 mantissa bits (excluding implied.)
maxZValue = 1.000030517578125f * gstate_c.vpDepthScale;
minZValue = -maxZValue;
// Scale and offset the Z appropriately, since we baked that into a projection transform.
if (params_.usesHalfZ) {
maxZValue = maxZValue * 0.5f + 0.5f + gstate_c.vpZOffset * 0.5f;
minZValue = minZValue * 0.5f + 0.5f + gstate_c.vpZOffset * 0.5f;
} else {
maxZValue += gstate_c.vpZOffset;
minZValue += gstate_c.vpZOffset;
}
// In case scale was negative, flip.
if (minZValue > maxZValue)
std::swap(minZValue, maxZValue);
}
void SoftwareTransform::ExpandRectangles(int vertexCount, int &maxIndex, u16 *&inds, TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode) {
// Rectangles always need 2 vertices, disregard the last one if there's an odd number.
vertexCount = vertexCount & ~1;
numTrans = 0;
result->drawBuffer = transformedExpanded;
TransformedVertex *trans = &transformedExpanded[0];
const u16 *indsIn = (const u16 *)inds;
u16 *newInds = inds + vertexCount;
u16 *indsOut = newInds;
float minZValue, maxZValue;
CalcCullParams(minZValue, maxZValue);
maxIndex = 4 * (vertexCount / 2);
for (int i = 0; i < vertexCount; i += 2) {
const TransformedVertex &transVtxTL = transformed[indsIn[i + 0]];
@ -746,27 +786,4 @@ void SoftwareTransform::BuildDrawingParams(int prim, int vertexCount, u32 vertTy
numTrans += 6;
}
inds = newInds;
result->drawIndexed = true;
// We don't know the color until here, so we have to do it now, instead of in StateMapping.
// Might want to reconsider the order of things later...
if (gstate.isModeClear() && gstate.isClearModeAlphaMask()) {
result->setStencil = true;
if (vertexCount > 1) {
// Take the bottom right alpha value of the first rect as the stencil value.
// Technically, each rect could individually fill its stencil, but most of the
// time they use the same one.
result->stencilValue = transformed[indsIn[1]].color0[3];
} else {
result->stencilValue = 0;
}
}
}
if (gstate.isModeClear()) {
gpuStats.numClears++;
}
result->action = SW_DRAW_PRIMITIVES;
result->drawNumTrans = numTrans;
}

View file

@ -71,6 +71,9 @@ public:
void BuildDrawingParams(int prim, int vertexCount, u32 vertType, u16 *&inds, int &maxIndex, SoftwareTransformResult *result);
protected:
void CalcCullParams(float &minZValue, float &maxZValue);
void ExpandRectangles(int vertexCount, int &maxIndex, u16 *&inds, TransformedVertex *transformed, TransformedVertex *transformedExpanded, int &numTrans, bool throughmode);
const SoftwareTransformParams &params_;
Lin::Matrix4x4 projMatrix_;
};