-#include "precompiled.h"
//
// Copyright 2014 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// Buffer11.cpp Defines the Buffer11 class.
#include "libGLESv2/renderer/d3d/d3d11/Buffer11.h"
-#include "libGLESv2/main.h"
#include "libGLESv2/renderer/d3d/d3d11/Renderer11.h"
#include "libGLESv2/renderer/d3d/d3d11/formatutils11.h"
+#include "libGLESv2/main.h"
namespace rx
{
virtual void *map(size_t offset, size_t length, GLbitfield access);
virtual void unmap();
+ bool setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset);
+
private:
ID3D11Buffer *mNativeBuffer;
virtual void *map(size_t offset, size_t length, GLbitfield access);
virtual void unmap();
- void packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms);
+ gl::Error packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms);
private:
return static_cast<Buffer11*>(buffer);
}
-void Buffer11::setData(const void* data, size_t size, GLenum usage)
+gl::Error Buffer11::setData(const void *data, size_t size, GLenum usage)
{
- mIndexRangeCache.clear();
-
- setSubData(data, size, 0);
+ gl::Error error = setSubData(data, size, 0);
+ if (error.isError())
+ {
+ return error;
+ }
if (usage == GL_STATIC_DRAW)
{
initializeStaticData();
}
+
+ return error;
}
void *Buffer11::getData()
mReadUsageCount = 0;
+ // Only happens if we initialized the buffer with no data (NULL)
+ if (mResolvedData.empty())
+ {
+ if (!mResolvedData.resize(mSize))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
+ }
+ }
+
+ ASSERT(mResolvedData.size() >= mSize);
+
return mResolvedData.data();
}
-void Buffer11::setSubData(const void* data, size_t size, size_t offset)
+gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
{
size_t requiredSize = size + offset;
- mSize = std::max(mSize, requiredSize);
-
- mIndexRangeCache.invalidateRange(offset, size);
- invalidateStaticData();
if (data && size > 0)
{
if (!stagingBuffer)
{
- // Out-of-memory
- return;
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
}
// Explicitly resize the staging buffer, preserving data if the new data will not
bool preserveData = (offset > 0);
if (!stagingBuffer->resize(requiredSize, preserveData))
{
- // Out-of-memory
- return;
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to resize internal staging buffer.");
}
}
- ID3D11DeviceContext *context = mRenderer->getDeviceContext();
-
- D3D11_MAPPED_SUBRESOURCE mappedResource;
- HRESULT result = context->Map(stagingBuffer->getNativeBuffer(), 0, D3D11_MAP_WRITE, 0, &mappedResource);
- if (FAILED(result))
+ if (!stagingBuffer->setData(D3D11_MAP_WRITE, reinterpret_cast<const uint8_t *>(data), size, offset))
{
- return gl::error(GL_OUT_OF_MEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to set data on internal staging buffer.");
}
- unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
- memcpy(offsetBufferPointer, data, size);
-
- context->Unmap(stagingBuffer->getNativeBuffer(), 0);
-
stagingBuffer->setDataRevision(stagingBuffer->getDataRevision() + 1);
}
+
+ mSize = std::max(mSize, requiredSize);
+ invalidateStaticData();
+
+ return gl::Error(GL_NO_ERROR);
}
-void Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
+gl::Error Buffer11::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintptr destOffset, GLsizeiptr size)
{
Buffer11 *sourceBuffer = makeBuffer11(source);
- if (sourceBuffer)
+ ASSERT(sourceBuffer != NULL);
+
+ BufferStorage11 *copyDest = getLatestBufferStorage();
+ if (!copyDest)
{
- BufferStorage11 *dest = getLatestBufferStorage();
- if (!dest)
- {
- dest = getStagingBuffer();
- }
+ copyDest = getStagingBuffer();
+ }
- BufferStorage11 *source = sourceBuffer->getLatestBufferStorage();
- if (source && dest)
- {
- // If copying to/from a pixel pack buffer, we must have a staging or
- // pack buffer partner, because other native buffers can't be mapped
- if (dest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !source->isMappable())
- {
- source = sourceBuffer->getStagingBuffer();
- }
- else if (source->getUsage() == BUFFER_USAGE_PIXEL_PACK && !dest->isMappable())
- {
- dest = getStagingBuffer();
- }
+ BufferStorage11 *copySource = sourceBuffer->getLatestBufferStorage();
- // D3D11 does not allow overlapped copies until 11.1, and only if the
- // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
- // Get around this via a different source buffer
- if (source == dest)
- {
- if (source->getUsage() == BUFFER_USAGE_STAGING)
- {
- source = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
- }
- else
- {
- source = getStagingBuffer();
- }
- }
+ if (!copySource || !copyDest)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging buffer.");
+ }
- dest->copyFromStorage(source, sourceOffset, size, destOffset);
- dest->setDataRevision(dest->getDataRevision() + 1);
- }
+ // If copying to/from a pixel pack buffer, we must have a staging or
+ // pack buffer partner, because other native buffers can't be mapped
+ if (copyDest->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copySource->isMappable())
+ {
+ copySource = sourceBuffer->getStagingBuffer();
+ }
+ else if (copySource->getUsage() == BUFFER_USAGE_PIXEL_PACK && !copyDest->isMappable())
+ {
+ copyDest = getStagingBuffer();
+ }
- mSize = std::max<size_t>(mSize, destOffset + size);
+ // D3D11 does not allow overlapped copies until 11.1, and only if the
+ // device supports D3D11_FEATURE_DATA_D3D11_OPTIONS::CopyWithOverlap
+ // Get around this via a different source buffer
+ if (copySource == copyDest)
+ {
+ if (copySource->getUsage() == BUFFER_USAGE_STAGING)
+ {
+ copySource = getBufferStorage(BUFFER_USAGE_VERTEX_OR_TRANSFORM_FEEDBACK);
+ }
+ else
+ {
+ copySource = getStagingBuffer();
+ }
}
- mIndexRangeCache.invalidateRange(destOffset, size);
+ copyDest->copyFromStorage(copySource, sourceOffset, size, destOffset);
+ copyDest->setDataRevision(copyDest->getDataRevision() + 1);
+
+ mSize = std::max<size_t>(mSize, destOffset + size);
invalidateStaticData();
+
+ return gl::Error(GL_NO_ERROR);
}
-GLvoid *Buffer11::map(size_t offset, size_t length, GLbitfield access)
+gl::Error Buffer11::map(size_t offset, size_t length, GLbitfield access, GLvoid **mapPtr)
{
ASSERT(!mMappedStorage);
if (!mMappedStorage)
{
- // Out-of-memory
- return NULL;
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate mappable internal buffer.");
}
if ((access & GL_MAP_WRITE_BIT) > 0)
{
- mIndexRangeCache.invalidateRange(offset, length);
-
// Update the data revision immediately, since the data might be changed at any time
mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
}
- return mMappedStorage->map(offset, length, access);
+ void *mappedBuffer = mMappedStorage->map(offset, length, access);
+ if (!mappedBuffer)
+ {
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal buffer.");
+ }
+
+ *mapPtr = mappedBuffer;
+ return gl::Error(GL_NO_ERROR);
}
-void Buffer11::unmap()
+gl::Error Buffer11::unmap()
{
ASSERT(mMappedStorage);
mMappedStorage->unmap();
mMappedStorage = NULL;
+ return gl::Error(GL_NO_ERROR);
}
void Buffer11::markTransformFeedbackUsage()
transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
}
- mIndexRangeCache.clear();
invalidateStaticData();
}
return bufferSRV;
}
-void Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms)
+gl::Error Buffer11::packPixels(ID3D11Texture2D *srcTexture, UINT srcSubresource, const PackPixelsParams ¶ms)
{
PackStorage11 *packStorage = getPackStorage();
if (packStorage)
{
- packStorage->packPixels(srcTexture, srcSubresource, params);
+ gl::Error error = packStorage->packPixels(srcTexture, srcSubresource, params);
+ if (error.isError())
+ {
+ return error;
+ }
packStorage->setDataRevision(latestStorage ? latestStorage->getDataRevision() + 1 : 1);
}
- mIndexRangeCache.clear();
+ return gl::Error(GL_NO_ERROR);
}
Buffer11::BufferStorage11 *Buffer11::getBufferStorage(BufferUsage usage)
return static_cast<PackStorage11*>(packStorage);
}
+bool Buffer11::supportsDirectBinding() const
+{
+ // Do not support direct buffers for dynamic data. The streaming buffer
+ // offers better performance for data which changes every frame.
+ // Check for absence of static buffer interfaces to detect dynamic data.
+ return (mStaticVertexBuffer && mStaticIndexBuffer);
+}
+
Buffer11::BufferStorage11::BufferStorage11(Renderer11 *renderer, BufferUsage usage)
: mRenderer(renderer),
mUsage(usage),
// Constant buffers must be of a limited size, and aligned to 16 byte boundaries
// For our purposes we ignore any buffer data past the maximum constant buffer size
bufferDesc->ByteWidth = roundUp(bufferDesc->ByteWidth, 16u);
- bufferDesc->ByteWidth = std::min(bufferDesc->ByteWidth, renderer->getMaxUniformBufferSize());
+ bufferDesc->ByteWidth = std::min<UINT>(bufferDesc->ByteWidth, renderer->getRendererCaps().maxUniformBlockSize);
break;
default:
return static_cast<GLubyte*>(mappedResource.pData) + offset;
}
+bool Buffer11::NativeBuffer11::setData(D3D11_MAP mapMode, const uint8_t *data, size_t size, size_t offset)
+{
+ ID3D11DeviceContext *context = mRenderer->getDeviceContext();
+
+ D3D11_MAPPED_SUBRESOURCE mappedResource;
+ HRESULT result = context->Map(mNativeBuffer, 0, mapMode, 0, &mappedResource);
+ if (FAILED(result))
+ {
+ return gl::error(GL_OUT_OF_MEMORY, false);
+ }
+
+ uint8_t *offsetBufferPointer = reinterpret_cast<uint8_t *>(mappedResource.pData) + offset;
+ memcpy(offsetBufferPointer, data, size);
+
+ context->Unmap(mNativeBuffer, 0);
+
+ return true;
+}
+
void Buffer11::NativeBuffer11::unmap()
{
ASSERT(mUsage == BUFFER_USAGE_STAGING);
// No-op
}
-void Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms)
+gl::Error Buffer11::PackStorage11::packPixels(ID3D11Texture2D *srcTexure, UINT srcSubresource, const PackPixelsParams ¶ms)
{
flushQueuedPackCommand();
mQueuedPackCommand = new PackPixelsParams(params);
stagingDesc.MiscFlags = 0;
hr = device->CreateTexture2D(&stagingDesc, NULL, &mStagingTexture);
- ASSERT(SUCCEEDED(hr));
+ if (FAILED(hr))
+ {
+ ASSERT(hr == E_OUTOFMEMORY);
+ return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal staging texture.");
+ }
}
// ReadPixels from multisampled FBOs isn't supported in current GL
// Asynchronous copy
immediateContext->CopySubresourceRegion(mStagingTexture, 0, 0, 0, 0, srcTexure, srcSubresource, &srcBox);
+
+ return gl::Error(GL_NO_ERROR);
}
void Buffer11::PackStorage11::flushQueuedPackCommand()