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 // D3D11InputLayoutCacheTest:
7 // Stress to to reproduce a bug where we weren't flushing the case correctly.
8 //
9
10 #include <sstream>
11
12 #include "libANGLE/Context.h"
13 #include "libANGLE/Display.h"
14 #include "libANGLE/renderer/d3d/d3d11/Context11.h"
15 #include "libANGLE/renderer/d3d/d3d11/Renderer11.h"
16 #include "test_utils/ANGLETest.h"
17 #include "test_utils/angle_test_instantiate.h"
18 #include "util/EGLWindow.h"
19
20 using namespace angle;
21
22 namespace
23 {
24
25 class D3D11InputLayoutCacheTest : public ANGLETest<>
26 {
27 protected:
D3D11InputLayoutCacheTest()28 D3D11InputLayoutCacheTest()
29 {
30 setWindowWidth(64);
31 setWindowHeight(64);
32 setConfigRedBits(8);
33 setConfigAlphaBits(8);
34 }
35
makeProgramWithAttribCount(unsigned int attribCount)36 GLuint makeProgramWithAttribCount(unsigned int attribCount)
37 {
38 std::stringstream strstr;
39
40 strstr << "attribute vec2 position;" << std::endl;
41 for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
42 {
43 strstr << "attribute float a" << attribIndex << ";" << std::endl;
44 }
45 strstr << "varying float v;" << std::endl
46 << "void main() {" << std::endl
47 << " v = 0.0;" << std::endl;
48 for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
49 {
50 strstr << " v += a" << attribIndex << ";" << std::endl;
51 }
52 strstr << " gl_Position = vec4(position, 0.0, 1.0);" << std::endl << "}" << std::endl;
53
54 constexpr char kFS[] =
55 "varying highp float v;\n"
56 "void main() {"
57 " gl_FragColor = vec4(v / 255.0, 0.0, 0.0, 1.0);\n"
58 "}\n";
59
60 return CompileProgram(strstr.str().c_str(), kFS);
61 }
62 };
63
64 // Stress the cache by setting a small cache size and drawing with a bunch of shaders
65 // with different input signatures.
TEST_P(D3D11InputLayoutCacheTest,StressTest)66 TEST_P(D3D11InputLayoutCacheTest, StressTest)
67 {
68 // Hack the ANGLE!
69 egl::Display *display = static_cast<egl::Display *>(getEGLWindow()->getDisplay());
70 gl::ContextID contextID = {
71 static_cast<GLuint>(reinterpret_cast<uintptr_t>(getEGLWindow()->getContext()))};
72 gl::Context *context = display->getContext(contextID);
73 rx::Context11 *context11 = rx::GetImplAs<rx::Context11>(context);
74 rx::Renderer11 *renderer11 = context11->getRenderer();
75 rx::InputLayoutCache *inputLayoutCache = renderer11->getStateManager()->getInputLayoutCache();
76
77 // Clamp the cache size to something tiny
78 inputLayoutCache->setCacheSize(4);
79
80 GLint maxAttribs = 0;
81 context->getIntegerv(GL_MAX_VERTEX_ATTRIBS, &maxAttribs);
82
83 // Reserve one attrib for position
84 unsigned int maxInputs = static_cast<unsigned int>(maxAttribs) - 2;
85
86 std::vector<GLuint> programs;
87 for (unsigned int attribCount = 0; attribCount <= maxInputs; ++attribCount)
88 {
89 GLuint program = makeProgramWithAttribCount(attribCount);
90 ASSERT_NE(0u, program);
91 programs.push_back(program);
92 }
93
94 // Iteratively do a simple drop operation, trying every attribute count from 0..MAX_ATTRIBS.
95 // This should thrash the cache.
96 for (unsigned int iterationCount = 0; iterationCount < 10; ++iterationCount)
97 {
98 ASSERT_GL_NO_ERROR();
99
100 for (unsigned int attribCount = 0; attribCount <= maxInputs; ++attribCount)
101 {
102 GLuint program = programs[attribCount];
103 glUseProgram(program);
104
105 for (unsigned int attribIndex = 0; attribIndex < attribCount; ++attribIndex)
106 {
107 std::stringstream attribNameStr;
108 attribNameStr << "a" << attribIndex;
109 std::string attribName = attribNameStr.str();
110
111 GLint location = glGetAttribLocation(program, attribName.c_str());
112 ASSERT_NE(-1, location);
113 glVertexAttrib1f(location, 1.0f);
114 glDisableVertexAttribArray(location);
115 }
116
117 drawQuad(program, "position", 0.5f);
118 EXPECT_PIXEL_EQ(0, 0, attribCount, 0, 0, 255u);
119 }
120 }
121
122 for (GLuint program : programs)
123 {
124 glDeleteProgram(program);
125 }
126 }
127
128 ANGLE_INSTANTIATE_TEST(D3D11InputLayoutCacheTest, ES2_D3D11(), ES3_D3D11(), ES31_D3D11());
129
130 } // anonymous namespace
131