| // |
| // Copyright 2015 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. |
| // |
| // IndexDataManagerPerfTest: |
| // Performance test for index buffer management. |
| // |
| |
| #include "ANGLEPerfTest.h" |
| |
| #include <gmock/gmock.h> |
| |
| #include "angle_unittests_utils.h" |
| #include "libANGLE/renderer/d3d/BufferD3D.h" |
| #include "libANGLE/renderer/d3d/IndexBuffer.h" |
| #include "libANGLE/renderer/d3d/IndexDataManager.h" |
| |
| using namespace testing; |
| |
| namespace |
| { |
| constexpr unsigned int kIterationsPerStep = 100; |
| |
| class MockIndexBuffer : public rx::IndexBuffer |
| { |
| public: |
| MockIndexBuffer(unsigned int bufferSize, gl::DrawElementsType indexType) |
| : mBufferSize(bufferSize), mIndexType(indexType) |
| {} |
| |
| MOCK_METHOD4(initialize, |
| angle::Result(const gl::Context *, unsigned int, gl::DrawElementsType, bool)); |
| MOCK_METHOD4(mapBuffer, |
| angle::Result(const gl::Context *, unsigned int, unsigned int, void **)); |
| MOCK_METHOD1(unmapBuffer, angle::Result(const gl::Context *)); |
| MOCK_METHOD1(discard, angle::Result(const gl::Context *)); |
| MOCK_METHOD3(setSize, angle::Result(const gl::Context *, unsigned int, gl::DrawElementsType)); |
| |
| // inlined for speed |
| gl::DrawElementsType getIndexType() const override { return mIndexType; } |
| unsigned int getBufferSize() const override { return mBufferSize; } |
| |
| private: |
| unsigned int mBufferSize; |
| gl::DrawElementsType mIndexType; |
| }; |
| |
| class MockBufferFactoryD3D : public rx::BufferFactoryD3D |
| { |
| public: |
| MockBufferFactoryD3D(unsigned int bufferSize, gl::DrawElementsType indexType) |
| : mBufferSize(bufferSize), mIndexType(indexType) |
| {} |
| |
| MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer *()); |
| MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(angle::FormatID)); |
| MOCK_CONST_METHOD1(getVertexComponentType, GLenum(angle::FormatID)); |
| MOCK_CONST_METHOD6(getVertexSpaceRequired, |
| angle::Result(const gl::Context *, |
| const gl::VertexAttribute &, |
| const gl::VertexBinding &, |
| size_t, |
| GLsizei, |
| unsigned int *)); |
| |
| // Dependency injection |
| rx::IndexBuffer *createIndexBuffer() override |
| { |
| return new MockIndexBuffer(mBufferSize, mIndexType); |
| } |
| |
| private: |
| unsigned int mBufferSize; |
| gl::DrawElementsType mIndexType; |
| }; |
| |
| class MockBufferD3D : public rx::BufferD3D |
| { |
| public: |
| MockBufferD3D(rx::BufferFactoryD3D *factory) : BufferD3D(mockState, factory), mData() {} |
| |
| // BufferImpl |
| angle::Result setData(const gl::Context *context, |
| gl::BufferBinding target, |
| const void *data, |
| size_t size, |
| gl::BufferUsage) override |
| { |
| mData.resize(size); |
| if (data && size > 0) |
| { |
| memcpy(&mData[0], data, size); |
| } |
| return angle::Result::Continue; |
| } |
| |
| MOCK_METHOD5( |
| setSubData, |
| angle::Result(const gl::Context *, gl::BufferBinding, const void *, size_t, size_t)); |
| MOCK_METHOD5(copySubData, |
| angle::Result(const gl::Context *, BufferImpl *, GLintptr, GLintptr, GLsizeiptr)); |
| MOCK_METHOD3(map, angle::Result(const gl::Context *context, GLenum, void **)); |
| MOCK_METHOD5(mapRange, angle::Result(const gl::Context *, size_t, size_t, GLbitfield, void **)); |
| MOCK_METHOD2(unmap, angle::Result(const gl::Context *context, GLboolean *)); |
| |
| // BufferD3D |
| MOCK_METHOD1(markTransformFeedbackUsage, angle::Result(const gl::Context *)); |
| |
| // inlined for speed |
| bool supportsDirectBinding() const override { return false; } |
| size_t getSize() const override { return mData.size(); } |
| |
| angle::Result getData(const gl::Context *context, const uint8_t **outData) override |
| { |
| *outData = &mData[0]; |
| return angle::Result::Continue; |
| } |
| |
| private: |
| gl::BufferState mockState; |
| std::vector<uint8_t> mData; |
| }; |
| |
| class MockGLFactoryD3D : public rx::MockGLFactory |
| { |
| public: |
| MockGLFactoryD3D(MockBufferFactoryD3D *bufferFactory) : mBufferFactory(bufferFactory) {} |
| |
| rx::BufferImpl *createBuffer(const gl::BufferState &state) override |
| { |
| MockBufferD3D *mockBufferD3D = new MockBufferD3D(mBufferFactory); |
| |
| EXPECT_CALL(*mBufferFactory, createVertexBuffer()) |
| .WillOnce(Return(nullptr)) |
| .RetiresOnSaturation(); |
| mockBufferD3D->initializeStaticData(nullptr); |
| |
| return mockBufferD3D; |
| } |
| |
| MockBufferFactoryD3D *mBufferFactory; |
| }; |
| |
| class IndexDataManagerPerfTest : public ANGLEPerfTest |
| { |
| public: |
| IndexDataManagerPerfTest(); |
| |
| void step() override; |
| |
| rx::IndexDataManager mIndexDataManager; |
| GLsizei mIndexCount; |
| unsigned int mBufferSize; |
| MockBufferFactoryD3D mMockBufferFactory; |
| MockGLFactoryD3D mMockGLFactory; |
| gl::Buffer mIndexBuffer; |
| }; |
| |
| IndexDataManagerPerfTest::IndexDataManagerPerfTest() |
| : ANGLEPerfTest("IndexDataManager", "", "_run", kIterationsPerStep), |
| mIndexDataManager(&mMockBufferFactory), |
| mIndexCount(4000), |
| mBufferSize(mIndexCount * sizeof(GLushort)), |
| mMockBufferFactory(mBufferSize, gl::DrawElementsType::UnsignedShort), |
| mMockGLFactory(&mMockBufferFactory), |
| mIndexBuffer(&mMockGLFactory, {1}) |
| { |
| std::vector<GLushort> indexData(mIndexCount); |
| for (GLsizei index = 0; index < mIndexCount; ++index) |
| { |
| indexData[index] = static_cast<GLushort>(index); |
| } |
| EXPECT_EQ( |
| angle::Result::Continue, |
| mIndexBuffer.bufferData(nullptr, gl::BufferBinding::Array, &indexData[0], |
| indexData.size() * sizeof(GLushort), gl::BufferUsage::StaticDraw)); |
| } |
| |
| void IndexDataManagerPerfTest::step() |
| { |
| rx::TranslatedIndexData translatedIndexData; |
| gl::IndexRange indexRange; |
| for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration) |
| { |
| (void)mIndexBuffer.getIndexRange(nullptr, gl::DrawElementsType::UnsignedShort, 0, |
| mIndexCount, false, &indexRange); |
| (void)mIndexDataManager.prepareIndexData(nullptr, gl::DrawElementsType::UnsignedShort, |
| gl::DrawElementsType::UnsignedShort, mIndexCount, |
| &mIndexBuffer, nullptr, &translatedIndexData); |
| } |
| } |
| |
| TEST_F(IndexDataManagerPerfTest, Run) |
| { |
| run(); |
| } |
| |
| } // anonymous namespace |