Stab at fixing the VertexArray compile error on VC++.

Added float-to-byte color conversion, including an SSE assembler
version.
Model renderer: Push UV coordinates into a shared vertex array and use
bytes instead of floats for the color array, thereby, significantly
reducing
the total size of vertex arrays.

This was SVN commit r2827.
This commit is contained in:
prefect
2005-10-03 03:41:42 +00:00
parent a05e712319
commit 6fc1f45fa6
12 changed files with 210 additions and 50 deletions
+19
View File
@@ -0,0 +1,19 @@
#include "precompiled.h"
#include "MathUtil.h"
#include "graphics/Color.h"
static u32 fallback_ConvertRGBColorTo4ub(const RGBColor& src)
{
SColor4ub result;
result.R=clamp(int(src.X*255),0,255);
result.G=clamp(int(src.Y*255),0,255);
result.B=clamp(int(src.Z*255),0,255);
result.A=0xff;
return *(u32*)&result;
}
// on IA32, this is replaced by an SSE assembly version in ia32.cpp
u32 (*ConvertRGBColorTo4ub)(const RGBColor& src) = fallback_ConvertRGBColorTo4ub;
+2
View File
@@ -35,5 +35,7 @@ struct SColor4ub
u8 A;
};
extern u32 (*ConvertRGBColorTo4ub)(const RGBColor& src);
#endif
+29 -1
View File
@@ -128,7 +128,7 @@ int cpu_ht_units = -1;
int cpu_cores = -1;
int cpu_speedstep = -1;
void get_cpu_info()
static void get_cpu_info()
{
#if OS_WIN
win_get_cpu_info();
@@ -142,6 +142,34 @@ void get_cpu_info()
}
void cpu_init()
{
#if CPU_IA32
ia32_init();
#endif
// If you ever want to catch a particular allocation:
//_CrtSetBreakAlloc(187);
// no longer set 24 bit (float) precision by default: for
// very long game uptimes (> 1 day; e.g. dedicated server),
// we need full precision when calculating the time.
// if there's a spot where we want to speed up divides|sqrts,
// we can temporarily change precision there.
// _control87(_PC_24, _MCW_PC);
// detects CPU clock frequency and capabilities, which are prerequisites
// for using the TSC as a timer (desirable due to its high resolution).
// do this before lengthy init so we can time those accurately.
get_cpu_info();
#if CPU_IA32
// If possible, hook up capability-sensitive assembler routines
ia32_hook_capabilities();
#endif
}
//
// sound
//
+1 -1
View File
@@ -21,7 +21,7 @@ extern int cpu_cores; // cores per package, typically 2
extern int cpu_speedstep;
extern void get_cpu_info(void);
extern void cpu_init(void);
// atomic "compare and swap". compare the machine word at <location> against
+49
View File
@@ -398,3 +398,52 @@ extern sym(ia32_cap)
pop ebx
ret
;-------------------------------------------------------------------------------
; Color conversion (SSE)
;-------------------------------------------------------------------------------
; extern "C" u32 ConvertRGBColorTo4ub(const RGBColor& color)
[section .data]
align 16
zero:
dd 0.0
twofivefive:
dd 255.0
__SECT__
align 16
global sym(sse_ConvertRGBColorTo4ub)
sym(sse_ConvertRGBColorTo4ub):
mov eax, [esp+4]
; xmm0, 1, 2 = R, G, B
movss xmm4, [zero]
movss xmm0, [eax+8]
movss xmm1, [eax+4]
movss xmm2, [eax]
movss xmm5, [twofivefive]
; C = min(255, 255*max(C, 0)) ( == clamp(255*C, 0, 255) )
maxss xmm0, xmm4
maxss xmm1, xmm4
maxss xmm2, xmm4
mulss xmm0, xmm5
mulss xmm1, xmm5
mulss xmm2, xmm5
minss xmm0, xmm5
minss xmm1, xmm5
minss xmm2, xmm5
; convert to integer and combine channels using bit logic
cvtss2si eax, xmm0
cvtss2si ecx, xmm1
cvtss2si edx, xmm2
shl eax, 16
shl ecx, 8
or eax, 0xff000000
or edx, ecx
or eax, edx
ret
+20 -1
View File
@@ -28,6 +28,7 @@
#include "win/wtime.h"
#endif
#include "graphics/Color.h"
#include <string.h>
#include <stdio.h>
@@ -525,7 +526,7 @@ static void measure_cpu_freq()
u64 c1; double t1;
do
{
// note: get_time effectively has a long delay (up to 5 µs)
// note: get_time effectively has a long delay (up to 5 s)
// before returning the time. we call it before rdtsc to
// minimize the delay between actually sampling time / TSC,
// thus decreasing the chance for interference.
@@ -588,3 +589,21 @@ void ia32_get_cpu_info()
wtime_reset_impl();
#endif
}
// Assembler-optimized function for color conversion
extern "C" {
u32 sse_ConvertRGBColorTo4ub(const RGBColor& src);
}
void ia32_hook_capabilities()
{
if (ia32_cap(SSE))
{
ConvertRGBColorTo4ub = sse_ConvertRGBColorTo4ub;
}
else
{
debug_printf("No SSE available. Slow fallback routines will be used.\n");
}
}
+1
View File
@@ -83,6 +83,7 @@ extern bool ia32_cap(CpuCap cap);
extern void ia32_get_cpu_info(void);
extern void ia32_hook_capabilities(void);
// internal use only
+3 -19
View File
@@ -779,25 +779,9 @@ void Init(int argc, char* argv[], bool setup_gfx, bool setup_gui)
debug_set_thread_name("main");
#if CPU_IA32
ia32_init();
#endif
// If you ever want to catch a particular allocation:
//_CrtSetBreakAlloc(187);
// no longer set 24 bit (float) precision by default: for
// very long game uptimes (> 1 day; e.g. dedicated server),
// we need full precision when calculating the time.
// if there's a spot where we want to speed up divides|sqrts,
// we can temporarily change precision there.
// _control87(_PC_24, _MCW_PC);
// detects CPU clock frequency and capabilities, which are prerequisites
// for using the TSC as a timer (desirable due to its high resolution).
// do this before lengthy init so we can time those accurately.
get_cpu_info();
// Query CPU capabilities, possibly set some CPU-dependent flags
cpu_init();
// Do this as soon as possible, because it chdirs
// and will mess up the error reporting if anything
// crashes before the working directory is set.
+35 -1
View File
@@ -8,6 +8,7 @@
#include "graphics/Model.h"
#include "renderer/ModelRData.h"
#include "renderer/ModelDefRData.h"
#include "renderer/Renderer.h"
#define LOG_CATEGORY "graphics"
@@ -17,7 +18,7 @@
CModelDefRData* CModelDefRData::m_Submissions = 0;
CModelDefRData::CModelDefRData(CModelDef* mdef)
: m_ModelDef(mdef)
: m_ModelDef(mdef), m_Array(false)
{
m_SubmissionNext = 0;
m_SubmissionSlots = 0;
@@ -33,8 +34,41 @@ CModelDefRData::~CModelDefRData()
// Create and upload shared vertex arrays
void CModelDefRData::Build()
{
size_t numVertices = m_ModelDef->GetNumVertices();
m_UV.type = GL_FLOAT;
m_UV.elems = 2;
m_Array.AddAttribute(&m_UV);
m_Array.SetNumVertices(numVertices);
m_Array.Layout();
SModelVertex* vertices = m_ModelDef->GetVertices();
VertexArrayIterator<float[2]> UVit = m_UV.GetIterator<float[2]>();
for (uint j=0; j < numVertices; ++j, ++UVit) {
(*UVit)[0] = vertices[j].m_U;
(*UVit)[1] = 1.0-vertices[j].m_V;
}
m_Array.Upload();
m_Array.FreeBackingStore();
}
// Setup shared vertex arrays as needed.
void CModelDefRData::PrepareStream(uint streamflags)
{
if (!(streamflags & STREAM_UV0))
return;
u8* base = m_Array.Bind();
size_t stride = m_Array.GetStride();
glTexCoordPointer(2, GL_FLOAT, stride, base + m_UV.offset);
}
// Submit one model.
// Models are sorted into a hash-table to avoid ping-ponging between
// different render states later on.
+6
View File
@@ -18,6 +18,9 @@ public:
CModelDefRData(CModelDef* mdef);
virtual ~CModelDefRData();
// Setup shared vertex arrays required by streamflags
void PrepareStream(uint streamflags);
// Submit one model
void Submit(CModelRData* data);
// Clear all submissions for this CModelDef
@@ -30,6 +33,9 @@ private:
private:
CModelDef* m_ModelDef;
VertexArray m_Array;
VertexArray::Attribute m_UV;
CModelDefRData* m_SubmissionNext;
uint m_SubmissionSlots;
std::vector<CModelRData*> m_SubmissionModels;
+42 -25
View File
@@ -47,12 +47,12 @@ void CModelRData::Build()
m_Position.type = GL_FLOAT;
m_Position.elems = 3;
m_DynamicArray.AddAttribute(&m_Position);
/*
m_UV.type = GL_FLOAT;
m_UV.elems = 2;
m_DynamicArray.AddAttribute(&m_UV);
m_Color.type = GL_FLOAT;
*/
m_Color.type = GL_UNSIGNED_BYTE;
m_Color.elems = 3;
m_DynamicArray.AddAttribute(&m_Color);
@@ -80,7 +80,7 @@ void CModelRData::Build()
}
void CModelRData::BuildIndices()
{
{
CModelDefPtr mdef=m_Model->GetModelDef();
debug_assert(mdef);
@@ -100,14 +100,7 @@ void CModelRData::BuildIndices()
}
}
static SColor3ub ConvertColor(const RGBColor& src)
{
SColor3ub result;
result.R=clamp(int(src.X*255),0,255);
result.G=clamp(int(src.Y*255),0,255);
result.B=clamp(int(src.Z*255),0,255);
return result;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////////
// SkinPoint: skin the vertex position using it's blend data and given bone matrices
@@ -153,6 +146,7 @@ static void SkinNormal(const SModelVertex& vertex,const CMatrix3D* invmatrices,C
void CModelRData::BuildStaticVertices()
{
/*
CModelDefPtr mdef = m_Model->GetModelDef();
size_t numVertices = mdef->GetNumVertices();
SModelVertex* vertices = mdef->GetVertices();
@@ -162,6 +156,7 @@ void CModelRData::BuildStaticVertices()
(*UVit)[0] = vertices[j].m_U;
(*UVit)[1] = 1.0-vertices[j].m_V;
}
*/
}
void CModelRData::BuildVertices()
@@ -177,7 +172,7 @@ void CModelRData::BuildVertices()
// build vertices
VertexArrayIterator<CVector3D> Position = m_Position.GetIterator<CVector3D>();
VertexArrayIterator<CVector3D> Color = m_Color.GetIterator<CVector3D>();
VertexArrayIterator<SColor3ub> Color = m_Color.GetIterator<SColor3ub>();
const CMatrix3D* bonematrices=m_Model->GetBoneMatrices();
if (bonematrices) {
// boned model - calculate skinned vertex positions/normals
@@ -199,12 +194,13 @@ void CModelRData::BuildVertices()
PROFILE_START( "lighting vertices" );
// now fill in UV and vertex colour data
CSHCoeffs& shcoeffs = g_Renderer.m_SHCoeffsUnits;
CColor sc = m_Model->GetShadingColor();
RGBColor shadingcolor(sc.r, sc.g, sc.b);
RGBColor tempcolor;
for (uint j=0; j<numVertices; j++) {
CColor sc = m_Model->GetShadingColor();
RGBColor tempcolor;
g_Renderer.m_SHCoeffsUnits.Evaluate(m_Normals[j], tempcolor,
RGBColor(sc.r, sc.g, sc.b));
Color[j] = tempcolor;//ConvertColor(tempcolor);
shcoeffs.Evaluate(m_Normals[j], tempcolor, shadingcolor);
*(u32*)&Color[j] = ConvertRGBColorTo4ub(tempcolor);
}
PROFILE_END( "lighting vertices" );
@@ -227,6 +223,8 @@ void CModelRData::RenderStreams(u32 streamflags, bool isplayer)
g_Renderer.SetTexture(0,m_Model->GetTexture());
}
((CModelDefRData*)mdldef->GetRenderData())->PrepareStream(streamflags);
u8* base = m_DynamicArray.Bind();
size_t stride = m_DynamicArray.GetStride();
@@ -243,7 +241,6 @@ void CModelRData::RenderStreams(u32 streamflags, bool isplayer)
glDisableClientState(GL_COLOR_ARRAY);
}
#endif
if (streamflags & STREAM_UV0) glTexCoordPointer(2, GL_FLOAT, stride, base + m_UV.offset);
// render the lot
size_t numFaces=mdldef->GetNumFaces();
@@ -340,19 +337,39 @@ void CModelRData::RenderModels(u32 streamflags, u32 flags)
mdefdata;
mdefdata = mdefdata->m_SubmissionNext)
{
mdefdata->PrepareStream(streamflags);
for(uint idx = 0; idx < mdefdata->m_SubmissionSlots; ++idx)
{
if (!mdefdata->m_SubmissionModels[idx])
break;
CModelRData* modeldata = mdefdata->m_SubmissionModels[idx];
for(CModelRData* modeldata = mdefdata->m_SubmissionModels[idx];
modeldata;
modeldata = modeldata->m_SubmissionNext)
if (streamflags & STREAM_UV0)
g_Renderer.SetTexture(0, modeldata->GetModel()->GetTexture());
for(; modeldata; modeldata = modeldata->m_SubmissionNext)
{
if (flags && !(modeldata->GetModel()->GetFlags()&flags))
continue;
modeldata->RenderStreams(streamflags, false);
CModelDefPtr mdldef = modeldata->GetModel()->GetModelDef();
u8* base = modeldata->m_DynamicArray.Bind();
size_t stride = modeldata->m_DynamicArray.GetStride();
glVertexPointer(3, GL_FLOAT, stride,
base + modeldata->m_Position.offset);
if (streamflags & STREAM_COLOR)
glColorPointer(3, modeldata->m_Color.type, stride,
base + modeldata->m_Color.offset);
// render the lot
size_t numFaces=mdldef->GetNumFaces();
glDrawRangeElements(GL_TRIANGLES, 0, mdldef->GetNumVertices(),
numFaces*3, GL_UNSIGNED_SHORT, modeldata->m_Indices);
// bump stats
g_Renderer.m_Stats.m_DrawCalls++;
g_Renderer.m_Stats.m_ModelTris+=numFaces;
}
}
}
+3 -2
View File
@@ -87,12 +87,13 @@ VertexArrayIterator<CVector4D> VertexArray::Attribute::GetIterator<CVector4D>()
}
template<>
VertexArrayIterator<float[]> VertexArray::Attribute::GetIterator<float[]>() const
VertexArrayIterator<float[2]> VertexArray::Attribute::GetIterator<float[2]>() const
{
debug_assert(vertexArray);
debug_assert(type == GL_FLOAT);
debug_assert(elems >= 2);
return vertexArray->MakeIterator<float[]>(this);
return vertexArray->MakeIterator<float[2]>(this);
}
template<>