Selaa lähdekoodia

gpu: refactor the vertex declaration code to allow several vertex streams.

legacy
Sam Hocevar sam 12 vuotta sitten
vanhempi
commit
2601c970a2
5 muutettua tiedostoa jossa 285 lisäystä ja 93 poistoa
  1. +162
    -7
      src/gpu/vertexbuffer.cpp
  2. +108
    -54
      src/gpu/vertexbuffer.h
  3. +5
    -10
      test/tutorial/tut01.cpp
  4. +5
    -11
      test/tutorial/tut02.cpp
  5. +5
    -11
      test/tutorial/tut03.cpp

+ 162
- 7
src/gpu/vertexbuffer.cpp Näytä tiedosto

@@ -15,25 +15,180 @@
#include "core.h"
#include "lolgl.h"

#if defined _WIN32 && defined USE_D3D9
# define FAR
# define NEAR
# include <d3d9.h>
#endif

using namespace std;

#if defined USE_D3D9
extern IDirect3DDevice9 *g_d3ddevice;
#elif defined _XBOX
extern D3DDevice *g_d3ddevice;
#endif

namespace lol
{

/* For some reason defining this in the .h leads to duplicate definitions
* between the executable and the static library. */
template<> void VertexBuffer::AddStream<void>(int n, int index)
VertexStreamBase const VertexStreamBase::Empty;
void VertexDeclaration::Initialize()
{
(void)index;
m_streams[n].size = 0;
#if defined _XBOX || defined USE_D3D9
static D3DVERTEXELEMENT9 const end_element[] = { D3DDECL_END() };
static D3DECLTYPE const X = D3DDECLTYPE_UNUSED;
static D3DECLTYPE const tlut[] =
{
D3DDECLTYPE_UNUSED,
X, D3DDECLTYPE_FLOAT16_2, X, D3DDECLTYPE_FLOAT16_4, /* half */
D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3,
D3DDECLTYPE_FLOAT4, /* float */
X, X, X, X, /* double */
X, X, X, X, /* int8_t */
X, X, X, D3DDECLTYPE_UBYTE4, /* uint8_t */
X, D3DDECLTYPE_SHORT2N, X, D3DDECLTYPE_SHORT4N, /* int16_t */
X, D3DDECLTYPE_USHORT2N, X, D3DDECLTYPE_USHORT4N, /* uint16_t */
X, X, X, X, /* int32_t */
X, X, X, X, /* int64_t */
};
static D3DDECLUSAGE const ulut[] =
{
D3DDECLUSAGE_POSITION,
D3DDECLUSAGE_BLENDWEIGHT,
D3DDECLUSAGE_BLENDINDICES,
D3DDECLUSAGE_NORMAL,
D3DDECLUSAGE_PSIZE,
D3DDECLUSAGE_TEXCOORD,
D3DDECLUSAGE_TANGENT,
D3DDECLUSAGE_BINORMAL,
D3DDECLUSAGE_TESSFACTOR,
D3DDECLUSAGE_POSITIONT,
D3DDECLUSAGE_COLOR,
D3DDECLUSAGE_FOG,
D3DDECLUSAGE_DEPTH,
D3DDECLUSAGE_SAMPLE,
};

D3DVERTEXELEMENT9 elements[12 + 1];
int nstreams = 0;
while (m_streams[nstreams].size)
{
elements[nstreams].Stream = m_streams[nstreams].index;
elements[nstreams].Offset = 0;
for (int i = 0; i < nstreams; i++)
elements[nstreams].Offset += m_streams[nstreams].size;

if (m_streams[nstreams].type >= 0
&& m_streams[nstreams].type < sizeof(tlut) / sizeof(*tlut))
elements[nstreams].Type = tlut[m_streams[nstreams].type];
else
elements[nstreams].Type = D3DDECLTYPE_UNUSED;

elements[nstreams].Method = D3DDECLMETHOD_DEFAULT;

if (m_streams[nstreams].usage >= 0
&& m_streams[nstreams].usage < sizeof(ulut) / sizeof(*ulut))
elements[nstreams].Type = ulut[m_streams[nstreams].usage];
else
elements[nstreams].Type = D3DDECLUSAGE_POSITION;

elements[nstreams].UsageIndex = 0;
for (int i = 0; i < nstreams; i++)
if (elements[i].Stream == elements[nstreams].Stream
&& elements[i].Usage == elements[nstreams].Usage)
elements[nstreams].UsageIndex++;

nstreams++;
}
elements[nstreams] = end_element[0];

# if defined USE_D3D9
IDirect3DVertexDeclaration9 *vdecl;
# elif defined _XBOX
D3DVertexDeclaration *vdecl;
# endif

g_d3ddevice->CreateVertexDeclaration(elements, &vdecl);

m_data = vdecl;
#else

#endif
}

void VertexBuffer::Initialize()
VertexDeclaration::~VertexDeclaration()
{
#if defined _XBOX || defined USE_D3D9
# if defined USE_D3D9
IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
# elif defined _XBOX
D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
# endif

vdecl->Release();
#else

#endif
}

void VertexDeclaration::Bind()
{
#if defined _XBOX || defined USE_D3D9
# if defined USE_D3D9
IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
# elif defined _XBOX
D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
# endif

g_d3ddevice->SetVertexDeclaration(vdecl);
#else

#endif
}

VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
VertexStreamBase const &s2,
VertexStreamBase const &s3,
VertexStreamBase const &s4,
VertexStreamBase const &s5,
VertexStreamBase const &s6,
VertexStreamBase const &s7,
VertexStreamBase const &s8,
VertexStreamBase const &s9,
VertexStreamBase const &s10,
VertexStreamBase const &s11,
VertexStreamBase const &s12) : m_count(0)
{
if (&s1 != &VertexStreamBase::Empty) AddStream(s1);
if (&s2 != &VertexStreamBase::Empty) AddStream(s2);
if (&s3 != &VertexStreamBase::Empty) AddStream(s3);
if (&s4 != &VertexStreamBase::Empty) AddStream(s4);
if (&s5 != &VertexStreamBase::Empty) AddStream(s5);
if (&s6 != &VertexStreamBase::Empty) AddStream(s6);
if (&s7 != &VertexStreamBase::Empty) AddStream(s7);
if (&s8 != &VertexStreamBase::Empty) AddStream(s8);
if (&s9 != &VertexStreamBase::Empty) AddStream(s9);
if (&s10 != &VertexStreamBase::Empty) AddStream(s10);
if (&s11 != &VertexStreamBase::Empty) AddStream(s11);
if (&s12 != &VertexStreamBase::Empty) AddStream(s12);
Initialize();
}

void VertexDeclaration::AddStream(VertexStreamBase const &s)
{
int index = m_count ? m_streams[m_count - 1].index + 1 : 0;

for (int i = 0; s.m_streams[i].size; i++)
{
m_streams[m_count].stream_type = s.m_streams[i].stream_type;
m_streams[m_count].usage = s.m_streams[i].usage;
m_streams[m_count].size = s.m_streams[i].size;
m_streams[m_count].index = index;
m_count++;
}
}

} /* namespace lol */


+ 108
- 54
src/gpu/vertexbuffer.h Näytä tiedosto

@@ -21,89 +21,143 @@
namespace lol
{

#if 0
VertexBuffer(0, LOL_TYPE_VEC2 | LOL_USAGE_TEXTURE(0),
LOL_TYPE_FLOAT | LOL_USAGE_POSITION(0),
1, LOL_TYPE_FLOAT | LOL_USAGE_TEXCOORD(0),
2, LOL_TYPE_FLOAT | LOL_USAGE_TEXCOORD(1));

VertexBuffer(VertexStream<vec2, LOL_USAGE_TEXTURE(0)
float, Texture(
#endif

class VertexBuffer
struct VertexUsage
{
public:
VertexBuffer(VertexBuffer const& that)
enum Value
{
memcpy(this, &that, sizeof(*this));

/* Now call the platform-specific initialisation code */
Initialize();
Position = 0,
BlendWeight,
BlendIndices,
Normal,
PSize,
TexCoord,
Tangent,
Binormal,
TessFactor,
PositionT,
Color,
Fog,
Depth,
Sample,
}
m_value;

~VertexBuffer() {}
inline VertexUsage(Value v) { m_value = v; }
inline operator Value() { return m_value; }
};

protected:
VertexBuffer() {}
class VertexStreamBase
{
friend class VertexDeclaration;

protected:
enum
{
VBO_TYPE_VOID = 0,
VBO_TYPE_FLOAT,
VBO_TYPE_VEC2,
VBO_TYPE_VEC3,
VBO_TYPE_VEC4,
VBO_TYPE_I16VEC4,
VBO_TYPE_U8VEC4,
Typevoid = 0,
Typehalf, Typef16vec2, Typef16vec3, Typef16vec4,
Typefloat, Typevec2, Typevec3, Typevec4,
Typedouble, Typef64vec2, Typef64vec3, Typef64vec4,
Typeuint8_t, Typeu8vec2, Typeu8vec3, Typeu8vec4,
Typeint8_t, Typei8vec2, Typei8vec3, Typei8vec4,
Typeuint16_t, Typeu16vec2, Typeu16vec3, Typeu16vec4,
Typeint16_t, Typei16vec2, Typei16vec3, Typei16vec4,
Typeuint32_t, Typeuvec2, Typeuvec3, Typeuvec4,
Typeint32_t, Typeivec2, Typeivec3, Typeivec4,
};

static uint8_t GetType(void *x) { (void)x; return VBO_TYPE_VOID; }
static uint8_t GetType(float *x) { (void)x; return VBO_TYPE_FLOAT; }
static uint8_t GetType(vec2 *x) { (void)x; return VBO_TYPE_VEC2; }
static uint8_t GetType(vec3 *x) { (void)x; return VBO_TYPE_VEC3; }
static uint8_t GetType(vec4 *x) { (void)x; return VBO_TYPE_VEC4; }
static uint8_t GetType(i16vec4 *x) { (void)x; return VBO_TYPE_I16VEC4; }
static uint8_t GetType(u8vec4 *x) { (void)x; return VBO_TYPE_U8VEC4; }

struct { uint8_t stream_type, index, size; } m_streams[12 + 1];

template<typename T> void AddStream(int n, int index)
#define LOL_TYPE(T) \
static uint8_t GetType(T *x) { (void)x; return Type##T; }

LOL_TYPE(void)
LOL_TYPE(half) LOL_TYPE(f16vec2) LOL_TYPE(f16vec3) LOL_TYPE(f16vec4)
LOL_TYPE(float) LOL_TYPE(vec2) LOL_TYPE(vec3) LOL_TYPE(vec4)
LOL_TYPE(double) LOL_TYPE(f64vec2) LOL_TYPE(f64vec3) LOL_TYPE(f64vec4)
LOL_TYPE(uint8_t) LOL_TYPE(u8vec2) LOL_TYPE(u8vec3) LOL_TYPE(u8vec4)
LOL_TYPE(int8_t) LOL_TYPE(i8vec2) LOL_TYPE(i8vec3) LOL_TYPE(i8vec4)
LOL_TYPE(uint16_t) LOL_TYPE(u16vec2) LOL_TYPE(u16vec3) LOL_TYPE(u16vec4)
LOL_TYPE(int16_t) LOL_TYPE(i16vec2) LOL_TYPE(i16vec3) LOL_TYPE(i16vec4)
LOL_TYPE(uint32_t) LOL_TYPE(uvec2) LOL_TYPE(uvec3) LOL_TYPE(uvec4)
LOL_TYPE(int32_t) LOL_TYPE(ivec2) LOL_TYPE(ivec3) LOL_TYPE(ivec4)
#undef LOL_TYPE

template<typename T> inline void AddStream(int n, int usage)
{
m_streams[n].stream_type = GetType((T *)NULL);
m_streams[n].index = index;
m_streams[n].usage = usage;
m_streams[n].size = sizeof(T);
}

VertexStreamBase() {}

private:
void Initialize();
struct { uint8_t stream_type, usage, size; } m_streams[12 + 1];

static VertexStreamBase const Empty;
};

template<> void VertexBuffer::AddStream<void>(int n, int index);
template<>
inline void VertexStreamBase::AddStream<void>(int n, int usage)
{
(void)usage;
m_streams[n].size = 0;
}

template<typename T1 = void, typename T2 = void, typename T3 = void,
typename T4 = void, typename T5 = void, typename T6 = void,
typename T7 = void, typename T8 = void, typename T9 = void,
typename T10 = void, typename T11 = void, typename T12 = void>
class VertexDeclaration : public VertexBuffer
class VertexStream : public VertexStreamBase
{
public:
/* Arguments are the stream index; default to zero */
VertexDeclaration(int s1 = 0, int s2 = 0, int s3 = 0,
int s4 = 0, int s5 = 0, int s6 = 0,
int s7 = 0, int s8 = 0, int s9 = 0,
int s10 = 0, int s11 = 0, int s12 = 0)
inline VertexStream(VertexUsage u1,
VertexUsage u2 = VertexUsage::Position,
VertexUsage u3 = VertexUsage::Position,
VertexUsage u4 = VertexUsage::Position,
VertexUsage u5 = VertexUsage::Position,
VertexUsage u6 = VertexUsage::Position,
VertexUsage u7 = VertexUsage::Position,
VertexUsage u8 = VertexUsage::Position,
VertexUsage u9 = VertexUsage::Position,
VertexUsage u10 = VertexUsage::Position,
VertexUsage u11 = VertexUsage::Position,
VertexUsage u12 = VertexUsage::Position)
{
for (int i = 0; i < 12 + 1; i++)
m_streams[i].stream_type = VBO_TYPE_VOID;

AddStream<T1>(0, s1); AddStream<T2>(1, s2); AddStream<T3>(2, s3);
AddStream<T4>(3, s4); AddStream<T5>(4, s5); AddStream<T6>(5, s6);
AddStream<T7>(6, s7); AddStream<T8>(7, s8); AddStream<T9>(8, s9);
AddStream<T10>(9, s10); AddStream<T11>(10, s11); AddStream<T12>(11, s12);
AddStream<T1>(0, u1); AddStream<T2>(1, u2);
AddStream<T3>(2, u3); AddStream<T4>(3, u4);
AddStream<T5>(4, u5); AddStream<T6>(5, u6);
AddStream<T7>(6, u7); AddStream<T8>(7, u8);
AddStream<T9>(8, u9); AddStream<T10>(9, u10);
AddStream<T11>(10, u11); AddStream<T12>(11, u12);
}
};

class VertexDeclaration
{
public:
VertexDeclaration(VertexStreamBase const &s1,
VertexStreamBase const &s2 = VertexStreamBase::Empty,
VertexStreamBase const &s3 = VertexStreamBase::Empty,
VertexStreamBase const &s4 = VertexStreamBase::Empty,
VertexStreamBase const &s5 = VertexStreamBase::Empty,
VertexStreamBase const &s6 = VertexStreamBase::Empty,
VertexStreamBase const &s7 = VertexStreamBase::Empty,
VertexStreamBase const &s8 = VertexStreamBase::Empty,
VertexStreamBase const &s9 = VertexStreamBase::Empty,
VertexStreamBase const &s10 = VertexStreamBase::Empty,
VertexStreamBase const &s11 = VertexStreamBase::Empty,
VertexStreamBase const &s12 = VertexStreamBase::Empty);
~VertexDeclaration();

void Bind();

private:
void Initialize();
void AddStream(VertexStreamBase const &);

struct { uint8_t stream_type, index, usage, size; } m_streams[12 + 1];
int m_count;

void *m_data;
};

} /* namespace lol */


+ 5
- 10
test/tutorial/tut01.cpp Näytä tiedosto

@@ -61,7 +61,6 @@ public:

if (!m_ready)
{
VertexBuffer vb(VertexDeclaration<vec2, float, ivec3>(0, 0, 1));



@@ -114,12 +113,9 @@ public:
#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ && !defined _XBOX && !defined USE_D3D9
/* Method 2: upload vertex information at each frame */
#elif defined _XBOX || defined USE_D3D9
D3DVERTEXELEMENT9 const elements[2] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
D3DDECL_END()
};
g_d3ddevice->CreateVertexDeclaration(elements, &m_vdecl);
m_vdecl =
new VertexDeclaration(VertexStream<vec2>(VertexUsage::Position));

if (FAILED(g_d3ddevice->CreateVertexBuffer(sizeof(m_vertices), D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &m_vbo, NULL)))
exit(0);

@@ -135,9 +131,9 @@ public:
}

m_shader->Bind();
m_vdecl->Bind();
#if defined _XBOX || defined USE_D3D9
g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
g_d3ddevice->SetVertexDeclaration(m_vdecl);
g_d3ddevice->SetStreamSource(0, m_vbo, 0, sizeof(*m_vertices));
#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__
glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
@@ -174,11 +170,10 @@ public:
private:
vec2 m_vertices[3];
Shader *m_shader;
VertexDeclaration *m_vdecl;
#if defined USE_D3D9
IDirect3DVertexDeclaration9 *m_vdecl;
IDirect3DVertexBuffer9 *m_vbo;
#elif defined _XBOX
D3DVertexDeclaration *m_vdecl;
D3DVertexBuffer *m_vbo;
#else
int m_attrib;


+ 5
- 11
test/tutorial/tut02.cpp Näytä tiedosto

@@ -145,6 +145,9 @@ public:
m_mvp = m_shader->GetUniformLocation("in_Matrix");
m_ready = true;

m_vdecl =
new VertexDeclaration(VertexStream<vec3>(VertexUsage::Position),
VertexStream<vec3>(VertexUsage::Color));
#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined __APPLE__ && !defined _XBOX && !defined USE_D3D9
/* Method 1: store vertex buffer on the GPU memory */
glGenBuffers(1, &m_vbo);
@@ -160,14 +163,6 @@ public:
glBufferData(GL_ELEMENT_ARRAY_BUFFER, sizeof(m_indices), m_indices,
GL_STATIC_DRAW);
#elif defined _XBOX || defined USE_D3D9
D3DVERTEXELEMENT9 const elements[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 1, 0, D3DDECLTYPE_FLOAT3, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 },
D3DDECL_END()
};
g_d3ddevice->CreateVertexDeclaration(elements, &m_vdecl);

if (FAILED(g_d3ddevice->CreateVertexBuffer(sizeof(m_vertices), D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &m_vbo, NULL)))
exit(0);

@@ -202,9 +197,9 @@ public:

m_shader->Bind();
m_shader->SetUniform(m_mvp, m_matrix);
m_vdecl->Bind();
#if defined _XBOX || defined USE_D3D9
g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
g_d3ddevice->SetVertexDeclaration(m_vdecl);
g_d3ddevice->SetStreamSource(0, m_vbo, 0, sizeof(*m_vertices));
g_d3ddevice->SetStreamSource(1, m_cbo, 0, sizeof(*m_colors));
g_d3ddevice->SetIndices(m_ibo);
@@ -242,12 +237,11 @@ private:
vec3 m_colors[8];
i16vec3 m_indices[12];
Shader *m_shader;
VertexDeclaration *m_vdecl;
#if defined USE_D3D9
IDirect3DVertexDeclaration9 *m_vdecl;
IDirect3DVertexBuffer9 *m_vbo, *m_cbo;
IDirect3DIndexBuffer9 *m_ibo;
#elif defined _XBOX
D3DVertexDeclaration *m_vdecl;
D3DVertexBuffer *m_vbo, *m_cbo;
D3DIndexBuffer *m_ibo;
#else


+ 5
- 11
test/tutorial/tut03.cpp Näytä tiedosto

@@ -675,6 +675,9 @@ public:
m_zoomuni = m_shader->GetUniformLocation("u_ZoomSettings");
m_ready = true;

m_vdecl =
new VertexDeclaration(VertexStream<vec2>(VertexUsage::Position),
VertexStream<vec2>(VertexUsage::TexCoord));
#if !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined _XBOX && !defined USE_D3D9
/* Method 1: store vertex buffer on the GPU memory */
glGenBuffers(1, &m_vbo);
@@ -688,14 +691,6 @@ public:
#elif !defined __CELLOS_LV2__ && !defined __ANDROID__ && !defined _XBOX && !defined USE_D3D9
/* Method 2: upload vertex information at each frame */
#elif defined _XBOX || defined USE_D3D9
D3DVERTEXELEMENT9 const elements[] =
{
{ 0, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 },
{ 1, 0, D3DDECLTYPE_FLOAT2, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 },
D3DDECL_END()
};
g_d3ddevice->CreateVertexDeclaration(elements, &m_vdecl);

if (FAILED(g_d3ddevice->CreateVertexBuffer(sizeof(vertices), D3DUSAGE_WRITEONLY, NULL, D3DPOOL_MANAGED, &m_vbo, NULL)))
exit(0);
vec2 *tmp1;
@@ -766,11 +761,11 @@ public:
m_shader->SetUniform(m_texeluni, m_texel_settings);
m_shader->SetUniform(m_screenuni, m_screen_settings);
m_shader->SetUniform(m_zoomuni, m_zoom_settings);
m_vdecl->Bind();
#if defined _XBOX || defined USE_D3D9
g_d3ddevice->SetTexture(0, m_tex);
//g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW);
g_d3ddevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE);
g_d3ddevice->SetVertexDeclaration(m_vdecl);
g_d3ddevice->SetStreamSource(0, m_vbo, 0, sizeof(*vertices));
g_d3ddevice->SetStreamSource(1, m_tbo, 0, sizeof(*texcoords));
#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
@@ -826,13 +821,12 @@ private:
f64vec2 m_texel2world;
u8vec4 *m_pixels, *m_tmppixels, *m_palette;
Shader *m_shader;
VertexDeclaration *m_vdecl;
#if defined USE_D3D9
IDirect3DTexture9 *m_tex;
IDirect3DVertexDeclaration9 *m_vdecl;
IDirect3DVertexBuffer9 *m_vbo, *m_tbo;
#elif defined _XBOX
D3DTexture *m_tex;
D3DVertexDeclaration *m_vdecl;
D3DVertexBuffer *m_vbo, *m_tbo;
#else
GLuint m_texid;


Ladataan…
Peruuta
Tallenna