|
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 |
|
20 VertexBuffer11::VertexBuffer11(rx::Renderer11 *const renderer) : mRenderer(renderer) |
|
21 { |
|
22 mBuffer = NULL; |
|
23 mBufferSize = 0; |
|
24 mDynamicUsage = false; |
|
25 } |
|
26 |
|
27 VertexBuffer11::~VertexBuffer11() |
|
28 { |
|
29 if (mBuffer) |
|
30 { |
|
31 mBuffer->Release(); |
|
32 mBuffer = NULL; |
|
33 } |
|
34 } |
|
35 |
|
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 |
|
70 VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer) |
|
71 { |
|
72 ASSERT(HAS_DYNAMIC_TYPE(VertexBuffer11*, vetexBuffer)); |
|
73 return static_cast<VertexBuffer11*>(vetexBuffer); |
|
74 } |
|
75 |
|
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 |
|
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 |
|
155 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 |
|
192 bool VertexBuffer11::requiresConversion(const gl::VertexAttribute &attrib) const |
|
193 { |
|
194 return !getVertexConversion(attrib).identity; |
|
195 } |
|
196 |
|
197 unsigned int VertexBuffer11::getBufferSize() const |
|
198 { |
|
199 return mBufferSize; |
|
200 } |
|
201 |
|
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 |
|
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 |
|
239 unsigned int VertexBuffer11::getVertexSize(const gl::VertexAttribute &attrib) const |
|
240 { |
|
241 return getVertexConversion(attrib).outputElementSize; |
|
242 } |
|
243 |
|
244 DXGI_FORMAT VertexBuffer11::getDXGIFormat(const gl::VertexAttribute &attrib) const |
|
245 { |
|
246 return getVertexConversion(attrib).dxgiFormat; |
|
247 } |
|
248 |
|
249 ID3D11Buffer *VertexBuffer11::getBuffer() const |
|
250 { |
|
251 return mBuffer; |
|
252 } |
|
253 |
|
254 template <typename T, unsigned int componentCount, bool widen, bool normalized> |
|
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> |
|
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> |
|
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 |
|
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 } |