mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-25 11:19:03 +01:00
Merge pull request #6946 from unknownbrackets/gpu-minor
Simplify the viewport calculation
This commit is contained in:
commit
7442e5746b
5 files changed
+131
-136
No files matched your search
+103
-103
@@ -238,106 +238,106 @@ bool DrawEngineCommon::GetCurrentSimpleVertices(int count, std::vector<GPUDebugV
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning.
|
||||
// The rest of the transform pipeline like lighting will go as normal, either hardware or software.
|
||||
// The implementation is initially a bit inefficient but shouldn't be a big deal.
|
||||
// An intermediate buffer of not-easy-to-predict size is stored at bufPtr.
|
||||
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) {
|
||||
// First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate
|
||||
// implementation of the vertex decoder.
|
||||
dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound);
|
||||
|
||||
// OK, morphing eliminated but bones still remain to be taken care of.
|
||||
// Let's do a partial software transform where we only do skinning.
|
||||
|
||||
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
|
||||
|
||||
SimpleVertex *sverts = (SimpleVertex *)outPtr;
|
||||
|
||||
const u8 defaultColor[4] = {
|
||||
(u8)gstate.getMaterialAmbientR(),
|
||||
(u8)gstate.getMaterialAmbientG(),
|
||||
(u8)gstate.getMaterialAmbientB(),
|
||||
(u8)gstate.getMaterialAmbientA(),
|
||||
};
|
||||
|
||||
// Let's have two separate loops, one for non skinning and one for skinning.
|
||||
if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
|
||||
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
}
|
||||
|
||||
if (vertType & GE_VTYPE_COL_MASK) {
|
||||
reader.ReadColor0_8888(sv.color);
|
||||
} else {
|
||||
memcpy(sv.color, defaultColor, 4);
|
||||
}
|
||||
|
||||
float nrm[3], pos[3];
|
||||
float bnrm[3], bpos[3];
|
||||
|
||||
if (vertType & GE_VTYPE_NRM_MASK) {
|
||||
// Normals are generated during tesselation anyway, not sure if any need to supply
|
||||
reader.ReadNrm(nrm);
|
||||
} else {
|
||||
nrm[0] = 0;
|
||||
nrm[1] = 0;
|
||||
nrm[2] = 1.0f;
|
||||
}
|
||||
reader.ReadPos(pos);
|
||||
|
||||
// Apply skinning transform directly
|
||||
float weights[8];
|
||||
reader.ReadWeights(weights);
|
||||
// Skinning
|
||||
Vec3Packedf psum(0, 0, 0);
|
||||
Vec3Packedf nsum(0, 0, 0);
|
||||
for (int w = 0; w < numBoneWeights; w++) {
|
||||
if (weights[w] != 0.0f) {
|
||||
Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12);
|
||||
Vec3Packedf tpos(bpos);
|
||||
psum += tpos * weights[w];
|
||||
|
||||
Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12);
|
||||
Vec3Packedf tnorm(bnrm);
|
||||
nsum += tnorm * weights[w];
|
||||
}
|
||||
}
|
||||
sv.pos = psum;
|
||||
sv.nrm = nsum;
|
||||
}
|
||||
} else {
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
} else {
|
||||
sv.uv[0] = 0; // This will get filled in during tesselation
|
||||
sv.uv[1] = 0;
|
||||
}
|
||||
if (vertType & GE_VTYPE_COL_MASK) {
|
||||
reader.ReadColor0_8888(sv.color);
|
||||
} else {
|
||||
memcpy(sv.color, defaultColor, 4);
|
||||
}
|
||||
if (vertType & GE_VTYPE_NRM_MASK) {
|
||||
// Normals are generated during tesselation anyway, not sure if any need to supply
|
||||
reader.ReadNrm((float *)&sv.nrm);
|
||||
} else {
|
||||
sv.nrm.x = 0;
|
||||
sv.nrm.y = 0;
|
||||
sv.nrm.z = 1.0f;
|
||||
}
|
||||
reader.ReadPos((float *)&sv.pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Okay, there we are! Return the new type (but keep the index bits)
|
||||
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH));
|
||||
}
|
||||
|
||||
// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning.
|
||||
// The rest of the transform pipeline like lighting will go as normal, either hardware or software.
|
||||
// The implementation is initially a bit inefficient but shouldn't be a big deal.
|
||||
// An intermediate buffer of not-easy-to-predict size is stored at bufPtr.
|
||||
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType) {
|
||||
// First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate
|
||||
// implementation of the vertex decoder.
|
||||
dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound);
|
||||
|
||||
// OK, morphing eliminated but bones still remain to be taken care of.
|
||||
// Let's do a partial software transform where we only do skinning.
|
||||
|
||||
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
|
||||
|
||||
SimpleVertex *sverts = (SimpleVertex *)outPtr;
|
||||
|
||||
const u8 defaultColor[4] = {
|
||||
(u8)gstate.getMaterialAmbientR(),
|
||||
(u8)gstate.getMaterialAmbientG(),
|
||||
(u8)gstate.getMaterialAmbientB(),
|
||||
(u8)gstate.getMaterialAmbientA(),
|
||||
};
|
||||
|
||||
// Let's have two separate loops, one for non skinning and one for skinning.
|
||||
if (!g_Config.bSoftwareSkinning && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
|
||||
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
}
|
||||
|
||||
if (vertType & GE_VTYPE_COL_MASK) {
|
||||
reader.ReadColor0_8888(sv.color);
|
||||
} else {
|
||||
memcpy(sv.color, defaultColor, 4);
|
||||
}
|
||||
|
||||
float nrm[3], pos[3];
|
||||
float bnrm[3], bpos[3];
|
||||
|
||||
if (vertType & GE_VTYPE_NRM_MASK) {
|
||||
// Normals are generated during tesselation anyway, not sure if any need to supply
|
||||
reader.ReadNrm(nrm);
|
||||
} else {
|
||||
nrm[0] = 0;
|
||||
nrm[1] = 0;
|
||||
nrm[2] = 1.0f;
|
||||
}
|
||||
reader.ReadPos(pos);
|
||||
|
||||
// Apply skinning transform directly
|
||||
float weights[8];
|
||||
reader.ReadWeights(weights);
|
||||
// Skinning
|
||||
Vec3Packedf psum(0, 0, 0);
|
||||
Vec3Packedf nsum(0, 0, 0);
|
||||
for (int w = 0; w < numBoneWeights; w++) {
|
||||
if (weights[w] != 0.0f) {
|
||||
Vec3ByMatrix43(bpos, pos, gstate.boneMatrix + w * 12);
|
||||
Vec3Packedf tpos(bpos);
|
||||
psum += tpos * weights[w];
|
||||
|
||||
Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix + w * 12);
|
||||
Vec3Packedf tnorm(bnrm);
|
||||
nsum += tnorm * weights[w];
|
||||
}
|
||||
}
|
||||
sv.pos = psum;
|
||||
sv.nrm = nsum;
|
||||
}
|
||||
} else {
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
} else {
|
||||
sv.uv[0] = 0; // This will get filled in during tesselation
|
||||
sv.uv[1] = 0;
|
||||
}
|
||||
if (vertType & GE_VTYPE_COL_MASK) {
|
||||
reader.ReadColor0_8888(sv.color);
|
||||
} else {
|
||||
memcpy(sv.color, defaultColor, 4);
|
||||
}
|
||||
if (vertType & GE_VTYPE_NRM_MASK) {
|
||||
// Normals are generated during tesselation anyway, not sure if any need to supply
|
||||
reader.ReadNrm((float *)&sv.nrm);
|
||||
} else {
|
||||
sv.nrm.x = 0;
|
||||
sv.nrm.y = 0;
|
||||
sv.nrm.z = 1.0f;
|
||||
}
|
||||
reader.ReadPos((float *)&sv.pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Okay, there we are! Return the new type (but keep the index bits)
|
||||
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & (GE_VTYPE_IDX_MASK | GE_VTYPE_THROUGH));
|
||||
}
|
||||
@@ -35,8 +35,8 @@ public:
|
||||
virtual u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) = 0;
|
||||
|
||||
bool GetCurrentSimpleVertices(int count, std::vector<GPUDebugVertex> &vertices, std::vector<u16> &indices);
|
||||
|
||||
static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
|
||||
|
||||
static u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, VertexDecoder *dec, int lowerBound, int upperBound, u32 vertType);
|
||||
|
||||
protected:
|
||||
// Vertex collector buffers
|
||||
|
||||
@@ -291,7 +291,7 @@ void ShaderManagerDX9::VSUpdateUniforms(int dirtyUniforms) {
|
||||
memcpy(&flippedMatrix, gstate.projMatrix, 16 * sizeof(float));
|
||||
|
||||
const bool invertedY = gstate_c.vpHeight < 0;
|
||||
if (invertedY) {
|
||||
if (!invertedY) {
|
||||
flippedMatrix[5] = -flippedMatrix[5];
|
||||
flippedMatrix[13] = -flippedMatrix[13];
|
||||
}
|
||||
|
||||
@@ -708,21 +708,21 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) {
|
||||
0.f, 1.f);
|
||||
} else {
|
||||
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
||||
float vpXa = getFloat24(gstate.viewportx1);
|
||||
float vpXb = getFloat24(gstate.viewportx2);
|
||||
float vpYa = getFloat24(gstate.viewporty1);
|
||||
float vpYb = getFloat24(gstate.viewporty2);
|
||||
float vpXScale = getFloat24(gstate.viewportx1);
|
||||
float vpXCenter = getFloat24(gstate.viewportx2);
|
||||
float vpYScale = getFloat24(gstate.viewporty1);
|
||||
float vpYCenter = getFloat24(gstate.viewporty2);
|
||||
|
||||
// The viewport transform appears to go like this:
|
||||
// Xscreen = -offsetX + vpXb + vpXa * Xview
|
||||
// Yscreen = -offsetY + vpYb + vpYa * Yview
|
||||
// Zscreen = vpZb + vpZa * Zview
|
||||
// Xscreen = -offsetX + vpXCenter + vpXScale * Xview
|
||||
// Yscreen = -offsetY + vpYCenter + vpYScale * Yview
|
||||
// Zscreen = vpZCenter + vpZScale * Zview
|
||||
|
||||
// This means that to get the analogue glViewport we must:
|
||||
float vpX0 = vpXb - offsetX - vpXa;
|
||||
float vpY0 = vpYb - offsetY + vpYa; // Need to account for sign of Y
|
||||
gstate_c.vpWidth = vpXa * 2.0f;
|
||||
gstate_c.vpHeight = -vpYa * 2.0f;
|
||||
float vpX0 = vpXCenter - offsetX - fabsf(vpXScale);
|
||||
float vpY0 = vpYCenter - offsetY - fabsf(vpYScale);
|
||||
gstate_c.vpWidth = vpXScale * 2.0f;
|
||||
gstate_c.vpHeight = vpYScale * 2.0f;
|
||||
|
||||
float vpWidth = fabsf(gstate_c.vpWidth);
|
||||
float vpHeight = fabsf(gstate_c.vpHeight);
|
||||
@@ -731,10 +731,6 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) {
|
||||
vpY0 *= renderHeightFactor;
|
||||
vpWidth *= renderWidthFactor;
|
||||
vpHeight *= renderHeightFactor;
|
||||
|
||||
vpX0 = (vpXb - offsetX - fabsf(vpXa)) * renderWidthFactor;
|
||||
// Flip vpY0 to match the OpenGL coordinate system.
|
||||
vpY0 = (framebufferManager_->GetTargetHeight() - (vpYb - offsetY + fabsf(vpYa))) * renderHeightFactor;
|
||||
|
||||
// shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
|
||||
|
||||
|
||||
+14
-15
@@ -772,21 +772,21 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
glstate.depthRange.set(0.0f, 1.0f);
|
||||
} else {
|
||||
// These we can turn into a glViewport call, offset by offsetX and offsetY. Math after.
|
||||
float vpXa = getFloat24(gstate.viewportx1);
|
||||
float vpXb = getFloat24(gstate.viewportx2);
|
||||
float vpYa = getFloat24(gstate.viewporty1);
|
||||
float vpYb = getFloat24(gstate.viewporty2);
|
||||
float vpXScale = getFloat24(gstate.viewportx1);
|
||||
float vpXCenter = getFloat24(gstate.viewportx2);
|
||||
float vpYScale = getFloat24(gstate.viewporty1);
|
||||
float vpYCenter = getFloat24(gstate.viewporty2);
|
||||
|
||||
// The viewport transform appears to go like this:
|
||||
// Xscreen = -offsetX + vpXb + vpXa * Xview
|
||||
// Yscreen = -offsetY + vpYb + vpYa * Yview
|
||||
// Zscreen = vpZb + vpZa * Zview
|
||||
// The viewport transform appears to go like this:
|
||||
// Xscreen = -offsetX + vpXCenter + vpXScale * Xview
|
||||
// Yscreen = -offsetY + vpYCenter + vpYScale * Yview
|
||||
// Zscreen = vpZCenter + vpZScale * Zview
|
||||
|
||||
// This means that to get the analogue glViewport we must:
|
||||
float vpX0 = vpXb - offsetX - vpXa;
|
||||
float vpY0 = vpYb - offsetY + vpYa; // Need to account for sign of Y
|
||||
gstate_c.vpWidth = vpXa * 2.0f;
|
||||
gstate_c.vpHeight = -vpYa * 2.0f;
|
||||
float vpX0 = vpXCenter - offsetX - fabsf(vpXScale);
|
||||
float vpY0 = vpYCenter - offsetY + fabsf(vpYScale); // Need to account for sign of Y
|
||||
gstate_c.vpWidth = vpXScale * 2.0f;
|
||||
gstate_c.vpHeight = -vpYScale * 2.0f;
|
||||
|
||||
float vpWidth = fabsf(gstate_c.vpWidth);
|
||||
float vpHeight = fabsf(gstate_c.vpHeight);
|
||||
@@ -796,10 +796,9 @@ void TransformDrawEngine::ApplyDrawState(int prim) {
|
||||
vpWidth *= renderWidthFactor;
|
||||
vpHeight *= renderHeightFactor;
|
||||
|
||||
vpX0 = (vpXb - offsetX - fabsf(vpXa)) * renderWidthFactor;
|
||||
// Flip vpY0 to match the OpenGL coordinate system.
|
||||
vpY0 = renderHeight - (vpYb - offsetY + fabsf(vpYa)) * renderHeightFactor;
|
||||
|
||||
vpY0 = renderHeight - vpY0;
|
||||
|
||||
glstate.viewport.set(vpX0 + renderX, vpY0 + renderY, vpWidth, vpHeight);
|
||||
// Sadly, as glViewport takes integers, we will not be able to support sub pixel offsets this way. But meh.
|
||||
// shaderManager_->DirtyUniform(DIRTY_PROJMATRIX);
|
||||
|
||||
Reference in new issue
Block a user