mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-10-21 02:09:05 +02:00
Preparation for proper spline/bez: Convert control points to a simple format.
The bezier/spline code will no longer need to handle morph and splines, when it's finally written. This is done by pre-skinning in software and pre-decoding to get rid of the morph.
This commit is contained in:
1 parent
c733f7a7ab
commit
82e5787bbe
16 files changed
+218
-68
No files matched your search
@@ -285,6 +285,30 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
void ReadColor0_8888(u8 color[4]) const {
|
||||
switch (decFmt_.c0fmt) {
|
||||
case DEC_U8_4:
|
||||
{
|
||||
const u8 *b = (const u8 *)(data_ + decFmt_.c0off);
|
||||
for (int i = 0; i < 4; i++)
|
||||
color[i] = b[i];
|
||||
}
|
||||
break;
|
||||
case DEC_FLOAT_4:
|
||||
{
|
||||
const float *f = (const float *)(data_ + decFmt_.c0off);
|
||||
for (int i = 0; i < 4; i++)
|
||||
color[i] = f[i] * 255.0f;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
ERROR_LOG_REPORT_ONCE(fmt, G3D, "Reader: Unsupported C0 Format %d", decFmt_.c0fmt);
|
||||
memset(color, 0, sizeof(float) * 4);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ReadColor1(float color[3]) const {
|
||||
switch (decFmt_.c1fmt) {
|
||||
case DEC_U8_4:
|
||||
|
||||
@@ -616,7 +616,7 @@ void DIRECTX9_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
break;
|
||||
|
||||
// Discard AA lines in Summon Night 5
|
||||
if ((prim == GE_PRIM_LINES) && gstate.isAntiAliasEnabled() && gstate.isSkinningEnabled())
|
||||
if ((prim == GE_PRIM_LINES) && gstate.isAntiAliasEnabled() && vertTypeIsSkinningEnabled(gstate.vertType))
|
||||
break;
|
||||
|
||||
// This also make skipping drawing very effective.
|
||||
|
||||
@@ -101,7 +101,7 @@ D3DXHANDLE LinkedShaderDX9::GetConstantByName(LPCSTR pName) {
|
||||
return ret;
|
||||
}
|
||||
|
||||
LinkedShaderDX9::LinkedShaderDX9(VSShader *vs, PSShader *fs, bool useHWTransform)
|
||||
LinkedShaderDX9::LinkedShaderDX9(VSShader *vs, PSShader *fs, u32 vertType, bool useHWTransform)
|
||||
:dirtyUniforms(0), useHWTransform_(useHWTransform) {
|
||||
|
||||
INFO_LOG(G3D, "Linked shader: vs %i fs %i", (int)vs->shader, (int)fs->shader);
|
||||
@@ -124,7 +124,7 @@ LinkedShaderDX9::LinkedShaderDX9(VSShader *vs, PSShader *fs, bool useHWTransform
|
||||
u_texmtx = GetConstantByName("u_texmtx");
|
||||
|
||||
if (gstate.getWeightMask() != 0)
|
||||
numBones = TranslateNumBonesDX9(gstate.getNumBoneWeights());
|
||||
numBones = TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType));
|
||||
else
|
||||
numBones = 0;
|
||||
|
||||
@@ -560,7 +560,7 @@ void ShaderManagerDX9::EndFrame() { // disables vertex arrays
|
||||
}
|
||||
|
||||
|
||||
LinkedShaderDX9 *ShaderManagerDX9::ApplyShader(int prim) {
|
||||
LinkedShaderDX9 *ShaderManagerDX9::ApplyShader(int prim, u32 vertType) {
|
||||
if (globalDirty_) {
|
||||
if (lastShader_)
|
||||
lastShader_->dirtyUniforms |= globalDirty_;
|
||||
@@ -640,7 +640,7 @@ LinkedShaderDX9 *ShaderManagerDX9::ApplyShader(int prim) {
|
||||
shaderSwitchDirty_ = 0;
|
||||
|
||||
if (ls == NULL) {
|
||||
ls = new LinkedShaderDX9(vs, fs, vs->UseHWTransform()); // This does "use" automatically
|
||||
ls = new LinkedShaderDX9(vs, fs, vertType, vs->UseHWTransform()); // This does "use" automatically
|
||||
const LinkedShaderCacheEntry entry(vs, fs, ls);
|
||||
linkedShaderCache_.push_back(entry);
|
||||
} else {
|
||||
|
||||
@@ -42,7 +42,7 @@ protected:
|
||||
void SetFloatArray(D3DXHANDLE uniform, const float* pArray, int len);
|
||||
void SetFloat(D3DXHANDLE uniform, float value);
|
||||
public:
|
||||
LinkedShaderDX9(VSShader *vs, PSShader *fs, bool useHWTransform);
|
||||
LinkedShaderDX9(VSShader *vs, PSShader *fs, u32 vertType, bool useHWTransform);
|
||||
~LinkedShaderDX9();
|
||||
|
||||
void use();
|
||||
@@ -189,7 +189,7 @@ public:
|
||||
~ShaderManagerDX9();
|
||||
|
||||
void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected
|
||||
LinkedShaderDX9 *ApplyShader(int prim);
|
||||
LinkedShaderDX9 *ApplyShader(int prim, u32 vertType);
|
||||
void DirtyShader();
|
||||
void DirtyUniform(u32 what) {
|
||||
globalDirty_ |= what;
|
||||
|
||||
@@ -1135,7 +1135,7 @@ void TransformDrawEngineDX9::DoFlush() {
|
||||
GEPrimitiveType prim = prevPrim_;
|
||||
ApplyDrawState(prim);
|
||||
|
||||
LinkedShaderDX9 *program = shaderManager_->ApplyShader(prim);
|
||||
LinkedShaderDX9 *program = shaderManager_->ApplyShader(prim, lastVType_);
|
||||
|
||||
if (program->useHWTransform_) {
|
||||
LPDIRECT3DVERTEXBUFFER9 vb_ = NULL;
|
||||
|
||||
@@ -88,7 +88,7 @@ void ComputeVertexShaderIDDX9(VertexShaderIDDX9 *id, int prim, bool useHWTransfo
|
||||
|
||||
// Bones
|
||||
if (hasBones)
|
||||
id->d[0] |= (TranslateNumBonesDX9(gstate.getNumBoneWeights()) - 1) << 22;
|
||||
id->d[0] |= (TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType)) - 1) << 22;
|
||||
|
||||
// Okay, d[1] coming up. ==============
|
||||
|
||||
@@ -104,7 +104,7 @@ void ComputeVertexShaderIDDX9(VertexShaderIDDX9 *id, int prim, bool useHWTransfo
|
||||
}
|
||||
}
|
||||
id->d[1] |= gstate.isLightingEnabled() << 24;
|
||||
id->d[1] |= (gstate.getWeightMask() >> GE_VTYPE_WEIGHT_SHIFT) << 25;
|
||||
id->d[1] |= (vertTypeGetWeightMask(vertType) >> GE_VTYPE_WEIGHT_SHIFT) << 25;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +172,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
|
||||
if (gstate.getUVGenMode() == 1)
|
||||
WRITE(p, "float4x4 u_texmtx;\n");
|
||||
if (gstate.getWeightMask() != GE_VTYPE_WEIGHT_NONE) {
|
||||
int numBones = TranslateNumBonesDX9(gstate.getNumBoneWeights());
|
||||
int numBones = TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType));
|
||||
#ifdef USE_BONE_ARRAY
|
||||
WRITE(p, "float4x4 u_bone[%i];\n", numBones);
|
||||
#else
|
||||
@@ -223,7 +223,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
|
||||
WRITE(p, " \n");
|
||||
WRITE(p, " { \n");
|
||||
if (gstate.getWeightMask() != GE_VTYPE_WEIGHT_NONE) {
|
||||
WRITE(p, "%s", boneWeightAttrDecl[TranslateNumBonesDX9(gstate.getNumBoneWeights())]);
|
||||
WRITE(p, "%s", boneWeightAttrDecl[TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType))]);
|
||||
}
|
||||
if (doTexture) {
|
||||
if (doTextureProjection)
|
||||
@@ -286,7 +286,7 @@ void GenerateVertexShaderDX9(int prim, char *buffer, bool useHWTransform) {
|
||||
else
|
||||
WRITE(p, " float3 worldnormal = float3(0.0, 0.0, 1.0);\n");
|
||||
} else {
|
||||
int numWeights = TranslateNumBonesDX9(gstate.getNumBoneWeights());
|
||||
int numWeights = TranslateNumBonesDX9(vertTypeGetNumBoneWeights(vertType));
|
||||
|
||||
static const char *rescale[4] = {"", " * 1.9921875", " * 1.999969482421875", ""}; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
||||
const char *factor = rescale[gstate.getWeightMask() >> GE_VTYPE_WEIGHT_SHIFT];
|
||||
|
||||
@@ -675,7 +675,7 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
break;
|
||||
|
||||
// Discard AA lines in Summon Night 5
|
||||
if ((prim == GE_PRIM_LINES) && gstate.isAntiAliasEnabled() && gstate.isSkinningEnabled())
|
||||
if ((prim == GE_PRIM_LINES) && gstate.isAntiAliasEnabled() && vertTypeIsSkinningEnabled(gstate.vertType))
|
||||
break;
|
||||
|
||||
// This also make skipping drawing very effective.
|
||||
@@ -759,8 +759,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
if (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) {
|
||||
DEBUG_LOG_REPORT(G3D, "Bezier + morph: %i", (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT);
|
||||
}
|
||||
if (gstate.isSkinningEnabled()) {
|
||||
DEBUG_LOG_REPORT(G3D, "Bezier + skinning: %i", gstate.getNumBoneWeights());
|
||||
if (vertTypeIsSkinningEnabled(gstate.vertType)) {
|
||||
DEBUG_LOG_REPORT(G3D, "Bezier + skinning: %i", vertTypeGetNumBoneWeights(gstate.vertType));
|
||||
}
|
||||
|
||||
// TODO: Get rid of this old horror...
|
||||
@@ -799,8 +799,8 @@ void GLES_GPU::ExecuteOp(u32 op, u32 diff) {
|
||||
if (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) {
|
||||
DEBUG_LOG_REPORT(G3D, "Spline + morph: %i", (gstate.vertType & GE_VTYPE_MORPHCOUNT_MASK) >> GE_VTYPE_MORPHCOUNT_SHIFT);
|
||||
}
|
||||
if (gstate.isSkinningEnabled()) {
|
||||
DEBUG_LOG_REPORT(G3D, "Spline + skinning: %i", gstate.getNumBoneWeights());
|
||||
if (vertTypeIsSkinningEnabled(gstate.vertType)) {
|
||||
DEBUG_LOG_REPORT(G3D, "Spline + skinning: %i", vertTypeGetNumBoneWeights(gstate.vertType));
|
||||
}
|
||||
|
||||
int sp_ucount = data & 0xFF;
|
||||
|
||||
@@ -72,7 +72,7 @@ Shader::~Shader() {
|
||||
glDeleteShader(shader);
|
||||
}
|
||||
|
||||
LinkedShader::LinkedShader(Shader *vs, Shader *fs, bool useHWTransform)
|
||||
LinkedShader::LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTransform)
|
||||
: useHWTransform_(useHWTransform), program(0), dirtyUniforms(0) {
|
||||
program = glCreateProgram();
|
||||
glAttachShader(program, vs->shader);
|
||||
@@ -118,8 +118,8 @@ LinkedShader::LinkedShader(Shader *vs, Shader *fs, bool useHWTransform)
|
||||
u_view = glGetUniformLocation(program, "u_view");
|
||||
u_world = glGetUniformLocation(program, "u_world");
|
||||
u_texmtx = glGetUniformLocation(program, "u_texmtx");
|
||||
if (gstate.getWeightMask() != GE_VTYPE_WEIGHT_NONE)
|
||||
numBones = TranslateNumBones(gstate.getNumBoneWeights());
|
||||
if (vertTypeGetWeightMask(vertType) != GE_VTYPE_WEIGHT_NONE)
|
||||
numBones = TranslateNumBones(vertTypeGetNumBoneWeights(vertType));
|
||||
else
|
||||
numBones = 0;
|
||||
|
||||
@@ -499,7 +499,7 @@ void ShaderManager::EndFrame() { // disables vertex arrays
|
||||
}
|
||||
|
||||
|
||||
LinkedShader *ShaderManager::ApplyShader(int prim) {
|
||||
LinkedShader *ShaderManager::ApplyShader(int prim, u32 vertType) {
|
||||
if (globalDirty_) {
|
||||
if (lastShader_)
|
||||
lastShader_->dirtyUniforms |= globalDirty_;
|
||||
@@ -511,7 +511,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim) {
|
||||
|
||||
VertexShaderID VSID;
|
||||
FragmentShaderID FSID;
|
||||
ComputeVertexShaderID(&VSID, prim, useHWTransform);
|
||||
ComputeVertexShaderID(&VSID, vertType, prim, useHWTransform);
|
||||
ComputeFragmentShaderID(&FSID);
|
||||
|
||||
// Just update uniforms if this is the same shader as last time.
|
||||
@@ -532,7 +532,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim) {
|
||||
Shader *vs;
|
||||
if (vsIter == vsCache_.end()) {
|
||||
// Vertex shader not in cache. Let's compile it.
|
||||
GenerateVertexShader(prim, codeBuffer_, useHWTransform);
|
||||
GenerateVertexShader(prim, vertType, codeBuffer_, useHWTransform);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, useHWTransform);
|
||||
|
||||
if (vs->Failed()) {
|
||||
@@ -545,7 +545,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim) {
|
||||
// next time and we'll do this over and over...
|
||||
|
||||
// Can still work with software transform.
|
||||
GenerateVertexShader(prim, codeBuffer_, false);
|
||||
GenerateVertexShader(prim, vertType, codeBuffer_, false);
|
||||
vs = new Shader(codeBuffer_, GL_VERTEX_SHADER, false);
|
||||
}
|
||||
|
||||
@@ -579,7 +579,7 @@ LinkedShader *ShaderManager::ApplyShader(int prim) {
|
||||
shaderSwitchDirty_ = 0;
|
||||
|
||||
if (ls == NULL) {
|
||||
ls = new LinkedShader(vs, fs, vs->UseHWTransform()); // This does "use" automatically
|
||||
ls = new LinkedShader(vs, fs, vertType, vs->UseHWTransform()); // This does "use" automatically
|
||||
const LinkedShaderCacheEntry entry(vs, fs, ls);
|
||||
linkedShaderCache_.push_back(entry);
|
||||
} else {
|
||||
|
||||
@@ -28,7 +28,7 @@ class Shader;
|
||||
class LinkedShader
|
||||
{
|
||||
public:
|
||||
LinkedShader(Shader *vs, Shader *fs, bool useHWTransform);
|
||||
LinkedShader(Shader *vs, Shader *fs, u32 vertType, bool useHWTransform);
|
||||
~LinkedShader();
|
||||
|
||||
void use();
|
||||
@@ -154,7 +154,7 @@ public:
|
||||
~ShaderManager();
|
||||
|
||||
void ClearCache(bool deleteThem); // TODO: deleteThem currently not respected
|
||||
LinkedShader *ApplyShader(int prim);
|
||||
LinkedShader *ApplyShader(int prim, u32 vertType);
|
||||
void DirtyShader();
|
||||
void DirtyUniform(u32 what) {
|
||||
globalDirty_ |= what;
|
||||
|
||||
+141
-19
@@ -17,6 +17,120 @@
|
||||
|
||||
#include "TransformPipeline.h"
|
||||
#include "Core/MemMap.h"
|
||||
#include "GPU/Math3D.h"
|
||||
|
||||
// PSP compatible format so we can use the end of the pipeline
|
||||
struct SimpleVertex {
|
||||
float uv[2];
|
||||
u8 color[4];
|
||||
float nrm[3];
|
||||
float pos[3];
|
||||
};
|
||||
|
||||
// This normalizes a set of vertices in any format to SimpleVertex format, by processing away morphing AND skinning.
|
||||
// The rest of the transform pipeline like lighting will go as normal, either hardware or software.
|
||||
// The implementation is initially a bit inefficient but shouldn't be a big deal.
|
||||
// An intermediate buffer of not-easy-to-predict size is stored at bufPtr.
|
||||
u32 TransformDrawEngine::NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType) {
|
||||
// First, decode the vertices into a GPU compatible format. This step can be eliminated but will need a separate
|
||||
// implementation of the vertex decoder.
|
||||
VertexDecoder *dec = GetVertexDecoder(vertType);
|
||||
dec->DecodeVerts(bufPtr, inPtr, lowerBound, upperBound);
|
||||
|
||||
// OK, morphing eliminated but bones still remain to be taken care of.
|
||||
// Let's do a partial software transform where we only do skinning.
|
||||
|
||||
VertexReader reader(bufPtr, dec->GetDecVtxFmt(), vertType);
|
||||
|
||||
SimpleVertex *sverts = (SimpleVertex *)outPtr;
|
||||
|
||||
const u8 defaultColor[4] = {
|
||||
gstate.getMaterialAmbientR(),
|
||||
gstate.getMaterialAmbientG(),
|
||||
gstate.getMaterialAmbientB(),
|
||||
gstate.getMaterialAmbientA(),
|
||||
};
|
||||
|
||||
// Let's have two separate loops, one for non skinning and one for skinning.
|
||||
if ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE) {
|
||||
int numBoneWeights = vertTypeGetNumBoneWeights(vertType);
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
}
|
||||
|
||||
if (vertType & GE_VTYPE_COL_MASK) {
|
||||
reader.ReadColor0_8888(sv.color);
|
||||
} else {
|
||||
memcpy(sv.color, defaultColor, 4);
|
||||
}
|
||||
|
||||
float nrm[3], pos[3];
|
||||
float bnrm[3], bpos[3];
|
||||
|
||||
if (vertType & GE_VTYPE_NRM_MASK) {
|
||||
// Normals are generated during tesselation anyway, not sure if any need to supply
|
||||
reader.ReadNrm(nrm);
|
||||
} else {
|
||||
nrm[0] = 0;
|
||||
nrm[1] = 0;
|
||||
nrm[2] = 1.0f;
|
||||
}
|
||||
reader.ReadPos(pos);
|
||||
|
||||
// Apply skinning transform directly
|
||||
float weights[8];
|
||||
reader.ReadWeights(weights);
|
||||
// Skinning
|
||||
Vec3f psum(0,0,0);
|
||||
Vec3f nsum(0,0,0);
|
||||
for (int i = 0; i < numBoneWeights; i++) {
|
||||
if (weights[i] != 0.0f) {
|
||||
Vec3ByMatrix43(bpos, pos, gstate.boneMatrix+i*12);
|
||||
Vec3f tpos(bpos);
|
||||
psum += tpos * weights[i];
|
||||
|
||||
Norm3ByMatrix43(bnrm, nrm, gstate.boneMatrix+i*12);
|
||||
Vec3f tnorm(bnrm);
|
||||
nsum += tnorm * weights[i];
|
||||
}
|
||||
}
|
||||
memcpy(sv.pos, &psum[0], 12);
|
||||
memcpy(sv.nrm, &nsum[0], 12);
|
||||
}
|
||||
} else {
|
||||
for (int i = lowerBound; i <= upperBound; i++) {
|
||||
reader.Goto(i);
|
||||
SimpleVertex &sv = sverts[i];
|
||||
if (vertType & GE_VTYPE_TC_MASK) {
|
||||
reader.ReadUV(sv.uv);
|
||||
} else {
|
||||
sv.uv[0] = 0; // This will get filled in during tesselation
|
||||
sv.uv[1] = 0;
|
||||
}
|
||||
if (vertType & GE_VTYPE_COL_MASK) {
|
||||
reader.ReadColor0_8888(sv.color);
|
||||
} else {
|
||||
memcpy(sv.color, defaultColor, 4);
|
||||
}
|
||||
if (vertType & GE_VTYPE_NRM_MASK) {
|
||||
// Normals are generated during tesselation anyway, not sure if any need to supply
|
||||
reader.ReadNrm(sv.nrm);
|
||||
} else {
|
||||
sv.nrm[0] = 0;
|
||||
sv.nrm[1] = 0;
|
||||
sv.nrm[2] = 1.0f;
|
||||
}
|
||||
reader.ReadPos(sv.pos);
|
||||
}
|
||||
}
|
||||
|
||||
// Okay, there we are! Return the new type (but keep the index bits)
|
||||
return GE_VTYPE_TC_FLOAT | GE_VTYPE_COL_8888 | GE_VTYPE_NRM_FLOAT | GE_VTYPE_POS_FLOAT | (vertType & GE_VTYPE_IDX_MASK);
|
||||
}
|
||||
|
||||
|
||||
// Just to get something on the screen, we'll just not subdivide correctly.
|
||||
void TransformDrawEngine::DrawBezier(int ucount, int vcount) {
|
||||
@@ -84,14 +198,15 @@ void TransformDrawEngine::DrawBezier(int ucount, int vcount) {
|
||||
// We decode all vertices into a common format for easy interpolation and stuff.
|
||||
// Not fast but can be optimized later.
|
||||
struct HWSplinePatch {
|
||||
u8 *points[16];
|
||||
SimpleVertex *points[16];
|
||||
int type;
|
||||
|
||||
// We need to generate both UVs and normals later...
|
||||
// float u0, v0, u1, v1;
|
||||
};
|
||||
|
||||
static void CopyTriangle(u8 *&dest, u8 *v1, u8 *v2, u8 * v3, int vertexSize) {
|
||||
static void CopyTriangle(u8 *&dest, SimpleVertex *v1, SimpleVertex *v2, SimpleVertex* v3) {
|
||||
int vertexSize = sizeof(SimpleVertex);
|
||||
memcpy(dest, v1, vertexSize);
|
||||
dest += vertexSize;
|
||||
memcpy(dest, v2, vertexSize);
|
||||
@@ -100,6 +215,7 @@ static void CopyTriangle(u8 *&dest, u8 *v1, u8 *v2, u8 * v3, int vertexSize) {
|
||||
dest += vertexSize;
|
||||
}
|
||||
|
||||
|
||||
void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int count_u, int count_v, int type_u, int type_v, GEPatchPrimType prim_type, u32 vertex_type) {
|
||||
Flush();
|
||||
|
||||
@@ -108,13 +224,6 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
return;
|
||||
}
|
||||
|
||||
// We're not actually going to decode, only reshuffle.
|
||||
VertexDecoder *vdecoder = GetVertexDecoder(vertex_type);
|
||||
|
||||
int undecodedVertexSize = vdecoder->VertexSize();
|
||||
|
||||
const DecVtxFormat& vtxfmt = vdecoder->GetDecVtxFmt();
|
||||
|
||||
u16 index_lower_bound = 0;
|
||||
u16 index_upper_bound = count_u * count_v - 1;
|
||||
bool indices_16bit = (vertex_type & GE_VTYPE_IDX_MASK) == GE_VTYPE_IDX_16BIT;
|
||||
@@ -123,6 +232,20 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
if (indices)
|
||||
GetIndexBounds(indices, count_u*count_v, vertex_type, &index_lower_bound, &index_upper_bound);
|
||||
|
||||
// Simplify away bones and morph before proceeding
|
||||
SimpleVertex *simplified_control_points = (SimpleVertex *)(decoded + 65536 * 12);
|
||||
u8 *temp_buffer = decoded + 65536 * 24;
|
||||
|
||||
vertex_type = NormalizeVertices((u8 *)simplified_control_points, temp_buffer, (u8 *)control_points, index_lower_bound, index_upper_bound, vertex_type);
|
||||
|
||||
VertexDecoder *vdecoder = GetVertexDecoder(vertex_type);
|
||||
|
||||
int vertexSize = vdecoder->VertexSize();
|
||||
if (vertexSize != sizeof(SimpleVertex)) {
|
||||
ERROR_LOG(G3D, "Something went really wrong, vertex size: %i vs %i", vertexSize, sizeof(SimpleVertex));
|
||||
}
|
||||
const DecVtxFormat& vtxfmt = vdecoder->GetDecVtxFmt();
|
||||
|
||||
int num_patches_u = count_u - 3;
|
||||
int num_patches_v = count_v - 3;
|
||||
|
||||
@@ -135,9 +258,9 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
for (int point = 0; point < 16; ++point) {
|
||||
int idx = (patch_u + point%4) + (patch_v + point/4) * count_u;
|
||||
if (indices)
|
||||
patch.points[point] = (u8 *)control_points + undecodedVertexSize * (indices_16bit ? indices16[idx] : indices8[idx]);
|
||||
patch.points[point] = simplified_control_points + (indices_16bit ? indices16[idx] : indices8[idx]);
|
||||
else
|
||||
patch.points[point] = (u8 *)control_points + undecodedVertexSize * idx;
|
||||
patch.points[point] = simplified_control_points + idx;
|
||||
}
|
||||
patch.type = (type_u | (type_v << 2));
|
||||
if (patch_u != 0) patch.type &= ~START_OPEN_U;
|
||||
@@ -147,7 +270,7 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
}
|
||||
}
|
||||
|
||||
u8 *decoded2 = decoded + 65536 * 24;
|
||||
u8 *decoded2 = decoded + 65536 * 36;
|
||||
|
||||
int count = 0;
|
||||
u8 *dest = decoded2;
|
||||
@@ -164,14 +287,13 @@ void TransformDrawEngine::SubmitSpline(void* control_points, void* indices, int
|
||||
for (int tile_v = tile_min_v; tile_v < tile_max_v; ++tile_v) {
|
||||
int point_index = tile_u + tile_v*4;
|
||||
|
||||
u8 *v0 = patch.points[point_index];
|
||||
u8 *v1 = patch.points[point_index+1];
|
||||
u8 *v2 = patch.points[point_index+4];
|
||||
u8 *v3 = patch.points[point_index+5];
|
||||
SimpleVertex *v0 = patch.points[point_index];
|
||||
SimpleVertex *v1 = patch.points[point_index+1];
|
||||
SimpleVertex *v2 = patch.points[point_index+4];
|
||||
SimpleVertex *v3 = patch.points[point_index+5];
|
||||
|
||||
// TODO: Insert UVs and normals if not present.
|
||||
CopyTriangle(dest, v0, v2, v1, undecodedVertexSize);
|
||||
CopyTriangle(dest, v1, v2, v3, undecodedVertexSize);
|
||||
CopyTriangle(dest, v0, v2, v1);
|
||||
CopyTriangle(dest, v1, v2, v3);
|
||||
count += 6;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -490,7 +490,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
if (reader.hasNormal())
|
||||
reader.ReadNrm(nrm);
|
||||
|
||||
if (!gstate.isSkinningEnabled()) {
|
||||
if (!vertTypeIsSkinningEnabled(vertType)) {
|
||||
Vec3ByMatrix43(out, pos, gstate.worldMatrix);
|
||||
if (reader.hasNormal()) {
|
||||
Norm3ByMatrix43(norm, nrm, gstate.worldMatrix);
|
||||
@@ -502,7 +502,7 @@ void TransformDrawEngine::SoftwareTransformAndDraw(
|
||||
// Skinning
|
||||
Vec3f psum(0,0,0);
|
||||
Vec3f nsum(0,0,0);
|
||||
for (int i = 0; i < gstate.getNumBoneWeights(); i++) {
|
||||
for (int i = 0; i < vertTypeGetNumBoneWeights(vertType); i++) {
|
||||
if (weights[i] != 0.0f) {
|
||||
Vec3ByMatrix43(out, pos, gstate.boneMatrix+i*12);
|
||||
Vec3f tpos(out);
|
||||
@@ -1042,7 +1042,7 @@ void TransformDrawEngine::DoFlush() {
|
||||
GEPrimitiveType prim = prevPrim_;
|
||||
ApplyDrawState(prim);
|
||||
|
||||
LinkedShader *program = shaderManager_->ApplyShader(prim);
|
||||
LinkedShader *program = shaderManager_->ApplyShader(prim, lastVType_);
|
||||
|
||||
if (program->useHWTransform_) {
|
||||
GLuint vbo = 0, ebo = 0;
|
||||
|
||||
@@ -138,6 +138,9 @@ private:
|
||||
void ApplyDrawState(int prim);
|
||||
bool IsReallyAClear(int numVerts) const;
|
||||
|
||||
// Preprocessing for spline/bezier
|
||||
u32 NormalizeVertices(u8 *outPtr, u8 *bufPtr, const u8 *inPtr, int lowerBound, int upperBound, u32 vertType);
|
||||
|
||||
// drawcall ID
|
||||
u32 ComputeFastDCID();
|
||||
u32 ComputeHash(); // Reads deferred vertex data.
|
||||
|
||||
@@ -53,8 +53,7 @@ int TranslateNumBones(int bones) {
|
||||
}
|
||||
|
||||
// prim so we can special case for RECTANGLES :(
|
||||
void ComputeVertexShaderID(VertexShaderID *id, int prim, bool useHWTransform) {
|
||||
const u32 vertType = gstate.vertType;
|
||||
void ComputeVertexShaderID(VertexShaderID *id, u32 vertType, int prim, bool useHWTransform) {
|
||||
int doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
bool doTextureProjection = gstate.getUVGenMode() == GE_TEXMAP_TEXTURE_MATRIX;
|
||||
bool doShadeMapping = gstate.getUVGenMode() == GE_TEXMAP_ENVIRONMENT_MAP;
|
||||
@@ -91,8 +90,8 @@ void ComputeVertexShaderID(VertexShaderID *id, int prim, bool useHWTransform) {
|
||||
}
|
||||
|
||||
// Bones
|
||||
if (gstate.isSkinningEnabled())
|
||||
id->d[0] |= (TranslateNumBones(gstate.getNumBoneWeights()) - 1) << 22;
|
||||
if (vertTypeIsSkinningEnabled(vertType))
|
||||
id->d[0] |= (TranslateNumBones(vertTypeGetNumBoneWeights(vertType)) - 1) << 22;
|
||||
|
||||
// Okay, d[1] coming up. ==============
|
||||
|
||||
@@ -130,7 +129,7 @@ enum DoLightComputation {
|
||||
LIGHT_FULL,
|
||||
};
|
||||
|
||||
void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
|
||||
void GenerateVertexShader(int prim, u32 vertType, char *buffer, bool useHWTransform) {
|
||||
char *p = buffer;
|
||||
|
||||
// #define USE_FOR_LOOP
|
||||
@@ -149,7 +148,6 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
|
||||
WRITE(p, "#define lowp\n");
|
||||
WRITE(p, "#define mediump\n");
|
||||
#endif
|
||||
const u32 vertType = gstate.vertType;
|
||||
|
||||
int lmode = gstate.isUsingSecondaryColor() && gstate.isLightingEnabled();
|
||||
int doTexture = gstate.isTextureMapEnabled() && !gstate.isModeClear();
|
||||
@@ -174,8 +172,8 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
|
||||
}
|
||||
}
|
||||
|
||||
if (gstate.isSkinningEnabled()) {
|
||||
WRITE(p, "%s", boneWeightAttrDecl[TranslateNumBones(gstate.getNumBoneWeights())]);
|
||||
if (vertTypeIsSkinningEnabled(vertType)) {
|
||||
WRITE(p, "%s", boneWeightAttrDecl[TranslateNumBones(vertTypeGetNumBoneWeights(vertType))]);
|
||||
}
|
||||
|
||||
if (useHWTransform)
|
||||
@@ -211,8 +209,8 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
|
||||
WRITE(p, "uniform mat4 u_view;\n");
|
||||
if (doTextureProjection)
|
||||
WRITE(p, "uniform mediump mat4 u_texmtx;\n");
|
||||
if (gstate.isSkinningEnabled()) {
|
||||
int numBones = TranslateNumBones(gstate.getNumBoneWeights());
|
||||
if (vertTypeIsSkinningEnabled(vertType)) {
|
||||
int numBones = TranslateNumBones(vertTypeGetNumBoneWeights(vertType));
|
||||
#ifdef USE_BONE_ARRAY
|
||||
WRITE(p, "uniform mediump mat4 u_bone[%i];\n", numBones);
|
||||
#else
|
||||
@@ -299,7 +297,7 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
|
||||
}
|
||||
} else {
|
||||
// Step 1: World Transform / Skinning
|
||||
if (!gstate.isSkinningEnabled()) {
|
||||
if (!vertTypeIsSkinningEnabled(vertType)) {
|
||||
// No skinning, just standard T&L.
|
||||
WRITE(p, " vec3 worldpos = (u_world * vec4(a_position.xyz, 1.0)).xyz;\n");
|
||||
if (hasNormal)
|
||||
@@ -307,7 +305,7 @@ void GenerateVertexShader(int prim, char *buffer, bool useHWTransform) {
|
||||
else
|
||||
WRITE(p, " vec3 worldnormal = vec3(0.0, 0.0, 1.0);\n");
|
||||
} else {
|
||||
int numWeights = TranslateNumBones(gstate.getNumBoneWeights());
|
||||
int numWeights = TranslateNumBones(vertTypeGetNumBoneWeights(vertType));
|
||||
|
||||
static const char *rescale[4] = {"", " * 1.9921875", " * 1.999969482421875", ""}; // 2*127.5f/128.f, 2*32767.5f/32768.f, 1.0f};
|
||||
const char *factor = rescale[gstate.getWeightMask() >> GE_VTYPE_WEIGHT_SHIFT];
|
||||
|
||||
@@ -50,8 +50,8 @@ struct VertexShaderID
|
||||
|
||||
bool CanUseHardwareTransform(int prim);
|
||||
|
||||
void ComputeVertexShaderID(VertexShaderID *id, int prim, bool useHWTransform);
|
||||
void GenerateVertexShader(int prim, char *buffer, bool useHWTransform);
|
||||
void ComputeVertexShaderID(VertexShaderID *id, u32 vertexType, int prim, bool useHWTransform);
|
||||
void GenerateVertexShader(int prim, u32 vertexType, char *buffer, bool useHWTransform);
|
||||
|
||||
// Collapse to less skinning shaders to reduce shader switching, which is expensive.
|
||||
int TranslateNumBones(int bones);
|
||||
+5
-2
@@ -369,8 +369,6 @@ struct GPUgstate
|
||||
// Vertex type
|
||||
bool isModeThrough() const { return (vertType & GE_VTYPE_THROUGH) != 0; }
|
||||
int getWeightMask() const { return vertType & GE_VTYPE_WEIGHT_MASK; }
|
||||
int getNumBoneWeights() const { return 1 + ((vertType & GE_VTYPE_WEIGHTCOUNT_MASK) >> GE_VTYPE_WEIGHTCOUNT_SHIFT); }
|
||||
bool isSkinningEnabled() const { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); }
|
||||
int getTexCoordMask() const { return vertType & GE_VTYPE_TC_MASK; }
|
||||
bool areNormalsReversed() const { return reversenormals & 1; }
|
||||
|
||||
@@ -401,6 +399,11 @@ enum SkipDrawReasonFlags {
|
||||
SKIPDRAW_BAD_FB_TEXTURE = 4,
|
||||
};
|
||||
|
||||
inline bool vertTypeIsSkinningEnabled(u32 vertType) { return ((vertType & GE_VTYPE_WEIGHT_MASK) != GE_VTYPE_WEIGHT_NONE); }
|
||||
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; }
|
||||
|
||||
|
||||
// The rest is cached simplified/converted data for fast access.
|
||||
// Does not need to be saved when saving/restoring context.
|
||||
|
||||
|
||||
@@ -118,14 +118,14 @@ static VertexData ReadVertex(VertexReader& vreader)
|
||||
vertex.normal = -vertex.normal;
|
||||
}
|
||||
|
||||
if (gstate.isSkinningEnabled() && !gstate.isModeThrough()) {
|
||||
if (vertTypeIsSkinningEnabled(gstate.vertType) && !gstate.isModeThrough()) {
|
||||
float W[8] = { 1.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f, 0.f };
|
||||
vreader.ReadWeights(W);
|
||||
|
||||
Vec3<float> tmppos(0.f, 0.f, 0.f);
|
||||
Vec3<float> tmpnrm(0.f, 0.f, 0.f);
|
||||
|
||||
for (int i = 0; i < gstate.getNumBoneWeights(); ++i) {
|
||||
for (int i = 0; i < vertTypeGetNumBoneWeights(gstate.vertType); ++i) {
|
||||
Mat3x3<float> bone(&gstate.boneMatrix[12*i]);
|
||||
tmppos += W[i] * (bone * ModelCoords(pos[0], pos[1], pos[2]) + Vec3<float>(gstate.boneMatrix[12*i+9], gstate.boneMatrix[12*i+10], gstate.boneMatrix[12*i+11]));
|
||||
if (vreader.hasNormal())
|
||||
|
||||
Reference in new issue
Block a user