mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-07-11 01:25:07 +02:00
Merge pull request #21881 from hrydgard/render-code-cleanup
Misc render code cleanup - remove cached UVScale, etc
This commit is contained in:
@@ -232,7 +232,8 @@ bool DrawEngineCommon::TestBoundingBox(const void *vdata, const void *inds, int
|
||||
// TODO: Avoid normalization if just plain skinning.
|
||||
// Force software skinning.
|
||||
const u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), true);
|
||||
::NormalizeVertices(corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, dec, vertType);
|
||||
UVScale uvScale{}; // We don't care about UV.
|
||||
::NormalizeVertices(corners, temp_buffer, (const u8 *)vdata, indexLowerBound, indexUpperBound, uvScale, dec, vertType);
|
||||
IndexConverter conv(vertType, inds);
|
||||
for (int i = 0; i < vertexCount; i++) {
|
||||
verts[i * 3] = corners[conv(i)].pos.x;
|
||||
@@ -891,7 +892,7 @@ bool DrawEngineCommon::SubmitPrim(const void *verts, const void *inds, GEPrimiti
|
||||
numDrawVerts_ = numDrawVerts + 1; // Increment the uncached variable
|
||||
dv.verts = verts;
|
||||
dv.vertexCount = vertexCount;
|
||||
dv.uvScale = gstate_c.uv;
|
||||
dv.uvScale = LoadUVScaleOffset(gstate);
|
||||
// Does handle the unindexed case.
|
||||
GetIndexBounds(inds, vertexCount, vertTypeID, &dv.indexLowerBound, &dv.indexUpperBound);
|
||||
}
|
||||
@@ -1064,6 +1065,7 @@ Mat4F32 ComputeFinalProjMatrix() {
|
||||
0.0f,
|
||||
};
|
||||
|
||||
// TODO: Simply use Mat4F32 m(gstate_c.worldviewproj);
|
||||
Mat4F32 wv = Mul4x3By4x4(Mat4x3F32(gstate.worldMatrix), Mat4F32::Load4x3(gstate.viewMatrix));
|
||||
Mat4F32 m = Mul4x4By4x4(wv, Mat4F32(gstate.projMatrix));
|
||||
// NOTE: Applying the translation actually works pre-divide, since W is also affected.
|
||||
|
||||
@@ -154,10 +154,7 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
|
||||
ReplaceBlendType replaceBlend = static_cast<ReplaceBlendType>(id.Bits(FS_BIT_REPLACE_BLEND, 3));
|
||||
|
||||
bool blueToAlpha = false;
|
||||
if (replaceBlend == ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA) {
|
||||
blueToAlpha = true;
|
||||
}
|
||||
const bool blueToAlpha = replaceBlend == ReplaceBlendType::REPLACE_BLEND_BLUE_TO_ALPHA;
|
||||
|
||||
bool isModeClear = id.Bit(FS_BIT_CLEARMODE);
|
||||
|
||||
@@ -854,8 +851,8 @@ bool GenerateFragmentShader(const FShaderID &id, char *buffer, const ShaderLangu
|
||||
// This happens before fog is applied.
|
||||
*uniformMask |= DIRTY_TEX_ALPHA_MUL;
|
||||
|
||||
// We only need a clamp if the color will be further processed. Otherwise the hardware color conversion will clamp for us.
|
||||
// TODO: Clamp is so cheap that this probably is pretty meaningless.
|
||||
// We only need a clamp if the color will be further processed directly in the shader.
|
||||
// Otherwise the hardware color conversion will clamp for us (unless we start using FP formats for fake HDR but then we probably don't want the clamp...)
|
||||
if (enableFog || enableColorTest || replaceBlend != REPLACE_BLEND_NO || simulateLogicOpType != LOGICOPTYPE_NORMAL || colorWriteMask || blueToAlpha) {
|
||||
WRITE(p, " v.rgb = clamp(v.rgb * u_texNoAlphaMul.y, 0.0, 1.0);\n");
|
||||
} else {
|
||||
|
||||
@@ -313,7 +313,7 @@ void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, int fb_stride
|
||||
DEBUG_LOG(Log::G3D, "Est: %08x V: %ix%i, R: %ix%i, S: %ix%i, STR: %i, THR:%i, Z:%08x = %ix%i %s", fb_address, viewport_width,viewport_height, region_width, region_height, scissor_width, scissor_height, fb_stride, gstate.isModeThrough(), gstate.isDepthWriteEnabled() ? gstate.getDepthBufAddress() : 0, drawing_width, drawing_height, margin ? " (margin!)" : "");
|
||||
}
|
||||
|
||||
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate) {
|
||||
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GEState &gstate) {
|
||||
// GetFramebufferHeuristicInputs is only called from rendering, and thus, it's VRAM.
|
||||
params->fb_address = gstate.getFrameBufRawAddress() | 0x04000000;
|
||||
params->fb_stride = gstate.FrameBufStride();
|
||||
|
||||
@@ -195,10 +195,10 @@ struct FramebufferHeuristicParams {
|
||||
int16_t scissorBottom;
|
||||
};
|
||||
|
||||
struct GPUgstate;
|
||||
extern GPUgstate gstate;
|
||||
struct GEState;
|
||||
extern GEState gstate;
|
||||
|
||||
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPUgstate &gstate);
|
||||
void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GEState &gstate);
|
||||
|
||||
enum BindFramebufferColorFlags {
|
||||
BINDFBCOLOR_SKIP_COPY = 0,
|
||||
|
||||
@@ -621,7 +621,7 @@ bool GEExpressionFunctions::parseSymbol(char *str, uint32_t &symbolValue) {
|
||||
}
|
||||
|
||||
uint32_t GEExpressionFunctions::getReferenceValue(uint32_t referenceIndex) {
|
||||
GPUgstate state = gpu_->GetGState();
|
||||
GEState state = gpu_->GetGState();
|
||||
if (referenceIndex < 0x100) {
|
||||
GECmdFormat fmt = GECmdInfoByCmd(GECommand(referenceIndex)).cmdFmt;
|
||||
uint32_t value = state.cmdmem[referenceIndex];
|
||||
|
||||
@@ -59,7 +59,7 @@ bool NeedsTestDiscard();
|
||||
bool IsDepthTestEffectivelyDisabled();
|
||||
bool IsStencilTestOutputDisabled();
|
||||
|
||||
inline bool CanForceBilinear(const GPUgstate &gstate) {
|
||||
inline bool CanForceBilinear(const GEState &gstate) {
|
||||
return ((!gstate.isColorTestEnabled() || IsColorTestTriviallyTrue()) && (!gstate.isAlphaTestEnabled() || IsAlphaTestTriviallyTrue()));
|
||||
}
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms) {
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateFogCoef(const GPUgstate &state, float fogCoef[2]) {
|
||||
void UpdateFogCoef(const GEState &state, float fogCoef[2]) {
|
||||
fogCoef[0] = getFloat24(gstate.fog1);
|
||||
fogCoef[1] = getFloat24(gstate.fog2);
|
||||
// The PSP just ignores infnan here (ignoring IEEE), so take it down to a valid float.
|
||||
|
||||
@@ -123,10 +123,10 @@ void BoneUpdateUniforms(UB_VS_Bones *ub, uint64_t dirtyUniforms);
|
||||
uint32_t PackLightControlBits();
|
||||
uint32_t PackDepalBits();
|
||||
|
||||
void UpdateFogCoef(const GPUgstate &state, float fogCoef[2]);
|
||||
void UpdateFogCoef(const GEState &state, float fogCoef[2]);
|
||||
|
||||
// This happens so much that I want it inline.
|
||||
inline void UpdateUVScaleOff(const GPUgstate &state, float uvScaleOff[4]) {
|
||||
inline void UpdateUVScaleOff(const GEState &state, float uvScaleOff[4]) {
|
||||
float widthFactor;
|
||||
float heightFactor;
|
||||
if (gstate_c.textureIsFramebuffer) {
|
||||
|
||||
@@ -80,7 +80,7 @@ static void RotateUV(TransformedVertex v[4]) {
|
||||
}
|
||||
}
|
||||
|
||||
static bool ShouldApplySpriteBorderFix(const GPUgstate &gstate) {
|
||||
static bool ShouldApplySpriteBorderFix(const GEState &gstate) {
|
||||
return gstate.isMagnifyFilteringEnabled() && gstate.isAlphaBlendEnabled() && gstate.getBlendFuncA() != GE_SRCBLEND_FIXA && gstate.isTextureAlphaUsed();
|
||||
}
|
||||
|
||||
@@ -407,7 +407,7 @@ SoftwareTransformAction RunSoftwareTransform(SoftwareTransformParams ¶ms, in
|
||||
|
||||
// Modifies the vertices in-place. Applies viewport and projection.
|
||||
// TODO: SIMD.
|
||||
static void ProjectVertices(const GPUgstate &gstate, TransformedVertex *transformed, int vertexCount) {
|
||||
static void ProjectVertices(const GEState &gstate, TransformedVertex *transformed, int vertexCount) {
|
||||
#if 0
|
||||
Lin::Vec3 vpOffset(gstate.getViewportXCenter(), gstate.getViewportYCenter(), gstate.getViewportZCenter());
|
||||
Lin::Vec3 vpScale(gstate.getViewportXScale(), gstate.getViewportYScale(), gstate.getViewportZScale());
|
||||
@@ -1366,13 +1366,13 @@ static bool ExpandPoints(int vertexCount, int &maxIndex, int vertsSize, u16 *&in
|
||||
// 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 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const VertexDecoder *dec, u32 vertType) {
|
||||
u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const UVScale &uvScale, const VertexDecoder *dec, 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.
|
||||
// Actually if software transform is off, we could enforce it in the vertex decoder lookup before calling this,
|
||||
// avoiding having to implement it again below.
|
||||
const int count = upperBound + 1 - lowerBound;
|
||||
dec->DecodeVerts(bufPtr, inPtr + lowerBound * dec->VertexSize(), &gstate_c.uv, count);
|
||||
dec->DecodeVerts(bufPtr, inPtr + lowerBound * dec->VertexSize(), &uvScale, count);
|
||||
|
||||
// OK, morphing eliminated but bones still remain to be taken care of.
|
||||
// Let's do a partial software transform where we only do skinning.
|
||||
@@ -1543,12 +1543,10 @@ bool GetCurrentDrawAsDebugVertices(DrawEngineCommon *drawEngine, GECommand cmd,
|
||||
const int stride = (int)dec->GetDecVtxFmt().stride;
|
||||
vertsTemp.resize(stride * verticesToDecode + 32); // Add some padding bytes for "over-writes".
|
||||
|
||||
UVScale uvScale{};
|
||||
LoadUVScaleOffsetVec(gstate).Store(&uvScale.uScale);
|
||||
|
||||
const u8 *startPos = verts + indexLowerBound * dec->VertexSize();
|
||||
|
||||
bool savedVertexFullAlpha = gstate_c.vertexFullAlpha;
|
||||
const UVScale uvScale = LoadUVScaleOffset(gstate);
|
||||
dec->DecodeVerts(vertsTemp.data(), startPos, &uvScale, verticesToDecode);
|
||||
gstate_c.vertexFullAlpha = savedVertexFullAlpha;
|
||||
|
||||
|
||||
@@ -83,7 +83,7 @@ SoftwareTransformAction RunSoftwareTransform(SoftwareTransformParams ¶ms, in
|
||||
class DrawEngineCommon;
|
||||
|
||||
// Slow. See description in the cpp file.
|
||||
u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const VertexDecoder *dec, u32 vertType);
|
||||
u32 NormalizeVertices(SimpleVertex *sverts, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, const UVScale &uvScale, const VertexDecoder *dec, u32 vertType);
|
||||
|
||||
// In the returned data, you should subtract the value of lowerIndexBound from the indices to get the actual vertex index in the vertices array.
|
||||
// This is because some draws in some games use very large indices, but they only use a small range of them in each PRIM submission.
|
||||
|
||||
+13
-20
@@ -159,6 +159,8 @@ private:
|
||||
}
|
||||
|
||||
static void CalcWeights(float t, const float *knots, const KnotDiv &div, Weight &w) {
|
||||
// TODO: This SSE code doesn't look like it's worth it. We need to parallelize across another
|
||||
// dimension.
|
||||
#ifdef _M_SSE
|
||||
const __m128 knot012 = _mm_loadu_ps(knots);
|
||||
const __m128 t012 = _mm_sub_ps(_mm_set_ps1(t), knot012);
|
||||
@@ -463,8 +465,9 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
u16 index_lower_bound = 0;
|
||||
u16 index_upper_bound = num_points - 1;
|
||||
IndexConverter ConvertIndex(vertType, indices);
|
||||
if (indices)
|
||||
if (indices) {
|
||||
GetIndexBounds(indices, num_points, vertType, &index_lower_bound, &index_upper_bound);
|
||||
}
|
||||
|
||||
u32 vertTypeID = GetVertTypeID(vertType, gstate.getUVGenMode(), applySkinInDecode_);
|
||||
VertexDecoder *origVDecoder = GetVertexDecoder(vertTypeID);
|
||||
@@ -485,7 +488,8 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
}
|
||||
|
||||
const u32 origVertType = vertType;
|
||||
vertType = ::NormalizeVertices(simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, origVDecoder, vertType);
|
||||
UVScale neutralUVScale{1.0f, 1.0f, 0.0f, 0.0f}; // Avoid rescaling UV during normalization, it will happen anyway later (in DispatchSubmitPrim). Although ideally we should avoid running Decode at all there.
|
||||
vertType = ::NormalizeVertices(simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, neutralUVScale, origVDecoder, vertType);
|
||||
|
||||
VertexDecoder *vdecoder = GetVertexDecoder(vertType);
|
||||
|
||||
@@ -500,8 +504,9 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
ERROR_LOG(Log::G3D, "Failed to allocate space for control point pointers, skipping curve draw");
|
||||
return;
|
||||
}
|
||||
for (int idx = 0; idx < num_points; idx++)
|
||||
for (int idx = 0; idx < num_points; idx++) {
|
||||
points[idx] = simplified_control_points + (indices ? ConvertIndex(idx) : idx);
|
||||
}
|
||||
|
||||
OutputBuffers output;
|
||||
output.vertices = (SimpleVertex *)(decoded_ + DECODED_VERTEX_BUFFER_SIZE / 2);
|
||||
@@ -513,23 +518,15 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
surface.Init(maxVerts);
|
||||
|
||||
ControlPoints cpoints(points, num_points, managedBuf);
|
||||
if (cpoints.IsValid())
|
||||
if (cpoints.IsValid()) {
|
||||
// Run the tessellation!
|
||||
SoftwareTessellation(output, surface, origVertType, cpoints);
|
||||
else
|
||||
} else {
|
||||
ERROR_LOG(Log::G3D, "Failed to allocate space for control point values, skipping curve draw");
|
||||
}
|
||||
|
||||
u32 vertTypeWithIndex16 = (vertType & ~GE_VTYPE_IDX_MASK) | GE_VTYPE_IDX_16BIT;
|
||||
|
||||
UVScale prevUVScale;
|
||||
if (origVertType & GE_VTYPE_TC_MASK) {
|
||||
// We scaled during Normalize already so let's turn it off when drawing.
|
||||
prevUVScale = gstate_c.uv;
|
||||
gstate_c.uv.uScale = 1.0f;
|
||||
gstate_c.uv.vScale = 1.0f;
|
||||
gstate_c.uv.uOff = 0;
|
||||
gstate_c.uv.vOff = 0;
|
||||
}
|
||||
|
||||
vertTypeID = GetVertTypeID(vertTypeWithIndex16, gstate.getUVGenMode(), applySkinInDecode_);
|
||||
int generatedBytesRead;
|
||||
if (output.count) {
|
||||
@@ -537,11 +534,7 @@ void DrawEngineCommon::SubmitCurve(const void *control_points, const void *indic
|
||||
DispatchSubmitPrim(output.vertices, output.indices, PatchPrimToPrim(surface.primType), output.count, vertTypeID, true, &generatedBytesRead, flags);
|
||||
}
|
||||
|
||||
if (flushOnParams_)
|
||||
if (flushOnParams_) {
|
||||
Flush();
|
||||
|
||||
if (origVertType & GE_VTYPE_TC_MASK) {
|
||||
// If analysis says this is uninitialized, it's wrong.
|
||||
gstate_c.uv = prevUVScale;
|
||||
}
|
||||
}
|
||||
|
||||
+23
-22
@@ -27,7 +27,7 @@
|
||||
|
||||
#include "Core/Config.h"
|
||||
|
||||
#define HALF_CEIL(x) (x + 1) / 2 // Integer ceil = (int)ceil((float)x / 2.0f)
|
||||
inline int half_ceil(int x) { return (x + 1) / 2; } // Integer ceil = (int)ceil((float)x / 2.0f)
|
||||
|
||||
class SimpleBufferManager;
|
||||
|
||||
@@ -61,8 +61,8 @@ struct SurfaceInfo {
|
||||
break;
|
||||
case SplineQuality::MEDIUM_QUALITY:
|
||||
// Don't cut below 2, though.
|
||||
if (tess_u > 2) tess_u = HALF_CEIL(tess_u);
|
||||
if (tess_v > 2) tess_v = HALF_CEIL(tess_v);
|
||||
if (tess_u > 2) tess_u = half_ceil(tess_u);
|
||||
if (tess_v > 2) tess_v = half_ceil(tess_v);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@@ -140,7 +140,8 @@ struct SplineSurface : public SurfaceInfo {
|
||||
};
|
||||
|
||||
struct Weight {
|
||||
float basis[4], deriv[4];
|
||||
float basis[4];
|
||||
float deriv[4];
|
||||
};
|
||||
|
||||
template<class T>
|
||||
@@ -207,10 +208,10 @@ struct NAME { \
|
||||
} \
|
||||
};
|
||||
|
||||
template<typename Func, int NumParams, class Dispatcher>
|
||||
template<typename Func, int NumParams, class Dispatcher>
|
||||
class TemplateParameterDispatcher {
|
||||
|
||||
/* Store all combinations of template functions into an array */
|
||||
// Store all combinations of template functions into an array
|
||||
template<int LoopCount, int Index = 0, bool ...Params>
|
||||
struct Initializer {
|
||||
static void Init(Func funcs[]) {
|
||||
@@ -218,7 +219,7 @@ class TemplateParameterDispatcher {
|
||||
Initializer<LoopCount - 1, (Index << 1) + 0, false, Params...>::Init(funcs); // false
|
||||
}
|
||||
};
|
||||
/* Specialized for terminates the recursive loop */
|
||||
// Specialized for terminates the recursive loop
|
||||
template<int Index, bool ...Params>
|
||||
struct Initializer<0, Index, Params...> {
|
||||
static void Init(Func funcs[]) {
|
||||
@@ -226,19 +227,19 @@ class TemplateParameterDispatcher {
|
||||
}
|
||||
};
|
||||
|
||||
private:
|
||||
Func funcs[1 << NumParams]; /* Function pointers array */
|
||||
public:
|
||||
TemplateParameterDispatcher() {
|
||||
Initializer<NumParams>::Init(funcs);
|
||||
}
|
||||
|
||||
Func GetFunc(const bool params[]) const {
|
||||
/* Convert bool parameters to index of the array */
|
||||
int index = 0;
|
||||
for (int i = 0; i < NumParams; ++i)
|
||||
index |= params[i] << i;
|
||||
|
||||
return funcs[index];
|
||||
}
|
||||
private:
|
||||
Func funcs[1 << NumParams]; /* Function pointers array */
|
||||
public:
|
||||
TemplateParameterDispatcher() {
|
||||
Initializer<NumParams>::Init(funcs);
|
||||
}
|
||||
|
||||
Func GetFunc(const bool params[]) const {
|
||||
// Convert bool parameters to index of the array
|
||||
int index = 0;
|
||||
for (int i = 0; i < NumParams; ++i) {
|
||||
index |= params[i] << i;
|
||||
}
|
||||
return funcs[index];
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2301,7 +2301,7 @@ static bool CanDepalettizeBufferAs(GETextureFormat texFormat, GEBufferFormat buf
|
||||
// But we only do it if the mask/shift exactly matches a color channel, else something different might be going
|
||||
// on and we definitely don't want to interpolate.
|
||||
// Great enhancement for Test Drive and Manhunt 2.
|
||||
static bool CanUseSmoothDepal(const GPUgstate &gstate, GEBufferFormat framebufferFormat, const ClutTexture &clutTexture) {
|
||||
static bool CanUseSmoothDepal(const GEState &gstate, GEBufferFormat framebufferFormat, const ClutTexture &clutTexture) {
|
||||
for (int i = 0; i < ClutTexture::MAX_RAMPS; i++) {
|
||||
if (gstate.getClutIndexStartPos() == clutTexture.rampStarts[i] &&
|
||||
gstate.getClutIndexMask() < clutTexture.rampLengths[i]) {
|
||||
|
||||
@@ -68,7 +68,7 @@ static bool lastWasFramebuffer;
|
||||
static u32 pauseSetCmdValue;
|
||||
|
||||
// This is used only to highlight differences. Should really be owned by the debugger.
|
||||
static GPUgstate lastGState;
|
||||
static GEState lastGState;
|
||||
|
||||
const char *PauseActionToString(PauseAction action) {
|
||||
switch (action) {
|
||||
@@ -291,7 +291,7 @@ bool GPU_FlushDrawing() {
|
||||
return true;
|
||||
}
|
||||
|
||||
const GPUgstate &LastState() {
|
||||
const GEState &LastState() {
|
||||
return lastGState;
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,5 @@ namespace GPUStepping {
|
||||
bool GPU_FlushDrawing();
|
||||
|
||||
// Can be used to highlight differences in a debugger.
|
||||
const GPUgstate &LastState();
|
||||
const GEState &LastState();
|
||||
};
|
||||
|
||||
+1
-3
@@ -1325,8 +1325,6 @@ void GPUCommon::FlushImm() {
|
||||
|
||||
SetDrawType(DRAW_PRIM, immPrim_);
|
||||
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
|
||||
VirtualFramebuffer *vfb = nullptr;
|
||||
if (framebufferManager_) {
|
||||
bool changed;
|
||||
@@ -1707,7 +1705,7 @@ u32 GPUCommon::GetIndexAddress() {
|
||||
return gstate_c.indexAddr;
|
||||
}
|
||||
|
||||
const GPUgstate &GPUCommon::GetGState() {
|
||||
const GEState &GPUCommon::GetGState() {
|
||||
return gstate;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -30,7 +30,7 @@ class TextureCacheCommon;
|
||||
class DrawEngineCommon;
|
||||
class GraphicsContext;
|
||||
struct PspGeListArgs;
|
||||
struct GPUgstate;
|
||||
struct GEState;
|
||||
class PointerWrap;
|
||||
struct VirtualFramebuffer;
|
||||
|
||||
@@ -221,7 +221,7 @@ public:
|
||||
u32 GetRelativeAddress(u32 data);
|
||||
u32 GetVertexAddress();
|
||||
u32 GetIndexAddress();
|
||||
const GPUgstate &GetGState();
|
||||
const GEState &GetGState();
|
||||
void SetCmdValue(u32 op);
|
||||
|
||||
DisplayList* getList(int listid) {
|
||||
|
||||
@@ -967,8 +967,6 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
canExtend = false;
|
||||
}
|
||||
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
|
||||
// cull mode
|
||||
int cullMode = gstate.getCullMode();
|
||||
|
||||
@@ -1190,22 +1188,18 @@ void GPUCommonHW::Execute_Prim(u32 op, u32 diff) {
|
||||
// when texscale commands are in line with the prims like this, they actually have an effect
|
||||
// and requires us to stop extending strips anyway.
|
||||
gstate.cmdmem[GE_CMD_TEXSCALEU] = data;
|
||||
gstate_c.uv.uScale = getFloat24(data);
|
||||
canExtend = false;
|
||||
break;
|
||||
case GE_CMD_TEXSCALEV:
|
||||
gstate.cmdmem[GE_CMD_TEXSCALEV] = data;
|
||||
gstate_c.uv.vScale = getFloat24(data);
|
||||
canExtend = false;
|
||||
break;
|
||||
case GE_CMD_TEXOFFSETU:
|
||||
gstate.cmdmem[GE_CMD_TEXOFFSETU] = data;
|
||||
gstate_c.uv.uOff = getFloat24(data);
|
||||
canExtend = false;
|
||||
break;
|
||||
case GE_CMD_TEXOFFSETV:
|
||||
gstate.cmdmem[GE_CMD_TEXOFFSETV] = data;
|
||||
gstate_c.uv.vOff = getFloat24(data);
|
||||
canExtend = false;
|
||||
break;
|
||||
case GE_CMD_TEXLEVEL:
|
||||
@@ -1333,7 +1327,6 @@ void GPUCommonHW::Execute_Bezier(u32 op, u32 diff) {
|
||||
gstate_c.submitType = SubmitType::BEZIER;
|
||||
|
||||
int bytesRead = 0;
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier");
|
||||
|
||||
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET);
|
||||
@@ -1405,7 +1398,6 @@ void GPUCommonHW::Execute_Spline(u32 op, u32 diff) {
|
||||
gstate_c.submitType = SubmitType::SPLINE;
|
||||
|
||||
int bytesRead = 0;
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline");
|
||||
|
||||
gstate_c.Dirty(DIRTY_RASTER_STATE | DIRTY_VERTEXSHADER_STATE | DIRTY_UVSCALEOFFSET);
|
||||
|
||||
+7
-6
@@ -27,7 +27,7 @@
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
// This must be aligned so that the matrices within are aligned.
|
||||
alignas(16) GPUgstate gstate;
|
||||
alignas(16) GEState gstate;
|
||||
// Let's align this one too for good measure.
|
||||
alignas(16) GPUStateCache gstate_c;
|
||||
|
||||
@@ -102,7 +102,7 @@ static const u32_le *LoadMatrix(const u32_le *cmds, float *mtx, int sz) {
|
||||
return cmds;
|
||||
}
|
||||
|
||||
void GPUgstate::Reset() {
|
||||
void GEState::Reset() {
|
||||
memset(gstate.cmdmem, 0, sizeof(gstate.cmdmem));
|
||||
for (int i = 0; i < 256; i++) {
|
||||
gstate.cmdmem[i] = i << 24;
|
||||
@@ -120,7 +120,7 @@ void GPUgstate::Reset() {
|
||||
gstate_c.Dirty(DIRTY_WORLD_VIEW_PROJ_MATRIX | DIRTY_VIEW_PROJ_MATRIX | DIRTY_CULL_MATRIX);
|
||||
}
|
||||
|
||||
void GPUgstate::Save(u32_le *ptr) {
|
||||
void GEState::Save(u32_le *ptr) {
|
||||
// Not sure what the first 10 values are, exactly, but these seem right.
|
||||
ptr[5] = gstate_c.vertexAddr;
|
||||
ptr[6] = gstate_c.indexAddr;
|
||||
@@ -168,7 +168,7 @@ void GPUgstate::Save(u32_le *ptr) {
|
||||
}
|
||||
}
|
||||
|
||||
void GPUgstate::FastLoadBoneMatrix(u32 addr) {
|
||||
void GEState::FastLoadBoneMatrix(u32 addr) {
|
||||
const u32 *src = (const u32 *)Memory::GetPointerUnchecked(addr);
|
||||
u32 num = boneMatrixNumber;
|
||||
u32 *dst = (u32 *)(boneMatrix + (num & 0x7F));
|
||||
@@ -204,7 +204,7 @@ void GPUgstate::FastLoadBoneMatrix(u32 addr) {
|
||||
gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | (num & 0x00FFFFFF);
|
||||
}
|
||||
|
||||
void GPUgstate::Restore(const u32_le *ptr) {
|
||||
void GEState::Restore(const u32_le *ptr) {
|
||||
// Not sure what the first 10 values are, exactly, but these seem right.
|
||||
gstate_c.vertexAddr = ptr[5];
|
||||
gstate_c.indexAddr = ptr[6];
|
||||
@@ -292,7 +292,6 @@ void GPUStateCache::DoState(PointerWrap &p) {
|
||||
textureSolidAlpha = old.textureSolidAlpha;
|
||||
vertexFullAlpha = old.vertexFullAlpha;
|
||||
skipDrawReason = old.skipDrawReason;
|
||||
uv = old.uv;
|
||||
|
||||
savedContextVersion = 0;
|
||||
} else {
|
||||
@@ -310,6 +309,8 @@ void GPUStateCache::DoState(PointerWrap &p) {
|
||||
|
||||
Do(p, skipDrawReason);
|
||||
|
||||
// Legacy, remove in the next bump.
|
||||
UVScale uv{};
|
||||
Do(p, uv);
|
||||
|
||||
bool oldFlipTexture = false;
|
||||
|
||||
+2
-20
@@ -26,12 +26,11 @@
|
||||
#include "GPU/GPU.h"
|
||||
#include "GPU/ge_constants.h"
|
||||
#include "GPU/Common/ShaderCommon.h"
|
||||
#include "Common/Math/SIMDHeaders.h"
|
||||
#include "Common/Math/lin/vec3.h"
|
||||
|
||||
class PointerWrap;
|
||||
|
||||
struct GPUgstate {
|
||||
struct GEState {
|
||||
// Getting rid of this ugly union in favor of the accessor functions
|
||||
// might be a good idea....
|
||||
union {
|
||||
@@ -514,7 +513,7 @@ enum class SubmitType {
|
||||
SPLINE,
|
||||
};
|
||||
|
||||
extern GPUgstate gstate;
|
||||
extern GEState gstate;
|
||||
|
||||
struct GPUStateCache {
|
||||
bool Use(u32 flags) const { return (useFlags_ & flags) != 0; } // Return true if ANY of flags are true.
|
||||
@@ -588,21 +587,6 @@ struct GPUStateCache {
|
||||
return useFlags_;
|
||||
}
|
||||
|
||||
void UpdateUVScaleOffset() {
|
||||
#if defined(_M_SSE)
|
||||
__m128i values = _mm_slli_epi32(_mm_load_si128((const __m128i *)&gstate.texscaleu), 8);
|
||||
_mm_storeu_si128((__m128i *)&uv, values);
|
||||
#elif PPSSPP_ARCH(ARM_NEON)
|
||||
const uint32x4_t values = vshlq_n_u32(vld1q_u32((const u32 *)&gstate.texscaleu), 8);
|
||||
vst1q_u32((u32 *)&uv, values);
|
||||
#else
|
||||
uv.uScale = getFloat24(gstate.texscaleu);
|
||||
uv.vScale = getFloat24(gstate.texscalev);
|
||||
uv.uOff = getFloat24(gstate.texoffsetu);
|
||||
uv.vOff = getFloat24(gstate.texoffsetv);
|
||||
#endif
|
||||
}
|
||||
|
||||
private:
|
||||
u32 useFlags_;
|
||||
public:
|
||||
@@ -625,8 +609,6 @@ public:
|
||||
|
||||
int skipDrawReason;
|
||||
|
||||
UVScale uv;
|
||||
|
||||
bool bgraTexture;
|
||||
bool needShaderTexClamp;
|
||||
bool textureIsArray;
|
||||
|
||||
@@ -3,14 +3,16 @@
|
||||
#include "Common/Math/CrossSIMD.h"
|
||||
#include "GPU/GPUState.h"
|
||||
|
||||
inline Vec4F32 LoadViewportOffsetVec(const GPUgstate &gstate) {
|
||||
inline Vec4F32 LoadViewportOffsetVec(const GEState &gstate) {
|
||||
// We ignore the last member.
|
||||
return Vec4F32::LoadF24x4(&gstate.viewportxcenter);
|
||||
}
|
||||
inline Vec4F32 LoadViewportScaleVec(const GPUgstate &gstate) {
|
||||
inline Vec4F32 LoadViewportScaleVec(const GEState &gstate) {
|
||||
// We ignore the last member.
|
||||
return Vec4F32::LoadF24x4(&gstate.viewportxscale);
|
||||
}
|
||||
inline Vec4F32 LoadUVScaleOffsetVec(const GPUgstate &gstate) {
|
||||
return Vec4F32::LoadF24x4(&gstate.texscaleu);
|
||||
inline UVScale LoadUVScaleOffset(const GEState &gstate) {
|
||||
UVScale uvScale;
|
||||
Vec4F32::LoadF24x4(&gstate.texscaleu).Store(&uvScale.uScale);
|
||||
return uvScale;
|
||||
}
|
||||
|
||||
@@ -863,7 +863,6 @@ void SoftGPU::Execute_Prim(u32 op, u32 diff) {
|
||||
|
||||
cyclesExecuted += EstimatePerVertexCost() * count;
|
||||
int bytesRead;
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
drawEngine_->transformUnit.SetDirty(dirtyFlags_);
|
||||
drawEngine_->transformUnit.SubmitPrimitive(verts, indices, prim, count, gstate.vertType, &bytesRead, drawEngine_);
|
||||
dirtyFlags_ = drawEngine_->transformUnit.GetDirty();
|
||||
@@ -916,7 +915,6 @@ void SoftGPU::Execute_Bezier(u32 op, u32 diff) {
|
||||
SetDrawType(DRAW_BEZIER, PatchPrimToPrim(surface.primType));
|
||||
|
||||
int bytesRead = 0;
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
drawEngine_->transformUnit.SetDirty(dirtyFlags_);
|
||||
drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "bezier");
|
||||
dirtyFlags_ = drawEngine_->transformUnit.GetDirty();
|
||||
@@ -970,7 +968,6 @@ void SoftGPU::Execute_Spline(u32 op, u32 diff) {
|
||||
SetDrawType(DRAW_SPLINE, PatchPrimToPrim(surface.primType));
|
||||
|
||||
int bytesRead = 0;
|
||||
gstate_c.UpdateUVScaleOffset();
|
||||
drawEngine_->transformUnit.SetDirty(dirtyFlags_);
|
||||
drawEngineCommon_->SubmitCurve(control_points, indices, surface, gstate.vertType, &bytesRead, "spline");
|
||||
dirtyFlags_ = drawEngine_->transformUnit.GetDirty();
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
#include "GPU/Common/VertexDecoderCommon.h"
|
||||
#include "GPU/Common/SoftwareTransformCommon.h"
|
||||
#include "GPU/Common/VertexReader.h"
|
||||
#include "GPU/GPUStateSIMDUtil.h"
|
||||
#include "Common/Math/SIMDHeaders.h"
|
||||
#include "GPU/Software/BinManager.h"
|
||||
#include "GPU/Software/Clipper.h"
|
||||
@@ -482,7 +483,8 @@ public:
|
||||
GetIndexBounds(indices, vertex_count, vertex_type, &lowerBound_, &upperBound_);
|
||||
if (vertex_count != 0) {
|
||||
const int count = upperBound_ - lowerBound_ + 1;
|
||||
vdecoder.DecodeVerts(base, (const u8 *)vertices + vdecoder.VertexSize() * lowerBound_, &gstate_c.uv, count);
|
||||
const UVScale uvScale = LoadUVScaleOffset(gstate);
|
||||
vdecoder.DecodeVerts(base, (const u8 *)vertices + vdecoder.VertexSize() * lowerBound_, &uvScale, count);
|
||||
}
|
||||
|
||||
// If we're only using a subset of verts, it's better to decode with random access (usually.)
|
||||
|
||||
@@ -1643,7 +1643,7 @@ void ImGeStateWindow::Draw(ImConfig &cfg, ImControl &control, GPUCommon *gpuDebu
|
||||
bool sectionOpen = false;
|
||||
for (size_t i = 0; i < numRows; i++) {
|
||||
const GECmdInfo &info = GECmdInfoByCmd(rows[i].cmd);
|
||||
const GPUgstate &lastState = GPUStepping::LastState();
|
||||
const GEState &lastState = GPUStepping::LastState();
|
||||
bool diff = lastState.cmdmem[rows[i].cmd] != gstate.cmdmem[rows[i].cmd];
|
||||
|
||||
if (rows[i].header) {
|
||||
|
||||
@@ -377,7 +377,7 @@ void CGEDebugger::SetupPreviews() {
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::DescribePrimaryPreview(const GPUgstate &state, char desc[256]) {
|
||||
void CGEDebugger::DescribePrimaryPreview(const GEState &state, char desc[256]) {
|
||||
if (primaryTrackX_ < primaryBuffer_->GetStride() && primaryTrackY_ < primaryBuffer_->GetHeight()) {
|
||||
u32 pix = primaryBuffer_->GetRawPixel(primaryTrackX_, primaryTrackY_);
|
||||
DescribePixel(pix, primaryBuffer_->GetFormat(), primaryTrackX_, primaryTrackY_, desc);
|
||||
@@ -410,7 +410,7 @@ void CGEDebugger::DescribePrimaryPreview(const GPUgstate &state, char desc[256])
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::DescribeSecondPreview(const GPUgstate &state, char desc[256]) {
|
||||
void CGEDebugger::DescribeSecondPreview(const GEState &state, char desc[256]) {
|
||||
if (secondTrackX_ != 0xFFFFFFFF) {
|
||||
uint32_t x = secondTrackX_;
|
||||
uint32_t y = secondTrackY_;
|
||||
@@ -557,7 +557,7 @@ void CGEDebugger::UpdatePreviews() {
|
||||
return;
|
||||
}
|
||||
|
||||
GPUgstate state{};
|
||||
GEState state{};
|
||||
|
||||
if (gpu != nullptr) {
|
||||
state = gpu->GetGState();
|
||||
@@ -663,7 +663,7 @@ int CGEDebugger::HasTabIndex(GEDebuggerTab *tab, GETabPosition pos) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) {
|
||||
u32 CGEDebugger::TexturePreviewFlags(const GEState &state) {
|
||||
if (state.isTextureAlphaUsed() && !forceOpaque_) {
|
||||
return SimpleGLWindow::ALPHA_BLEND | SimpleGLWindow::RESIZE_BEST_CENTER;
|
||||
} else {
|
||||
@@ -671,7 +671,7 @@ u32 CGEDebugger::TexturePreviewFlags(const GPUgstate &state) {
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) {
|
||||
void CGEDebugger::UpdatePrimaryPreview(const GEState &state) {
|
||||
bool bufferResult = false;
|
||||
u32 flags = SimpleGLWindow::ALPHA_IGNORE | SimpleGLWindow::RESIZE_SHRINK_CENTER;
|
||||
|
||||
@@ -724,7 +724,7 @@ void CGEDebugger::UpdatePrimaryPreview(const GPUgstate &state) {
|
||||
}
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdateSecondPreview(const GPUgstate &state) {
|
||||
void CGEDebugger::UpdateSecondPreview(const GEState &state) {
|
||||
bool bufferResult = false;
|
||||
|
||||
SetupPreviews();
|
||||
@@ -784,7 +784,7 @@ void CGEDebugger::PrimaryPreviewHover(int x, int y) {
|
||||
desc[0] = 0;
|
||||
} else if (x < 0 || y < 0) {
|
||||
// This means they left the area.
|
||||
GPUgstate state{};
|
||||
GEState state{};
|
||||
if (gpu != nullptr) {
|
||||
state = gpu->GetGState();
|
||||
}
|
||||
@@ -812,7 +812,7 @@ void CGEDebugger::SecondPreviewHover(int x, int y) {
|
||||
desc[0] = 0;
|
||||
} else if (x < 0 || y < 0) {
|
||||
// This means they left the area.
|
||||
GPUgstate state{};
|
||||
GEState state{};
|
||||
if (gpu != nullptr) {
|
||||
state = gpu->GetGState();
|
||||
}
|
||||
@@ -834,7 +834,7 @@ void CGEDebugger::SecondPreviewHover(int x, int y) {
|
||||
}
|
||||
|
||||
void CGEDebugger::UpdateTextureLevel(int level) {
|
||||
GPUgstate state{};
|
||||
GEState state{};
|
||||
if (gpu != nullptr) {
|
||||
state = gpu->GetGState();
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ class TabStateSettings;
|
||||
class TabVertices;
|
||||
class TabMatrices;
|
||||
class TabStateWatch;
|
||||
struct GPUgstate;
|
||||
struct GEState;
|
||||
|
||||
enum class GETabPosition {
|
||||
LEFT = 1,
|
||||
@@ -100,8 +100,8 @@ protected:
|
||||
private:
|
||||
void SetupPreviews();
|
||||
void UpdatePreviews();
|
||||
void UpdatePrimaryPreview(const GPUgstate &state);
|
||||
void UpdateSecondPreview(const GPUgstate &state);
|
||||
void UpdatePrimaryPreview(const GEState &state);
|
||||
void UpdateSecondPreview(const GEState &state);
|
||||
static u32 PrimPreviewOp();
|
||||
void UpdatePrimPreview(u32 op, int which);
|
||||
void CleanupPrimPreview();
|
||||
@@ -109,8 +109,8 @@ private:
|
||||
void UpdateSize(WORD width, WORD height);
|
||||
void SavePosition();
|
||||
void UpdateTextureLevel(int level);
|
||||
void DescribePrimaryPreview(const GPUgstate &state, char desc[256]);
|
||||
void DescribeSecondPreview(const GPUgstate &state, char desc[256]);
|
||||
void DescribePrimaryPreview(const GEState &state, char desc[256]);
|
||||
void DescribeSecondPreview(const GEState &state, char desc[256]);
|
||||
void PrimaryPreviewHover(int x, int y);
|
||||
void SecondPreviewHover(int x, int y);
|
||||
void PreviewExport(const GPUDebugBuffer *buffer);
|
||||
@@ -122,7 +122,7 @@ private:
|
||||
int HasTabIndex(GEDebuggerTab *tab, GETabPosition pos);
|
||||
void CheckTabMessage(TabControl *t, GETabPosition pos, LPARAM lParam);
|
||||
|
||||
u32 TexturePreviewFlags(const GPUgstate &state);
|
||||
u32 TexturePreviewFlags(const GEState &state);
|
||||
|
||||
SimpleGLWindow *primaryWindow = nullptr;
|
||||
SimpleGLWindow *secondWindow = nullptr;
|
||||
|
||||
@@ -328,7 +328,7 @@ bool CtrlMatrixList::OnColPrePaint(int row, int col, LPNMLVCUSTOMDRAW msg) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool CtrlMatrixList::ColChanged(const GPUgstate &lastState, const GPUgstate &state, int row, int col) {
|
||||
bool CtrlMatrixList::ColChanged(const GEState &lastState, const GEState &state, int row, int col) {
|
||||
union {
|
||||
float f;
|
||||
uint32_t u;
|
||||
@@ -340,7 +340,7 @@ bool CtrlMatrixList::ColChanged(const GPUgstate &lastState, const GPUgstate &sta
|
||||
return newVal.u != oldVal.u;
|
||||
}
|
||||
|
||||
bool CtrlMatrixList::GetValue(const GPUgstate &state, int row, int col, float &val) {
|
||||
bool CtrlMatrixList::GetValue(const GEState &state, int row, int col, float &val) {
|
||||
if (!gpu || row < 0 || row >= MATRIXLIST_ROW_COUNT || col < 0 || col >= MATRIXLIST_COL_COUNT)
|
||||
return false;
|
||||
|
||||
|
||||
@@ -83,8 +83,8 @@ protected:
|
||||
bool OnColPrePaint(int row, int col, LPNMLVCUSTOMDRAW msg) override;
|
||||
|
||||
private:
|
||||
bool GetValue(const GPUgstate &state, int row, int col, float &val);
|
||||
bool ColChanged(const GPUgstate &lastState, const GPUgstate &state, int row, int col);
|
||||
bool GetValue(const GEState &state, int row, int col, float &val);
|
||||
bool ColChanged(const GEState &lastState, const GEState &state, int row, int col);
|
||||
void ToggleBreakpoint(int row);
|
||||
void PromptBreakpointCond(int row);
|
||||
};
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "unittest/TestVertexJit.h"
|
||||
#include "unittest/UnitTest.h"
|
||||
|
||||
const UVScale g_uvScale{1.0f, 1.0f, 0.0f, 0.0f};
|
||||
|
||||
class VertexDecoderTestHarness {
|
||||
static const int BUFFER_SIZE = 64 * 65536;
|
||||
static const int ROUNDS = 200;
|
||||
@@ -37,9 +39,6 @@ public:
|
||||
src_ = new u8[BUFFER_SIZE];
|
||||
dst_ = new u8[BUFFER_SIZE];
|
||||
cache_ = new VertexDecoderJitCache();
|
||||
|
||||
gstate_c.uv.uScale = 1.0f;
|
||||
gstate_c.uv.vScale = 1.0f;
|
||||
}
|
||||
~VertexDecoderTestHarness() {
|
||||
delete [] src_;
|
||||
@@ -69,7 +68,7 @@ public:
|
||||
void Execute(int vtype, int count, bool useJit) {
|
||||
SetupExecute(vtype, useJit);
|
||||
|
||||
dec_->DecodeVerts(dst_, src_, &gstate_c.uv, count);
|
||||
dec_->DecodeVerts(dst_, src_, &g_uvScale, count);
|
||||
}
|
||||
|
||||
double ExecuteTimed(int vtype, int count, bool useJit) {
|
||||
@@ -79,7 +78,7 @@ public:
|
||||
double st = time_now_d();
|
||||
do {
|
||||
for (int j = 0; j < ROUNDS; ++j) {
|
||||
dec_->DecodeVerts(dst_, src_, &gstate_c.uv, count);
|
||||
dec_->DecodeVerts(dst_, src_, &g_uvScale, count);
|
||||
++total;
|
||||
}
|
||||
} while (time_now_d() - st < 0.5);
|
||||
|
||||
Reference in New Issue
Block a user