Commit 5b58cae2 by Jamie Madill

Revert "In D3D, cache static vertex buffers to prevent wasteful recreation"

Perf bisect traced performance regression to this CL: 8.1% regression in angle_perftests/DrawCallPerf_d3d9_null/score 6.2% regression in angle_perftests/DrawCallPerf_d3d11_null/score BUG=angleproject:197 This reverts commit 868651d3. Change-Id: Iaba7eb4e574eb886496361e61fd5fe78ca14dcb8 Reviewed-on: https://chromium-review.googlesource.com/311150 Tryjob-Request: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Tested-by: 's avatarJamie Madill <jmadill@chromium.org>
parent ff2ab571
...@@ -8,7 +8,6 @@ ...@@ -8,7 +8,6 @@
#include "libANGLE/renderer/d3d/BufferD3D.h" #include "libANGLE/renderer/d3d/BufferD3D.h"
#include "common/mathutil.h"
#include "common/utilities.h" #include "common/utilities.h"
#include "libANGLE/renderer/d3d/IndexBuffer.h" #include "libANGLE/renderer/d3d/IndexBuffer.h"
#include "libANGLE/renderer/d3d/VertexBuffer.h" #include "libANGLE/renderer/d3d/VertexBuffer.h"
...@@ -23,7 +22,6 @@ BufferD3D::BufferD3D(BufferFactoryD3D *factory) ...@@ -23,7 +22,6 @@ BufferD3D::BufferD3D(BufferFactoryD3D *factory)
mFactory(factory), mFactory(factory),
mStaticVertexBuffer(nullptr), mStaticVertexBuffer(nullptr),
mStaticIndexBuffer(nullptr), mStaticIndexBuffer(nullptr),
mStaticBufferCacheTotalSize(0),
mUnmodifiedDataUse(0), mUnmodifiedDataUse(0),
mUsage(D3D_BUFFER_USAGE_STATIC) mUsage(D3D_BUFFER_USAGE_STATIC)
{ {
...@@ -34,11 +32,6 @@ BufferD3D::~BufferD3D() ...@@ -34,11 +32,6 @@ BufferD3D::~BufferD3D()
{ {
SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticVertexBuffer);
SafeDelete(mStaticIndexBuffer); SafeDelete(mStaticIndexBuffer);
// Empty the cache of static vertex buffers too
SafeDeleteContainer(mStaticBufferCache);
mStaticBufferCacheTotalSize = 0;
} }
void BufferD3D::updateSerial() void BufferD3D::updateSerial()
...@@ -82,80 +75,8 @@ void BufferD3D::initializeStaticData() ...@@ -82,80 +75,8 @@ void BufferD3D::initializeStaticData()
} }
} }
StaticIndexBufferInterface *BufferD3D::getStaticIndexBuffer() void BufferD3D::invalidateStaticData()
{
return mStaticIndexBuffer;
}
StaticVertexBufferInterface *BufferD3D::getStaticVertexBuffer(const gl::VertexAttribute &attribute)
{ {
// If the default static vertex buffer contains the attribute, then return it
if (mStaticVertexBuffer && mStaticVertexBuffer->lookupAttribute(attribute, nullptr))
{
return mStaticVertexBuffer;
}
// If there is a cached static buffer that already contains the attribute, then return it
for (StaticVertexBufferInterface *staticBuffer : mStaticBufferCache)
{
if (staticBuffer->lookupAttribute(attribute, nullptr))
{
return staticBuffer;
}
}
if (mStaticVertexBuffer)
{
// If the default static vertex buffer hasn't been committed, then we can
// still use it
if (!mStaticVertexBuffer->isCommitted())
{
return mStaticVertexBuffer;
}
else
{
unsigned int staticVertexBufferSize = mStaticVertexBuffer->getBufferSize();
if (IsUnsignedAdditionSafe(staticVertexBufferSize, mStaticBufferCacheTotalSize))
{
// Ensure that the total size of the static buffer cache remains less than 4x the
// size of the original buffer
unsigned int maxStaticCacheSize =
IsUnsignedMultiplicationSafe(static_cast<unsigned int>(getSize()), 4u)
? 4u * static_cast<unsigned int>(getSize())
: std::numeric_limits<unsigned int>::max();
// We can't reuse the default static vertex buffer, so we add it to the cache
if (staticVertexBufferSize + mStaticBufferCacheTotalSize <= maxStaticCacheSize)
{
mStaticBufferCacheTotalSize += staticVertexBufferSize;
mStaticBufferCache.push_back(mStaticVertexBuffer);
mStaticVertexBuffer = nullptr;
// Then reinitialize the static buffers to create a new static vertex buffer
initializeStaticData();
}
}
}
}
// Return the default static vertex buffer
return mStaticVertexBuffer;
}
void BufferD3D::invalidateStaticData(bool invalidateWholeCache)
{
if (invalidateWholeCache)
{
// Empty the cache of static vertex buffers too
for (StaticVertexBufferInterface *staticBuffer : mStaticBufferCache)
{
SafeDelete(staticBuffer);
}
mStaticBufferCache.clear();
mStaticBufferCacheTotalSize = 0;
}
if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0)) if ((mStaticVertexBuffer && mStaticVertexBuffer->getBufferSize() != 0) || (mStaticIndexBuffer && mStaticIndexBuffer->getBufferSize() != 0))
{ {
SafeDelete(mStaticVertexBuffer); SafeDelete(mStaticVertexBuffer);
...@@ -177,10 +98,6 @@ void BufferD3D::promoteStaticUsage(int dataSize) ...@@ -177,10 +98,6 @@ void BufferD3D::promoteStaticUsage(int dataSize)
{ {
if (!mStaticVertexBuffer && !mStaticIndexBuffer) if (!mStaticVertexBuffer && !mStaticIndexBuffer)
{ {
// There isn't any scenario that involves promoting static usage and the static buffer cache
// being non-empty
ASSERT(mStaticBufferCache.empty());
mUnmodifiedDataUse += dataSize; mUnmodifiedDataUse += dataSize;
if (mUnmodifiedDataUse > 3 * getSize()) if (mUnmodifiedDataUse > 3 * getSize())
......
...@@ -13,7 +13,6 @@ ...@@ -13,7 +13,6 @@
#include "libANGLE/renderer/BufferImpl.h" #include "libANGLE/renderer/BufferImpl.h"
#include <stdint.h> #include <stdint.h>
#include <vector>
namespace rx namespace rx
{ {
...@@ -40,11 +39,11 @@ class BufferD3D : public BufferImpl ...@@ -40,11 +39,11 @@ class BufferD3D : public BufferImpl
virtual void markTransformFeedbackUsage() = 0; virtual void markTransformFeedbackUsage() = 0;
virtual gl::Error getData(const uint8_t **outData) = 0; virtual gl::Error getData(const uint8_t **outData) = 0;
StaticVertexBufferInterface *getStaticVertexBuffer(const gl::VertexAttribute &attribute); StaticVertexBufferInterface *getStaticVertexBuffer() { return mStaticVertexBuffer; }
StaticIndexBufferInterface *getStaticIndexBuffer(); StaticIndexBufferInterface *getStaticIndexBuffer() { return mStaticIndexBuffer; }
void initializeStaticData(); void initializeStaticData();
void invalidateStaticData(bool invalidateWholeCache); void invalidateStaticData();
void promoteStaticUsage(int dataSize); void promoteStaticUsage(int dataSize);
gl::Error getIndexRange(GLenum type, gl::Error getIndexRange(GLenum type,
...@@ -63,9 +62,6 @@ class BufferD3D : public BufferImpl ...@@ -63,9 +62,6 @@ class BufferD3D : public BufferImpl
StaticVertexBufferInterface *mStaticVertexBuffer; StaticVertexBufferInterface *mStaticVertexBuffer;
StaticIndexBufferInterface *mStaticIndexBuffer; StaticIndexBufferInterface *mStaticIndexBuffer;
std::vector<StaticVertexBufferInterface *> mStaticBufferCache;
unsigned int mStaticBufferCacheTotalSize;
unsigned int mUnmodifiedDataUse; unsigned int mUnmodifiedDataUse;
D3DBufferUsage mUsage; D3DBufferUsage mUsage;
}; };
......
...@@ -193,7 +193,7 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl:: ...@@ -193,7 +193,7 @@ gl::Error IndexDataManager::prepareIndexData(GLenum srcType, GLsizei count, gl::
if (staticBufferInitialized && !staticBufferUsable) if (staticBufferInitialized && !staticBufferUsable)
{ {
buffer->invalidateStaticData(true); buffer->invalidateStaticData();
staticBuffer = nullptr; staticBuffer = nullptr;
} }
......
...@@ -243,7 +243,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size) ...@@ -243,7 +243,7 @@ gl::Error StreamingVertexBufferInterface::reserveSpace(unsigned int size)
} }
StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory) StaticVertexBufferInterface::StaticVertexBufferInterface(BufferFactoryD3D *factory)
: VertexBufferInterface(factory, false), mIsCommitted(false) : VertexBufferInterface(factory, false)
{ {
} }
...@@ -321,11 +321,4 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt ...@@ -321,11 +321,4 @@ gl::Error StaticVertexBufferInterface::storeVertexAttributes(const gl::VertexAtt
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
void StaticVertexBufferInterface::commit()
{
if (getBufferSize() > 0)
{
mIsCommitted = true;
}
}
} }
...@@ -135,11 +135,6 @@ class StaticVertexBufferInterface : public VertexBufferInterface ...@@ -135,11 +135,6 @@ class StaticVertexBufferInterface : public VertexBufferInterface
bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset); bool lookupAttribute(const gl::VertexAttribute &attribute, unsigned int* outStreamFffset);
// If a static vertex buffer is committed then no more attribute data can be added to it
// A new static vertex buffer should be created instead
void commit();
bool isCommitted() { return mIsCommitted; }
protected: protected:
gl::Error reserveSpace(unsigned int size); gl::Error reserveSpace(unsigned int size);
...@@ -156,7 +151,6 @@ class StaticVertexBufferInterface : public VertexBufferInterface ...@@ -156,7 +151,6 @@ class StaticVertexBufferInterface : public VertexBufferInterface
unsigned int streamOffset; unsigned int streamOffset;
}; };
bool mIsCommitted;
std::vector<VertexElement> mCache; std::vector<VertexElement> mCache;
}; };
......
...@@ -88,8 +88,7 @@ void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttrib ...@@ -88,8 +88,7 @@ void VertexDataManager::hintUnmapAllResources(const std::vector<gl::VertexAttrib
{ {
gl::Buffer *buffer = translated->attribute->buffer.get(); gl::Buffer *buffer = translated->attribute->buffer.get();
BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr; BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
StaticVertexBufferInterface *staticBuffer = StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : nullptr;
storage ? storage->getStaticVertexBuffer(*translated->attribute) : nullptr;
if (staticBuffer) if (staticBuffer)
{ {
...@@ -198,22 +197,6 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state, ...@@ -198,22 +197,6 @@ gl::Error VertexDataManager::prepareVertexData(const gl::State &state,
} }
} }
// Commit all the static vertex buffers. This fixes them in size/contents, and forces ANGLE
// to use a new static buffer (or recreate the static buffers) next time
for (const TranslatedAttribute *activeAttrib : mActiveEnabledAttributes)
{
const gl::VertexAttribute &attrib = *activeAttrib->attribute;
gl::Buffer *buffer = attrib.buffer.get();
BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : nullptr;
StaticVertexBufferInterface *staticBuffer =
storage ? storage->getStaticVertexBuffer(attrib) : nullptr;
if (staticBuffer)
{
staticBuffer->commit();
}
}
// Hint to unmap all the resources // Hint to unmap all the resources
hintUnmapAllResources(vertexAttributes); hintUnmapAllResources(vertexAttributes);
...@@ -240,15 +223,14 @@ void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute & ...@@ -240,15 +223,14 @@ void VertexDataManager::invalidateMatchingStaticData(const gl::VertexAttribute &
if (buffer) if (buffer)
{ {
BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer); BufferD3D *bufferImpl = GetImplAs<BufferD3D>(buffer);
StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer(attrib); StaticVertexBufferInterface *staticBuffer = bufferImpl->getStaticVertexBuffer();
if (staticBuffer && if (staticBuffer &&
staticBuffer->getBufferSize() > 0 && staticBuffer->getBufferSize() > 0 &&
!staticBuffer->lookupAttribute(attrib, NULL) && !staticBuffer->lookupAttribute(attrib, NULL) &&
!staticBuffer->directStoragePossible(attrib, currentValue.Type)) !staticBuffer->directStoragePossible(attrib, currentValue.Type))
{ {
// This must be the default static vertex buffer, and we must invalidate it bufferImpl->invalidateStaticData();
bufferImpl->invalidateStaticData(false);
} }
} }
} }
...@@ -260,8 +242,7 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &tr ...@@ -260,8 +242,7 @@ gl::Error VertexDataManager::reserveSpaceForAttrib(const TranslatedAttribute &tr
const gl::VertexAttribute &attrib = *translatedAttrib.attribute; const gl::VertexAttribute &attrib = *translatedAttrib.attribute;
gl::Buffer *buffer = attrib.buffer.get(); gl::Buffer *buffer = attrib.buffer.get();
BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; BufferD3D *bufferImpl = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
StaticVertexBufferInterface *staticBuffer = StaticVertexBufferInterface *staticBuffer = bufferImpl ? bufferImpl->getStaticVertexBuffer() : NULL;
bufferImpl ? bufferImpl->getStaticVertexBuffer(attrib) : NULL;
VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType)) if (!vertexBuffer->directStoragePossible(attrib, translatedAttrib.currentValueType))
...@@ -310,8 +291,7 @@ gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated, ...@@ -310,8 +291,7 @@ gl::Error VertexDataManager::storeAttribute(TranslatedAttribute *translated,
ASSERT(attrib.enabled); ASSERT(attrib.enabled);
BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL; BufferD3D *storage = buffer ? GetImplAs<BufferD3D>(buffer) : NULL;
StaticVertexBufferInterface *staticBuffer = StaticVertexBufferInterface *staticBuffer = storage ? storage->getStaticVertexBuffer() : NULL;
storage ? storage->getStaticVertexBuffer(attrib) : NULL;
VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer); VertexBufferInterface *vertexBuffer = staticBuffer ? staticBuffer : static_cast<VertexBufferInterface*>(mStreamingBuffer);
bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType); bool directStorage = vertexBuffer->directStoragePossible(attrib, translated->currentValueType);
......
...@@ -361,7 +361,7 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset) ...@@ -361,7 +361,7 @@ gl::Error Buffer11::setSubData(const void *data, size_t size, size_t offset)
} }
mSize = std::max(mSize, requiredSize); mSize = std::max(mSize, requiredSize);
invalidateStaticData(true); invalidateStaticData();
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -417,7 +417,7 @@ gl::Error Buffer11::copySubData(BufferImpl *source, ...@@ -417,7 +417,7 @@ gl::Error Buffer11::copySubData(BufferImpl *source,
copyDest->setDataRevision(copyDest->getDataRevision() + 1); copyDest->setDataRevision(copyDest->getDataRevision() + 1);
mSize = std::max<size_t>(mSize, destOffset + size); mSize = std::max<size_t>(mSize, destOffset + size);
invalidateStaticData(true); invalidateStaticData();
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -457,7 +457,7 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL ...@@ -457,7 +457,7 @@ gl::Error Buffer11::mapRange(size_t offset, size_t length, GLbitfield access, GL
{ {
// Update the data revision immediately, since the data might be changed at any time // Update the data revision immediately, since the data might be changed at any time
mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1); mMappedStorage->setDataRevision(mMappedStorage->getDataRevision() + 1);
invalidateStaticData(true); invalidateStaticData();
} }
uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access); uint8_t *mappedBuffer = mMappedStorage->map(offset, length, access);
...@@ -492,7 +492,7 @@ void Buffer11::markTransformFeedbackUsage() ...@@ -492,7 +492,7 @@ void Buffer11::markTransformFeedbackUsage()
transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1); transformFeedbackStorage->setDataRevision(transformFeedbackStorage->getDataRevision() + 1);
} }
invalidateStaticData(true); invalidateStaticData();
} }
void Buffer11::markBufferUsage() void Buffer11::markBufferUsage()
......
...@@ -38,7 +38,7 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage) ...@@ -38,7 +38,7 @@ gl::Error Buffer9::setData(const void* data, size_t size, GLenum usage)
memcpy(mMemory.data(), data, size); memcpy(mMemory.data(), data, size);
} }
invalidateStaticData(true); invalidateStaticData();
updateD3DBufferUsage(usage); updateD3DBufferUsage(usage);
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
...@@ -66,7 +66,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset) ...@@ -66,7 +66,7 @@ gl::Error Buffer9::setSubData(const void* data, size_t size, size_t offset)
memcpy(mMemory.data() + offset, data, size); memcpy(mMemory.data() + offset, data, size);
} }
invalidateStaticData(true); invalidateStaticData();
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
...@@ -79,7 +79,7 @@ gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintp ...@@ -79,7 +79,7 @@ gl::Error Buffer9::copySubData(BufferImpl* source, GLintptr sourceOffset, GLintp
memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size); memcpy(mMemory.data() + destOffset, sourceBuffer->mMemory.data() + sourceOffset, size);
invalidateStaticData(true); invalidateStaticData();
return gl::Error(GL_NO_ERROR); return gl::Error(GL_NO_ERROR);
} }
......
...@@ -21,7 +21,6 @@ ...@@ -21,7 +21,6 @@
'<(angle_path)/src/tests/perf_tests/DrawCallPerf.cpp', '<(angle_path)/src/tests/perf_tests/DrawCallPerf.cpp',
'<(angle_path)/src/tests/perf_tests/EGLInitializePerf.cpp', '<(angle_path)/src/tests/perf_tests/EGLInitializePerf.cpp',
'<(angle_path)/src/tests/perf_tests/IndexConversionPerf.cpp', '<(angle_path)/src/tests/perf_tests/IndexConversionPerf.cpp',
'<(angle_path)/src/tests/perf_tests/InterleavedAttributeData.cpp',
'<(angle_path)/src/tests/perf_tests/PointSprites.cpp', '<(angle_path)/src/tests/perf_tests/PointSprites.cpp',
'<(angle_path)/src/tests/perf_tests/TexSubImage.cpp', '<(angle_path)/src/tests/perf_tests/TexSubImage.cpp',
'<(angle_path)/src/tests/perf_tests/third_party/perf/perf_test.cc', '<(angle_path)/src/tests/perf_tests/third_party/perf/perf_test.cc',
......
...@@ -45,7 +45,7 @@ struct BufferSubDataParams final : public RenderTestParams ...@@ -45,7 +45,7 @@ struct BufferSubDataParams final : public RenderTestParams
unsigned int iterations; unsigned int iterations;
}; };
std::ostream &operator<<(std::ostream &os, const BufferSubDataParams &params) inline std::ostream &operator<<(std::ostream &os, const BufferSubDataParams &params)
{ {
os << params.suffix().substr(1); os << params.suffix().substr(1);
return os; return os;
......
...@@ -55,7 +55,7 @@ struct DrawCallPerfParams final : public RenderTestParams ...@@ -55,7 +55,7 @@ struct DrawCallPerfParams final : public RenderTestParams
int numTris; int numTris;
}; };
std::ostream &operator<<(std::ostream &os, const DrawCallPerfParams &params) inline std::ostream &operator<<(std::ostream &os, const DrawCallPerfParams &params)
{ {
os << params.suffix().substr(1); os << params.suffix().substr(1);
return os; return os;
......
//
// Copyright (c) 2014 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.
//
// InterleavedAttributeData:
// Performance test for draws using interleaved attribute data in vertex buffers.
//
#include <sstream>
#include "ANGLEPerfTest.h"
#include "shader_utils.h"
using namespace angle;
namespace
{
struct InterleavedAttributeDataParams final : public RenderTestParams
{
InterleavedAttributeDataParams()
{
// Common default values
majorVersion = 2;
minorVersion = 0;
windowWidth = 512;
windowHeight = 512;
numSprites = 3000;
}
// static parameters
unsigned int numSprites;
};
std::ostream &operator<<(std::ostream &os, const InterleavedAttributeDataParams &params)
{
os << params.suffix().substr(1);
if (params.eglParameters.majorVersion != EGL_DONT_CARE)
{
os << "_" << params.eglParameters.majorVersion << "_" << params.eglParameters.minorVersion;
}
return os;
}
class InterleavedAttributeDataBenchmark
: public ANGLERenderTest,
public ::testing::WithParamInterface<InterleavedAttributeDataParams>
{
public:
InterleavedAttributeDataBenchmark();
void initializeBenchmark() override;
void destroyBenchmark() override;
void beginDrawBenchmark() override;
void drawBenchmark() override;
private:
GLuint mPointSpriteProgram;
GLuint mPositionColorBuffer[2];
// The buffers contain two floats and 3 unsigned bytes per point sprite
const size_t mBytesPerSprite = 2 * sizeof(float) + 3;
};
InterleavedAttributeDataBenchmark::InterleavedAttributeDataBenchmark()
: ANGLERenderTest("InterleavedAttributeData", GetParam()), mPointSpriteProgram(0)
{
}
void InterleavedAttributeDataBenchmark::initializeBenchmark()
{
const auto &params = GetParam();
// Compile point sprite shaders
const std::string vs =
"attribute vec4 aPosition;"
"attribute vec4 aColor;"
"varying vec4 vColor;"
"void main()"
"{"
" gl_PointSize = 25.0;"
" gl_Position = aPosition;"
" vColor = aColor;"
"}";
const std::string fs =
"precision mediump float;"
"varying vec4 vColor;"
"void main()"
"{"
" gl_FragColor = vColor;"
"}";
mPointSpriteProgram = CompileProgram(vs, fs);
ASSERT_TRUE(mPointSpriteProgram != 0);
glClearColor(0.0f, 1.0f, 0.0f, 1.0f);
for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
{
// Set up initial data for pointsprite positions and colors
std::vector<uint8_t> positionColorData(mBytesPerSprite * params.numSprites);
for (unsigned int j = 0; j < params.numSprites; j++)
{
float pointSpriteX =
(static_cast<float>(rand() % getWindow()->getWidth()) / getWindow()->getWidth()) *
2.0f - 1.0f;
float pointSpriteY =
(static_cast<float>(rand() % getWindow()->getHeight()) / getWindow()->getHeight()) *
2.0f - 1.0f;
GLubyte pointSpriteRed = static_cast<GLubyte>(rand() % 255);
GLubyte pointSpriteGreen = static_cast<GLubyte>(rand() % 255);
GLubyte pointSpriteBlue = static_cast<GLubyte>(rand() % 255);
// Add position data for the pointsprite
*reinterpret_cast<float *>(
&(positionColorData[j * mBytesPerSprite + 0 * sizeof(float) + 0])) =
pointSpriteX; // X
*reinterpret_cast<float *>(
&(positionColorData[j * mBytesPerSprite + 1 * sizeof(float) + 0])) =
pointSpriteY; // Y
// Add color data for the pointsprite
positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 0] = pointSpriteRed; // R
positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 1] = pointSpriteGreen; // G
positionColorData[j * mBytesPerSprite + 2 * sizeof(float) + 2] = pointSpriteBlue; // B
}
// Generate the GL buffer with the position/color data
glGenBuffers(1, &mPositionColorBuffer[i]);
glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
glBufferData(GL_ARRAY_BUFFER, params.numSprites * mBytesPerSprite, &(positionColorData[0]),
GL_STATIC_DRAW);
}
ASSERT_GL_NO_ERROR();
}
void InterleavedAttributeDataBenchmark::destroyBenchmark()
{
glDeleteProgram(mPointSpriteProgram);
for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
{
glDeleteBuffers(1, &mPositionColorBuffer[i]);
}
}
void InterleavedAttributeDataBenchmark::beginDrawBenchmark()
{
// Clear the color buffer
glClear(GL_COLOR_BUFFER_BIT);
}
void InterleavedAttributeDataBenchmark::drawBenchmark()
{
for (size_t k = 0; k < 4; k++)
{
for (size_t i = 0; i < ArraySize(mPositionColorBuffer); i++)
{
// Firstly get the attribute locations for the program
glUseProgram(mPointSpriteProgram);
GLint positionLocation = glGetAttribLocation(mPointSpriteProgram, "aPosition");
ASSERT_NE(positionLocation, -1);
GLint colorLocation = glGetAttribLocation(mPointSpriteProgram, "aColor");
ASSERT_NE(colorLocation, -1);
// Bind the position data from one buffer
glBindBuffer(GL_ARRAY_BUFFER, mPositionColorBuffer[i]);
glEnableVertexAttribArray(positionLocation);
glVertexAttribPointer(positionLocation, 2, GL_FLOAT, GL_FALSE,
static_cast<GLsizei>(mBytesPerSprite), 0);
// But bind the color data from the other buffer.
glBindBuffer(GL_ARRAY_BUFFER,
mPositionColorBuffer[(i + 1) % ArraySize(mPositionColorBuffer)]);
glEnableVertexAttribArray(colorLocation);
glVertexAttribPointer(colorLocation, 3, GL_UNSIGNED_BYTE, GL_TRUE,
static_cast<GLsizei>(mBytesPerSprite),
reinterpret_cast<void *>(2 * sizeof(float)));
// Then draw the colored pointsprites
glDrawArrays(GL_POINTS, 0, GetParam().numSprites);
glFlush();
glDisableVertexAttribArray(positionLocation);
glDisableVertexAttribArray(colorLocation);
}
}
ASSERT_GL_NO_ERROR();
}
TEST_P(InterleavedAttributeDataBenchmark, Run)
{
run();
}
InterleavedAttributeDataParams D3D11Params()
{
InterleavedAttributeDataParams params;
params.eglParameters = egl_platform::D3D11();
return params;
}
InterleavedAttributeDataParams D3D11_9_3Params()
{
InterleavedAttributeDataParams params;
params.eglParameters = egl_platform::D3D11_FL9_3();
return params;
}
InterleavedAttributeDataParams D3D9Params()
{
InterleavedAttributeDataParams params;
params.eglParameters = egl_platform::D3D9();
return params;
}
InterleavedAttributeDataParams OpenGLParams()
{
InterleavedAttributeDataParams params;
params.eglParameters = egl_platform::OPENGL();
return params;
}
ANGLE_INSTANTIATE_TEST(InterleavedAttributeDataBenchmark,
D3D11Params(),
D3D11_9_3Params(),
D3D9Params(),
OpenGLParams());
} // namespace
...@@ -45,7 +45,7 @@ struct PointSpritesParams final : public RenderTestParams ...@@ -45,7 +45,7 @@ struct PointSpritesParams final : public RenderTestParams
unsigned int iterations; unsigned int iterations;
}; };
std::ostream &operator<<(std::ostream &os, const PointSpritesParams &params) inline std::ostream &operator<<(std::ostream &os, const PointSpritesParams &params)
{ {
os << params.suffix().substr(1); os << params.suffix().substr(1);
return os; return os;
......
...@@ -44,7 +44,7 @@ struct TexSubImageParams final : public RenderTestParams ...@@ -44,7 +44,7 @@ struct TexSubImageParams final : public RenderTestParams
unsigned int iterations; unsigned int iterations;
}; };
std::ostream &operator<<(std::ostream &os, const TexSubImageParams &params) inline std::ostream &operator<<(std::ostream &os, const TexSubImageParams &params)
{ {
os << params.suffix().substr(1); os << params.suffix().substr(1);
return os; return os;
......
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