mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Remove the option to use hardware skinning - software skinning is better.
This commit is contained in:
1 parent
529df5e196
commit
58454894eb
22 files changed
+68
-243
No files matched your search
@@ -879,7 +879,6 @@ static ConfigSetting graphicsSettings[] = {
|
||||
ConfigSetting("SoftwareRenderer", &g_Config.bSoftwareRendering, false, true, true),
|
||||
ConfigSetting("SoftwareRendererJit", &g_Config.bSoftwareRenderingJit, true, true, true),
|
||||
ReportedConfigSetting("HardwareTransform", &g_Config.bHardwareTransform, true, true, true),
|
||||
ReportedConfigSetting("SoftwareSkinning", &g_Config.bSoftwareSkinning, true, true, true),
|
||||
ReportedConfigSetting("TextureFiltering", &g_Config.iTexFiltering, 1, true, true),
|
||||
ReportedConfigSetting("BufferFiltering", &g_Config.iBufFilter, SCALE_LINEAR, true, true),
|
||||
ReportedConfigSetting("InternalResolution", &g_Config.iInternalResolution, &DefaultInternalResolution, true, true),
|
||||
|
||||
@@ -162,7 +162,6 @@ public:
|
||||
bool bSoftwareRendering;
|
||||
bool bSoftwareRenderingJit;
|
||||
bool bHardwareTransform; // only used in the GLES backend
|
||||
bool bSoftwareSkinning;
|
||||
bool bVendorBugChecksEnabled;
|
||||
bool bUseGeometryShader;
|
||||
|
||||
|
||||
@@ -180,11 +180,10 @@ void DrawEngineCommon::NotifyConfigChanged() {
|
||||
|
||||
useHWTransform_ = g_Config.bHardwareTransform;
|
||||
useHWTessellation_ = UpdateUseHWTessellation(g_Config.bHardwareTessellation);
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType, int *vertexSize) {
|
||||
const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), decOptions_.applySkinInDecode);
|
||||
const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), true);
|
||||
VertexDecoder *dec = GetVertexDecoder(vertTypeID);
|
||||
if (vertexSize)
|
||||
*vertexSize = dec->VertexSize();
|
||||
@@ -232,7 +231,7 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex
|
||||
}
|
||||
|
||||
int bytesRead;
|
||||
uint32_t vertTypeID = GetVertTypeID(vtype, 0, decOptions_.applySkinInDecode);
|
||||
uint32_t vertTypeID = GetVertTypeID(vtype, 0, true);
|
||||
SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, cullMode, &bytesRead);
|
||||
DispatchFlush();
|
||||
|
||||
@@ -281,10 +280,7 @@ bool DrawEngineCommon::TestBoundingBox(const void *control_points, const void *i
|
||||
}
|
||||
|
||||
// Force software skinning.
|
||||
bool wasApplyingSkinInDecode = decOptions_.applySkinInDecode;
|
||||
decOptions_.applySkinInDecode = true;
|
||||
NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)control_points, indexLowerBound, indexUpperBound, vertType);
|
||||
decOptions_.applySkinInDecode = wasApplyingSkinInDecode;
|
||||
|
||||
IndexConverter conv(vertType, inds);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
@@ -499,8 +495,7 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
|
||||
// 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.
|
||||
// Morph and skin are both removed during decode now.
|
||||
|
||||
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
|
||||
|
||||
@@ -513,80 +508,29 @@ u32 DrawEngineCommon::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr,
|
||||
(u8)gstate.getMaterialAmbientA(),
|
||||
};
|
||||
|
||||
// Let's have two separate loops, one for non skinning and one for skinning.
|
||||
if (!dec->skinInDecode && (vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
|
||||
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i - lowerBound);
|
||||
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 tessellation 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;
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i - lowerBound);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
} else {
|
||||
sv.uv[0] = 0.0f; // This will get filled in during tessellation
|
||||
sv.uv[1] = 0.0f;
|
||||
}
|
||||
} else {
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i - lowerBound);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
} else {
|
||||
sv.uv[0] = 0.0f; // This will get filled in during tessellation
|
||||
sv.uv[1] = 0.0f;
|
||||
}
|
||||
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 tessellation anyway, not sure if any need to supply
|
||||
reader.ReadNrm((float *)&sv.nrm);
|
||||
} else {
|
||||
sv.nrm.x = 0.0f;
|
||||
sv.nrm.y = 0.0f;
|
||||
sv.nrm.z = 1.0f;
|
||||
}
|
||||
reader.ReadPos((float *)&sv.pos);
|
||||
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 tessellation anyway, not sure if any need to supply
|
||||
reader.ReadNrm((float *)&sv.nrm);
|
||||
} else {
|
||||
sv.nrm.x = 0.0f;
|
||||
sv.nrm.y = 0.0f;
|
||||
sv.nrm.z = 1.0f;
|
||||
}
|
||||
reader.ReadPos((float *)&sv.pos);
|
||||
}
|
||||
|
||||
// Okay, there we are! Return the new type (but keep the index bits)
|
||||
@@ -836,7 +780,7 @@ void DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti
|
||||
numDrawCalls++;
|
||||
vertexCountInDrawCalls_ += vertexCount;
|
||||
|
||||
if (decOptions_.applySkinInDecode && (vertTypeID & GE_VTYPE_WEIGHT_MASK)) {
|
||||
if (vertTypeID & GE_VTYPE_WEIGHT_MASK) {
|
||||
DecodeVertsStep(decoded, decodeCounter_, decodedVerts_);
|
||||
decodeCounter_++;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,7 @@ void ComputeVertexShaderID(VShaderID *id_out, u32 vertType, bool useHWTransform,
|
||||
}
|
||||
|
||||
// Bones.
|
||||
bool enableBones = !useSkinInDecode && vertTypeIsSkinningEnabled(vertType);
|
||||
bool enableBones = false;
|
||||
id.SetBit(VS_BIT_ENABLE_BONES, enableBones);
|
||||
if (enableBones) {
|
||||
id.SetBits(VS_BIT_BONES, 3, TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1);
|
||||
|
||||
@@ -507,7 +507,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
if (indices)
|
||||
GetIndexBounds(indices, num_points, vertType, &index_lower_bound, &index_upper_bound);
|
||||
|
||||
VertexDecoder *origVDecoder = GetVertexDecoder(GetVertTypeID(vertType, gstate.getUVGenMode(), decOptions_.applySkinInDecode));
|
||||
VertexDecoder *origVDecoder = GetVertexDecoder(GetVertTypeID(vertType, gstate.getUVGenMode(), true));
|
||||
*bytesRead = num_points * origVDecoder->VertexSize();
|
||||
|
||||
// Simplify away bones and morph before proceeding
|
||||
@@ -572,7 +572,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
gstate_c.uv.vOff = 0;
|
||||
}
|
||||
|
||||
uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), decOptions_.applySkinInDecode);
|
||||
uint32_t vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), true);
|
||||
int generatedBytesRead;
|
||||
if (output.count)
|
||||
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, gstate.getCullMode(), &generatedBytesRead);
|
||||
|
||||
@@ -1089,7 +1089,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
|
||||
DEBUG_LOG(G3D, "VTYPE: THRU=%i TC=%i COL=%i POS=%i NRM=%i WT=%i NW=%i IDX=%i MC=%i", (int)throughmode, tc, col, pos, nrm, weighttype, nweights, idx, morphcount);
|
||||
}
|
||||
|
||||
skinInDecode = weighttype != 0 && options.applySkinInDecode;
|
||||
skinInDecode = weighttype != 0;
|
||||
|
||||
if (weighttype) { // && nweights?
|
||||
weightoff = size;
|
||||
@@ -1098,43 +1098,11 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
|
||||
if (wtalign[weighttype] > biggest)
|
||||
biggest = wtalign[weighttype];
|
||||
|
||||
if (skinInDecode) {
|
||||
// No visible output, computes a matrix that is passed through the skinMatrix variable
|
||||
// to the "nrm" and "pos" steps.
|
||||
// Technically we should support morphing the weights too, but I have a hard time
|
||||
// imagining that any game would use that.. but you never know.
|
||||
steps_[numSteps_++] = wtstep_skin[weighttype];
|
||||
} else {
|
||||
int fmtBase = DEC_FLOAT_1;
|
||||
if (options.expandAllWeightsToFloat) {
|
||||
steps_[numSteps_++] = wtstepToFloat[weighttype];
|
||||
fmtBase = DEC_FLOAT_1;
|
||||
} else {
|
||||
steps_[numSteps_++] = wtstep[weighttype];
|
||||
if (weighttype == GE_VTYPE_WEIGHT_8BIT >> GE_VTYPE_WEIGHT_SHIFT) {
|
||||
fmtBase = DEC_U8_1;
|
||||
} else if (weighttype == GE_VTYPE_WEIGHT_16BIT >> GE_VTYPE_WEIGHT_SHIFT) {
|
||||
fmtBase = DEC_U16_1;
|
||||
} else if (weighttype == GE_VTYPE_WEIGHT_FLOAT >> GE_VTYPE_WEIGHT_SHIFT) {
|
||||
fmtBase = DEC_FLOAT_1;
|
||||
}
|
||||
}
|
||||
|
||||
int numWeights = TranslateNumBones(nweights);
|
||||
|
||||
if (numWeights <= 4) {
|
||||
decFmt.w0off = decOff;
|
||||
decFmt.w0fmt = fmtBase + numWeights - 1;
|
||||
decOff += DecFmtSize(decFmt.w0fmt);
|
||||
} else {
|
||||
decFmt.w0off = decOff;
|
||||
decFmt.w0fmt = fmtBase + 3;
|
||||
decOff += DecFmtSize(decFmt.w0fmt);
|
||||
decFmt.w1off = decOff;
|
||||
decFmt.w1fmt = fmtBase + numWeights - 5;
|
||||
decOff += DecFmtSize(decFmt.w1fmt);
|
||||
}
|
||||
}
|
||||
// No visible output, computes a matrix that is passed through the skinMatrix variable
|
||||
// to the "nrm" and "pos" steps.
|
||||
// Technically we should support morphing the weights too, but I have a hard time
|
||||
// imagining that any game would use that.. but you never know.
|
||||
steps_[numSteps_++] = wtstep_skin[weighttype];
|
||||
}
|
||||
|
||||
if (tc) {
|
||||
|
||||
@@ -333,7 +333,6 @@ typedef void(*JittedVertexDecoder)(const u8 *src, u8 *dst, int count);
|
||||
struct VertexDecoderOptions {
|
||||
bool expandAllWeightsToFloat;
|
||||
bool expand8BitNormalsToFloat;
|
||||
bool applySkinInDecode;
|
||||
};
|
||||
|
||||
class VertexDecoder {
|
||||
|
||||
@@ -364,8 +364,8 @@ void DrawEngineD3D11::DoFlush() {
|
||||
|
||||
// Cannot cache vertex data with morph enabled.
|
||||
bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
|
||||
// Also avoid caching when software skinning.
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK))
|
||||
// Also avoid caching when skinning.
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK)
|
||||
useCache = false;
|
||||
|
||||
if (useCache) {
|
||||
@@ -538,7 +538,7 @@ rotateVBO:
|
||||
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, true);
|
||||
ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
|
||||
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
|
||||
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
|
||||
@@ -581,7 +581,6 @@ rotateVBO:
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
decOptions_.applySkinInDecode = true;
|
||||
DecodeVerts(decoded);
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
if (gstate.isModeThrough()) {
|
||||
@@ -649,7 +648,7 @@ rotateVBO:
|
||||
if (result.action == SW_DRAW_PRIMITIVES) {
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true);
|
||||
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
|
||||
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
|
||||
shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering());
|
||||
@@ -710,7 +709,6 @@ rotateVBO:
|
||||
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
|
||||
}
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
gpuStats.numDrawCalls += numDrawCalls;
|
||||
|
||||
@@ -85,8 +85,7 @@ public:
|
||||
ShaderManagerD3D11(Draw::DrawContext *draw, ID3D11Device *device, ID3D11DeviceContext *context, D3D_FEATURE_LEVEL featureLevel);
|
||||
~ShaderManagerD3D11();
|
||||
|
||||
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode);
|
||||
void ClearShaders();
|
||||
void GetShaders(int prim, u32 vertType, D3D11VertexShader **vshader, D3D11FragmentShader **fshader, const ComputedPipelineState &pipelineState, bool useHWTransform, bool useHWTessellation, bool weightsAsFloat, bool useSkinInDecode); void ClearShaders();
|
||||
void DirtyLastShader() override;
|
||||
|
||||
int GetNumVertexShaders() const { return (int)vsCache_.size(); }
|
||||
|
||||
@@ -348,8 +348,8 @@ void DrawEngineDX9::DoFlush() {
|
||||
|
||||
// Cannot cache vertex data with morph enabled.
|
||||
bool useCache = g_Config.bVertexCache && !(lastVType_ & GE_VTYPE_MORPHCOUNT_MASK);
|
||||
// Also avoid caching when software skinning.
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK))
|
||||
// Also avoid caching when skinning.
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK)
|
||||
useCache = false;
|
||||
|
||||
if (useCache) {
|
||||
@@ -522,7 +522,7 @@ rotateVBO:
|
||||
ApplyDrawState(prim);
|
||||
ApplyDrawStateLate();
|
||||
|
||||
VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_);
|
||||
VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, true, pipelineState_);
|
||||
IDirect3DVertexDeclaration9 *pHardwareVertexDecl = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
|
||||
|
||||
if (pHardwareVertexDecl) {
|
||||
@@ -546,7 +546,6 @@ rotateVBO:
|
||||
}
|
||||
}
|
||||
} else {
|
||||
decOptions_.applySkinInDecode = true;
|
||||
DecodeVerts(decoded);
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
if (gstate.isModeThrough()) {
|
||||
@@ -614,7 +613,7 @@ rotateVBO:
|
||||
|
||||
ApplyDrawStateLate();
|
||||
|
||||
VSShader *vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_);
|
||||
VSShader *vshader = shaderManager_->ApplyShader(false, false, lastVType_, decOptions_.expandAllWeightsToFloat, true, pipelineState_);
|
||||
|
||||
if (result.action == SW_DRAW_PRIMITIVES) {
|
||||
if (result.setStencil) {
|
||||
@@ -654,7 +653,6 @@ rotateVBO:
|
||||
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
|
||||
}
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
gpuStats.numDrawCalls += numDrawCalls;
|
||||
|
||||
@@ -267,7 +267,7 @@ void DrawEngineGLES::DoFlush() {
|
||||
GEPrimitiveType prim = prevPrim_;
|
||||
|
||||
VShaderID vsid;
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, &vsid);
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, lastVType_, decOptions_.expandAllWeightsToFloat, true, &vsid);
|
||||
|
||||
GLRBuffer *vertexBuffer = nullptr;
|
||||
GLRBuffer *indexBuffer = nullptr;
|
||||
@@ -278,8 +278,8 @@ void DrawEngineGLES::DoFlush() {
|
||||
int vertexCount = 0;
|
||||
bool useElements = true;
|
||||
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
// If software skinning, we've already predecoded into "decoded". So push that content.
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK) {
|
||||
// Since we're software skinning, we've already predecoded into "decoded". So push that content.
|
||||
size_t size = decodedVerts_ * dec_->GetDecVtxFmt().stride;
|
||||
u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vertexBufferOffset, &vertexBuffer);
|
||||
memcpy(dest, decoded, size);
|
||||
@@ -331,7 +331,6 @@ void DrawEngineGLES::DoFlush() {
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
decOptions_.applySkinInDecode = true;
|
||||
DecodeVerts(decoded);
|
||||
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
@@ -448,7 +447,6 @@ void DrawEngineGLES::DoFlush() {
|
||||
}
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied.
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
gpuStats.numDrawCalls += numDrawCalls;
|
||||
|
||||
+16
-61
@@ -436,13 +436,8 @@ GPUCommon::~GPUCommon() {
|
||||
}
|
||||
|
||||
void GPUCommon::UpdateCmdInfo() {
|
||||
if (g_Config.bSoftwareSkinning) {
|
||||
cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
|
||||
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning;
|
||||
} else {
|
||||
cmdInfo_[GE_CMD_VERTEXTYPE].flags |= FLAG_FLUSHBEFOREONCHANGE;
|
||||
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexType;
|
||||
}
|
||||
cmdInfo_[GE_CMD_VERTEXTYPE].flags &= ~FLAG_FLUSHBEFOREONCHANGE;
|
||||
cmdInfo_[GE_CMD_VERTEXTYPE].func = &GPUCommon::Execute_VertexTypeSkinning;
|
||||
|
||||
if (g_Config.bFastMemory) {
|
||||
cmdInfo_[GE_CMD_JUMP].func = &GPUCommon::Execute_JumpFast;
|
||||
@@ -1834,7 +1829,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) {
|
||||
// cull mode
|
||||
int cullMode = gstate.getCullMode();
|
||||
|
||||
uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning);
|
||||
uint32_t vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), true);
|
||||
drawEngineCommon_->SubmitPrim(verts, inds, prim, count, vertTypeID, cullMode, &bytesRead);
|
||||
// After drawing, we advance the vertexAddr (when non indexed) or indexAddr (when indexed).
|
||||
// Some games rely on this, they don't bother reloading VADDR and IADDR.
|
||||
@@ -1853,8 +1848,6 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) {
|
||||
// between each prim, we just change the triangle winding right here to still be able to join draw calls.
|
||||
|
||||
uint32_t vtypeCheckMask = ~GE_VTYPE_WEIGHTCOUNT_MASK;
|
||||
if (!g_Config.bSoftwareSkinning)
|
||||
vtypeCheckMask = 0xFFFFFFFF;
|
||||
|
||||
if (debugRecording_)
|
||||
goto bail;
|
||||
@@ -1892,7 +1885,7 @@ void GPUCommon::Execute_Prim(u32 op, u32 diff) {
|
||||
goto bail;
|
||||
} else {
|
||||
vertexType = data;
|
||||
vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), g_Config.bSoftwareSkinning);
|
||||
vertTypeID = GetVertTypeID(vertexType, gstate.getUVGenMode(), true);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -2033,10 +2026,6 @@ void GPUCommon::Execute_Bezier(u32 op, u32 diff) {
|
||||
indices = Memory::GetPointerUnchecked(gstate_c.indexAddr);
|
||||
}
|
||||
|
||||
if (vertTypeIsSkinningEnabled(gstate.vertType)) {
|
||||
DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType));
|
||||
}
|
||||
|
||||
// Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already.
|
||||
if (flushOnParams_)
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
@@ -2106,10 +2095,6 @@ void GPUCommon::Execute_Spline(u32 op, u32 diff) {
|
||||
indices = Memory::GetPointerUnchecked(gstate_c.indexAddr);
|
||||
}
|
||||
|
||||
if (vertTypeIsSkinningEnabled(gstate.vertType)) {
|
||||
DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType));
|
||||
}
|
||||
|
||||
// Can't flush after setting gstate_c.submitType below since it'll be a mess - it must be done already.
|
||||
if (flushOnParams_)
|
||||
drawEngineCommon_->DispatchFlush();
|
||||
@@ -2451,35 +2436,16 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) {
|
||||
}
|
||||
|
||||
if (fastLoad) {
|
||||
// If we can't use software skinning, we have to flush and dirty.
|
||||
if (!g_Config.bSoftwareSkinning) {
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
const u32 newVal = src[i] << 8;
|
||||
if (dst[i] != newVal) {
|
||||
Flush();
|
||||
dst[i] = newVal;
|
||||
}
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
dst[i] = src[i] << 8;
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int numPlusCount = (op & 0x7F) + i;
|
||||
for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12));
|
||||
}
|
||||
} else {
|
||||
while ((src[i] >> 24) == GE_CMD_BONEMATRIXDATA) {
|
||||
dst[i] = src[i] << 8;
|
||||
if (++i >= end) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
const unsigned int numPlusCount = (op & 0x7F) + i;
|
||||
for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12);
|
||||
}
|
||||
const unsigned int numPlusCount = (op & 0x7F) + i;
|
||||
for (unsigned int num = op & 0x7F; num < numPlusCount; num += 12) {
|
||||
gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2496,13 +2462,8 @@ void GPUCommon::Execute_BoneMtxData(u32 op, u32 diff) {
|
||||
int num = gstate.boneMatrixNumber & 0x00FFFFFF;
|
||||
u32 newVal = op << 8;
|
||||
if (num < 96 && newVal != ((const u32 *)gstate.boneMatrix)[num]) {
|
||||
// Bone matrices should NOT flush when software skinning is enabled!
|
||||
if (!g_Config.bSoftwareSkinning) {
|
||||
Flush();
|
||||
gstate_c.Dirty(DIRTY_BONEMATRIX0 << (num / 12));
|
||||
} else {
|
||||
gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12);
|
||||
}
|
||||
// Bone matrices should NOT flush since we're software skinning!
|
||||
gstate_c.deferredVertTypeDirty |= DIRTY_BONEMATRIX0 << (num / 12);
|
||||
((u32 *)gstate.boneMatrix)[num] = newVal;
|
||||
}
|
||||
num++;
|
||||
@@ -2528,7 +2489,7 @@ void GPUCommon::Execute_ImmVertexAlphaPrim(u32 op, u32 diff) {
|
||||
|
||||
int prim = (op >> 8) & 0x7;
|
||||
if (prim != GE_PRIM_KEEP_PREVIOUS) {
|
||||
// Flush before changing the prim type. Only continue can be used to continue a prim.
|
||||
// Flush before changing the prim type. Only continue can be used to continue a prim.
|
||||
FlushImm();
|
||||
}
|
||||
|
||||
@@ -2692,13 +2653,7 @@ void GPUCommon::FastLoadBoneMatrix(u32 target) {
|
||||
uniformsToDirty |= DIRTY_BONEMATRIX0 << ((mtxNum + 1) & 7);
|
||||
}
|
||||
|
||||
if (!g_Config.bSoftwareSkinning) {
|
||||
if (flushOnParams_)
|
||||
Flush();
|
||||
gstate_c.Dirty(uniformsToDirty);
|
||||
} else {
|
||||
gstate_c.deferredVertTypeDirty |= uniformsToDirty;
|
||||
}
|
||||
gstate_c.deferredVertTypeDirty |= uniformsToDirty;
|
||||
gstate.FastLoadBoneMatrix(target);
|
||||
}
|
||||
|
||||
|
||||
@@ -260,10 +260,6 @@ void GPUgstate::Restore(u32_le *ptr) {
|
||||
gpu->ResetMatrices();
|
||||
}
|
||||
|
||||
bool vertTypeIsSkinningEnabled(u32 vertType) {
|
||||
return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE);
|
||||
}
|
||||
|
||||
struct GPUStateCache_v0 {
|
||||
u32 vertexAddr;
|
||||
u32 indexAddr;
|
||||
|
||||
@@ -448,8 +448,6 @@ struct GPUgstate {
|
||||
void Restore(u32_le *ptr);
|
||||
};
|
||||
|
||||
bool vertTypeIsSkinningEnabled(u32 vertType);
|
||||
|
||||
inline int vertTypeGetNumBoneWeights(u32 vertType) { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); }
|
||||
inline int vertTypeGetWeightMask(u32 vertType) { return vertType & GE_VTYPE_WEIGHT_MASK; }
|
||||
|
||||
|
||||
@@ -889,7 +889,7 @@ void SoftGPU::Execute_Bezier(u32 op, u32 diff) {
|
||||
indices = Memory::GetPointerUnchecked(gstate_c.indexAddr);
|
||||
}
|
||||
|
||||
if ((gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) || vertTypeIsSkinningEnabled(gstate.vertType)) {
|
||||
if (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) {
|
||||
DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType));
|
||||
}
|
||||
|
||||
@@ -941,7 +941,7 @@ void SoftGPU::Execute_Spline(u32 op, u32 diff) {
|
||||
indices = Memory::GetPointerUnchecked(gstate_c.indexAddr);
|
||||
}
|
||||
|
||||
if ((gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) || vertTypeIsSkinningEnabled(gstate.vertType)) {
|
||||
if (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) {
|
||||
DEBUG_LOG_REPORT(G3D, "Unusual bezier/spline vtype: %08x, morph: %d, bones: %d", gstate.vertType, (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT, vertTypeGetNumBoneWeights(gstate.vertType));
|
||||
}
|
||||
|
||||
|
||||
@@ -64,7 +64,6 @@ SoftwareDrawEngine::~SoftwareDrawEngine() {
|
||||
|
||||
void SoftwareDrawEngine::NotifyConfigChanged() {
|
||||
DrawEngineCommon::NotifyConfigChanged();
|
||||
decOptions_.applySkinInDecode = true;
|
||||
}
|
||||
|
||||
void SoftwareDrawEngine::DispatchFlush() {
|
||||
@@ -940,7 +939,6 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVert
|
||||
|
||||
VertexDecoder vdecoder;
|
||||
VertexDecoderOptions options{};
|
||||
options.applySkinInDecode = true;
|
||||
vdecoder.SetVertexType(gstate.vertType, options);
|
||||
|
||||
if (!Memory::IsValidRange(gstate_c.vertexAddr, (indexUpperBound + 1) * vdecoder.VertexSize()))
|
||||
|
||||
@@ -599,7 +599,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
// Also avoid caching when software skinning.
|
||||
VkBuffer vbuf = VK_NULL_HANDLE;
|
||||
VkBuffer ibuf = VK_NULL_HANDLE;
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK) {
|
||||
useCache = false;
|
||||
}
|
||||
|
||||
@@ -739,7 +739,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
if (lastVType_ & GE_VTYPE_WEIGHT_MASK) {
|
||||
// If software skinning, we've already predecoded into "decoded". So push that content.
|
||||
VkDeviceSize size = decodedVerts_ * dec_->GetDecVtxFmt().stride;
|
||||
u8 *dest = (u8 *)frameData.pushVertex->Push(size, &vbOffset, &vbuf);
|
||||
@@ -784,7 +784,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
VulkanFragmentShader *fshader = nullptr;
|
||||
VulkanGeometryShader *gshader = nullptr;
|
||||
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, true);
|
||||
if (!vshader) {
|
||||
// We're screwed.
|
||||
return;
|
||||
@@ -841,7 +841,6 @@ void DrawEngineVulkan::DoFlush() {
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
decOptions_.applySkinInDecode = true;
|
||||
DecodeVerts(decoded);
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
if (gstate.isModeThrough()) {
|
||||
@@ -920,7 +919,7 @@ void DrawEngineVulkan::DoFlush() {
|
||||
VulkanFragmentShader *fshader = nullptr;
|
||||
VulkanGeometryShader *gshader = nullptr;
|
||||
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode);
|
||||
shaderManager_->GetShaders(prim, lastVType_, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true);
|
||||
_dbg_assert_msg_(!vshader->UseHWTransform(), "Bad vshader");
|
||||
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, false, 0);
|
||||
if (!pipeline || !pipeline->pipeline) {
|
||||
@@ -928,7 +927,6 @@ void DrawEngineVulkan::DoFlush() {
|
||||
decodedVerts_ = 0;
|
||||
numDrawCalls = 0;
|
||||
decodeCounter_ = 0;
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
return;
|
||||
}
|
||||
BindShaderBlendTex(); // This might cause copies so super important to do before BindPipeline.
|
||||
@@ -996,7 +994,6 @@ void DrawEngineVulkan::DoFlush() {
|
||||
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color);
|
||||
}
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
gpuStats.numDrawCalls += numDrawCalls;
|
||||
|
||||
@@ -540,12 +540,6 @@ void GameSettingsScreen::CreateViews() {
|
||||
hwTransform->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||
}
|
||||
|
||||
CheckBox *swSkin = graphicsSettings->Add(new CheckBox(&g_Config.bSoftwareSkinning, gr->T("Software Skinning")));
|
||||
swSkin->OnClick.Add([=](EventParams &e) {
|
||||
settingInfo_->Show(gr->T("SoftwareSkinning Tip", "Combine skinned model draws on the CPU, faster in most games"), e.v);
|
||||
return UI::EVENT_CONTINUE;
|
||||
});
|
||||
swSkin->SetDisabledPtr(&g_Config.bSoftwareRendering);
|
||||
|
||||
CheckBox *tessellationHW = graphicsSettings->Add(new CheckBox(&g_Config.bHardwareTessellation, gr->T("Hardware Tessellation")));
|
||||
tessellationHW->OnClick.Add([=](EventParams &e) {
|
||||
|
||||
@@ -306,8 +306,6 @@ int CtrlVertexList::GetRowCount() {
|
||||
rowCount_ = 0;
|
||||
}
|
||||
VertexDecoderOptions options{};
|
||||
// TODO: Maybe an option?
|
||||
options.applySkinInDecode = true;
|
||||
decoder->SetVertexType(state.vertType, options);
|
||||
return rowCount_;
|
||||
}
|
||||
|
||||
@@ -436,7 +436,6 @@ int main(int argc, const char* argv[])
|
||||
g_Config.iInternalResolution = 1;
|
||||
g_Config.iFastForwardMode = (int)FastForwardMode::CONTINUOUS;
|
||||
g_Config.bEnableLogging = fullLog;
|
||||
g_Config.bSoftwareSkinning = true;
|
||||
g_Config.bVertexDecoderJit = true;
|
||||
g_Config.bSoftwareRendering = coreParameter.gpuCore == GPUCORE_SOFTWARE;
|
||||
g_Config.bSoftwareRenderingJit = true;
|
||||
|
||||
@@ -823,15 +823,6 @@ static void check_variables(CoreParameter &coreParam)
|
||||
g_Config.bHardwareTransform = true;
|
||||
}
|
||||
|
||||
var.key = "ppsspp_software_skinning";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
{
|
||||
if (!strcmp(var.value, "disabled"))
|
||||
g_Config.bSoftwareSkinning = false;
|
||||
else
|
||||
g_Config.bSoftwareSkinning = true;
|
||||
}
|
||||
|
||||
var.key = "ppsspp_vertex_cache";
|
||||
if (environ_cb(RETRO_ENVIRONMENT_GET_VARIABLE, &var) && var.value)
|
||||
{
|
||||
|
||||
@@ -546,7 +546,6 @@ static bool TestVertexColor565() {
|
||||
static bool TestVertex8Skin() {
|
||||
VertexDecoderTestHarness dec;
|
||||
VertexDecoderOptions opts{};
|
||||
opts.applySkinInDecode = true;
|
||||
dec.SetOptions(opts);
|
||||
|
||||
for (int i = 0; i < 8 * 12; ++i) {
|
||||
@@ -578,7 +577,6 @@ static bool TestVertex8Skin() {
|
||||
static bool TestVertex16Skin() {
|
||||
VertexDecoderTestHarness dec;
|
||||
VertexDecoderOptions opts{};
|
||||
opts.applySkinInDecode = true;
|
||||
dec.SetOptions(opts);
|
||||
|
||||
for (int i = 0; i < 8 * 12; ++i) {
|
||||
@@ -610,7 +608,6 @@ static bool TestVertex16Skin() {
|
||||
static bool TestVertexFloatSkin() {
|
||||
VertexDecoderTestHarness dec;
|
||||
VertexDecoderOptions opts{};
|
||||
opts.applySkinInDecode = true;
|
||||
dec.SetOptions(opts);
|
||||
|
||||
for (int i = 0; i < 8 * 12; ++i) {
|
||||
|
||||
Reference in new issue
Block a user