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:
Henrik Rydgard committed 2013-09-21 23:37:14 +02:00
1 parent c733f7a7ab
commit 82e5787bbe
16 files changed
+218 -68

No files matched your search

+24
View File
@@ -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:
+1 -1
View File
@@ -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.
+4 -4
View File
@@ -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 {
+2 -2
View File
@@ -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;
+1 -1
View File
@@ -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;
+5 -5
View File
@@ -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];
+5 -5
View File
@@ -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;
+8 -8
View File
@@ -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 {
+2 -2
View File
@@ -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
View File
@@ -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;
}
}
+3 -3
View File
@@ -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;
+3
View File
@@ -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.
+10 -12
View File
@@ -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];
+2 -2
View File
@@ -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
View File
@@ -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.
+2 -2
View File
@@ -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())