• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2015 The ANGLE Project Authors. All rights reserved.
3 // Use of this source code is governed by a BSD-style license that can be
4 // found in the LICENSE file.
5 //
6 // IndexDataManagerPerfTest:
7 //   Performance test for index buffer management.
8 //
9 
10 #include "ANGLEPerfTest.h"
11 
12 #include <gmock/gmock.h>
13 
14 #include "angle_unittests_utils.h"
15 #include "libANGLE/renderer/d3d/BufferD3D.h"
16 #include "libANGLE/renderer/d3d/IndexBuffer.h"
17 #include "libANGLE/renderer/d3d/IndexDataManager.h"
18 
19 using namespace testing;
20 
21 namespace
22 {
23 constexpr unsigned int kIterationsPerStep = 100;
24 
25 class MockIndexBuffer : public rx::IndexBuffer
26 {
27   public:
MockIndexBuffer(unsigned int bufferSize,gl::DrawElementsType indexType)28     MockIndexBuffer(unsigned int bufferSize, gl::DrawElementsType indexType)
29         : mBufferSize(bufferSize), mIndexType(indexType)
30     {}
31 
32     MOCK_METHOD4(initialize,
33                  angle::Result(const gl::Context *, unsigned int, gl::DrawElementsType, bool));
34     MOCK_METHOD4(mapBuffer,
35                  angle::Result(const gl::Context *, unsigned int, unsigned int, void **));
36     MOCK_METHOD1(unmapBuffer, angle::Result(const gl::Context *));
37     MOCK_METHOD1(discard, angle::Result(const gl::Context *));
38     MOCK_METHOD3(setSize, angle::Result(const gl::Context *, unsigned int, gl::DrawElementsType));
39 
40     // inlined for speed
getIndexType() const41     gl::DrawElementsType getIndexType() const override { return mIndexType; }
getBufferSize() const42     unsigned int getBufferSize() const override { return mBufferSize; }
43 
44   private:
45     unsigned int mBufferSize;
46     gl::DrawElementsType mIndexType;
47 };
48 
49 class MockBufferFactoryD3D : public rx::BufferFactoryD3D
50 {
51   public:
MockBufferFactoryD3D(unsigned int bufferSize,gl::DrawElementsType indexType)52     MockBufferFactoryD3D(unsigned int bufferSize, gl::DrawElementsType indexType)
53         : mBufferSize(bufferSize), mIndexType(indexType)
54     {}
55 
56     MOCK_METHOD0(createVertexBuffer, rx::VertexBuffer *());
57     MOCK_CONST_METHOD1(getVertexConversionType, rx::VertexConversionType(angle::FormatID));
58     MOCK_CONST_METHOD1(getVertexComponentType, GLenum(angle::FormatID));
59     MOCK_CONST_METHOD6(getVertexSpaceRequired,
60                        angle::Result(const gl::Context *,
61                                      const gl::VertexAttribute &,
62                                      const gl::VertexBinding &,
63                                      size_t,
64                                      GLsizei,
65                                      unsigned int *));
66 
67     // Dependency injection
createIndexBuffer()68     rx::IndexBuffer *createIndexBuffer() override
69     {
70         return new MockIndexBuffer(mBufferSize, mIndexType);
71     }
72 
73   private:
74     unsigned int mBufferSize;
75     gl::DrawElementsType mIndexType;
76 };
77 
78 class MockBufferD3D : public rx::BufferD3D
79 {
80   public:
MockBufferD3D(rx::BufferFactoryD3D * factory)81     MockBufferD3D(rx::BufferFactoryD3D *factory) : BufferD3D(mockState, factory), mData() {}
82 
83     // BufferImpl
setData(const gl::Context * context,gl::BufferBinding target,const void * data,size_t size,gl::BufferUsage)84     angle::Result setData(const gl::Context *context,
85                           gl::BufferBinding target,
86                           const void *data,
87                           size_t size,
88                           gl::BufferUsage) override
89     {
90         mData.resize(size);
91         if (data && size > 0)
92         {
93             memcpy(&mData[0], data, size);
94         }
95         return angle::Result::Continue;
96     }
97 
98     MOCK_METHOD5(
99         setSubData,
100         angle::Result(const gl::Context *, gl::BufferBinding, const void *, size_t, size_t));
101     MOCK_METHOD5(copySubData,
102                  angle::Result(const gl::Context *, BufferImpl *, GLintptr, GLintptr, GLsizeiptr));
103     MOCK_METHOD3(map, angle::Result(const gl::Context *context, GLenum, void **));
104     MOCK_METHOD5(mapRange, angle::Result(const gl::Context *, size_t, size_t, GLbitfield, void **));
105     MOCK_METHOD2(unmap, angle::Result(const gl::Context *context, GLboolean *));
106 
107     // BufferD3D
108     MOCK_METHOD1(markTransformFeedbackUsage, angle::Result(const gl::Context *));
109 
110     // inlined for speed
supportsDirectBinding() const111     bool supportsDirectBinding() const override { return false; }
getSize() const112     size_t getSize() const override { return mData.size(); }
113 
getData(const gl::Context * context,const uint8_t ** outData)114     angle::Result getData(const gl::Context *context, const uint8_t **outData) override
115     {
116         *outData = &mData[0];
117         return angle::Result::Continue;
118     }
119 
120   private:
121     gl::BufferState mockState;
122     std::vector<uint8_t> mData;
123 };
124 
125 class MockGLFactoryD3D : public rx::MockGLFactory
126 {
127   public:
MockGLFactoryD3D(MockBufferFactoryD3D * bufferFactory)128     MockGLFactoryD3D(MockBufferFactoryD3D *bufferFactory) : mBufferFactory(bufferFactory) {}
129 
createBuffer(const gl::BufferState & state)130     rx::BufferImpl *createBuffer(const gl::BufferState &state) override
131     {
132         MockBufferD3D *mockBufferD3D = new MockBufferD3D(mBufferFactory);
133 
134         EXPECT_CALL(*mBufferFactory, createVertexBuffer())
135             .WillOnce(Return(nullptr))
136             .RetiresOnSaturation();
137         mockBufferD3D->initializeStaticData(nullptr);
138 
139         return mockBufferD3D;
140     }
141 
142     MockBufferFactoryD3D *mBufferFactory;
143 };
144 
145 class IndexDataManagerPerfTest : public ANGLEPerfTest
146 {
147   public:
148     IndexDataManagerPerfTest();
149 
150     void step() override;
151 
152     rx::IndexDataManager mIndexDataManager;
153     GLsizei mIndexCount;
154     unsigned int mBufferSize;
155     MockBufferFactoryD3D mMockBufferFactory;
156     MockGLFactoryD3D mMockGLFactory;
157     gl::Buffer mIndexBuffer;
158 };
159 
IndexDataManagerPerfTest()160 IndexDataManagerPerfTest::IndexDataManagerPerfTest()
161     : ANGLEPerfTest("IndexDataManager", "", "_run", kIterationsPerStep),
162       mIndexDataManager(&mMockBufferFactory),
163       mIndexCount(4000),
164       mBufferSize(mIndexCount * sizeof(GLushort)),
165       mMockBufferFactory(mBufferSize, gl::DrawElementsType::UnsignedShort),
166       mMockGLFactory(&mMockBufferFactory),
167       mIndexBuffer(&mMockGLFactory, {1})
168 {
169     std::vector<GLushort> indexData(mIndexCount);
170     for (GLsizei index = 0; index < mIndexCount; ++index)
171     {
172         indexData[index] = static_cast<GLushort>(index);
173     }
174     EXPECT_EQ(
175         angle::Result::Continue,
176         mIndexBuffer.bufferData(nullptr, gl::BufferBinding::Array, &indexData[0],
177                                 indexData.size() * sizeof(GLushort), gl::BufferUsage::StaticDraw));
178 }
179 
step()180 void IndexDataManagerPerfTest::step()
181 {
182     rx::TranslatedIndexData translatedIndexData;
183     gl::IndexRange indexRange;
184     for (unsigned int iteration = 0; iteration < kIterationsPerStep; ++iteration)
185     {
186         (void)mIndexBuffer.getIndexRange(nullptr, gl::DrawElementsType::UnsignedShort, 0,
187                                          mIndexCount, false, &indexRange);
188         (void)mIndexDataManager.prepareIndexData(nullptr, gl::DrawElementsType::UnsignedShort,
189                                                  gl::DrawElementsType::UnsignedShort, mIndexCount,
190                                                  &mIndexBuffer, nullptr, &translatedIndexData);
191     }
192 }
193 
TEST_F(IndexDataManagerPerfTest,Run)194 TEST_F(IndexDataManagerPerfTest, Run)
195 {
196     run();
197 }
198 
199 }  // anonymous namespace
200