| // |
| // Copyright 2019 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. |
| // |
| // ClearPerf: |
| // Performance test for clearing framebuffers. |
| // |
| |
| #include "ANGLEPerfTest.h" |
| |
| #include <iostream> |
| #include <random> |
| #include <sstream> |
| |
| #include "test_utils/ANGLETest.h" |
| #include "test_utils/gl_raii.h" |
| #include "util/random_utils.h" |
| #include "util/shader_utils.h" |
| |
| using namespace angle; |
| |
| namespace |
| { |
| constexpr unsigned int kIterationsPerStep = 256; |
| |
| struct ClearParams final : public RenderTestParams |
| { |
| ClearParams() |
| { |
| iterationsPerStep = kIterationsPerStep; |
| trackGpuTime = true; |
| |
| fboSize = 2048; |
| |
| internalFormat = GL_RGBA8; |
| |
| scissoredClear = false; |
| } |
| |
| std::string story() const override; |
| |
| GLsizei fboSize; |
| GLsizei textureSize; |
| |
| GLenum internalFormat; |
| |
| bool scissoredClear; |
| }; |
| |
| std::ostream &operator<<(std::ostream &os, const ClearParams ¶ms) |
| { |
| os << params.backendAndStory().substr(1); |
| return os; |
| } |
| |
| std::string ClearParams::story() const |
| { |
| std::stringstream strstr; |
| |
| strstr << RenderTestParams::story(); |
| |
| if (internalFormat == GL_RGB8) |
| { |
| strstr << "_rgb"; |
| } |
| |
| if (scissoredClear) |
| { |
| strstr << "_scissoredClear"; |
| } |
| |
| return strstr.str(); |
| } |
| |
| class ClearBenchmark : public ANGLERenderTest, public ::testing::WithParamInterface<ClearParams> |
| { |
| public: |
| ClearBenchmark(); |
| |
| void initializeBenchmark() override; |
| void destroyBenchmark() override; |
| void drawBenchmark() override; |
| |
| private: |
| void initShaders(); |
| |
| std::vector<GLuint> mTextures; |
| |
| GLuint mProgram; |
| }; |
| |
| ClearBenchmark::ClearBenchmark() : ANGLERenderTest("Clear", GetParam()), mProgram(0u) |
| { |
| if (GetParam().getRenderer() == EGL_PLATFORM_ANGLE_TYPE_D3D11_ANGLE) |
| { |
| skipTest("http://crbug.com/945415 Crashes on nvidia+d3d11"); |
| } |
| } |
| |
| void ClearBenchmark::initializeBenchmark() |
| { |
| initShaders(); |
| glViewport(0, 0, getWindow()->getWidth(), getWindow()->getHeight()); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| void ClearBenchmark::initShaders() |
| { |
| constexpr char kVS[] = R"(void main() |
| { |
| gl_Position = vec4(0, 0, 0, 1); |
| })"; |
| |
| constexpr char kFS[] = R"(precision mediump float; |
| void main() |
| { |
| gl_FragColor = vec4(0); |
| })"; |
| |
| mProgram = CompileProgram(kVS, kFS); |
| ASSERT_NE(0u, mProgram); |
| |
| glUseProgram(mProgram); |
| |
| glDisable(GL_DEPTH_TEST); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| void ClearBenchmark::destroyBenchmark() |
| { |
| glDeleteProgram(mProgram); |
| } |
| |
| void ClearBenchmark::drawBenchmark() |
| { |
| const auto ¶ms = GetParam(); |
| |
| GLRenderbuffer colorRbo; |
| glBindRenderbuffer(GL_RENDERBUFFER, colorRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, params.internalFormat, params.fboSize, params.fboSize); |
| |
| GLRenderbuffer depthRbo; |
| glBindRenderbuffer(GL_RENDERBUFFER, depthRbo); |
| glRenderbufferStorage(GL_RENDERBUFFER, GL_DEPTH_COMPONENT16, params.fboSize, params.fboSize); |
| |
| GLFramebuffer fbo; |
| glBindFramebuffer(GL_FRAMEBUFFER, fbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, colorRbo); |
| glFramebufferRenderbuffer(GL_FRAMEBUFFER, GL_DEPTH_ATTACHMENT, GL_RENDERBUFFER, depthRbo); |
| |
| glViewport(0, 0, params.fboSize, params.fboSize); |
| glDisable(GL_SCISSOR_TEST); |
| |
| startGpuTimer(); |
| |
| if (params.scissoredClear) |
| { |
| angle::RNG rng; |
| const GLuint width = params.fboSize; |
| const GLuint height = params.fboSize; |
| for (GLuint index = 0; index < (width - 1) / 2; index++) |
| { |
| // Do the first clear without the scissor. |
| if (index > 0) |
| { |
| glEnable(GL_SCISSOR_TEST); |
| glScissor(index, index, width - (index * 2), height - (index * 2)); |
| } |
| |
| GLColor color = RandomColor(&rng); |
| Vector4 floatColor = color.toNormalizedVector(); |
| glClearColor(floatColor[0], floatColor[1], floatColor[2], floatColor[3]); |
| glClear(GL_COLOR_BUFFER_BIT); |
| } |
| } |
| else |
| { |
| for (size_t it = 0; it < params.iterationsPerStep; ++it) |
| { |
| float clearValue = (it % 2) * 0.5f + 0.2f; |
| glClearColor(clearValue, clearValue, clearValue, clearValue); |
| glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); |
| glDrawArrays(GL_TRIANGLES, 0, 3); |
| } |
| } |
| |
| stopGpuTimer(); |
| |
| ASSERT_GL_NO_ERROR(); |
| } |
| |
| ClearParams D3D11Params() |
| { |
| ClearParams params; |
| params.eglParameters = egl_platform::D3D11(); |
| return params; |
| } |
| |
| ClearParams MetalParams() |
| { |
| ClearParams params; |
| params.eglParameters = egl_platform::METAL(); |
| return params; |
| } |
| |
| ClearParams OpenGLOrGLESParams() |
| { |
| ClearParams params; |
| params.eglParameters = egl_platform::OPENGL_OR_GLES(); |
| return params; |
| } |
| |
| ClearParams VulkanParams(bool emulatedFormat, bool scissoredClear) |
| { |
| ClearParams params; |
| params.eglParameters = egl_platform::VULKAN(); |
| if (emulatedFormat) |
| { |
| params.internalFormat = GL_RGB8; |
| } |
| params.scissoredClear = scissoredClear; |
| return params; |
| } |
| |
| } // anonymous namespace |
| |
| TEST_P(ClearBenchmark, Run) |
| { |
| run(); |
| } |
| |
| ANGLE_INSTANTIATE_TEST(ClearBenchmark, |
| D3D11Params(), |
| MetalParams(), |
| OpenGLOrGLESParams(), |
| VulkanParams(false, false), |
| VulkanParams(true, false), |
| VulkanParams(false, true)); |