Commit 2c40ce44 by Geoff Lang

Merge ES3 direct buffer changes and split index and vertex buffers.

Change-Id: I7ecdb049352af0dd94e8fbaede5953dfad9a75ef Reviewed-on: https://chromium-review.googlesource.com/181903Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarShannon Woods <shannonwoods@chromium.org> Tested-by: 's avatarGeoff Lang <geofflang@chromium.org>
parent 2b8b3b77
...@@ -21,9 +21,6 @@ BufferStorage11::BufferStorage11(Renderer11 *renderer) ...@@ -21,9 +21,6 @@ BufferStorage11::BufferStorage11(Renderer11 *renderer)
mStagingBuffer = NULL; mStagingBuffer = NULL;
mStagingBufferSize = 0; mStagingBufferSize = 0;
mBuffer = NULL;
mBufferSize = 0;
mSize = 0; mSize = 0;
mResolvedData = NULL; mResolvedData = NULL;
...@@ -36,23 +33,18 @@ BufferStorage11::BufferStorage11(Renderer11 *renderer) ...@@ -36,23 +33,18 @@ BufferStorage11::BufferStorage11(Renderer11 *renderer)
BufferStorage11::~BufferStorage11() BufferStorage11::~BufferStorage11()
{ {
if (mStagingBuffer) SafeRelease(mStagingBuffer);
{
mStagingBuffer->Release();
mStagingBuffer = NULL;
}
if (mBuffer)
{
mBuffer->Release();
mBuffer = NULL;
}
if (mResolvedData) if (mResolvedData)
{ {
free(mResolvedData); free(mResolvedData);
mResolvedData = NULL; mResolvedData = NULL;
} }
for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
{
SafeDelete(it->second);
}
} }
BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage) BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStorage)
...@@ -63,55 +55,21 @@ BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStora ...@@ -63,55 +55,21 @@ BufferStorage11 *BufferStorage11::makeBufferStorage11(BufferStorage *bufferStora
void *BufferStorage11::getData() void *BufferStorage11::getData()
{ {
ASSERT(mStagingBuffer);
if (!mResolvedDataValid) if (!mResolvedDataValid)
{ {
ID3D11Device *device = mRenderer->getDevice(); ID3D11Device *device = mRenderer->getDevice();
ID3D11DeviceContext *context = mRenderer->getDeviceContext(); ID3D11DeviceContext *context = mRenderer->getDeviceContext();
HRESULT result; HRESULT result;
if (!mStagingBuffer || mStagingBufferSize < mBufferSize) if (!mResolvedData || mResolvedDataSize < mStagingBufferSize)
{
if (mStagingBuffer)
{
mStagingBuffer->Release();
mStagingBuffer = NULL;
mStagingBufferSize = 0;
}
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = mSize;
bufferDesc.Usage = D3D11_USAGE_STAGING;
bufferDesc.BindFlags = 0;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
if (FAILED(result))
{
return gl::error(GL_OUT_OF_MEMORY, (void*)NULL);
}
mStagingBufferSize = bufferDesc.ByteWidth;
}
if (!mResolvedData || mResolvedDataSize < mBufferSize)
{ {
free(mResolvedData); free(mResolvedData);
mResolvedData = malloc(mSize); mResolvedData = malloc(mSize);
mResolvedDataSize = mSize; mResolvedDataSize = mSize;
} }
D3D11_BOX srcBox;
srcBox.left = 0;
srcBox.right = mSize;
srcBox.top = 0;
srcBox.bottom = 1;
srcBox.front = 0;
srcBox.back = 1;
context->CopySubresourceRegion(mStagingBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox);
D3D11_MAPPED_SUBRESOURCE mappedResource; D3D11_MAPPED_SUBRESOURCE mappedResource;
result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource); result = context->Map(mStagingBuffer, 0, D3D11_MAP_READ, 0, &mappedResource);
if (FAILED(result)) if (FAILED(result))
...@@ -137,178 +95,110 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int ...@@ -137,178 +95,110 @@ void BufferStorage11::setData(const void* data, unsigned int size, unsigned int
ID3D11DeviceContext *context = mRenderer->getDeviceContext(); ID3D11DeviceContext *context = mRenderer->getDeviceContext();
HRESULT result; HRESULT result;
unsigned int requiredBufferSize = size + offset; const unsigned int requiredStagingBufferSize = size + offset;
unsigned int requiredStagingSize = size; const bool createStagingBuffer = !mStagingBuffer || mStagingBufferSize < requiredStagingBufferSize;
bool directInitialization = offset == 0 && (!mBuffer || mBufferSize < size + offset);
if (!directInitialization) if (createStagingBuffer)
{ {
if (!mStagingBuffer || mStagingBufferSize < requiredStagingSize) D3D11_BUFFER_DESC bufferDesc;
{ bufferDesc.ByteWidth = requiredStagingBufferSize;
if (mStagingBuffer) bufferDesc.Usage = D3D11_USAGE_STAGING;
{ bufferDesc.BindFlags = 0;
mStagingBuffer->Release(); bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
mStagingBuffer = NULL; bufferDesc.MiscFlags = 0;
mStagingBufferSize = 0; bufferDesc.StructureByteStride = 0;
}
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = size;
bufferDesc.Usage = D3D11_USAGE_STAGING;
bufferDesc.BindFlags = 0;
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
if (data)
{
D3D11_SUBRESOURCE_DATA initialData;
initialData.pSysMem = data;
initialData.SysMemPitch = size;
initialData.SysMemSlicePitch = 0;
result = device->CreateBuffer(&bufferDesc, &initialData, &mStagingBuffer); HRESULT result;
} ID3D11Device *device = mRenderer->getDevice();
else ID3D11DeviceContext *context = mRenderer->getDeviceContext();
{ ID3D11Buffer *newStagingBuffer;
result = device->CreateBuffer(&bufferDesc, NULL, &mStagingBuffer);
}
if (FAILED(result)) if (data && offset == 0)
{ {
return gl::error(GL_OUT_OF_MEMORY); D3D11_SUBRESOURCE_DATA initialData;
} initialData.pSysMem = data;
initialData.SysMemPitch = requiredStagingBufferSize;
initialData.SysMemSlicePitch = 0;
mStagingBufferSize = size; result = device->CreateBuffer(&bufferDesc, &initialData, &newStagingBuffer);
} }
else if (data) else
{ {
D3D11_MAPPED_SUBRESOURCE mappedResource; result = device->CreateBuffer(&bufferDesc, NULL, &newStagingBuffer);
result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
if (FAILED(result))
{
return gl::error(GL_OUT_OF_MEMORY);
}
memcpy(mappedResource.pData, data, size);
context->Unmap(mStagingBuffer, 0);
} }
}
if (!mBuffer || mBufferSize < size + offset)
{
D3D11_BUFFER_DESC bufferDesc;
bufferDesc.ByteWidth = requiredBufferSize;
bufferDesc.Usage = D3D11_USAGE_DEFAULT;
bufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER | D3D11_BIND_INDEX_BUFFER;
bufferDesc.CPUAccessFlags = 0;
bufferDesc.MiscFlags = 0;
bufferDesc.StructureByteStride = 0;
if (directInitialization) if (FAILED(result))
{ {
// Since the data will fill the entire buffer (being larger than the initial size and having mStagingBufferSize = 0;
// no offset), the buffer can be initialized with the data so no staging buffer is required return gl::error(GL_OUT_OF_MEMORY);
}
// No longer need the old buffer
if (mBuffer)
{
mBuffer->Release();
mBuffer = NULL;
mBufferSize = 0;
}
if (data)
{
D3D11_SUBRESOURCE_DATA initialData;
initialData.pSysMem = data;
initialData.SysMemPitch = size;
initialData.SysMemSlicePitch = 0;
result = device->CreateBuffer(&bufferDesc, &initialData, &mBuffer); mStagingBufferSize = requiredStagingBufferSize;
}
else
{
result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer);
}
if (FAILED(result)) if (mStagingBuffer && offset > 0)
{
return gl::error(GL_OUT_OF_MEMORY);
}
}
else if (mBuffer && offset > 0)
{ {
// If offset is greater than zero and the buffer is non-null, need to preserve the data from // If offset is greater than zero and the buffer is non-null, need to preserve the data from
// the old buffer up to offset // the old buffer up to offset
ID3D11Buffer *newBuffer = NULL;
result = device->CreateBuffer(&bufferDesc, NULL, &newBuffer);
if (FAILED(result))
{
return gl::error(GL_OUT_OF_MEMORY);
}
D3D11_BOX srcBox; D3D11_BOX srcBox;
srcBox.left = 0; srcBox.left = 0;
srcBox.right = std::min(offset, mBufferSize); srcBox.right = std::min(offset, requiredStagingBufferSize);
srcBox.top = 0; srcBox.top = 0;
srcBox.bottom = 1; srcBox.bottom = 1;
srcBox.front = 0; srcBox.front = 0;
srcBox.back = 1; srcBox.back = 1;
context->CopySubresourceRegion(newBuffer, 0, 0, 0, 0, mBuffer, 0, &srcBox); context->CopySubresourceRegion(newStagingBuffer, 0, 0, 0, 0, mStagingBuffer, 0, &srcBox);
mBuffer->Release();
mBuffer = newBuffer;
} }
else
{
// Simple case, nothing needs to be copied from the old buffer to the new one, just create
// a new buffer
// No longer need the old buffer SafeRelease(mStagingBuffer);
if (mBuffer) mStagingBuffer = newStagingBuffer;
{ }
mBuffer->Release();
mBuffer = NULL;
mBufferSize = 0;
}
// Create a new buffer for data storage if (data && (offset != 0 || !createStagingBuffer))
result = device->CreateBuffer(&bufferDesc, NULL, &mBuffer); {
if (FAILED(result)) D3D11_MAPPED_SUBRESOURCE mappedResource;
{ result = context->Map(mStagingBuffer, 0, D3D11_MAP_WRITE, 0, &mappedResource);
return gl::error(GL_OUT_OF_MEMORY); if (FAILED(result))
} {
return gl::error(GL_OUT_OF_MEMORY);
} }
updateSerial(); unsigned char *offsetBufferPointer = reinterpret_cast<unsigned char *>(mappedResource.pData) + offset;
mBufferSize = bufferDesc.ByteWidth; memcpy(offsetBufferPointer, data, size);
context->Unmap(mStagingBuffer, 0);
} }
if (!directInitialization) for (auto it = mDirectBuffers.begin(); it != mDirectBuffers.end(); it++)
{ {
ASSERT(mStagingBuffer && mStagingBufferSize >= requiredStagingSize); 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();
// Data is already put into the staging buffer, copy it over to the data buffer
D3D11_BOX srcBox; D3D11_BOX srcBox;
srcBox.left = 0; srcBox.left = sourceOffset;
srcBox.right = size; srcBox.right = sourceOffset + size;
srcBox.top = 0; srcBox.top = 0;
srcBox.bottom = 1; srcBox.bottom = 1;
srcBox.front = 0; srcBox.front = 0;
srcBox.back = 1; srcBox.back = 1;
context->CopySubresourceRegion(mBuffer, 0, offset, 0, 0, mStagingBuffer, 0, &srcBox); ASSERT(mStagingBuffer && source->mStagingBuffer);
context->CopySubresourceRegion(mStagingBuffer, 0, destOffset, 0, 0, source->mStagingBuffer, 0, &srcBox);
} }
mSize = std::max(mSize, offset + size);
mWriteUsageCount = 0;
mResolvedDataValid = false;
} }
void BufferStorage11::clear() void BufferStorage11::clear()
...@@ -332,7 +222,7 @@ void BufferStorage11::markBufferUsage() ...@@ -332,7 +222,7 @@ void BufferStorage11::markBufferUsage()
mReadUsageCount++; mReadUsageCount++;
mWriteUsageCount++; mWriteUsageCount++;
static const unsigned int usageLimit = 5; const unsigned int usageLimit = 5;
if (mReadUsageCount > usageLimit && mResolvedData) if (mReadUsageCount > usageLimit && mResolvedData)
{ {
...@@ -341,18 +231,136 @@ void BufferStorage11::markBufferUsage() ...@@ -341,18 +231,136 @@ void BufferStorage11::markBufferUsage()
mResolvedDataSize = 0; mResolvedDataSize = 0;
mResolvedDataValid = false; 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();
if (mReadUsageCount > usageLimit && mWriteUsageCount > usageLimit && mStagingBuffer) // unused for now
ASSERT(offset == 0);
unsigned int requiredBufferSize = size + offset;
bool createBuffer = !mDirectBuffer || mBufferSize < requiredBufferSize;
// (Re)initialize D3D buffer if needed
if (createBuffer)
{ {
mStagingBuffer->Release(); D3D11_BUFFER_DESC bufferDesc;
mStagingBuffer = NULL; fillBufferDesc(&bufferDesc, mRenderer, mUsage, requiredBufferSize);
mStagingBufferSize = 0;
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;
} }
ID3D11Buffer *BufferStorage11::getBuffer() const void DirectBufferStorage11::fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize)
{ {
return mBuffer; 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();
}
} }
} }
...@@ -13,7 +13,15 @@ ...@@ -13,7 +13,15 @@
namespace rx namespace rx
{ {
class Renderer;
class Renderer11; class Renderer11;
class DirectBufferStorage11;
enum BufferUsage
{
BUFFER_USAGE_VERTEX,
BUFFER_USAGE_INDEX,
};
class BufferStorage11 : public BufferStorage class BufferStorage11 : public BufferStorage
{ {
...@@ -25,12 +33,13 @@ class BufferStorage11 : public BufferStorage ...@@ -25,12 +33,13 @@ class BufferStorage11 : public BufferStorage
virtual void *getData(); virtual void *getData();
virtual void setData(const void* data, unsigned int size, unsigned int offset); virtual void setData(const void* data, unsigned int size, unsigned int offset);
virtual void copyData(BufferStorage* sourceStorage, unsigned int size,
unsigned int sourceOffset, unsigned int destOffset);
virtual void clear(); virtual void clear();
virtual unsigned int getSize() const; virtual unsigned int getSize() const;
virtual bool supportsDirectBinding() const; virtual bool supportsDirectBinding() const;
virtual void markBufferUsage();
ID3D11Buffer *getBuffer() const; ID3D11Buffer *getBuffer(BufferUsage usage);
private: private:
Renderer11 *mRenderer; Renderer11 *mRenderer;
...@@ -38,8 +47,7 @@ class BufferStorage11 : public BufferStorage ...@@ -38,8 +47,7 @@ class BufferStorage11 : public BufferStorage
ID3D11Buffer *mStagingBuffer; ID3D11Buffer *mStagingBuffer;
unsigned int mStagingBufferSize; unsigned int mStagingBufferSize;
ID3D11Buffer *mBuffer; std::map<BufferUsage, DirectBufferStorage11*> mDirectBuffers;
unsigned int mBufferSize;
unsigned int mSize; unsigned int mSize;
...@@ -49,6 +57,34 @@ class BufferStorage11 : public BufferStorage ...@@ -49,6 +57,34 @@ class BufferStorage11 : public BufferStorage
unsigned int mReadUsageCount; unsigned int mReadUsageCount;
unsigned int mWriteUsageCount; unsigned int mWriteUsageCount;
void markBufferUsage();
};
// Each instance of BufferStorageD3DBuffer11 is specialized for a class of D3D binding points
// - vertex buffers
// - index buffers
class DirectBufferStorage11
{
public:
DirectBufferStorage11(Renderer11 *renderer, BufferUsage usage);
~DirectBufferStorage11();
BufferUsage getUsage() const;
bool updateFromStagingBuffer(ID3D11Buffer *stagingBuffer, size_t size, size_t offset);
ID3D11Buffer *getD3DBuffer() { return mDirectBuffer; }
bool isDirty() const { return mDirty; }
void markDirty() { mDirty = true; }
private:
Renderer11 *mRenderer;
const BufferUsage mUsage;
ID3D11Buffer *mDirectBuffer;
size_t mBufferSize;
bool mDirty;
static void fillBufferDesc(D3D11_BUFFER_DESC* bufferDesc, Renderer *renderer, BufferUsage usage, unsigned int bufferSize);
}; };
} }
......
...@@ -114,7 +114,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M ...@@ -114,7 +114,7 @@ GLenum InputLayoutCache::applyVertexBuffers(TranslatedAttribute attributes[gl::M
ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor; ilKey.elements[ilKey.elementCount].desc.InstanceDataStepRate = attributes[i].divisor;
ilKey.elementCount++; ilKey.elementCount++;
vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer() : vertexBuffer->getBuffer(); vertexBuffers[i] = bufferStorage ? bufferStorage->getBuffer(BUFFER_USAGE_VERTEX) : vertexBuffer->getBuffer();
vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial(); vertexBufferSerials[i] = bufferStorage ? bufferStorage->getSerial() : vertexBuffer->getSerial();
vertexStrides[i] = attributes[i].stride; vertexStrides[i] = attributes[i].stride;
vertexOffsets[i] = attributes[i].offset; vertexOffsets[i] = attributes[i].offset;
......
...@@ -1063,7 +1063,7 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr ...@@ -1063,7 +1063,7 @@ GLenum Renderer11::applyIndexBuffer(const GLvoid *indices, gl::Buffer *elementAr
BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage); BufferStorage11 *storage = BufferStorage11::makeBufferStorage11(indexInfo->storage);
IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer); IndexBuffer11* indexBuffer = IndexBuffer11::makeIndexBuffer11(indexInfo->indexBuffer);
mDeviceContext->IASetIndexBuffer(storage->getBuffer(), indexBuffer->getIndexFormat(), indexInfo->startOffset); mDeviceContext->IASetIndexBuffer(storage->getBuffer(BUFFER_USAGE_INDEX), indexBuffer->getIndexFormat(), indexInfo->startOffset);
mAppliedIBSerial = 0; mAppliedIBSerial = 0;
mAppliedStorageIBSerial = storage->getSerial(); mAppliedStorageIBSerial = storage->getSerial();
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment