• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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             { &copyToFloatVertexData<GLbyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
340             { &copyToFloatVertexData<GLbyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
341             { &copyToFloatVertexData<GLbyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
342             { &copyToFloatVertexData<GLbyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
343         },
344         { // normalized
345             { &copyVertexData<GLbyte, 1, false, true>, true, DXGI_FORMAT_R8_SNORM, 1 },
346             { &copyVertexData<GLbyte, 2, false, true>, true, DXGI_FORMAT_R8G8_SNORM, 2 },
347             { &copyVertexData<GLbyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
348             { &copyVertexData<GLbyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_SNORM, 4 },
349         },
350     },
351     { // GL_UNSIGNED_BYTE
352         { // unnormalized
353             { &copyToFloatVertexData<GLubyte, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
354             { &copyToFloatVertexData<GLubyte, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
355             { &copyToFloatVertexData<GLubyte, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
356             { &copyToFloatVertexData<GLubyte, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
357         },
358         { // normalized
359             { &copyVertexData<GLubyte, 1, false, true>, true, DXGI_FORMAT_R8_UNORM, 1 },
360             { &copyVertexData<GLubyte, 2, false, true>, true, DXGI_FORMAT_R8G8_UNORM, 2 },
361             { &copyVertexData<GLubyte, 3, true, true>, false, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
362             { &copyVertexData<GLubyte, 4, false, true>, true, DXGI_FORMAT_R8G8B8A8_UNORM, 4 },
363         },
364     },
365     { // GL_SHORT
366         { // unnormalized
367             { &copyToFloatVertexData<GLshort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
368             { &copyToFloatVertexData<GLshort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
369             { &copyToFloatVertexData<GLshort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
370             { &copyToFloatVertexData<GLshort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
371         },
372         { // normalized
373             { &copyVertexData<GLshort, 1, false, true>, true, DXGI_FORMAT_R16_SNORM, 2 },
374             { &copyVertexData<GLshort, 2, false, true>, true, DXGI_FORMAT_R16G16_SNORM, 4 },
375             { &copyVertexData<GLshort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
376             { &copyVertexData<GLshort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_SNORM, 8 },
377         },
378     },
379     { // GL_UNSIGNED_SHORT
380         { // unnormalized
381             { &copyToFloatVertexData<GLushort, 1, false>, false, DXGI_FORMAT_R32_FLOAT, 4 },
382             { &copyToFloatVertexData<GLushort, 2, false>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
383             { &copyToFloatVertexData<GLushort, 3, false>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
384             { &copyToFloatVertexData<GLushort, 4, false>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
385         },
386         { // normalized
387             { &copyVertexData<GLushort, 1, false, true>, true, DXGI_FORMAT_R16_UNORM, 2 },
388             { &copyVertexData<GLushort, 2, false, true>, true, DXGI_FORMAT_R16G16_UNORM, 4 },
389             { &copyVertexData<GLushort, 3, true, true>, false, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
390             { &copyVertexData<GLushort, 4, false, true>, true, DXGI_FORMAT_R16G16B16A16_UNORM, 8 },
391         },
392     },
393     { // GL_FIXED
394         { // unnormalized
395             { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
396             { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
397             { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
398             { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
399         },
400         { // normalized
401             { &copyFixedVertexData<1>, false, DXGI_FORMAT_R32_FLOAT, 4 },
402             { &copyFixedVertexData<2>, false, DXGI_FORMAT_R32G32_FLOAT, 8 },
403             { &copyFixedVertexData<3>, false, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
404             { &copyFixedVertexData<4>, false, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
405         },
406     },
407     { // GL_FLOAT
408         { // unnormalized
409             { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
410             { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
411             { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
412             { &copyVertexData<GLfloat, 4, false, false>, true, DXGI_FORMAT_R32G32B32A32_FLOAT, 16 },
413         },
414         { // normalized
415             { &copyVertexData<GLfloat, 1, false, false>, true, DXGI_FORMAT_R32_FLOAT, 4 },
416             { &copyVertexData<GLfloat, 2, false, false>, true, DXGI_FORMAT_R32G32_FLOAT, 8 },
417             { &copyVertexData<GLfloat, 3, false, false>, true, DXGI_FORMAT_R32G32B32_FLOAT, 12 },
418             { &copyVertexData<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