1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
|
#include "VertexBuffer.h"
#include "../Profiling/FrameStats.h"
VertexBuffer::VertexBuffer(int vbSize, int ibSize, VertexBufferType type)
{
m_VB = GPU::ClaimBuffer(vbSize, GL_STATIC_DRAW);
m_IB = GPU::ClaimBuffer(ibSize, GL_STATIC_DRAW);
}
VertexBuffer::~VertexBuffer()
{
GPU::ReleaseBuffer(m_VB);
GPU::ReleaseBuffer(m_IB);
}
// GetChunk
// <fill>
// FlushChunk
// DrawChunk
void VertexBuffer::GetChunk(uint sizePerVert, uint sizePerIndex, int maxVerts, int maxIndices, EPrimitive primitive, void **out_vb, void **out_ib)
{
m_SizePerVertex = sizePerVert;
uint vbufferSize = sizePerVert * maxVerts;
uint ibufferSize = sizePerIndex * maxIndices;
GLenum usage = GL_STATIC_DRAW;
m_VB->Restore(vbufferSize, usage);
m_IB->Restore(ibufferSize, usage);
const GLenum access = GL_MAP_WRITE_BIT | GL_MAP_INVALIDATE_BUFFER_BIT | GL_MAP_FLUSH_EXPLICIT_BIT;
*out_vb = m_VB->MapRange(0, vbufferSize, access);
*out_ib = m_IB->MapRange(0, ibufferSize, access);
m_Primitive = primitive;
WipeGLError();
}
void VertexBuffer::FlushChunk(int actualVerts, int actualIndices)
{
int actualVBufferSize = m_SizePerVertex * actualVerts;
int actualIBufferSize = VertexLayout::GetDefaultIndexSize() * actualIndices;
m_CurIndexCount = actualIndices;
m_VB->FlushMapedRange(0, actualVBufferSize);
m_IB->FlushMapedRange(0, actualIBufferSize);
m_VB->UnMap();
m_IB->UnMap();
WipeGLError();
}
void VertexBuffer::Draw(CustomVertexLayout& layout)
{
const byte* basepointer = 0;
const GLuint buffer = m_VB->GetHandle();
FillCustomVertexLayout(layout);
VertexLayout::SetupCustomVertexLayout(layout);
layout.RestorePointer();
const void* indexPtr = 0;
CheckGLError(
throw GLException(error);
);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_IB->GetHandle());
CheckGLError(
throw GLException(error);
);
GLenum indexFormat = VertexLayout::GetDefaultIndexFormat();
switch (m_Primitive)
{
case Primitive_Triangle:
glDrawElements(GL_TRIANGLES, m_CurIndexCount, indexFormat, indexPtr);
g_FrameStats.AddDrawCall();
g_FrameStats.AddTrianglesCount(m_CurIndexCount / 3);
break;
case Primitive_Line:
glDrawElements(GL_LINE, m_CurIndexCount, indexFormat, indexPtr);
g_FrameStats.AddDrawCall();
break;
case Primitive_Point:
glDrawElements(GL_POINT, m_CurIndexCount, indexFormat, indexPtr);
g_FrameStats.AddDrawCall();
break;
}
CheckGLError(
throw GLException(error);
);
glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, 0);
}
void VertexBuffer::FillCustomVertexLayout(CustomVertexLayout& dst)
{
const byte* basepointer = 0;
const GLuint buffer = m_VB->GetHandle();
dst.buffer = buffer;
for (int i = 0; i < dst.attributes.size(); ++i)
{
int offset = dst.attributes[i].startOffset;
dst.attributes[i].pointer = basepointer + offset;
}
}
|