mirror of
https://gitea.wildfiregames.com/0ad/0ad.git
synced 2026-09-21 20:06:40 +00:00
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:
@@ -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;
|
||||
|
||||
@@ -35,5 +35,7 @@ struct SColor4ub
|
||||
u8 A;
|
||||
};
|
||||
|
||||
extern u32 (*ConvertRGBColorTo4ub)(const RGBColor& src);
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
+29
-1
@@ -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
|
||||
//
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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<>
|
||||
|
||||
Reference in New Issue
Block a user