Commit be0facc6 by Austin Kinross Committed by Geoff Lang

Reduce calls to ID3D11DeviceContext::Map() in VertexBuffer11.cpp

This change moves VertexBuffer11::storeVertexAttributes()'s call to Map() outside a for-loop, eliminating unnecessary calls to Map(). Since Map() is a relatively expensive operation (even when using NO_OVERWRITE) this change gives a noticeable performance boost in some scenarios. Change-Id: I320111b32f2bb9eed92efbd240206e12aaa9964e Reviewed-on: https://chromium-review.googlesource.com/240181Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarGeoff Lang <geofflang@chromium.org> Tested-by: 's avatarAustin Kinross <aukinros@microsoft.com>
parent 691e58cd
......@@ -47,6 +47,9 @@ class VertexBuffer
unsigned int getSerial() const;
// This may be overridden (e.g. by VertexBuffer11) if necessary.
virtual void hintUnmapResource() { };
protected:
void updateSerial();
......
......@@ -85,6 +85,35 @@ VertexDataManager::~VertexDataManager()
}
}
void VertexDataManager::hintUnmapAllResources(const gl::State &state)
{
mStreamingBuffer->getVertexBuffer()->hintUnmapResource();
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
const gl::VertexAttribute &attrib = state.getVertexAttribState(i);
if (attrib.enabled)
{
gl::Buffer *buffer = attrib.buffer.get();
BufferD3D *storage = buffer ? BufferD3D::makeBufferD3D(buffer->getImplementation()) : NULL;
StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
if (staticBuffer)
{
staticBuffer->getVertexBuffer()->hintUnmapResource();
}
}
}
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
if (mCurrentValueBuffer[i] != NULL)
{
mCurrentValueBuffer[i]->getVertexBuffer()->hintUnmapResource();
}
}
}
gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint start, GLsizei count,
TranslatedAttribute *translated, GLsizei instances)
{
......@@ -132,6 +161,7 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
if (error.isError())
{
hintUnmapAllResources(state);
return error;
}
}
......@@ -147,12 +177,16 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, GLint sta
mCurrentValueBuffer[i]);
if (error.isError())
{
hintUnmapAllResources(state);
return error;
}
}
}
}
// Hint to unmap all the resources
hintUnmapAllResources(state);
for (int i = 0; i < gl::MAX_VERTEX_ATTRIBS; i++)
{
const gl::VertexAttribute &curAttrib = state.getVertexAttribState(i);
......
......@@ -80,6 +80,8 @@ class VertexDataManager
size_t *cachedOffset,
StreamingVertexBufferInterface *buffer);
void hintUnmapAllResources(const gl::State &state);
RendererD3D *const mRenderer;
StreamingVertexBufferInterface *mStreamingBuffer;
......
......@@ -21,10 +21,12 @@ VertexBuffer11::VertexBuffer11(Renderer11 *const renderer) : mRenderer(renderer)
mBuffer = NULL;
mBufferSize = 0;
mDynamicUsage = false;
mMappedResourceData = NULL;
}
VertexBuffer11::~VertexBuffer11()
{
ASSERT(mMappedResourceData == NULL);
SafeRelease(mBuffer);
}
......@@ -65,6 +67,37 @@ VertexBuffer11 *VertexBuffer11::makeVertexBuffer11(VertexBuffer *vetexBuffer)
return static_cast<VertexBuffer11*>(vetexBuffer);
}
gl::Error VertexBuffer11::mapResource()
{
if (mMappedResourceData == NULL)
{
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (FAILED(result))
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
}
mMappedResourceData = reinterpret_cast<uint8_t*>(mappedResource.pData);
}
return gl::Error(GL_NO_ERROR);
}
void VertexBuffer11::hintUnmapResource()
{
if (mMappedResourceData != NULL)
{
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
dxContext->Unmap(mBuffer, 0);
mMappedResourceData = NULL;
}
}
gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attrib, const gl::VertexAttribCurrentValueData &currentValue,
GLint start, GLsizei count, GLsizei instances, unsigned int offset)
{
......@@ -75,16 +108,15 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri
gl::Buffer *buffer = attrib.buffer.get();
int inputStride = ComputeVertexAttributeStride(attrib);
ID3D11DeviceContext *dxContext = mRenderer->getDeviceContext();
D3D11_MAPPED_SUBRESOURCE mappedResource;
HRESULT result = dxContext->Map(mBuffer, 0, D3D11_MAP_WRITE_NO_OVERWRITE, 0, &mappedResource);
if (FAILED(result))
// This will map the resource if it isn't already mapped.
gl::Error error = mapResource();
if (error.isError())
{
return gl::Error(GL_OUT_OF_MEMORY, "Failed to map internal vertex buffer, HRESULT: 0x%08x.", result);
return error;
}
uint8_t *output = reinterpret_cast<uint8_t*>(mappedResource.pData) + offset;
uint8_t *output = mMappedResourceData + offset;
const uint8_t *input = NULL;
if (attrib.enabled)
......@@ -119,8 +151,6 @@ gl::Error VertexBuffer11::storeVertexAttributes(const gl::VertexAttribute &attri
ASSERT(vertexFormatInfo.copyFunction != NULL);
vertexFormatInfo.copyFunction(input, inputStride, count, output);
dxContext->Unmap(mBuffer, 0);
return gl::Error(GL_NO_ERROR);
}
......
......@@ -9,6 +9,8 @@
#ifndef LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
#define LIBANGLE_RENDERER_D3D_D3D11_VERTEXBUFFER11_H_
#include <stdint.h>
#include "libANGLE/renderer/d3d/VertexBuffer.h"
namespace rx
......@@ -35,16 +37,22 @@ class VertexBuffer11 : public VertexBuffer
virtual gl::Error setBufferSize(unsigned int size);
virtual gl::Error discard();
virtual void hintUnmapResource();
ID3D11Buffer *getBuffer() const;
private:
DISALLOW_COPY_AND_ASSIGN(VertexBuffer11);
gl::Error mapResource();
Renderer11 *const mRenderer;
ID3D11Buffer *mBuffer;
unsigned int mBufferSize;
bool mDynamicUsage;
uint8_t *mMappedResourceData;
};
}
......
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