mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-07-27 22:33:06 +00:00
Optimise vertex skinning code with SSE, based on patch by gruby.
Fixes #905. This was SVN commit r10499.
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
/* Copyright (C) 2009 Wildfire Games.
|
||||
/* Copyright (C) 2011 Wildfire Games.
|
||||
* This file is part of 0 A.D.
|
||||
*
|
||||
* 0 A.D. is free software: you can redistribute it and/or modify
|
||||
@@ -21,7 +21,9 @@
|
||||
|
||||
#include "precompiled.h"
|
||||
|
||||
#include "lib/bits.h"
|
||||
#include "lib/ogl.h"
|
||||
#include "lib/sysdep/rtl.h"
|
||||
#include "maths/Vector3D.h"
|
||||
#include "maths/Vector4D.h"
|
||||
|
||||
@@ -97,8 +99,13 @@ struct FFModel
|
||||
|
||||
struct FixedFunctionModelRendererInternals
|
||||
{
|
||||
/// Transformed vertex normals - required for recalculating lighting on skinned models
|
||||
std::vector<CVector3D> normals;
|
||||
/**
|
||||
* Scratch space for normal vector calculation.
|
||||
* Space is reserved so we don't have to do frequent reallocations.
|
||||
* Allocated with rtl_AllocateAligned(normalsNumVertices*16, 16) for SSE writes.
|
||||
*/
|
||||
char* normals;
|
||||
size_t normalsNumVertices;
|
||||
|
||||
/// Previously prepared modeldef
|
||||
FFModelDef* ffmodeldef;
|
||||
@@ -110,10 +117,14 @@ FixedFunctionModelRenderer::FixedFunctionModelRenderer()
|
||||
{
|
||||
m = new FixedFunctionModelRendererInternals;
|
||||
m->ffmodeldef = 0;
|
||||
m->normals = 0;
|
||||
m->normalsNumVertices = 0;
|
||||
}
|
||||
|
||||
FixedFunctionModelRenderer::~FixedFunctionModelRenderer()
|
||||
{
|
||||
rtl_FreeAligned(m->normals);
|
||||
|
||||
delete m;
|
||||
}
|
||||
|
||||
@@ -133,17 +144,26 @@ void* FixedFunctionModelRenderer::CreateModelData(CModel* model)
|
||||
// Build the per-model data
|
||||
FFModel* ffmodel = new FFModel;
|
||||
|
||||
ffmodel->m_Position.type = GL_FLOAT;
|
||||
ffmodel->m_Position.elems = 3;
|
||||
ffmodel->m_Array.AddAttribute(&ffmodel->m_Position);
|
||||
// Positions must be 16-byte aligned for SSE writes.
|
||||
// We can pack the color after the position; it will be corrupted by
|
||||
// BuildPositionAndNormals, but that's okay since we'll recompute the
|
||||
// colors afterwards.
|
||||
|
||||
ffmodel->m_Color.type = GL_UNSIGNED_BYTE;
|
||||
ffmodel->m_Color.elems = 4;
|
||||
ffmodel->m_Array.AddAttribute(&ffmodel->m_Color);
|
||||
|
||||
ffmodel->m_Position.type = GL_FLOAT;
|
||||
ffmodel->m_Position.elems = 3;
|
||||
ffmodel->m_Array.AddAttribute(&ffmodel->m_Position);
|
||||
|
||||
ffmodel->m_Array.SetNumVertices(mdef->GetNumVertices());
|
||||
ffmodel->m_Array.Layout();
|
||||
|
||||
// Verify alignment
|
||||
ENSURE(ffmodel->m_Position.offset % 16 == 0);
|
||||
ENSURE(ffmodel->m_Array.GetStride() % 16 == 0);
|
||||
|
||||
return ffmodel;
|
||||
}
|
||||
|
||||
@@ -159,11 +179,19 @@ void FixedFunctionModelRenderer::UpdateModelData(CModel* model, void* data, int
|
||||
size_t numVertices = mdef->GetNumVertices();
|
||||
|
||||
// build vertices
|
||||
if (m->normals.size() < numVertices)
|
||||
m->normals.resize(numVertices);
|
||||
|
||||
// allocate working space for computing normals
|
||||
if (numVertices > m->normalsNumVertices)
|
||||
{
|
||||
rtl_FreeAligned(m->normals);
|
||||
|
||||
size_t newSize = round_up_to_pow2(numVertices);
|
||||
m->normals = (char*)rtl_AllocateAligned(newSize*16, 16);
|
||||
m->normalsNumVertices = newSize;
|
||||
}
|
||||
|
||||
VertexArrayIterator<CVector3D> Position = ffmodel->m_Position.GetIterator<CVector3D>();
|
||||
VertexArrayIterator<CVector3D> Normal = VertexArrayIterator<CVector3D>((char*)&m->normals[0], sizeof(CVector3D));
|
||||
VertexArrayIterator<CVector3D> Normal = VertexArrayIterator<CVector3D>(m->normals, 16);
|
||||
|
||||
ModelRenderer::BuildPositionAndNormals(model, Position, Normal);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user