Upstream version 9.37.197.0
[platform/framework/web/crosswalk.git] / src / third_party / angle / src / libGLESv2 / renderer / d3d11 / BufferStorage11.cpp
1 #include "precompiled.h"
2 //
3 // Copyright (c) 2013-2014 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 // BufferStorage11.cpp Defines the BufferStorage11 class.
9
10 #include "libGLESv2/renderer/d3d11/BufferStorage11.h"
11 #include "libGLESv2/main.h"
12 #include "libGLESv2/renderer/d3d11/Renderer11.h"
13 #include "libGLESv2/renderer/d3d11/formatutils11.h"
14 #include "libGLESv2/Buffer.h"
15
16 namespace rx
17 {
18
19 PackPixelsParams::PackPixelsParams()
20   : format(GL_NONE),
21     type(GL_NONE),
22     outputPitch(0),
23     packBuffer(NULL),
24     offset(0)
25 {}
26
27 PackPixelsParams::PackPixelsParams(const gl::Rectangle &areaIn, GLenum formatIn, GLenum typeIn, GLuint outputPitchIn,
28                                    const gl::PixelPackState &packIn, ptrdiff_t offsetIn)
29   : area(areaIn),
30     format(formatIn),
31     type(typeIn),
32     outputPitch(outputPitchIn),
33     packBuffer(packIn.pixelBuffer.get()),
34     pack(packIn.alignment, packIn.reverseRowOrder),
35     offset(offsetIn)
36 {}
37
38 namespace gl_d3d11
39 {
40
41 D3D11_MAP GetD3DMapTypeFromBits(GLbitfield access)
42 {
43     bool readBit = ((access & GL_MAP_READ_BIT) != 0);
44     bool writeBit = ((access & GL_MAP_WRITE_BIT) != 0);
45
46     ASSERT(readBit || writeBit);
47
48     // Note : we ignore the discard bit, because in D3D11, staging buffers
49     //  don't accept the map-discard flag (discard only works for DYNAMIC usage)
50
51     if (readBit && !writeBit)
52     {
53         return D3D11_MAP_READ;
54     }
55     else if (writeBit && !readBit)
56     {
57         return D3D11_MAP_WRITE;
58     }
59     else if (writeBit && readBit)
60     {
61         return D3D11_MAP_READ_WRITE;
62     }
63     else
64     {
65         UNREACHABLE();
66         return D3D11_MAP_READ;
67     }
68 }
69
70 }
71
72 // Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points
73 // - vertex/transform feedback buffers
74 // - index buffers
75 // - pixel unpack buffers
76 // - uniform buffers
77 class BufferStorage11::TypedBufferStorage11
78 {
79   public:
80     virtual ~TypedBufferStorage11() {}
81
82     DataRevision getDataRevision() const { return mRevision; }
83     BufferUsage getUsage() const { return mUsage; }
84     size_t getSize() const { return mBufferSize; }
85     bool isMappable() const { return (mUsage == BUFFER_USAGE_STAGING || mUsage == BUFFER_USAGE_PIXEL_PACK); }
86
87     void setDataRevision(DataRevision rev) { mRevision = rev; }
88
89     virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
90                                  size_t size, size_t destOffset) = 0;
91     virtual bool resize(size_t size, bool preserveData) = 0;
92
93     virtual void *map(GLbitfield access) = 0;
94     virtual void unmap() = 0;
95
96   protected:
97     TypedBufferStorage11(Renderer11 *renderer, BufferUsage usage);
98
99     Renderer11 *mRenderer;
100     DataRevision mRevision;
101     const BufferUsage mUsage;
102     size_t mBufferSize;
103 };
104
105 // A native buffer storage represents an underlying D3D11 buffer for a particular
106 // type of storage.
107 class BufferStorage11::NativeBuffer11 : public BufferStorage11::TypedBufferStorage11
108 {
109   public:
110     NativeBuffer11(Renderer11 *renderer, BufferUsage usage);
111     ~NativeBuffer11();
112
113     ID3D11Buffer *getNativeBuffer() const { return mNativeBuffer; }
114
115     virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
116                                  size_t size, size_t destOffset);
117     virtual bool resize(size_t size, bool preserveData);
118
119     virtual void *map(GLbitfield access);
120     virtual void unmap();
121
122   private:
123     ID3D11Buffer *mNativeBuffer;
124
125     static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
126 };
127
128 // Pack storage represents internal storage for pack buffers. We implement pack buffers
129 // as CPU memory, tied to a staging texture, for asynchronous texture readback.
130 class BufferStorage11::PackStorage11 : public BufferStorage11::TypedBufferStorage11
131 {
132   public:
133     PackStorage11(Renderer11 *renderer);
134     ~PackStorage11();
135
136     virtual bool copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
137                                  size_t size, size_t destOffset);
138     virtual bool resize(size_t size, bool preserveData);
139
140     virtual void *map(GLbitfield access);
141     virtual void unmap();
142
143     void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params);
144
145   private:
146
147     void flushQueuedPackCommand();
148
149     ID3D11Texture2D *mStagingTexture;
150     DXGI_FORMAT mTextureFormat;
151     gl::Extents mTextureSize;
152     std::vector<unsigned char> mMemoryBuffer;
153     PackPixelsParams *mQueuedPackCommand;
154     PackPixelsParams mPackParams;
155     bool mDataModified;
156 };
157
158 BufferStorage11::BufferStorage11(Renderer11 *renderer)
159     : mRenderer(renderer),
160       mMappedStorage(NULL),
161       mResolvedDataRevision(0),
162       mReadUsageCount(0),
163       mSize(0)
164 {
165 }
166
167 BufferStorage11::~BufferStorage11()
168 {
169     for (auto it = mTypedBuffers.begin(); it != mTypedBuffers.end(); it++)
170     {
171         SafeDelete(it->second);
172     }
173 }
174
175 BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
176 {
177     ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
178     return static_cast<BufferStorage11*>(bufferStorage);
179 }
180
181 void *BufferStorage11::getData()
182 {
183     NativeBuffer11 *stagingBuffer = getStagingBuffer();
184
185     if (!stagingBuffer)
186     {
187         // Out-of-memory
188         return NULL;
189     }
190
191     if (stagingBuffer->getDataRevision() > mResolvedDataRevision)
192     {
193         if (stagingBuffer->getSize() > mResolvedData.size())
194         {
195             mResolvedData.resize(stagingBuffer->getSize());
196         }
197
198         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
199
200         D3D11_MAPPED_SUBRESOURCE mappedResource;
201         HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_READ, 0, &mappedResource);
202         if (FAILED(result))
203         {
204             return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
205         }
206
207         memcpy(mResolvedData.data(), mappedResource.pData, stagingBuffer->getSize());
208
209         context->Unmap(stagingBuffer->getNativeBuffer(), 0);
210
211         mResolvedDataRevision = stagingBuffer->getDataRevision();
212     }
213
214     mReadUsageCount = 0;
215
216     return mResolvedData.data();
217 }
218
219 void BufferStorage11::setData(const void* data, size_t size, size_t offset)
220 {
221     size_t requiredSize = size + offset;
222     mSize = std::max(mSize, requiredSize);
223
224     if (data)
225     {
226         NativeBuffer11 *stagingBuffer = getStagingBuffer();
227
228         if (!stagingBuffer)
229         {
230             // Out-of-memory
231             return;
232         }
233
234         // Explicitly resize the staging buffer, preserving data if the new data will not
235         // completely fill the buffer
236         if (stagingBuffer->getSize() < requiredSize)
237         {
238             bool preserveData = (offset > 0);
239             if (!stagingBuffer->resize(requiredSize, preserveData))
240             {
241                 // Out-of-memory
242                 return;
243             }
244         }
245
246         ID3D11DeviceContext *context = mRenderer->getDeviceContext();
247
248         D3D11_MAPPED_SUBRESOURCE mappedResource;
249         HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource);
250         if (FAILED(result))
251         {
252             return gl::error(GL_OUT_OF_MEMORY);
253         }
254
255         unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
256         memcpy(offsetBufferPointer, data, size);
257
258         context->Unmap(stagingBuffer->getNativeBuffer(), 0);
259
260         stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
261     }
262 }
263
264 void BufferStorage11::copyData(BufferStorage* sourceStorage, size_t size, size_t sourceOffset, size_t destOffset)
265 {
266     BufferStorage11* sourceStorage11 = makeBufferStorage11(sourceStorage);
267     if (sourceStorage11)
268     {
269         TypedBufferStorage11 *dest = getLatestStorage();
270         if (!dest)
271         {
272             dest = getStagingBuffer();
273         }
274
275         TypedBufferStorage11 *source = sourceStorage11->getLatestStorage();
276         if (source && dest)
277         {
278             // If copying to/from a pixel pack buffer, we must have a staging or
279             // pack buffer partner, because other native buffers can't be mapped
280             if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable())
281             {
282                 source = sourceStorage11->getStagingBuffer();
283             }
284             else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable())
285             {
286                 dest = getStagingBuffer();
287             }
288
289             dest->copyFromStorage(source, sourceOffset, size, destOffset);
290             dest->setDataRevision(dest->getDataRevision() + 1);
291         }
292
293         mSize = std::max<size_t>(mSize, destOffset + size);
294     }
295 }
296
297 void BufferStorage11::clear()
298 {
299     mSize = 0;
300     mResolvedDataRevision = 0;
301 }
302
303 void BufferStorage11::markTransformFeedbackUsage()
304 {
305     TypedBufferStorage11 *transformFeedbackStorage = getStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
306
307     if (transformFeedbackStorage)
308     {
309         transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
310     }
311 }
312
313 size_t BufferStorage11::getSize() const
314 {
315     return mSize;
316 }
317
318 bool BufferStorage11::supportsDirectBinding() const
319 {
320     return true;
321 }
322
323 void BufferStorage11::markBufferUsage()
324 {
325     mReadUsageCount++;
326
327     const unsigned int usageLimit = 5;
328
329     if (mReadUsageCount > usageLimit && mResolvedData.size() > 0)
330     {
331         mResolvedData.resize(0);
332         mResolvedDataRevision = 0;
333     }
334 }
335
336 ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage)
337 {
338     markBufferUsage();
339
340     TypedBufferStorage11 *typedBuffer = getStorage(usage);
341
342     if (!typedBuffer)
343     {
344         // Storage out-of-memory
345         return NULL;
346     }
347
348     ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, typedBuffer));
349
350     return static_cast<NativeBuffer11*>(typedBuffer)->getNativeBuffer();
351 }
352
353 ID3D11ShaderResourceView *BufferStorage11::getSRV(DXGI_FORMAT srvFormat)
354 {
355     TypedBufferStorage11 *storage = getStorage(BUFFER_USAGE_PIXEL_UNPACK);
356
357     if (!storage)
358     {
359         // Storage out-of-memory
360         return NULL;
361     }
362
363     ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, storage));
364     ID3D11Buffer *buffer = static_cast<NativeBuffer11*>(storage)->getNativeBuffer();
365
366     auto bufferSRVIt = mBufferResourceViews.find(srvFormat);
367
368     if (bufferSRVIt != mBufferResourceViews.end())
369     {
370         if (bufferSRVIt->second.first == buffer)
371         {
372             return bufferSRVIt->second.second;
373         }
374         else
375         {
376             // The underlying buffer has changed since the SRV was created: recreate the SRV.
377             SafeRelease(bufferSRVIt->second.second);
378         }
379     }
380
381     ID3D11Device *device = mRenderer->getDevice();
382     ID3D11ShaderResourceView *bufferSRV = NULL;
383
384     D3D11_SHADER_RESOURCE_VIEW_DESC bufferSRVDesc;
385     bufferSRVDesc.Buffer.ElementOffset = 0;
386     bufferSRVDesc.Buffer.ElementWidth = mSize / d3d11::GetFormatPixelBytes(srvFormat);
387     bufferSRVDesc.ViewDimension = D3D11_SRV_DIMENSION_BUFFER;
388     bufferSRVDesc.Format = srvFormat;
389
390     HRESULT result = device->CreateShaderResourceView(buffer, &bufferSRVDesc, &bufferSRV);
391     UNUSED_ASSERTION_VARIABLE(result);
392     ASSERT(SUCCEEDED(result));
393
394     mBufferResourceViews[srvFormat] = BufferSRVPair(buffer, bufferSRV);
395
396     return bufferSRV;
397 }
398
399 void BufferStorage11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams &params)
400 {
401     PackStorage11 *packStorage = getPackStorage();
402
403     TypedBufferStorage11 *latestStorage = getLatestStorage();
404
405     if (packStorage)
406     {
407         packStorage->packPixels(srcTexture, srcSubresource, params);
408         packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
409     }
410 }
411
412 BufferStorage11::TypedBufferStorage11 *BufferStorage11::getStorage(BufferUsage usage)
413 {
414     TypedBufferStorage11 *directBuffer = NULL;
415     auto directBufferIt = mTypedBuffers.find(usage);
416     if (directBufferIt != mTypedBuffers.end())
417     {
418         directBuffer = directBufferIt->second;
419     }
420
421     if (!directBuffer)
422     {
423         if (usage == BUFFER_USAGE_PIXEL_PACK)
424         {
425             directBuffer = new PackStorage11(mRenderer);
426         }
427         else
428         {
429             // buffer is not allocated, create it
430             directBuffer = new NativeBuffer11(mRenderer, usage);
431         }
432
433         mTypedBuffers.insert(std::make_pair(usage, directBuffer));
434     }
435
436     // resize buffer
437     if (directBuffer->getSize() < mSize)
438     {
439         if (!directBuffer->resize(mSize, true))
440         {
441             // Out of memory error
442             return NULL;
443         }
444     }
445
446     TypedBufferStorage11 *latestBuffer = getLatestStorage();
447     if (latestBuffer && latestBuffer->getDataRevision() > directBuffer->getDataRevision())
448     {
449         // if copying from a pack buffer to a non-staging native buffer, we must first
450         // copy through the staging buffer, because other native buffers can't be mapped
451         if (latestBuffer->getUsage() == BUFFER_USAGE_PIXEL_PACK && !directBuffer->isMappable())
452         {
453             NativeBuffer11 *stagingBuffer = getStagingBuffer();
454
455             stagingBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0);
456             directBuffer->setDataRevision(latestBuffer->getDataRevision());
457
458             latestBuffer = stagingBuffer;
459         }
460
461         // if copyFromStorage returns true, the D3D buffer has been recreated
462         // and we should update our serial
463         if (directBuffer->copyFromStorage(latestBuffer, 0, latestBuffer->getSize(), 0))
464         {
465             updateSerial();
466         }
467         directBuffer->setDataRevision(latestBuffer->getDataRevision());
468     }
469
470     return directBuffer;
471 }
472
473 BufferStorage11::TypedBufferStorage11 *BufferStorage11::getLatestStorage() const
474 {
475     // Even though we iterate over all the direct buffers, it is expected that only
476     // 1 or 2 will be present.
477     TypedBufferStorage11 *latestStorage = NULL;
478     DataRevision latestRevision = 0;
479     for (auto it = mTypedBuffers.begin(); it != mTypedBuffers.end(); it++)
480     {
481         TypedBufferStorage11 *storage = it->second;
482         if (!latestStorage || storage->getDataRevision() > latestRevision)
483         {
484             latestStorage = storage;
485             latestRevision = storage->getDataRevision();
486         }
487     }
488
489     return latestStorage;
490 }
491
492 bool BufferStorage11::isMapped() const
493 {
494     return mMappedStorage != NULL;
495 }
496
497 void *BufferStorage11::map(GLbitfield access)
498 {
499     ASSERT(!mMappedStorage);
500
501     TypedBufferStorage11 *latestStorage = getLatestStorage();
502     ASSERT(latestStorage);
503
504     if (latestStorage->getUsage() == BUFFER_USAGE_PIXEL_PACK ||
505         latestStorage->getUsage() == BUFFER_USAGE_STAGING)
506     {
507         mMappedStorage = latestStorage;
508     }
509     else
510     {
511         mMappedStorage = getStagingBuffer();
512     }
513
514     if (!mMappedStorage)
515     {
516         // Out-of-memory
517         return NULL;
518     }
519
520     return mMappedStorage->map(access);
521 }
522
523 void BufferStorage11::unmap()
524 {
525     ASSERT(mMappedStorage);
526     mMappedStorage->unmap();
527     mMappedStorage = NULL;
528 }
529
530 BufferStorage11::NativeBuffer11 *BufferStorage11::getStagingBuffer()
531 {
532     TypedBufferStorage11 *stagingStorage = getStorage(BUFFER_USAGE_STAGING);
533
534     if (!stagingStorage)
535     {
536         // Out-of-memory
537         return NULL;
538     }
539
540     ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, stagingStorage));
541     return static_cast<NativeBuffer11*>(stagingStorage);
542 }
543
544 BufferStorage11::PackStorage11 *BufferStorage11::getPackStorage()
545 {
546     TypedBufferStorage11 *packStorage = getStorage(BUFFER_USAGE_PIXEL_PACK);
547
548     if (!packStorage)
549     {
550         // Out-of-memory
551         return NULL;
552     }
553
554     ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, packStorage));
555     return static_cast<PackStorage11*>(packStorage);
556 }
557
558 BufferStorage11::TypedBufferStorage11::TypedBufferStorage11(Renderer11 *renderer, BufferUsage usage)
559     : mRenderer(renderer),
560       mUsage(usage),
561       mRevision(0),
562       mBufferSize(0)
563 {
564 }
565
566 BufferStorage11::NativeBuffer11::NativeBuffer11(Renderer11 *renderer, BufferUsage usage)
567     : TypedBufferStorage11(renderer, usage),
568       mNativeBuffer(NULL)
569 {
570 }
571
572 BufferStorage11::NativeBuffer11::~NativeBuffer11()
573 {
574     SafeRelease(mNativeBuffer);
575 }
576
577 // Returns true if it recreates the direct buffer
578 bool BufferStorage11::NativeBuffer11::copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
579                                                       size_t size, size_t destOffset)
580 {
581     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
582
583     size_t requiredSize = sourceOffset + size;
584     bool createBuffer = !mNativeBuffer || mBufferSize < requiredSize;
585
586     // (Re)initialize D3D buffer if needed
587     if (createBuffer)
588     {
589         bool preserveData = (destOffset > 0);
590         resize(source->getSize(), preserveData);
591     }
592
593     if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK)
594     {
595         ASSERT(HAS_DYNAMIC_TYPE(PackStorage11*, source));
596
597         unsigned char *sourcePointer = static_cast<unsigned char *>(source->map(GL_MAP_READ_BIT)) + sourceOffset;
598
599         D3D11_MAPPED_SUBRESOURCE mappedResource;
600         HRESULT hr = context->Map(mNativeBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
601         UNUSED_ASSERTION_VARIABLE(hr);
602         ASSERT(SUCCEEDED(hr));
603
604         unsigned char *destPointer = static_cast<unsigned char *>(mappedResource.pData) + destOffset;
605
606         // Offset bounds are validated at the API layer
607         ASSERT(sourceOffset + size <= destOffset + mBufferSize);
608         memcpy(destPointer, sourcePointer, size);
609     }
610     else
611     {
612         ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
613
614         D3D11_BOX srcBox;
615         srcBox.left = sourceOffset;
616         srcBox.right = sourceOffset + size;
617         srcBox.top = 0;
618         srcBox.bottom = 1;
619         srcBox.front = 0;
620         srcBox.back = 1;
621
622         ASSERT(HAS_DYNAMIC_TYPE(NativeBuffer11*, source));
623         ID3D11Buffer *sourceBuffer = static_cast<NativeBuffer11*>(source)->getNativeBuffer();
624
625         context->CopySubresourceRegion(mNativeBuffer, 0, destOffset, 0, 0, sourceBuffer, 0, &srcBox);
626     }
627
628     return createBuffer;
629 }
630
631 bool BufferStorage11::NativeBuffer11::resize(size_t size, bool preserveData)
632 {
633     ID3D11Device *device = mRenderer->getDevice();
634     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
635
636     D3D11_BUFFER_DESC bufferDesc;
637     fillBufferDesc(&bufferDesc, mRenderer, mUsage, size);
638
639     ID3D11Buffer *newBuffer;
640     HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
641
642     if (FAILED(result))
643     {
644         return gl::error(GL_OUT_OF_MEMORY, false);
645     }
646
647     if (mNativeBuffer && preserveData)
648     {
649         // We don't call resize if the buffer is big enough already.
650         ASSERT(mBufferSize <= size);
651
652         D3D11_BOX srcBox;
653         srcBox.left = 0;
654         srcBox.right = mBufferSize;
655         srcBox.top = 0;
656         srcBox.bottom = 1;
657         srcBox.front = 0;
658         srcBox.back = 1;
659
660         context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mNativeBuffer, 0, &srcBox);
661     }
662
663     // No longer need the old buffer
664     SafeRelease(mNativeBuffer);
665     mNativeBuffer = newBuffer;
666
667     mBufferSize = bufferDesc.ByteWidth;
668
669     return true;
670 }
671
672 void BufferStorage11::NativeBuffer11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer,
673                                                      BufferUsage usage, unsigned int bufferSize)
674 {
675     bufferDesc->ByteWidth = bufferSize;
676     bufferDesc->MiscFlags = 0;
677     bufferDesc->StructureByteStride = 0;
678
679     switch (usage)
680     {
681       case BUFFER_USAGE_STAGING:
682         bufferDesc->Usage = D3D11_USAGE_STAGING;
683         bufferDesc->BindFlags = 0;
684         bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
685         break;
686
687       case BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK:
688         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
689         bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_STREAM_OUTPUT;
690         bufferDesc->CPUAccessFlags = 0;
691         break;
692
693       case BUFFER_USAGE_INDEX:
694         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
695         bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER;
696         bufferDesc->CPUAccessFlags = 0;
697         break;
698
699       case BUFFER_USAGE_PIXEL_UNPACK:
700         bufferDesc->Usage = D3D11_USAGE_DEFAULT;
701         bufferDesc->BindFlags = D3D11_BIND_SHADER_RESOURCE;
702         bufferDesc->CPUAccessFlags = 0;
703         break;
704
705       case BUFFER_USAGE_UNIFORM:
706         bufferDesc->Usage = D3D11_USAGE_DYNAMIC;
707         bufferDesc->BindFlags = D3D11_BIND_CONSTANT_BUFFER;
708         bufferDesc->CPUAccessFlags = D3D11_CPU_ACCESS_WRITE;
709
710         // Constant buffers must be of a limited size, and aligned to 16 byte boundaries
711         // For our purposes we ignore any buffer data past the maximum constant buffer size
712         bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
713         bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize());
714         break;
715
716     default:
717         UNREACHABLE();
718     }
719 }
720
721 void *BufferStorage11::NativeBuffer11::map(GLbitfield access)
722 {
723     ASSERT(mUsage == BUFFER_USAGE_STAGING);
724
725     D3D11_MAPPED_SUBRESOURCE mappedResource;
726     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
727     D3D11_MAP d3dMapType = gl_d3d11::GetD3DMapTypeFromBits(access);
728     UINT d3dMapFlag = ((access & GL_MAP_UNSYNCHRONIZED_BIT) != 0 ? D3D11_MAP_FLAG_DO_NOT_WAIT : 0);
729
730     HRESULT result = context->Map(mNativeBuffer, 0, d3dMapType, d3dMapFlag, &mappedResource);
731     UNUSED_ASSERTION_VARIABLE(result);
732     ASSERT(SUCCEEDED(result));
733
734     return mappedResource.pData;
735 }
736
737 void BufferStorage11::NativeBuffer11::unmap()
738 {
739     ASSERT(mUsage == BUFFER_USAGE_STAGING);
740     ID3D11DeviceContext *context = mRenderer->getDeviceContext();
741     context->Unmap(mNativeBuffer, 0);
742 }
743
744 BufferStorage11::PackStorage11::PackStorage11(Renderer11 *renderer)
745     : TypedBufferStorage11(renderer, BUFFER_USAGE_PIXEL_PACK),
746       mStagingTexture(NULL),
747       mTextureFormat(DXGI_FORMAT_UNKNOWN),
748       mQueuedPackCommand(NULL),
749       mDataModified(false)
750 {
751 }
752
753 BufferStorage11::PackStorage11::~PackStorage11()
754 {
755     SafeRelease(mStagingTexture);
756     SafeDelete(mQueuedPackCommand);
757 }
758
759 bool BufferStorage11::PackStorage11::copyFromStorage(TypedBufferStorage11 *source, size_t sourceOffset,
760                                                      size_t size, size_t destOffset)
761 {
762     UNIMPLEMENTED();
763     return false;
764 }
765
766 bool BufferStorage11::PackStorage11::resize(size_t size, bool preserveData)
767 {
768     if (size != mBufferSize)
769     {
770         mMemoryBuffer.resize(size, 0);
771         mBufferSize = size;
772     }
773
774     return true;
775 }
776
777 void *BufferStorage11::PackStorage11::map(GLbitfield access)
778 {
779     // TODO: fast path
780     //  We might be able to optimize out one or more memcpy calls by detecting when
781     //  and if D3D packs the staging texture memory identically to how we would fill
782     //  the pack buffer according to the current pack state.
783
784     flushQueuedPackCommand();
785     mDataModified = (mDataModified || (access & GL_MAP_WRITE_BIT) != 0);
786
787     return &mMemoryBuffer[0];
788 }
789
790 void BufferStorage11::PackStorage11::unmap()
791 {
792     // No-op
793 }
794
795 void BufferStorage11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams &params)
796 {
797     flushQueuedPackCommand();
798     mQueuedPackCommand = new PackPixelsParams(params);
799
800     D3D11_TEXTURE2D_DESC textureDesc;
801     srcTexure->GetDesc(&textureDesc);
802
803     if (mStagingTexture != NULL &&
804         (mTextureFormat != textureDesc.Format ||
805          mTextureSize.width != params.area.width ||
806          mTextureSize.height != params.area.height))
807     {
808         SafeRelease(mStagingTexture);
809         mTextureSize.width = 0;
810         mTextureSize.height = 0;
811         mTextureFormat = DXGI_FORMAT_UNKNOWN;
812     }
813
814     if (mStagingTexture == NULL)
815     {
816         ID3D11Device *device = mRenderer->getDevice();
817         HRESULT hr;
818
819         mTextureSize.width = params.area.width;
820         mTextureSize.height = params.area.height;
821         mTextureFormat = textureDesc.Format;
822
823         D3D11_TEXTURE2D_DESC stagingDesc;
824         stagingDesc.Width = params.area.width;
825         stagingDesc.Height = params.area.height;
826         stagingDesc.MipLevels = 1;
827         stagingDesc.ArraySize = 1;
828         stagingDesc.Format = mTextureFormat;
829         stagingDesc.SampleDesc.Count = 1;
830         stagingDesc.SampleDesc.Quality = 0;
831         stagingDesc.Usage = D3D11_USAGE_STAGING;
832         stagingDesc.BindFlags = 0;
833         stagingDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ;
834         stagingDesc.MiscFlags = 0;
835
836         hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
837         ASSERT(SUCCEEDED(hr));
838     }
839
840     if (textureDesc.SampleDesc.Count > 1)
841     {
842         UNIMPLEMENTED();
843     }
844
845     ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
846     D3D11_BOX srcBox;
847     srcBox.left   = params.area.x;
848     srcBox.right  = params.area.x + params.area.width;
849     srcBox.top    = params.area.y;
850     srcBox.bottom = params.area.y + params.area.height;
851     srcBox.front  = 0;
852     srcBox.back   = 1;
853
854     // Asynchronous copy
855     immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);
856 }
857
858 void BufferStorage11::PackStorage11::flushQueuedPackCommand()
859 {
860     ASSERT(!mMemoryBuffer.empty());
861
862     if (mQueuedPackCommand)
863     {
864         mRenderer->packPixels(mStagingTexture, *mQueuedPackCommand, &mMemoryBuffer[0]);
865         SafeDelete(mQueuedPackCommand);
866     }
867 }
868
869 }