mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-13 17:49:29 +01:00
Merge pull request #19743 from hrydgard/vertex-decoder-minor-cleanup
Vertex decoder code cleanup
This commit is contained in:
17 files changed
+125
-100
No files matched your search
@@ -133,11 +133,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(), applySkinInDecode_);
|
||||
VertexDecoder *dec = GetVertexDecoder(vertTypeID);
|
||||
if (vertexSize)
|
||||
*vertexSize = dec->VertexSize();
|
||||
@@ -185,7 +184,7 @@ void DrawEngineCommon::DispatchSubmitImm(GEPrimitiveType prim, TransformedVertex
|
||||
}
|
||||
|
||||
int bytesRead;
|
||||
uint32_t vertTypeID = GetVertTypeID(vtype, 0, decOptions_.applySkinInDecode);
|
||||
uint32_t vertTypeID = GetVertTypeID(vtype, 0, applySkinInDecode_);
|
||||
|
||||
bool clockwise = !gstate.isCullEnabled() || gstate.getCullMode() == cullMode;
|
||||
SubmitPrim(&temp[0], nullptr, prim, vertexCount, vertTypeID, clockwise, &bytesRead);
|
||||
@@ -303,10 +302,10 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int
|
||||
}
|
||||
// TODO: Avoid normalization if just plain skinning.
|
||||
// Force software skinning.
|
||||
bool wasApplyingSkinInDecode = decOptions_.applySkinInDecode;
|
||||
decOptions_.applySkinInDecode = true;
|
||||
bool wasApplyingSkinInDecode = applySkinInDecode_;
|
||||
applySkinInDecode_ = true;
|
||||
NormalizeVertices((u8 *)corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, vertType);
|
||||
decOptions_.applySkinInDecode = wasApplyingSkinInDecode;
|
||||
applySkinInDecode_ = wasApplyingSkinInDecode;
|
||||
|
||||
IndexConverter conv(vertType, inds);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
@@ -985,7 +984,7 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti
|
||||
}
|
||||
}
|
||||
|
||||
bool applySkin = (vertTypeID & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode;
|
||||
bool applySkin = dec_->skinInDecode;
|
||||
|
||||
DeferredInds &di = drawInds_[numDrawInds_++];
|
||||
di.inds = inds;
|
||||
@@ -1038,10 +1037,17 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti
|
||||
return true;
|
||||
}
|
||||
|
||||
void DrawEngineCommon::DecodeVerts(u8 *dest) {
|
||||
void DrawEngineCommon::BeginFrame() {
|
||||
applySkinInDecode_ = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
void DrawEngineCommon::DecodeVerts(VertexDecoder *dec, u8 *dest) {
|
||||
if (!numDrawVerts_) {
|
||||
return;
|
||||
}
|
||||
// Note that this should be able to continue a partial decode - we don't necessarily start from zero here (although we do most of the time).
|
||||
int i = decodeVertsCounter_;
|
||||
int stride = (int)dec_->GetDecVtxFmt().stride;
|
||||
int stride = (int)dec->GetDecVtxFmt().stride;
|
||||
for (; i < numDrawVerts_; i++) {
|
||||
DeferredVerts &dv = drawVerts_[i];
|
||||
|
||||
@@ -1056,7 +1062,7 @@ void DrawEngineCommon::DecodeVerts(u8 *dest) {
|
||||
}
|
||||
|
||||
// Decode the verts (and at the same time apply morphing/skinning). Simple.
|
||||
dec_->DecodeVerts(dest + numDecodedVerts_ * stride, dv.verts, &dv.uvScale, indexLowerBound, indexUpperBound);
|
||||
dec->DecodeVerts(dest + numDecodedVerts_ * stride, dv.verts, &dv.uvScale, indexLowerBound, indexUpperBound);
|
||||
numDecodedVerts_ += indexUpperBound - indexLowerBound + 1;
|
||||
}
|
||||
decodeVertsCounter_ = i;
|
||||
|
||||
@@ -53,12 +53,6 @@ enum FBOTexState {
|
||||
FBO_TEX_READ_FRAMEBUFFER,
|
||||
};
|
||||
|
||||
inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode, bool skinInDecode) {
|
||||
// As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it
|
||||
// into the top of the verttype where there are unused bits.
|
||||
return (vertType & 0xFFFFFF) | (uvGenMode << 24) | (skinInDecode << 26);
|
||||
}
|
||||
|
||||
struct SimpleVertex;
|
||||
namespace Spline { struct Weight2D; }
|
||||
|
||||
@@ -83,6 +77,8 @@ public:
|
||||
|
||||
void Init();
|
||||
|
||||
virtual void BeginFrame();
|
||||
|
||||
void SetGPUCommon(GPUCommon *gpuCommon) {
|
||||
gpuCommon_ = gpuCommon;
|
||||
}
|
||||
@@ -114,9 +110,8 @@ public:
|
||||
bool TestBoundingBoxThrough(const void *vdata, int vertexCount, u32 vertType);
|
||||
|
||||
void FlushSkin() {
|
||||
bool applySkin = (lastVType_ & GE_VTYPE_WEIGHT_MASK) && decOptions_.applySkinInDecode;
|
||||
if (applySkin) {
|
||||
DecodeVerts(decoded_);
|
||||
if (dec_->skinInDecode) {
|
||||
DecodeVerts(dec_, decoded_);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -160,7 +155,7 @@ protected:
|
||||
virtual bool UpdateUseHWTessellation(bool enabled) const { return enabled; }
|
||||
void UpdatePlanes();
|
||||
|
||||
void DecodeVerts(u8 *dest);
|
||||
void DecodeVerts(VertexDecoder *dec, u8 *dest);
|
||||
int DecodeInds();
|
||||
|
||||
// Preprocessing for spline/bezier
|
||||
@@ -314,6 +309,8 @@ protected:
|
||||
bool anyCCWOrIndexed_ = 0;
|
||||
bool anyIndexed_ = 0;
|
||||
|
||||
bool applySkinInDecode_ = false;
|
||||
|
||||
// Vertex collector state
|
||||
IndexGenerator indexGen;
|
||||
int numDecodedVerts_ = 0;
|
||||
|
||||
@@ -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(), applySkinInDecode_));
|
||||
*bytesRead = num_points * origVDecoder->VertexSize();
|
||||
|
||||
// Simplify away bones and morph before proceeding
|
||||
@@ -574,7 +574,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(), applySkinInDecode_);
|
||||
int generatedBytesRead;
|
||||
if (output.count)
|
||||
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, true, &generatedBytesRead);
|
||||
|
||||
@@ -1125,7 +1125,7 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
|
||||
DEBUG_LOG(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 && VertTypeIDSkinInDecode(fmt);
|
||||
|
||||
if (weighttype) { // && nweights?
|
||||
weightoff = size;
|
||||
@@ -1182,7 +1182,8 @@ void VertexDecoder::SetVertexType(u32 fmt, const VertexDecoderOptions &options,
|
||||
|
||||
// NOTE: That we check getUVGenMode here means that we must include it in the decoder ID!
|
||||
// throughmode is automatically included though, because it's part of the vertType.
|
||||
if (!throughmode && (gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_COORDS || gstate.getUVGenMode() == GE_TEXMAP_UNKNOWN)) {
|
||||
GETexMapMode mode = VertTypeIDUVGenMode(fmt);
|
||||
if (!throughmode && (mode == GE_TEXMAP_TEXTURE_COORDS || mode == GE_TEXMAP_UNKNOWN)) {
|
||||
if (g_DoubleTextureCoordinates)
|
||||
steps_[numSteps_++] = morphcount == 1 ? tcstep_prescale_remaster[tc] : tcstep_prescale_morph_remaster[tc];
|
||||
else
|
||||
|
||||
@@ -325,9 +325,22 @@ typedef void (*JittedVertexDecoder)(const u8 *src, u8 *dst, int count, const UVS
|
||||
struct VertexDecoderOptions {
|
||||
bool expandAllWeightsToFloat;
|
||||
bool expand8BitNormalsToFloat;
|
||||
bool applySkinInDecode;
|
||||
};
|
||||
|
||||
inline uint32_t GetVertTypeID(uint32_t vertType, int uvGenMode, bool skinInDecode) {
|
||||
// As the decoder depends on the UVGenMode when we use UV prescale, we simply mash it
|
||||
// into the top of the verttype where there are unused bits.
|
||||
return (vertType & 0xFFFFFF) | (uvGenMode << 24) | (skinInDecode << 26);
|
||||
}
|
||||
|
||||
inline bool VertTypeIDSkinInDecode(uint32_t vertType) {
|
||||
return ((vertType >> 26) & 1) != 0;
|
||||
}
|
||||
|
||||
inline GETexMapMode VertTypeIDUVGenMode(uint32_t vertType) {
|
||||
return (GETexMapMode)((vertType >> 24) & 3);
|
||||
}
|
||||
|
||||
class VertexDecoder {
|
||||
public:
|
||||
// A jit cache is not mandatory.
|
||||
@@ -512,7 +525,6 @@ public:
|
||||
|
||||
// Returns a pointer to the code to run.
|
||||
JittedVertexDecoder Compile(const VertexDecoder &dec, int32_t *jittedSize);
|
||||
bool DescribeCodePtr(const u8 *ptr, std::string &name) const;
|
||||
void Clear();
|
||||
|
||||
void Jit_WeightsU8();
|
||||
|
||||
@@ -239,6 +239,8 @@ ID3D11InputLayout *DrawEngineD3D11::SetupDecFmtForDraw(D3D11VertexShader *vshade
|
||||
}
|
||||
|
||||
void DrawEngineD3D11::BeginFrame() {
|
||||
DrawEngineCommon::BeginFrame();
|
||||
|
||||
pushVerts_->Reset();
|
||||
pushInds_->Reset();
|
||||
|
||||
@@ -282,7 +284,7 @@ void DrawEngineD3D11::Flush() {
|
||||
int vertexCount;
|
||||
int maxIndex;
|
||||
bool useElements;
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false);
|
||||
gpuStats.numUncachedVertsDrawn += vertexCount;
|
||||
|
||||
@@ -303,7 +305,7 @@ void DrawEngineD3D11::Flush() {
|
||||
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode);
|
||||
shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, pipelineState_, useHWTransform, useHWTessellation_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_);
|
||||
ID3D11InputLayout *inputLayout = SetupDecFmtForDraw(vshader, dec_->GetDecVtxFmt(), dec_->VertexType());
|
||||
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
|
||||
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
|
||||
@@ -346,12 +348,15 @@ void DrawEngineD3D11::Flush() {
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
if (!decOptions_.applySkinInDecode) {
|
||||
decOptions_.applySkinInDecode = true;
|
||||
lastVType_ |= (1 << 26);
|
||||
dec_ = GetVertexDecoder(lastVType_);
|
||||
VertexDecoder *swDec = dec_;
|
||||
if (swDec->nweights != 0) {
|
||||
u32 withSkinning = lastVType_ | (1 << 26);
|
||||
if (withSkinning != lastVType_) {
|
||||
swDec = GetVertexDecoder(withSkinning);
|
||||
}
|
||||
}
|
||||
DecodeVerts(decoded_);
|
||||
|
||||
DecodeVerts(swDec, decoded_);
|
||||
int vertexCount = DecodeInds();
|
||||
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
@@ -400,7 +405,7 @@ void DrawEngineD3D11::Flush() {
|
||||
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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
swTransform.Transform(prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
@@ -416,7 +421,7 @@ void DrawEngineD3D11::Flush() {
|
||||
ApplyDrawState(prim);
|
||||
|
||||
if (result.action == SW_NOT_READY)
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
|
||||
@@ -425,7 +430,7 @@ void DrawEngineD3D11::Flush() {
|
||||
if (result.action == SW_DRAW_INDEXED) {
|
||||
D3D11VertexShader *vshader;
|
||||
D3D11FragmentShader *fshader;
|
||||
shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true);
|
||||
shaderManager_->GetShaders(prim, swDec, &vshader, &fshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true);
|
||||
context_->PSSetShader(fshader->GetShader(), nullptr, 0);
|
||||
context_->VSSetShader(vshader->GetShader(), nullptr, 0);
|
||||
shaderManager_->UpdateUniforms(framebufferManager_->UseBufferedRendering());
|
||||
@@ -478,7 +483,6 @@ void DrawEngineD3D11::Flush() {
|
||||
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
|
||||
}
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
ResetAfterDrawInline();
|
||||
|
||||
@@ -75,12 +75,12 @@ public:
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
void BeginFrame();
|
||||
void BeginFrame() override;
|
||||
|
||||
void Flush() override;
|
||||
|
||||
void FinishDeferred() {
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
}
|
||||
|
||||
void NotifyConfigChanged() override;
|
||||
|
||||
@@ -219,6 +219,7 @@ static uint32_t SwapRB(uint32_t c) {
|
||||
}
|
||||
|
||||
void DrawEngineDX9::BeginFrame() {
|
||||
DrawEngineCommon::BeginFrame();
|
||||
lastRenderStepId_ = -1;
|
||||
}
|
||||
|
||||
@@ -256,7 +257,7 @@ void DrawEngineDX9::Flush() {
|
||||
int vertexCount;
|
||||
int maxIndex;
|
||||
bool useElements;
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false);
|
||||
gpuStats.numUncachedVertsDrawn += vertexCount;
|
||||
|
||||
@@ -276,7 +277,7 @@ void DrawEngineDX9::Flush() {
|
||||
ApplyDrawState(prim);
|
||||
ApplyDrawStateLate();
|
||||
|
||||
VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode, pipelineState_);
|
||||
VSShader *vshader = shaderManager_->ApplyShader(true, useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_, pipelineState_);
|
||||
ComPtr<IDirect3DVertexDeclaration9> pHardwareVertexDecl;
|
||||
SetupDecFmtForDraw(dec_->GetDecVtxFmt(), dec_->VertexType(), &pHardwareVertexDecl);
|
||||
|
||||
@@ -301,12 +302,14 @@ void DrawEngineDX9::Flush() {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!decOptions_.applySkinInDecode) {
|
||||
decOptions_.applySkinInDecode = true;
|
||||
lastVType_ |= (1 << 26);
|
||||
dec_ = GetVertexDecoder(lastVType_);
|
||||
VertexDecoder *swDec = dec_;
|
||||
if (swDec->nweights != 0) {
|
||||
u32 withSkinning = lastVType_ | (1 << 26);
|
||||
if (withSkinning != lastVType_) {
|
||||
swDec = GetVertexDecoder(withSkinning);
|
||||
}
|
||||
}
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(swDec, decoded_);
|
||||
int vertexCount = DecodeInds();
|
||||
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
@@ -361,7 +364,7 @@ void DrawEngineDX9::Flush() {
|
||||
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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
swTransform.Transform(prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
@@ -376,13 +379,13 @@ void DrawEngineDX9::Flush() {
|
||||
ApplyDrawState(prim);
|
||||
|
||||
if (result.action == SW_NOT_READY)
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
|
||||
ApplyDrawStateLate();
|
||||
|
||||
VSShader *vshader = shaderManager_->ApplyShader(false, false, dec_, decOptions_.expandAllWeightsToFloat, true, pipelineState_);
|
||||
VSShader *vshader = shaderManager_->ApplyShader(false, false, swDec, decOptions_.expandAllWeightsToFloat, true, pipelineState_);
|
||||
|
||||
if (result.action == SW_DRAW_INDEXED) {
|
||||
if (result.setStencil) {
|
||||
@@ -414,7 +417,6 @@ void DrawEngineDX9::Flush() {
|
||||
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, clearColor);
|
||||
}
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
ResetAfterDrawInline();
|
||||
|
||||
@@ -65,13 +65,13 @@ public:
|
||||
void InitDeviceObjects();
|
||||
void DestroyDeviceObjects();
|
||||
|
||||
void BeginFrame();
|
||||
void BeginFrame() override;
|
||||
|
||||
// So that this can be inlined
|
||||
void Flush() override;
|
||||
|
||||
void FinishDeferred() {
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
}
|
||||
|
||||
protected:
|
||||
|
||||
+16
-13
@@ -147,6 +147,8 @@ void DrawEngineGLES::ClearInputLayoutMap() {
|
||||
}
|
||||
|
||||
void DrawEngineGLES::BeginFrame() {
|
||||
DrawEngineCommon::BeginFrame();
|
||||
|
||||
FrameData &frameData = frameData_[render_->GetCurFrame()];
|
||||
frameData.pushIndex->Begin();
|
||||
frameData.pushVertex->Begin();
|
||||
@@ -264,7 +266,7 @@ void DrawEngineGLES::Flush() {
|
||||
|
||||
GEPrimitiveType prim = prevPrim_;
|
||||
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode || !CanUseHardwareTransform(prim), &vsid);
|
||||
Shader *vshader = shaderManager_->ApplyVertexShader(CanUseHardwareTransform(prim), useHWTessellation_, dec_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_ || !CanUseHardwareTransform(prim), &vsid);
|
||||
|
||||
GLRBuffer *vertexBuffer = nullptr;
|
||||
GLRBuffer *indexBuffer = nullptr;
|
||||
@@ -272,9 +274,9 @@ void DrawEngineGLES::Flush() {
|
||||
uint32_t indexBufferOffset = 0;
|
||||
|
||||
if (vshader->UseHWTransform()) {
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
if (applySkinInDecode_ && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
// If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content.
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
uint32_t size = numDecodedVerts_ * dec_->GetDecVtxFmt().stride;
|
||||
u8 *dest = (u8 *)frameData.pushVertex->Allocate(size, 4, &vertexBuffer, &vertexBufferOffset);
|
||||
memcpy(dest, decoded_, size);
|
||||
@@ -282,13 +284,13 @@ void DrawEngineGLES::Flush() {
|
||||
// Figure out how much pushbuffer space we need to allocate.
|
||||
int vertsToDecode = ComputeNumVertsToDecode();
|
||||
u8 *dest = (u8 *)frameData.pushVertex->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, &vertexBuffer, &vertexBufferOffset);
|
||||
DecodeVerts(dest);
|
||||
DecodeVerts(dec_, dest);
|
||||
}
|
||||
|
||||
int vertexCount;
|
||||
int maxIndex;
|
||||
bool useElements;
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
DecodeIndsAndGetData(&prim, &vertexCount, &maxIndex, &useElements, false);
|
||||
|
||||
if (useElements) {
|
||||
@@ -328,12 +330,14 @@ void DrawEngineGLES::Flush() {
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
if (!decOptions_.applySkinInDecode) {
|
||||
decOptions_.applySkinInDecode = true;
|
||||
lastVType_ |= (1 << 26);
|
||||
dec_ = GetVertexDecoder(lastVType_);
|
||||
VertexDecoder *swDec = dec_;
|
||||
if (swDec->nweights != 0) {
|
||||
u32 withSkinning = lastVType_ | (1 << 26);
|
||||
if (withSkinning != lastVType_) {
|
||||
swDec = GetVertexDecoder(withSkinning);
|
||||
}
|
||||
}
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(swDec, decoded_);
|
||||
int vertexCount = DecodeInds();
|
||||
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
@@ -387,7 +391,7 @@ void DrawEngineGLES::Flush() {
|
||||
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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
swTransform.Transform(prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
@@ -403,7 +407,7 @@ void DrawEngineGLES::Flush() {
|
||||
ApplyDrawState(prim);
|
||||
|
||||
if (result.action == SW_NOT_READY)
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
if (result.setSafeSize)
|
||||
framebufferManager_->SetSafeSize(result.safeWidth, result.safeHeight);
|
||||
|
||||
@@ -447,7 +451,6 @@ void DrawEngineGLES::Flush() {
|
||||
}
|
||||
gstate_c.Dirty(DIRTY_BLEND_STATE); // Make sure the color mask gets re-applied.
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
bail:
|
||||
|
||||
@@ -81,7 +81,7 @@ public:
|
||||
|
||||
void ClearTrackedVertexArrays() override {}
|
||||
|
||||
void BeginFrame();
|
||||
void BeginFrame() override;
|
||||
void EndFrame();
|
||||
|
||||
// So that this can be inlined
|
||||
|
||||
@@ -63,7 +63,7 @@ SoftwareDrawEngine::~SoftwareDrawEngine() {}
|
||||
|
||||
void SoftwareDrawEngine::NotifyConfigChanged() {
|
||||
DrawEngineCommon::NotifyConfigChanged();
|
||||
decOptions_.applySkinInDecode = true;
|
||||
applySkinInDecode_ = true;
|
||||
}
|
||||
|
||||
void SoftwareDrawEngine::Flush() {
|
||||
@@ -973,8 +973,8 @@ bool TransformUnit::GetCurrentSimpleVertices(int count, std::vector<GPUDebugVert
|
||||
|
||||
VertexDecoder vdecoder;
|
||||
VertexDecoderOptions options{};
|
||||
options.applySkinInDecode = true;
|
||||
vdecoder.SetVertexType(gstate.vertType, options);
|
||||
u32 vertTypeID = GetVertTypeID(gstate.vertType, gstate.getUVGenMode(), true);
|
||||
vdecoder.SetVertexType(vertTypeID, options);
|
||||
|
||||
if (!Memory::IsValidRange(gstate_c.vertexAddr, (indexUpperBound + 1) * vdecoder.VertexSize()))
|
||||
return false;
|
||||
|
||||
@@ -164,6 +164,8 @@ void DrawEngineVulkan::DeviceRestore(Draw::DrawContext *draw) {
|
||||
}
|
||||
|
||||
void DrawEngineVulkan::BeginFrame() {
|
||||
DrawEngineCommon::BeginFrame();
|
||||
|
||||
lastPipeline_ = nullptr;
|
||||
|
||||
// These will be re-bound if needed, let's not let old bindings linger around too long.
|
||||
@@ -258,9 +260,9 @@ void DrawEngineVulkan::Flush() {
|
||||
uint32_t vbOffset;
|
||||
|
||||
VkBuffer vbuf = VK_NULL_HANDLE;
|
||||
if (decOptions_.applySkinInDecode && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
if (applySkinInDecode_ && (lastVType_ & GE_VTYPE_WEIGHT_MASK)) {
|
||||
// If software skinning, we're predecoding into "decoded". So make sure we're done, then push that content.
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(dec_, decoded_);
|
||||
VkDeviceSize size = numDecodedVerts_ * dec_->GetDecVtxFmt().stride;
|
||||
u8 *dest = (u8 *)pushVertex_->Allocate(size, 4, &vbuf, &vbOffset);
|
||||
memcpy(dest, decoded_, size);
|
||||
@@ -269,7 +271,7 @@ void DrawEngineVulkan::Flush() {
|
||||
int vertsToDecode = ComputeNumVertsToDecode();
|
||||
// Decode directly into the pushbuffer
|
||||
u8 *dest = pushVertex_->Allocate(vertsToDecode * dec_->GetDecVtxFmt().stride, 4, &vbuf, &vbOffset);
|
||||
DecodeVerts(dest);
|
||||
DecodeVerts(dec_, dest);
|
||||
}
|
||||
|
||||
int vertexCount;
|
||||
@@ -302,7 +304,7 @@ void DrawEngineVulkan::Flush() {
|
||||
VulkanFragmentShader *fshader = nullptr;
|
||||
VulkanGeometryShader *gshader = nullptr;
|
||||
|
||||
shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, decOptions_.applySkinInDecode);
|
||||
shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, true, useHWTessellation_, decOptions_.expandAllWeightsToFloat, applySkinInDecode_);
|
||||
_dbg_assert_msg_(vshader->UseHWTransform(), "Bad vshader");
|
||||
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &dec_->decFmt, vshader, fshader, gshader, true, 0, framebufferManager_->GetMSAALevel(), false);
|
||||
if (!pipeline || !pipeline->pipeline) {
|
||||
@@ -381,14 +383,16 @@ void DrawEngineVulkan::Flush() {
|
||||
}
|
||||
} else {
|
||||
PROFILE_THIS_SCOPE("soft");
|
||||
if (!decOptions_.applySkinInDecode) {
|
||||
decOptions_.applySkinInDecode = true;
|
||||
lastVType_ |= (1 << 26);
|
||||
dec_ = GetVertexDecoder(lastVType_);
|
||||
VertexDecoder *swDec = dec_;
|
||||
if (swDec->nweights != 0) {
|
||||
u32 withSkinning = lastVType_ | (1 << 26);
|
||||
if (withSkinning != lastVType_) {
|
||||
swDec = GetVertexDecoder(withSkinning);
|
||||
}
|
||||
}
|
||||
int prevDecodedVerts = numDecodedVerts_;
|
||||
|
||||
DecodeVerts(decoded_);
|
||||
DecodeVerts(swDec, decoded_);
|
||||
int vertexCount = DecodeInds();
|
||||
|
||||
bool hasColor = (lastVType_ & GE_VTYPE_COL_MASK) != GE_VTYPE_COL_NONE;
|
||||
@@ -444,7 +448,7 @@ void DrawEngineVulkan::Flush() {
|
||||
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.Transform(prim, dec_->VertexType(), dec_->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
swTransform.Transform(prim, swDec->VertexType(), swDec->GetDecVtxFmt(), numDecodedVerts_, &result);
|
||||
// Non-zero depth clears are unusual, but some drivers don't match drawn depth values to cleared values.
|
||||
// Games sometimes expect exact matches (see #12626, for example) for equal comparisons.
|
||||
if (result.action == SW_CLEAR && everUsedEqualDepth_ && gstate.isClearModeDepthMask() && result.depth > 0.0f && result.depth < 1.0f)
|
||||
@@ -452,7 +456,7 @@ void DrawEngineVulkan::Flush() {
|
||||
|
||||
if (result.action == SW_NOT_READY) {
|
||||
// decIndex_ here is always equal to inds currently, but it may not be in the future.
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, dec_->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
swTransform.BuildDrawingParams(prim, vertexCount, swDec->VertexType(), inds, RemainingIndices(inds), numDecodedVerts_, VERTEX_BUFFER_MAX, &result);
|
||||
}
|
||||
|
||||
if (result.setSafeSize)
|
||||
@@ -480,9 +484,9 @@ void DrawEngineVulkan::Flush() {
|
||||
VulkanFragmentShader *fshader = nullptr;
|
||||
VulkanGeometryShader *gshader = nullptr;
|
||||
|
||||
shaderManager_->GetShaders(prim, dec_, &vshader, &fshader, &gshader, pipelineState_, false, false, decOptions_.expandAllWeightsToFloat, true);
|
||||
shaderManager_->GetShaders(prim, swDec, &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, framebufferManager_->GetMSAALevel(), false);
|
||||
VulkanPipeline *pipeline = pipelineManager_->GetOrCreatePipeline(renderManager, pipelineLayout_, pipelineKey_, &swDec->decFmt, vshader, fshader, gshader, false, 0, framebufferManager_->GetMSAALevel(), false);
|
||||
if (!pipeline || !pipeline->pipeline) {
|
||||
// Already logged, let's bail out.
|
||||
ResetAfterDraw();
|
||||
@@ -563,7 +567,6 @@ void DrawEngineVulkan::Flush() {
|
||||
framebufferManager_->ApplyClearToMemory(scissorX1, scissorY1, scissorX2, scissorY2, result.color);
|
||||
}
|
||||
}
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
}
|
||||
|
||||
ResetAfterDrawInline();
|
||||
@@ -581,7 +584,6 @@ void DrawEngineVulkan::ResetAfterDraw() {
|
||||
vertexCountInDrawCalls_ = 0;
|
||||
decodeIndsCounter_ = 0;
|
||||
decodeVertsCounter_ = 0;
|
||||
decOptions_.applySkinInDecode = g_Config.bSoftwareSkinning;
|
||||
gstate_c.vertexFullAlpha = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -136,7 +136,7 @@ public:
|
||||
return pipelineLayout_;
|
||||
}
|
||||
|
||||
void BeginFrame();
|
||||
void BeginFrame() override;
|
||||
void EndFrame();
|
||||
|
||||
void DirtyAllUBOs();
|
||||
|
||||
@@ -1360,15 +1360,13 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUDebugInterface
|
||||
if (!gpuDebug->GetCurrentSimpleVertices(rowCount_, vertices, indices)) {
|
||||
rowCount_ = 0;
|
||||
}
|
||||
VertexDecoderOptions options{};
|
||||
// TODO: Maybe an option?
|
||||
options.applySkinInDecode = true;
|
||||
|
||||
auto buildVertexTable = [&](bool raw) {
|
||||
// Ignore indices for now.
|
||||
if (ImGui::BeginTable("rawverts", VERTEXLIST_COL_COUNT + 1, tableFlags)) {
|
||||
static VertexDecoder decoder;
|
||||
decoder.SetVertexType(state.vertType, options);
|
||||
u32 vertTypeID = GetVertTypeID(state.vertType, state.getUVGenMode(), true);
|
||||
VertexDecoderOptions options{};
|
||||
decoder.SetVertexType(vertTypeID, options);
|
||||
|
||||
static const char * const colNames[] = {
|
||||
"Index",
|
||||
|
||||
@@ -175,8 +175,8 @@ int CtrlVertexList::GetRowCount() {
|
||||
}
|
||||
VertexDecoderOptions options{};
|
||||
// TODO: Maybe an option?
|
||||
options.applySkinInDecode = true;
|
||||
decoder->SetVertexType(state.vertType, options);
|
||||
u32 vertTypeID = GetVertTypeID(state.vertType, state.getUVGenMode(), true);
|
||||
decoder->SetVertexType(vertTypeID, options);
|
||||
return rowCount_;
|
||||
}
|
||||
|
||||
|
||||
@@ -51,7 +51,7 @@ public:
|
||||
void Reset() {
|
||||
memset(src_, 0, BUFFER_SIZE);
|
||||
memset(dst_, 0, BUFFER_SIZE);
|
||||
memset(&options_, 0, sizeof(options_));
|
||||
options_ = {};
|
||||
delete dec_;
|
||||
dec_ = nullptr;
|
||||
indexLowerBound_ = 0;
|
||||
@@ -65,7 +65,7 @@ public:
|
||||
if (needsReset_) {
|
||||
Reset();
|
||||
}
|
||||
memcpy(&options_, &opts, sizeof(options_));
|
||||
options_ = opts;
|
||||
}
|
||||
|
||||
void SetIndexLowerBound(const int lower) {
|
||||
@@ -543,7 +543,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) {
|
||||
@@ -558,13 +557,14 @@ static bool TestVertex8Skin() {
|
||||
gstate.boneMatrix[20] = 5.0f;
|
||||
|
||||
int vtype = GE_VTYPE_POS_8BIT | GE_VTYPE_NRM_8BIT | GE_VTYPE_WEIGHT_8BIT | (1 << GE_VTYPE_WEIGHTCOUNT_SHIFT);
|
||||
u32 vertTypeID = GetVertTypeID(vtype, 0, true); // enable skinning in decode
|
||||
|
||||
dec.Add8(128 + 64, 128 - 64);
|
||||
dec.Add8(127, 0, 128);
|
||||
dec.Add8(127, 0, 128);
|
||||
|
||||
for (int jit = 0; jit <= 1; ++jit) {
|
||||
dec.Execute(vtype, 0, jit == 1);
|
||||
dec.Execute(vertTypeID, 0, jit == 1);
|
||||
dec.AssertFloat("TestVertex8Skin-Nrm", (2.0f * 1.5f + 1.0f * 0.5f) * 127.0f / 128.0f, 0.0f, 2.0f * 5.0f * -1.0f);
|
||||
dec.AssertFloat("TestVertex8Skin-Pos", (2.0f * 1.5f + 1.0f * 0.5f) * 127.0f / 128.0f, 0.0f, 2.0f * 5.0f * -1.0f);
|
||||
}
|
||||
@@ -575,7 +575,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) {
|
||||
@@ -590,13 +589,14 @@ static bool TestVertex16Skin() {
|
||||
gstate.boneMatrix[20] = 5.0f;
|
||||
|
||||
int vtype = GE_VTYPE_POS_16BIT | GE_VTYPE_NRM_16BIT | GE_VTYPE_WEIGHT_16BIT | (1 << GE_VTYPE_WEIGHTCOUNT_SHIFT);
|
||||
u32 vertTypeID = GetVertTypeID(vtype, 0, true); // enable skinning in decode
|
||||
|
||||
dec.Add16(32768 + 16384, 32768 - 16384);
|
||||
dec.Add16(32767, 0, 32768);
|
||||
dec.Add16(32767, 0, 32768);
|
||||
|
||||
for (int jit = 0; jit <= 1; ++jit) {
|
||||
dec.Execute(vtype, 0, jit == 1);
|
||||
dec.Execute(vertTypeID, 0, jit == 1);
|
||||
dec.AssertFloat("TestVertex16Skin-Nrm", (2.0f * 1.5f + 1.0f * 0.5f) * 32767.0f / 32768.0f, 0.0f, 2.0f * 5.0f * -1.0f);
|
||||
dec.AssertFloat("TestVertex16Skin-Pos", (2.0f * 1.5f + 1.0f * 0.5f) * 32767.0f / 32768.0f, 0.0f, 2.0f * 5.0f * -1.0f);
|
||||
}
|
||||
@@ -607,7 +607,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) {
|
||||
@@ -622,13 +621,14 @@ static bool TestVertexFloatSkin() {
|
||||
gstate.boneMatrix[20] = 5.0f;
|
||||
|
||||
int vtype = GE_VTYPE_POS_FLOAT | GE_VTYPE_NRM_FLOAT | GE_VTYPE_WEIGHT_FLOAT | (1 << GE_VTYPE_WEIGHTCOUNT_SHIFT);
|
||||
u32 vertTypeID = GetVertTypeID(vtype, 0, true); // enable skinning in decode
|
||||
|
||||
dec.AddFloat(1.5f, 0.5f);
|
||||
dec.AddFloat(1.0f, 0, -1.0f);
|
||||
dec.AddFloat(1.0f, 0, -1.0f);
|
||||
|
||||
for (int jit = 0; jit <= 1; ++jit) {
|
||||
dec.Execute(vtype, 0, jit == 1);
|
||||
dec.Execute(vertTypeID, 0, jit == 1);
|
||||
dec.AssertFloat("TestVertexFloatSkin-Nrm", (2.0f * 1.5f + 1.0f * 0.5f) * 1.0f, 0.0f, 2.0f * 5.0f * -1.0f);
|
||||
dec.AssertFloat("TestVertexFloatSkin-Pos", (2.0f * 1.5f + 1.0f * 0.5f) * 1.0f, 0.0f, 2.0f * 5.0f * -1.0f);
|
||||
}
|
||||
|
||||
Reference in new issue
Block a user