summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp')
-rw-r--r--src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp366
1 files changed, 366 insertions, 0 deletions
diff --git a/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp
new file mode 100644
index 0000000000..31d5b8b886
--- /dev/null
+++ b/src/3rdparty/angle/src/libGLESv2/renderer/d3d11/BufferStorage11.cpp
@@ -0,0 +1,366 @@
+#include "precompiled.h"
+//
+// Copyright (c) 2013 The ANGLE Project Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+//
+
+// BufferStorage11.cpp Defines the BufferStorage11 class.
+
+#include "libGLESv2/renderer/d3d11/BufferStorage11.h"
+#include "libGLESv2/main.h"
+#include "libGLESv2/renderer/d3d11/Renderer11.h"
+
+namespace rx
+{
+
+BufferStorage11::BufferStorage11(Renderer11 *renderer)
+{
+ mRenderer = renderer;
+
+ mStagingBuffer = NULL;
+ mStagingBufferSize = 0;
+
+ mSize = 0;
+
+ mResolvedData = NULL;
+ mResolvedDataSize = 0;
+ mResolvedDataValid = false;
+
+ mReadUsageCount = 0;
+ mWriteUsageCount = 0;
+}
+
+BufferStorage11::~BufferStorage11()
+{
+ SafeRelease(mStagingBuffer);
+
+ if (mResolvedData)
+ {
+ free(mResolvedData);
+ mResolvedData = NULL;
+ }
+
+ for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
+ {
+ SafeDelete(it->second);
+ }
+}
+
+BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
+{
+ ASSERT(HAS_DYNAMIC_TYPE(BufferStorage11*, bufferStorage));
+ return static_cast<BufferStorage11*>(bufferStorage);
+}
+
+void *BufferStorage11::getData()
+{
+ ASSERT(mStagingBuffer);
+
+ if (!mResolvedDataValid)
+ {
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ HRESULT result;
+
+ if (!mResolvedData || mResolvedDataSize < mStagingBufferSize)
+ {
+ free(mResolvedData);
+ mResolvedData = malloc(mSize);
+ mResolvedDataSize = mSize;
+ }
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+
+ memcpy(mResolvedData, mappedResource.pData, mSize);
+
+ context->Unmap(mStagingBuffer, 0);
+
+ mResolvedDataValid = true;
+ }
+
+ mReadUsageCount = 0;
+
+ return mResolvedData;
+}
+
+void BufferStorage11::setData(const void* data, unsigned int size, unsigned int offset)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ HRESULT result;
+
+ const unsigned int requiredStagingBufferSize = size + offset;
+ const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize;
+
+ if (createStagingBuffer)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ bufferDesc.ByteWidth = requiredStagingBufferSize;
+ bufferDesc.Usage = D3D11_USAGE_STAGING;
+ bufferDesc.BindFlags = 0;
+ bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
+ bufferDesc.MiscFlags = 0;
+ bufferDesc.StructureByteStride = 0;
+
+ HRESULT result;
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+ ID3D11Buffer *newStagingBuffer;
+
+ if (data && offset == 0)
+ {
+ D3D11_SUBRESOURCE_DATA initialData;
+ initialData.pSysMem = data;
+ initialData.SysMemPitch = requiredStagingBufferSize;
+ initialData.SysMemSlicePitch = 0;
+
+ result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer);
+ }
+ else
+ {
+ result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer);
+ }
+
+ if (FAILED(result))
+ {
+ mStagingBufferSize = 0;
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ mStagingBufferSize = requiredStagingBufferSize;
+
+ if (mStagingBuffer && offset > 0)
+ {
+ // If offset is greater than zero and the buffer is non-null, need to preserve the data from
+ // the old buffer up to offset
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = std::min(offset, requiredStagingBufferSize);
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox);
+ }
+
+ SafeRelease(mStagingBuffer);
+ mStagingBuffer = newStagingBuffer;
+ }
+
+ if (data && (offset != 0 || !createStagingBuffer))
+ {
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY);
+ }
+
+ unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
+ memcpy(offsetBufferPointer, data, size);
+
+ context->Unmap(mStagingBuffer, 0);
+ }
+
+ for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
+ {
+ it->second->markDirty();
+ }
+
+ mSize = std::max(mSize, requiredStagingBufferSize);
+ mWriteUsageCount = 0;
+
+ mResolvedDataValid = false;
+}
+
+void BufferStorage11::copyData(BufferStorage* sourceStorage, unsigned int size,
+ unsigned int sourceOffset, unsigned int destOffset)
+{
+ BufferStorage11* source = makeBufferStorage11(sourceStorage);
+ if (source)
+ {
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_BOX srcBox;
+ srcBox.left = sourceOffset;
+ srcBox.right = sourceOffset + size;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ ASSERT(mStagingBuffer && source->mStagingBuffer);
+ context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox);
+ }
+}
+
+void BufferStorage11::clear()
+{
+ mResolvedDataValid = false;
+ mSize = 0;
+}
+
+unsigned int BufferStorage11::getSize() const
+{
+ return mSize;
+}
+
+bool BufferStorage11::supportsDirectBinding() const
+{
+ return true;
+}
+
+void BufferStorage11::markBufferUsage()
+{
+ mReadUsageCount++;
+ mWriteUsageCount++;
+
+ const unsigned int usageLimit = 5;
+
+ if (mReadUsageCount > usageLimit && mResolvedData)
+ {
+ free(mResolvedData);
+ mResolvedData = NULL;
+ mResolvedDataSize = 0;
+ mResolvedDataValid = false;
+ }
+}
+
+ID3D11Buffer *BufferStorage11::getBuffer(BufferUsage usage)
+{
+ markBufferUsage();
+
+ DirectBufferStorage11 *directBuffer = NULL;
+
+ auto directBufferIt = mDirectBuffers.find(usage);
+ if (directBufferIt != mDirectBuffers.end())
+ {
+ directBuffer = directBufferIt->second;
+ }
+
+ if (directBuffer)
+ {
+ if (directBuffer->isDirty())
+ {
+ // if updateFromStagingBuffer returns true, the D3D buffer has been recreated
+ // and we should update our serial
+ if (directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0))
+ {
+ updateSerial();
+ }
+ }
+ }
+ else
+ {
+ // buffer is not allocated, create it
+ directBuffer = new DirectBufferStorage11(mRenderer, usage);
+ directBuffer->updateFromStagingBuffer(mStagingBuffer, mSize, 0);
+
+ mDirectBuffers.insert(std::make_pair(usage, directBuffer));
+ updateSerial();
+ }
+
+ return directBuffer->getD3DBuffer();
+}
+
+DirectBufferStorage11::DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage)
+ : mRenderer(renderer),
+ mUsage(usage),
+ mDirectBuffer(NULL),
+ mBufferSize(0),
+ mDirty(false)
+{
+}
+
+DirectBufferStorage11::~DirectBufferStorage11()
+{
+ SafeRelease(mDirectBuffer);
+}
+
+BufferUsage DirectBufferStorage11::getUsage() const
+{
+ return mUsage;
+}
+
+// Returns true if it recreates the direct buffer
+bool DirectBufferStorage11::updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset)
+{
+ ID3D11Device *device = mRenderer->getDevice();
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ // unused for now
+ ASSERT(offset == 0);
+
+ unsigned int requiredBufferSize = size + offset;
+ bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize;
+
+ // (Re)initialize D3D buffer if needed
+ if (createBuffer)
+ {
+ D3D11_BUFFER_DESC bufferDesc;
+ fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize);
+
+ ID3D11Buffer *newBuffer;
+ HRESULT result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
+
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ // No longer need the old buffer
+ SafeRelease(mDirectBuffer);
+ mDirectBuffer = newBuffer;
+
+ mBufferSize = bufferDesc.ByteWidth;
+ }
+
+ // Copy data via staging buffer
+ D3D11_BOX srcBox;
+ srcBox.left = 0;
+ srcBox.right = size;
+ srcBox.top = 0;
+ srcBox.bottom = 1;
+ srcBox.front = 0;
+ srcBox.back = 1;
+
+ context->CopySubresourceRegion(mDirectBuffer, 0, offset, 0, 0, stagingBuffer, 0, &srcBox);
+
+ mDirty = false;
+
+ return createBuffer;
+}
+
+void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize)
+{
+ bufferDesc->ByteWidth = bufferSize;
+ bufferDesc->MiscFlags = 0;
+ bufferDesc->StructureByteStride = 0;
+
+ switch (usage)
+ {
+ case BUFFER_USAGE_VERTEX:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_VERTEX_BUFFER;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ case BUFFER_USAGE_INDEX:
+ bufferDesc->Usage = D3D11_USAGE_DEFAULT;
+ bufferDesc->BindFlags = D3D11_BIND_INDEX_BUFFER;
+ bufferDesc->CPUAccessFlags = 0;
+ break;
+
+ default:
+ UNREACHABLE();
+ }
+}
+
+}