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
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
|
#ifndef VBO_GLES30_H
#define VBO_GLES30_H
#include "Runtime/Shaders/VBO.h"
#include "Runtime/GfxDevice/ChannelAssigns.h"
#include "DataBuffersGLES30.h"
#include "IncludesGLES30.h"
#include <map>
enum AttribLocationGLES30
{
kGLES3AttribLocationPosition = 0,
kGLES3AttribLocationColor = 1,
kGLES3AttribLocationNormal = 2,
kGLES3AttribLocationTexCoord0 = 3,
kGLES3AttribLocationTexCoord1 = 4,
kGLES3AttribLocationTexCoord2 = 5,
kGLES3AttribLocationTexCoord3 = 6,
kGLES3AttribLocationTexCoord4 = 7,
kGLES3AttribLocationTexCoord5 = 8,
kGLES3AttribLocationTexCoord6 = 9,
kGLES3AttribLocationTexCoord7 = 10,
kGLES3MaxVertexAttribs, //!< Although implementations may support more, this limits VertexArrayInfoGLES30 to a reasonable value.
};
struct VertexInputInfoGLES30
{
const void* pointer; //!< Pointer or offset.
UInt8 componentType; //!< Component type - of type VertexChannelFormat.
UInt8 numComponents; //!< Number of components.
UInt16 stride; //!< Attribute stride.
// Following parameters come from outside:
// normalize: Deduced based on location and type.
// buffer: Comes from VertexArrayInfoGLES30
VertexInputInfoGLES30 (void)
: pointer (0)
, componentType (0)
, numComponents (0)
, stride (0)
{
}
VertexInputInfoGLES30 (const void* pointer_, VertexChannelFormat componentType_, int numComponents_, UInt32 stride_)
: pointer (pointer_)
, componentType ((UInt8)componentType_)
, numComponents ((UInt8)numComponents_)
, stride ((UInt16)stride_)
{
// Check overflows.
Assert((VertexChannelFormat)componentType == componentType_ &&
(int)numComponents == numComponents_ &&
(UInt32)stride == stride_);
}
};
struct VertexArrayInfoGLES30
{
UInt32 enabledArrays; //!< Bitmask of enabled arrays.
UInt32 buffers[kGLES3MaxVertexAttribs];
VertexInputInfoGLES30 arrays[kGLES3MaxVertexAttribs];
VertexArrayInfoGLES30 (void)
: enabledArrays(0)
{
}
};
// Setup vertex array state when no VAO is bound.
void SetupDefaultVertexArrayStateGLES30 (const VertexArrayInfoGLES30& info);
// Invalidate default VA input cache. Call this if you mess up with VA bindings or state gets lost otherwise.
void InvalidateVertexInputCacheGLES30();
struct VertexArrayInfoGLES30;
class VertexArrayObjectGLES30;
struct VAOCacheKeyGLES30
{
UInt32 bufferIndices; //!< 4 indices with 8 bits each
ChannelAssigns channels;
inline VAOCacheKeyGLES30 (const ChannelAssigns& channels, UInt32 bufNdx0, UInt32 bufNdx1, UInt32 bufNdx2, UInt32 bufNdx3)
: bufferIndices ((bufNdx0 << 24) | (bufNdx1 << 16) | (bufNdx2 << 8) | bufNdx3)
, channels (channels)
{
Assert((bufNdx0 & ~0xff) == 0 &&
(bufNdx1 & ~0xff) == 0 &&
(bufNdx2 & ~0xff) == 0 &&
(bufNdx3 & ~0xff) == 0);
}
inline VAOCacheKeyGLES30 (void)
: bufferIndices (~0u)
, channels ()
{
}
inline bool operator== (const VAOCacheKeyGLES30& other) const
{
return bufferIndices == other.bufferIndices && channels == other.channels;
}
};
// Cache key must be changed if stream count changes.
typedef char vaoCacheStreamCountAssert[kMaxVertexStreams == 4 ? 1 : -1];
// VAO cache for single VBO. Can not be shared between VBOs. Cache must be cleared
// if layout or any buffer in VAO is changed.
// Linear search is used since VAO cache is very small and most static VBOs should find
// match in first slot(s) anyway.
class VAOCacheGLES30
{
public:
VAOCacheGLES30 (void);
~VAOCacheGLES30 (void);
const VertexArrayObjectGLES30* Find (const VAOCacheKeyGLES30& key) const;
void Insert (const VAOCacheKeyGLES30& key, VertexArrayObjectGLES30* vao);
bool IsFull (void) const;
void Clear (void);
public:
VAOCacheGLES30 (const VAOCacheGLES30&); // Not allowed!
VAOCacheGLES30& operator= (const VAOCacheGLES30&); // Not allowed!
enum
{
kCacheSize = 8
};
struct Entry
{
VAOCacheKeyGLES30 key;
VertexArrayObjectGLES30* vao;
inline Entry (void) : vao(0) {}
};
Entry m_Entries[kCacheSize];
int m_NextEntryNdx;
};
class GLES3VBO : public VBO
{
public:
GLES3VBO (void);
virtual ~GLES3VBO (void);
virtual void UpdateVertexData (const VertexBufferData& buffer);
virtual void UpdateIndexData (const IndexBufferData& buffer);
virtual bool MapVertexStream (VertexStreamData& outData, unsigned stream);
virtual void UnmapVertexStream (unsigned stream);
virtual void Cleanup (void);
virtual void Recreate (void);
virtual bool IsVertexBufferLost (void) const;
virtual bool IsUsingSourceVertices (void) const;
virtual bool IsUsingSourceIndices (void) const;
virtual int GetRuntimeMemorySize (void) const;
virtual void DrawVBO (const ChannelAssigns& channels, UInt32 firstIndexByte, UInt32 indexCount,
GfxPrimitiveType topology, UInt32 firstVertex, UInt32 vertexCount);
virtual void DrawCustomIndexed (const ChannelAssigns& channels, void* indices, UInt32 indexCount,
GfxPrimitiveType topology, UInt32 vertexRangeBegin, UInt32 vertexRangeEnd, UInt32 drawVertexCount);
// This will return VBO for skinned (first) stream
UInt32 GetSkinningTargetVBO (void);
virtual void MarkBuffersLost() {}
private:
void ComputeVertexInputState (VertexArrayInfoGLES30& dst, const ChannelAssigns& channels);
void MarkBuffersRendered (const ChannelAssigns& channels);
DataBufferGLES30* GetCurrentBuffer (int streamNdx);
const VertexArrayObjectGLES30* TryGetVAO (const ChannelAssigns& channels);
void Draw (DataBufferGLES30* indexBuffer,
const ChannelAssigns& channels,
GfxPrimitiveType topology,
UInt32 indexCount,
UInt32 indexOffset,
UInt32 vertexCountForStats);
enum
{
kBufferSwapChainSize = kBufferUpdateMinAgeGLES30+1
};
struct Stream
{
UInt32 channelMask; //!< Shader channels which this stream contains.
UInt32 stride;
int curBufferNdx; //!< Current buffer in swap chain
DataBufferGLES30* buffers[kBufferSwapChainSize];
UInt8* cpuBuf; //!< CPU-side copy, used for Recreate() and emulating mapbuffer.
Stream (void) : channelMask(0), stride(0), curBufferNdx(0), cpuBuf(0) { memset(&buffers[0], 0, sizeof(buffers)); }
};
// Vertex data
Stream m_StreamBuffers[kMaxVertexStreams];
ChannelInfoArray m_Channels;
int m_VertexCount;
// Index data
std::vector<UInt16> m_Indices; //!< Index data. Copy is kept for emulating quad primitive type.
DataBufferGLES30* m_IndexBuffer;
VAOCacheGLES30 m_VAOCache;
};
class DynamicGLES3VBO : public DynamicVBO
{
public:
DynamicGLES3VBO (void);
~DynamicGLES3VBO (void);
virtual bool GetChunk (UInt32 shaderChannelMask, UInt32 maxVertices, UInt32 maxIndices, RenderMode renderMode, void** outVB, void** outIB);
virtual void ReleaseChunk (UInt32 actualVertices, UInt32 actualIndices);
virtual void DrawChunk (const ChannelAssigns& channels);
virtual void Recreate (void);
private:
void ComputeVertexInputState (VertexArrayInfoGLES30& info, const ChannelAssigns& channels);
void Cleanup (void);
DataBufferGLES30* GetQuadArrayIndexBuffer (int vertexCount);
enum
{
kDataBufferThreshold = 1024
};
std::vector<UInt8> m_CurVertexData;
std::vector<UInt16> m_CurIndexData;
DataBufferGLES30* m_CurVertexBuffer;
DataBufferGLES30* m_CurIndexBuffer;
RenderMode m_CurRenderMode;
UInt32 m_CurShaderChannelMask;
UInt32 m_CurStride;
UInt32 m_CurVertexCount;
UInt32 m_CurIndexCount;
DataBufferGLES30* m_QuadArrayIndexBuffer; //!< Used for kDrawQuads mode.
};
#endif
|