1 #include "precompiled.h"
2 //
3 // Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
4 // Use of this source code is governed by a BSD-style license that can be
5 // found in the LICENSE file.
6 //
7
8 // VertexBuffer11.cpp: Defines the D3D11 VertexBuffer implementation.
9
10 #include "libGLESv2/renderer/VertexBuffer11.h"
11 #include "libGLESv2/renderer/BufferStorage.h"
12
13 #include "libGLESv2/Buffer.h"
14 #include "libGLESv2/renderer/Renderer11.h"
15 #include "libGLESv2/Context.h"
16
17 namespace rx
18 {
19
VertexBuffer11(rx::Renderer11 * const renderer)20 VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer)
21 {
22 mBuffer = NULL;
23 mBufferSize = 0;
24 mDynamicUsage = false;
25 }
26
~VertexBuffer11()27 VertexBuffer11::~VertexBuffer11()
28 {
29 if (mBuffer)
30 {
31 mBuffer->Release();
32 mBuffer = NULL;
33 }
34 }
35
initialize(unsigned int size,bool dynamicUsage)36 bool VertexBuffer11::initialize(unsigned int size, bool dynamicUsage)
37 {
38 if (mBuffer)
39 {
40 mBuffer->Release();
41 mBuffer = NULL;
42 }
43
44 updateSerial();
45
46 if (size > 0)
47 {
48 ID3D11Device* dxDevice = mRenderer->getDevice();
49
50 D3D11_BUFFER_DESC bufferDesc;
51 bufferDesc.ByteWidth = size;
52 bufferDesc.Usage = D3D11_USAGE_DYNAMIC;
53 bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
54 bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
55 bufferDesc.MiscFlags = 0;
56 bufferDesc.StructureByteStride = 0;
57
58 HRESULT result = dxDevice->CreateBuffer(&bufferDesc, NULL, &mBuffer);
59 if (FAILED(result))
60 {
61 return false;
62 }
63 }
64
65 mBufferSize = size;
66 mDynamicUsage = dynamicUsage;
67 return true;
68 }
69
makeVertexBuffer11(VertexBuffer * vetexBuffer)70 VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
71 {
72 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer));
73 return static_cast<VertexBuffer11*>(vetexBuffer);
74 }
75
storeVertexAttributes(const gl::VertexAttribute & attrib,GLint start,GLsizei count,GLsizei instances,unsigned int offset)76 bool VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, GLint start, GLsizei count,
77 GLsizei instances, unsigned int offset)
78 {
79 if (mBuffer)
80 {
81 gl::Buffer *buffer = attrib.mBoundBuffer.get();
82
83 int inputStride = attrib.stride();
84 const VertexConverter &converter = getVertexConversion(attrib);
85
86 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
87
88 D3D11_MAPPED_SUBRESOURCE mappedResource;
89 HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
90 if (FAILED(result))
91 {
92 ERR("Vertex buffer map failed with error 0x%08x", result);
93 return false;
94 }
95
96 char* output = reinterpret_cast<char*>(mappedResource.pData) + offset;
97
98 const char *input = NULL;
99 if (buffer)
100 {
101 BufferStorage *storage = buffer->getStorage();
102 input = static_cast<const char*>(storage->getData()) + static_cast<int>(attrib.mOffset);
103 }
104 else
105 {
106 input = static_cast<const char*>(attrib.mPointer);
107 }
108
109 if (instances == 0 || attrib.mDivisor == 0)
110 {
111 input += inputStride * start;
112 }
113
114 converter.conversionFunc(input, inputStride, count, output);
115
116 dxContext->Unmap(mBuffer, 0);
117
118 return true;
119 }
120 else
121 {
122 ERR("Vertex buffer not initialized.");
123 return false;
124 }
125 }
126
storeRawData(const void * data,unsigned int size,unsigned int offset)127 bool VertexBuffer11::storeRawData(const void* data, unsigned int size, unsigned int offset)
128 {
129 if (mBuffer)
130 {
131 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
132
133 D3D11_MAPPED_SUBRESOURCE mappedResource;
134 HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
135 if (FAILED(result))
136 {
137 ERR("Vertex buffer map failed with error 0x%08x", result);
138 return false;
139 }
140
141 char* bufferData = static_cast<char*>(mappedResource.pData);
142 memcpy(bufferData + offset, data, size);
143
144 dxContext->Unmap(mBuffer, 0);
145
146 return true;
147 }
148 else
149 {
150 ERR("Vertex buffer not initialized.");
151 return false;
152 }
153 }
154
getSpaceRequired(const gl::VertexAttribute & attrib,GLsizei count,GLsizei instances,unsigned int * outSpaceRequired) const155 bool VertexBuffer11::getSpaceRequired(const gl::VertexAttribute &attrib, GLsizei count,
156 GLsizei instances, unsigned int *outSpaceRequired) const
157 {
158 unsigned int elementSize = getVertexConversion(attrib).outputElementSize;
159
160 unsigned int elementCount = 0;
161 if (instances == 0 || attrib.mDivisor == 0)
162 {
163 elementCount = count;
164 }
165 else
166 {
167 if (static_cast<unsigned int>(instances) < std::numeric_limits<unsigned int>::max() - (attrib.mDivisor - 1))
168 {
169 // Round up
170 elementCount = (static_cast<unsigned int>(instances) + (attrib.mDivisor - 1)) / attrib.mDivisor;
171 }
172 else
173 {
174 elementCount = instances / attrib.mDivisor;
175 }
176 }
177
178 if (elementSize <= std::numeric_limits<unsigned int>::max() / elementCount)
179 {
180 if (outSpaceRequired)
181 {
182 *outSpaceRequired = elementSize * elementCount;
183 }
184 return true;
185 }
186 else
187 {
188 return false;
189 }
190 }
191
requiresConversion(const gl::VertexAttribute & attrib) const192 bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const
193 {
194 return !getVertexConversion(attrib).identity;
195 }
196
getBufferSize() const197 unsigned int VertexBuffer11::getBufferSize() const
198 {
199 return mBufferSize;
200 }
201
setBufferSize(unsigned int size)202 bool VertexBuffer11::setBufferSize(unsigned int size)
203 {
204 if (size > mBufferSize)
205 {
206 return initialize(size, mDynamicUsage);
207 }
208 else
209 {
210 return true;
211 }
212 }
213
discard()214 bool VertexBuffer11::discard()
215 {
216 if (mBuffer)
217 {
218 ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
219
220 D3D11_MAPPED_SUBRESOURCE mappedResource;
221 HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_DISCARD, 0, &mappedResource);
222 if (FAILED(result))
223 {
224 ERR("Vertex buffer map failed with error 0x%08x", result);
225 return false;
226 }
227
228 dxContext->Unmap(mBuffer, 0);
229
230 return true;
231 }
232 else
233 {
234 ERR("Vertex buffer not initialized.");
235 return false;
236 }
237 }
238
getVertexSize(const gl::VertexAttribute & attrib) const239 unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const
240 {
241 return getVertexConversion(attrib).outputElementSize;
242 }
243
getDXGIFormat(const gl::VertexAttribute & attrib) const244 DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const
245 {
246 return getVertexConversion(attrib).dxgiFormat;
247 }
248
getBuffer() const249 ID3D11Buffer *VertexBuffer11::getBuffer() const
250 {
251 return mBuffer;
252 }
253
254 template <typename T, unsigned int componentCount, bool widen, bool normalized>
copyVertexData(const void * input,unsigned int stride,unsigned int count,void * output)255 static void copyVertexData(const void *input, unsigned int stride, unsigned int count, void *output)
256 {
257 unsigned int attribSize = sizeof(T) * componentCount;
258
259 if (attribSize == stride && !widen)
260 {
261 memcpy(output, input, count * attribSize);
262 }
263 else
264 {
265 unsigned int outputStride = widen ? 4 : componentCount;
266 T defaultVal = normalized ? std::numeric_limits<T>::max() : T(1);
267
268 for (unsigned int i = 0; i < count; i++)
269 {
270 const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + i * stride);
271 T *offsetOutput = reinterpret_cast<T*>(output) + i * outputStride;
272
273 for (unsigned int j = 0; j < componentCount; j++)
274 {
275 offsetOutput[j] = offsetInput[j];
276 }
277
278 if (widen)
279 {
280 offsetOutput[3] = defaultVal;
281 }
282 }
283 }
284 }
285
286 template <unsigned int componentCount>
copyFixedVertexData(const void * input,unsigned int stride,unsigned int count,void * output)287 static void copyFixedVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
288 {
289 static const float divisor = 1.0f / (1 << 16);
290
291 for (unsigned int i = 0; i < count; i++)
292 {
293 const GLfixed* offsetInput = reinterpret_cast<const GLfixed*>(reinterpret_cast<const char*>(input) + stride * i);
294 float* offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
295
296 for (unsigned int j = 0; j < componentCount; j++)
297 {
298 offsetOutput[j] = static_cast<float>(offsetInput[j]) * divisor;
299 }
300 }
301 }
302
303 template <typename T, unsigned int componentCount, bool normalized>
copyToFloatVertexData(const void * input,unsigned int stride,unsigned int count,void * output)304 static void copyToFloatVertexData(const void* input, unsigned int stride, unsigned int count, void* output)
305 {
306 typedef std::numeric_limits<T> NL;
307
308 for (unsigned int i = 0; i < count; i++)
309 {
310 const T *offsetInput = reinterpret_cast<const T*>(reinterpret_cast<const char*>(input) + stride * i);
311 float *offsetOutput = reinterpret_cast<float*>(output) + i * componentCount;
312
313 for (unsigned int j = 0; j < componentCount; j++)
314 {
315 if (normalized)
316 {
317 if (NL::is_signed)
318 {
319 const float divisor = 1.0f / (2 * static_cast<float>(NL::max()) + 1);
320 offsetOutput[j] = (2 * static_cast<float>(offsetInput[j]) + 1) * divisor;
321 }
322 else
323 {
324 offsetOutput[j] = static_cast<float>(offsetInput[j]) / NL::max();
325 }
326 }
327 else
328 {
329 offsetOutput[j] = static_cast<float>(offsetInput[j]);
330 }
331 }
332 }
333 }
334
335 const VertexBuffer11::VertexConverter VertexBuffer11::mPossibleTranslations[NUM_GL_VERTEX_ATTRIB_TYPES][2][4] =
336 {
337 { // GL_BYTE
338 { // unnormalized
339 { ©ToFloatVertexData<GLbyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
340 { ©ToFloatVertexData<GLbyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
341 { ©ToFloatVertexData<GLbyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
342 { ©ToFloatVertexData<GLbyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
343 },
344 { // normalized
345 { ©VertexData<GLbyte, 1, false, true>, true, DXGI_FORMAT_R8_SNORM, 1 },
346 { ©VertexData<GLbyte, 2, false, true>, true, DXGI_FORMAT_R8G8_SNORM, 2 },
347 { ©VertexData<GLbyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
348 { ©VertexData<GLbyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
349 },
350 },
351 { // GL_UNSIGNED_BYTE
352 { // unnormalized
353 { ©ToFloatVertexData<GLubyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
354 { ©ToFloatVertexData<GLubyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
355 { ©ToFloatVertexData<GLubyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
356 { ©ToFloatVertexData<GLubyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
357 },
358 { // normalized
359 { ©VertexData<GLubyte, 1, false, true>, true, DXGI_FORMAT_R8_UNORM, 1 },
360 { ©VertexData<GLubyte, 2, false, true>, true, DXGI_FORMAT_R8G8_UNORM, 2 },
361 { ©VertexData<GLubyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
362 { ©VertexData<GLubyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
363 },
364 },
365 { // GL_SHORT
366 { // unnormalized
367 { ©ToFloatVertexData<GLshort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
368 { ©ToFloatVertexData<GLshort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
369 { ©ToFloatVertexData<GLshort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
370 { ©ToFloatVertexData<GLshort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
371 },
372 { // normalized
373 { ©VertexData<GLshort, 1, false, true>, true, DXGI_FORMAT_R16_SNORM, 2 },
374 { ©VertexData<GLshort, 2, false, true>, true, DXGI_FORMAT_R16G16_SNORM, 4 },
375 { ©VertexData<GLshort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
376 { ©VertexData<GLshort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
377 },
378 },
379 { // GL_UNSIGNED_SHORT
380 { // unnormalized
381 { ©ToFloatVertexData<GLushort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
382 { ©ToFloatVertexData<GLushort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
383 { ©ToFloatVertexData<GLushort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
384 { ©ToFloatVertexData<GLushort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
385 },
386 { // normalized
387 { ©VertexData<GLushort, 1, false, true>, true, DXGI_FORMAT_R16_UNORM, 2 },
388 { ©VertexData<GLushort, 2, false, true>, true, DXGI_FORMAT_R16G16_UNORM, 4 },
389 { ©VertexData<GLushort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
390 { ©VertexData<GLushort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
391 },
392 },
393 { // GL_FIXED
394 { // unnormalized
395 { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
396 { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
397 { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
398 { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
399 },
400 { // normalized
401 { ©FixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
402 { ©FixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
403 { ©FixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
404 { ©FixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
405 },
406 },
407 { // GL_FLOAT
408 { // unnormalized
409 { ©VertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
410 { ©VertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
411 { ©VertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
412 { ©VertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
413 },
414 { // normalized
415 { ©VertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
416 { ©VertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
417 { ©VertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
418 { ©VertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
419 },
420 },
421 };
422
getVertexConversion(const gl::VertexAttribute & attribute)423 const VertexBuffer11::VertexConverter &VertexBuffer11::getVertexConversion(const gl::VertexAttribute &attribute)
424 {
425 unsigned int typeIndex = 0;
426 switch (attribute.mType)
427 {
428 case GL_BYTE: typeIndex = 0; break;
429 case GL_UNSIGNED_BYTE: typeIndex = 1; break;
430 case GL_SHORT: typeIndex = 2; break;
431 case GL_UNSIGNED_SHORT: typeIndex = 3; break;
432 case GL_FIXED: typeIndex = 4; break;
433 case GL_FLOAT: typeIndex = 5; break;
434 default: UNREACHABLE(); break;
435 }
436
437 return mPossibleTranslations[typeIndex][attribute.mNormalized ? 1 : 0][attribute.mSize - 1];
438 }
439
440 }
441