source: trunk/src/gpu/vertexbuffer.cpp @ 1227

Last change on this file since 1227 was 1227, checked in by sam, 10 years ago

gpu: implement vertex buffer streams for Direct3D. OpenGL is missing for now.

File size: 9.7 KB
Line 
1//
2// Lol Engine
3//
4// Copyright: (c) 2010-2012 Sam Hocevar <sam@hocevar.net>
5//   This program is free software; you can redistribute it and/or
6//   modify it under the terms of the Do What The Fuck You Want To
7//   Public License, Version 2, as published by Sam Hocevar. See
8//   http://sam.zoy.org/projects/COPYING.WTFPL for more details.
9//
10
11#if defined HAVE_CONFIG_H
12#   include "config.h"
13#endif
14
15#include "core.h"
16#include "lolgl.h"
17
18#if defined _WIN32 && defined USE_D3D9
19#   define FAR
20#   define NEAR
21#   include <d3d9.h>
22#endif
23
24using namespace std;
25
26#if defined USE_D3D9
27extern IDirect3DDevice9 *g_d3ddevice;
28#elif defined _XBOX
29extern D3DDevice *g_d3ddevice;
30#endif
31
32namespace lol
33{
34
35//
36// The VertexBufferData class
37// --------------------------
38//
39
40class VertexBufferData
41{
42    friend class VertexBuffer;
43    friend class VertexDeclaration;
44
45#if defined USE_D3D9
46    IDirect3DVertexBuffer9 *m_vbo;
47#elif defined _XBOX
48    D3DVertexBuffer *m_vbo;
49#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
50    GLuint m_vbo;
51    uint8_t *m_memory;
52    size_t m_size;
53#endif
54};
55
56//
57// The VertexDeclaration class
58// ---------------------------
59//
60
61VertexStreamBase const VertexStreamBase::Empty;
62
63VertexDeclaration::VertexDeclaration(VertexStreamBase const &s1,
64                                     VertexStreamBase const &s2,
65                                     VertexStreamBase const &s3,
66                                     VertexStreamBase const &s4,
67                                     VertexStreamBase const &s5,
68                                     VertexStreamBase const &s6,
69                                     VertexStreamBase const &s7,
70                                     VertexStreamBase const &s8,
71                                     VertexStreamBase const &s9,
72                                     VertexStreamBase const &s10,
73                                     VertexStreamBase const &s11,
74                                     VertexStreamBase const &s12) : m_count(0)
75{
76    if (&s1 != &VertexStreamBase::Empty) AddStream(s1);
77    if (&s2 != &VertexStreamBase::Empty) AddStream(s2);
78    if (&s3 != &VertexStreamBase::Empty) AddStream(s3);
79    if (&s4 != &VertexStreamBase::Empty) AddStream(s4);
80    if (&s5 != &VertexStreamBase::Empty) AddStream(s5);
81    if (&s6 != &VertexStreamBase::Empty) AddStream(s6);
82    if (&s7 != &VertexStreamBase::Empty) AddStream(s7);
83    if (&s8 != &VertexStreamBase::Empty) AddStream(s8);
84    if (&s9 != &VertexStreamBase::Empty) AddStream(s9);
85    if (&s10 != &VertexStreamBase::Empty) AddStream(s10);
86    if (&s11 != &VertexStreamBase::Empty) AddStream(s11);
87    if (&s12 != &VertexStreamBase::Empty) AddStream(s12);
88    Initialize();
89}
90
91VertexDeclaration::~VertexDeclaration()
92{
93#if defined _XBOX || defined USE_D3D9
94#   if defined USE_D3D9
95    IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
96#   elif defined _XBOX
97    D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
98#   endif
99
100    vdecl->Release();
101#else
102
103#endif
104}
105
106void VertexDeclaration::Bind()
107{
108#if defined _XBOX || defined USE_D3D9
109#   if defined USE_D3D9
110    IDirect3DVertexDeclaration9 *vdecl = (IDirect3DVertexDeclaration9 *)m_data;
111#   elif defined _XBOX
112    D3DVertexDeclaration *vdecl = (D3DVertexDeclaration *)m_data;
113#   endif
114
115    g_d3ddevice->SetVertexDeclaration(vdecl);
116#else
117
118#endif
119}
120
121void VertexDeclaration::SetStream(VertexBuffer *vb, ShaderAttrib attr1,
122                                                    ShaderAttrib attr2,
123                                                    ShaderAttrib attr3,
124                                                    ShaderAttrib attr4,
125                                                    ShaderAttrib attr5,
126                                                    ShaderAttrib attr6,
127                                                    ShaderAttrib attr7,
128                                                    ShaderAttrib attr8,
129                                                    ShaderAttrib attr9,
130                                                    ShaderAttrib attr10,
131                                                    ShaderAttrib attr11,
132                                                    ShaderAttrib attr12)
133{
134#if defined _XBOX || defined USE_D3D9
135    /* Only the first item is required to know which stream this
136     * is about; the rest of the information is stored in the
137     * vertex declaration already. */
138    uint32_t usage = attr1.m_flags >> 16;
139    uint32_t index = attr1.m_flags & 0xffff;
140    int usage_index = 0, stream = -1, stride = 0;
141    for (int i = 0; i < m_count; i++)
142    {
143        if (m_streams[i].usage == usage)
144            if (usage_index++ == index)
145                stream = m_streams[i].index;
146        if (stream == m_streams[i].index)
147            stride += m_streams[i].size;
148    }
149
150    /* Now we know the stream index and the element stride */
151    /* FIXME: precompute most of the crap above! */
152    if (stream >= 0)
153        g_d3ddevice->SetStreamSource(stream, vb->m_data->m_vbo, 0, stride);
154#else
155    glBindBuffer(GL_ARRAY_BUFFER, vb);
156    ShaderAttrib l[12] = { attr1, attr2, attr3, attr4, attr5, attr6,
157                           attr7, attr8, attr9, attr10, attr11, attr12 };
158    for (int i = 0; i < 12 && l[i].m_flags != 0xffffffff; i++)
159    {
160        uint32_t usage = l[i].m_flags >> 16;
161        uint32_t index = l[i].m_flags & 0xffff;
162    glEnableVertexAttribArray((GLint)attr.flags);
163    /* FIXME: Hardcoded!! Where to get that from? */
164    glVertexAttribPointer((GLint)attr.flags, 3, GL_FLOAT, GL_FALSE, 0, 0);
165#endif
166}
167
168void VertexDeclaration::Initialize()
169{
170#if defined _XBOX || defined USE_D3D9
171    static D3DVERTEXELEMENT9 const end_element[] = { D3DDECL_END() };
172    static D3DDECLTYPE const X = D3DDECLTYPE_UNUSED;
173    static D3DDECLTYPE const tlut[] =
174    {
175        D3DDECLTYPE_UNUSED,
176        X, D3DDECLTYPE_FLOAT16_2, X, D3DDECLTYPE_FLOAT16_4, /* half */
177        D3DDECLTYPE_FLOAT1, D3DDECLTYPE_FLOAT2, D3DDECLTYPE_FLOAT3,
178            D3DDECLTYPE_FLOAT4, /* float */
179        X, X, X, X, /* double */
180        X, X, X, X, /* int8_t */
181        X, X, X, D3DDECLTYPE_UBYTE4, /* uint8_t */
182        X, D3DDECLTYPE_SHORT2N, X, D3DDECLTYPE_SHORT4N, /* int16_t */
183        X, D3DDECLTYPE_USHORT2N, X, D3DDECLTYPE_USHORT4N, /* uint16_t */
184        X, X, X, X, /* int32_t */
185        X, X, X, X, /* int64_t */
186    };
187    static D3DDECLUSAGE const ulut[] =
188    {
189        D3DDECLUSAGE_POSITION,
190        D3DDECLUSAGE_BLENDWEIGHT,
191        D3DDECLUSAGE_BLENDINDICES,
192        D3DDECLUSAGE_NORMAL,
193        D3DDECLUSAGE_PSIZE,
194        D3DDECLUSAGE_TEXCOORD,
195        D3DDECLUSAGE_TANGENT,
196        D3DDECLUSAGE_BINORMAL,
197        D3DDECLUSAGE_TESSFACTOR,
198        D3DDECLUSAGE_POSITIONT,
199        D3DDECLUSAGE_COLOR,
200        D3DDECLUSAGE_FOG,
201        D3DDECLUSAGE_DEPTH,
202        D3DDECLUSAGE_SAMPLE,
203    };
204
205    D3DVERTEXELEMENT9 elements[12 + 1];
206    for (int n = 0; n < m_count; n++)
207    {
208        elements[n].Stream = m_streams[n].index;
209        elements[n].Offset = 0;
210        for (int i = 0; i < n; i++)
211            elements[n].Offset += m_streams[n].size;
212
213        if (m_streams[n].stream_type >= 0
214             && m_streams[n].stream_type < sizeof(tlut) / sizeof(*tlut))
215            elements[n].Type = tlut[m_streams[n].stream_type];
216        else
217            elements[n].Type = D3DDECLTYPE_UNUSED;
218
219        elements[n].Method = D3DDECLMETHOD_DEFAULT;
220
221        if (m_streams[n].usage >= 0
222             && m_streams[n].usage < sizeof(ulut) / sizeof(*ulut))
223            elements[n].Usage = ulut[m_streams[n].usage];
224        else
225            elements[n].Usage = D3DDECLUSAGE_POSITION;
226
227        elements[n].UsageIndex = 0;
228        for (int i = 0; i < n; i++)
229            if (elements[i].Stream == elements[n].Stream
230                 && elements[i].Usage == elements[n].Usage)
231                elements[n].UsageIndex++;
232    }
233    elements[m_count] = end_element[0];
234
235#   if defined USE_D3D9
236    IDirect3DVertexDeclaration9 *vdecl;
237#   elif defined _XBOX
238    D3DVertexDeclaration *vdecl;
239#   endif
240
241    g_d3ddevice->CreateVertexDeclaration(elements, &vdecl);
242
243    m_data = vdecl;
244#else
245
246#endif
247}
248
249void VertexDeclaration::AddStream(VertexStreamBase const &s)
250{
251    int index = m_count ? m_streams[m_count - 1].index + 1 : 0;
252
253    for (int i = 0; s.m_streams[i].size; i++)
254    {
255        m_streams[m_count].stream_type = s.m_streams[i].stream_type;
256        m_streams[m_count].usage = s.m_streams[i].usage;
257        m_streams[m_count].size = s.m_streams[i].size;
258        m_streams[m_count].index = index;
259        m_count++;
260    }
261}
262
263//
264// The VertexBuffer class
265// ----------------------
266//
267
268VertexBuffer::VertexBuffer(size_t size)
269  : m_data(new VertexBufferData)
270{
271#if defined USE_D3D9 || defined _XBOX
272    g_d3ddevice->CreateVertexBuffer(size, D3DUSAGE_WRITEONLY, NULL,
273                                    D3DPOOL_MANAGED, &m_data->m_vbo, NULL);
274    new uint8_t[size];
275#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
276    glGenBuffers(1, &m_data->m_vbo);
277    m_data->m_memory = new uint8_t[size];
278    m_data->m_size = size;
279#endif
280}
281
282VertexBuffer::~VertexBuffer()
283{
284#if defined USE_D3D9 || defined _XBOX
285    m_data->m_vbo->Release();
286#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
287    glDeleteBuffers(1, &m_data->m_vbo);
288    delete[] m_data->m_memory;
289#endif
290}
291
292void *VertexBuffer::Lock(size_t offset, size_t size)
293{
294#if defined USE_D3D9 || defined _XBOX
295    void *ret;
296    if (FAILED(m_data->m_vbo->Lock(offset, size, (void **)&ret, 0)))
297        exit(0);
298    return ret;
299#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
300    return m_data->m_memory + offset;
301#endif
302}
303
304void VertexBuffer::Unlock()
305{
306#if defined USE_D3D9 || defined _XBOX
307    m_data->m_vbo->Unlock();
308#elif !defined __CELLOS_LV2__ && !defined __ANDROID__
309    glBindBuffer(GL_ARRAY_BUFFER, m_vbo);
310    glBufferData(GL_ARRAY_BUFFER, m_data->m_size, m_data->m_memory,
311                 GL_STATIC_DRAW);
312#endif
313}
314
315} /* namespace lol */
316
Note: See TracBrowser for help on using the repository browser.