diff --git a/src/gpu/vertexbuffer.cpp b/src/gpu/vertexbuffer.cpp index 7797c403..54be30fc 100644 --- a/src/gpu/vertexbuffer.cpp +++ b/src/gpu/vertexbuffer.cpp @@ -15,25 +15,180 @@ #include "core.h" #include "lolgl.h" +#if defined _WIN32 && defined USE_D3D9 +# define FAR +# define NEAR +# include +#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(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 */ diff --git a/src/gpu/vertexbuffer.h b/src/gpu/vertexbuffer.h index 45debf65..b7038d56 100644 --- a/src/gpu/vertexbuffer.h +++ b/src/gpu/vertexbuffer.h @@ -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 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 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(int n, int index); +template<> +inline void VertexStreamBase::AddStream(int n, int usage) +{ + (void)usage; + m_streams[n].size = 0; +} template -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(0, s1); AddStream(1, s2); AddStream(2, s3); - AddStream(3, s4); AddStream(4, s5); AddStream(5, s6); - AddStream(6, s7); AddStream(7, s8); AddStream(8, s9); - AddStream(9, s10); AddStream(10, s11); AddStream(11, s12); + AddStream(0, u1); AddStream(1, u2); + AddStream(2, u3); AddStream(3, u4); + AddStream(4, u5); AddStream(5, u6); + AddStream(6, u7); AddStream(7, u8); + AddStream(8, u9); AddStream(9, u10); + AddStream(10, u11); AddStream(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 */ diff --git a/test/tutorial/tut01.cpp b/test/tutorial/tut01.cpp index 4ee38278..49080983 100644 --- a/test/tutorial/tut01.cpp +++ b/test/tutorial/tut01.cpp @@ -61,7 +61,6 @@ public: if (!m_ready) { - VertexBuffer vb(VertexDeclaration(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(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; diff --git a/test/tutorial/tut02.cpp b/test/tutorial/tut02.cpp index dc34bf8f..6499fff7 100644 --- a/test/tutorial/tut02.cpp +++ b/test/tutorial/tut02.cpp @@ -145,6 +145,9 @@ public: m_mvp = m_shader->GetUniformLocation("in_Matrix"); m_ready = true; + m_vdecl = + new VertexDeclaration(VertexStream(VertexUsage::Position), + VertexStream(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 diff --git a/test/tutorial/tut03.cpp b/test/tutorial/tut03.cpp index eeaad98a..8b2d1b5b 100644 --- a/test/tutorial/tut03.cpp +++ b/test/tutorial/tut03.cpp @@ -675,6 +675,9 @@ public: m_zoomuni = m_shader->GetUniformLocation("u_ZoomSettings"); m_ready = true; + m_vdecl = + new VertexDeclaration(VertexStream(VertexUsage::Position), + VertexStream(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;