Commit 36e86234 by Bruce Dawson Committed by Jamie Madill

Improve image update perf by re-using a MemoryBuffer.

Instead of allocating a new MemoryBuffer every frame, we can store one scratch buffer in the Renderer, and occasionally re-create it to ensure we aren't stuck using the maximum amount of memory. BUG=angle:842 Change-Id: Id7c1912921ed8f84b151413453c3268d853352db Reviewed-on: https://chromium-review.googlesource.com/230861Tested-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarBruce Dawson <brucedawson@google.com> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org>
parent 9d59a044
......@@ -32,26 +32,31 @@ bool MemoryBuffer::resize(size_t size)
free(mData);
mData = NULL;
mSize = 0;
return true;
}
else
if (size == mSize)
{
uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
if (newMemory == NULL)
{
return false;
}
return true;
}
if (mData)
{
// Copy the intersection of the old data and the new data
std::copy(mData, mData + std::min(mSize, size), newMemory);
free(mData);
}
// Only reallocate if the size has changed.
uint8_t *newMemory = reinterpret_cast<uint8_t*>(malloc(sizeof(uint8_t) * size));
if (newMemory == NULL)
{
return false;
}
mData = newMemory;
mSize = size;
if (mData)
{
// Copy the intersection of the old data and the new data
std::copy(mData, mData + std::min(mSize, size), newMemory);
free(mData);
}
mData = newMemory;
mSize = size;
return true;
}
......
......@@ -18,13 +18,23 @@
#include "libANGLE/formatutils.h"
#include "libANGLE/renderer/d3d/DisplayD3D.h"
#include "libANGLE/renderer/d3d/IndexDataManager.h"
#include "libANGLE/renderer/d3d/MemoryBuffer.h"
namespace rx
{
namespace
{
// If we request a scratch buffer requesting a smaller size this many times,
// release and recreate the scratch buffer. This ensures we don't have a
// degenerate case where we are stuck hogging memory.
const int ScratchMemoryBufferLifetime = 1000;
}
RendererD3D::RendererD3D(egl::Display *display)
: mDisplay(display),
mDeviceLost(false)
mDeviceLost(false),
mScratchMemoryBufferResetCounter(0)
{
}
......@@ -35,6 +45,7 @@ RendererD3D::~RendererD3D()
void RendererD3D::cleanup()
{
mScratchMemoryBuffer.resize(0);
for (auto &incompleteTexture : mIncompleteTextures)
{
incompleteTexture.second.set(NULL);
......@@ -830,4 +841,34 @@ DisplayImpl *RendererD3D::createDisplay()
return new DisplayD3D(this);
}
gl::Error RendererD3D::getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut)
{
if (mScratchMemoryBuffer.size() == requestedSize)
{
mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
*bufferOut = &mScratchMemoryBuffer;
return gl::Error(GL_NO_ERROR);
}
if (mScratchMemoryBuffer.size() > requestedSize)
{
mScratchMemoryBufferResetCounter--;
}
if (mScratchMemoryBufferResetCounter <= 0 || mScratchMemoryBuffer.size() < requestedSize)
{
mScratchMemoryBuffer.resize(0);
if (!mScratchMemoryBuffer.resize(requestedSize))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
}
mScratchMemoryBufferResetCounter = ScratchMemoryBufferLifetime;
}
ASSERT(mScratchMemoryBuffer.size() >= requestedSize);
*bufferOut = &mScratchMemoryBuffer;
return gl::Error(GL_NO_ERROR);
}
}
......@@ -9,9 +9,10 @@
#ifndef LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
#define LIBANGLE_RENDERER_D3D_RENDERERD3D_H_
#include "libANGLE/Data.h"
#include "libANGLE/renderer/Renderer.h"
#include "libANGLE/renderer/d3d/MemoryBuffer.h"
#include "libANGLE/renderer/d3d/d3d11/NativeWindow.h"
#include "libANGLE/Data.h"
//FIXME(jmadill): std::array is currently prohibited by Chromium style guide
#include <array>
......@@ -25,15 +26,14 @@ class Texture;
namespace rx
{
class TextureStorage;
class VertexBuffer;
class Image;
class IndexBuffer;
class RenderTarget;
class ShaderExecutable;
class SwapChain;
class RenderTarget;
class Image;
class TextureStorage;
class UniformStorage;
class VertexBuffer;
class RendererD3D : public Renderer
{
......@@ -161,6 +161,8 @@ class RendererD3D : public Renderer
void notifyDeviceLost() override;
virtual bool resetDevice() = 0;
gl::Error getScratchMemoryBuffer(size_t requestedSize, MemoryBuffer **bufferOut);
protected:
virtual gl::Error drawArrays(GLenum mode, GLsizei count, GLsizei instances, bool transformFeedbackActive) = 0;
virtual gl::Error drawElements(GLenum mode, GLsizei count, GLenum type, const GLvoid *indices,
......@@ -204,6 +206,8 @@ class RendererD3D : public Renderer
gl::Texture *getIncompleteTexture(GLenum type);
gl::TextureMap mIncompleteTextures;
MemoryBuffer mScratchMemoryBuffer;
unsigned int mScratchMemoryBufferResetCounter;
};
}
......
......@@ -499,17 +499,19 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
UINT bufferRowPitch = outputPixelSize * width;
UINT bufferDepthPitch = bufferRowPitch * height;
MemoryBuffer conversionBuffer;
if (!conversionBuffer.resize(bufferDepthPitch * depth))
size_t neededSize = bufferDepthPitch * depth;
MemoryBuffer *conversionBuffer = NULL;
error = mRenderer->getScratchMemoryBuffer(neededSize, &conversionBuffer);
if (error.isError())
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to allocate internal buffer.");
return error;
}
// TODO: fast path
LoadImageFunction loadFunction = d3d11Format.loadFunctions.at(type);
loadFunction(width, height, depth,
pixelData, srcRowPitch, srcDepthPitch,
conversionBuffer.data(), bufferRowPitch, bufferDepthPitch);
conversionBuffer->data(), bufferRowPitch, bufferDepthPitch);
ID3D11DeviceContext *immediateContext = mRenderer->getDeviceContext();
......@@ -526,13 +528,13 @@ gl::Error TextureStorage11::setData(const gl::ImageIndex &index, Image *image, c
destD3DBox.back = 1;
immediateContext->UpdateSubresource(resource, destSubresource,
&destD3DBox, conversionBuffer.data(),
&destD3DBox, conversionBuffer->data(),
bufferRowPitch, bufferDepthPitch);
}
else
{
immediateContext->UpdateSubresource(resource, destSubresource,
NULL, conversionBuffer.data(),
NULL, conversionBuffer->data(),
bufferRowPitch, bufferDepthPitch);
}
......
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