Edit

kc3-lang/angle/src/tests/perf_tests/CompilerPerf.cpp

Branch :

  • Show log

    Commit

  • Author : Brian Sheedy
    Date : 2019-08-16 14:09:13
    Hash : 2f4a7518
    Message : Refactor perf tests to fix metric/story swapping Refactors the perf tests to fix the issue of metric and story being swapped, which causes issues when trying to convert to histograms. Specifically, does the following: 1. Rolls the version of src/tests/perf_tests/third_party/perf/ to Chromium 476dae823269c8d05b544271af97ad1adb0db8ee 2. Switch to using PerfResultReporter instead of PrintResult directly. 3. Split RenderTestParams::suffix into backend and story; backend is used as part of the metric, while story is used as the story. 4. Remove the "average" metric that was being automatically reported by ANGLEPerfTest, as reported results are automatically averaged. 5. Update the reported metric to more clearly distinguish between test, backend, and metric. It is now name_backend.metric. e.g. DrawCallPerf_vulkan.wall_time. Bug: chromium:923564,chromium:924618 Change-Id: I00cc191407052f23df57dbfa53b6fb088fc26960 Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/1762360 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jamie Madill <jmadill@chromium.org> Reviewed-by: Jonah Ryan-Davis <jonahr@google.com>

  • src/tests/perf_tests/CompilerPerf.cpp
  • //
    // Copyright 2018 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.
    //
    // CompilerPerfTest:
    //   Performance test for the shader translator. The test initializes the compiler once and then
    //   compiles the same shader repeatedly. There are different variations of the tests using
    //   different shaders.
    //
    
    #include "ANGLEPerfTest.h"
    
    #include "GLSLANG/ShaderLang.h"
    #include "compiler/translator/Compiler.h"
    #include "compiler/translator/InitializeGlobals.h"
    #include "compiler/translator/PoolAlloc.h"
    
    namespace
    {
    
    const char *kSimpleESSL100FragSource = R"(
    precision mediump float;
    void main()
    {
        gl_FragColor = vec4(0, 1, 0, 1);
    }
    )";
    
    const char *kSimpleESSL100Id = "SimpleESSL100";
    
    const char *kSimpleESSL300FragSource = R"(#version 300 es
    precision highp float;
    out vec4 outColor;
    void main()
    {
        outColor = vec4(0, 1, 0, 1);
    }
    )";
    
    const char *kSimpleESSL300Id = "SimpleESSL300";
    
    const char *kRealWorldESSL100FragSource = R"(precision highp float;
    precision highp sampler2D;
    precision highp int;
    varying vec2 vPixelCoords; // in pixels
    uniform int uCircleCount;
    uniform sampler2D uCircleParameters;
    uniform sampler2D uBrushTex;
    void main(void)
    {
        float destAlpha = 0.0;
        for (int i = 0; i < 32; ++i)
        {
            vec4 parameterColor = texture2D(uCircleParameters,vec2(0.25, (float(i) + 0.5) / 32.0));
            vec2 center = parameterColor.xy;
            float circleRadius = parameterColor.z;
            float circleFlowAlpha = parameterColor.w;
            vec4 parameterColor2 = texture2D(uCircleParameters,vec2(0.75, (float(i) + 0.5) / 32.0));
            float circleRotation = parameterColor2.x;
            vec2 centerDiff = vPixelCoords - center;
            float radius = max(circleRadius, 0.5);
            float flowAlpha = (circleRadius < 0.5) ? circleFlowAlpha * circleRadius * circleRadius * 4.0: circleFlowAlpha;
            float antialiasMult = clamp((radius + 1.0 - length(centerDiff)) * 0.5, 0.0, 1.0);
            mat2 texRotation = mat2(cos(circleRotation), -sin(circleRotation), sin(circleRotation), cos(circleRotation));
            vec2 texCoords = texRotation * centerDiff / radius * 0.5 + 0.5;
            float texValue = texture2D(uBrushTex, texCoords).r;
            float circleAlpha = flowAlpha * antialiasMult * texValue;
            if (i < uCircleCount)
            {
                destAlpha = clamp(circleAlpha + (1.0 - circleAlpha) * destAlpha, 0.0, 1.0);
            }
        }
        gl_FragColor = vec4(0.0, 0.0, 0.0, destAlpha);
    })";
    
    const char *kRealWorldESSL100Id = "RealWorldESSL100";
    
    // This shader is intended to trigger many AST transformations, particularly on the HLSL backend.
    const char *kTrickyESSL300FragSource = R"(#version 300 es
    precision highp float;
    precision highp sampler2D;
    precision highp isampler2D;
    precision highp int;
    
    float globalF;
    
    uniform ivec4 uivec;
    uniform int ui;
    
    struct SS
    {
        int iField;
        float fField;
        vec2 f2Field;
        sampler2D sField;
        isampler2D isField;
    };
    uniform SS us;
    
    out vec4 my_FragColor;
    
    float[3] sideEffectArray()
    {
        globalF += 1.0;
        return float[3](globalF, globalF * 2.0, globalF * 3.0);
    }
    
    // This struct is unused and can be pruned.
    struct SUnused
    {
        vec2 fField;
    };
    
    void main()
    {
        struct S2
        {
            float fField;
        } s2;
        vec4 foo = vec4(ui);
        mat4 fooM = mat4(foo.x);
    
        // Some unused variables that can be pruned.
        float fUnused, fUnused2;
        ivec4 iUnused, iUnused2;
    
        globalF = us.fField;
        s2.fField = us.fField;
    
        float[3] fa = sideEffectArray();
    
        globalF -= us.fField;
        if (fa == sideEffectArray())
        {
            globalF += us.fField * sin(2.0);
        }
    
        // Switch with fall-through.
        switch (ui)
        {
          case 0:
            // Sequence operator and matrix and vector dynamic indexing.
            (globalF += 1.0, fooM[ui][ui] += fooM[ui - 1][uivec[ui] + 1]);
          case 1:
            // Built-in emulation.
            foo[3] = tanh(foo[1]);
          default:
            // Sequence operator and length of an array expression with side effects.
            foo[2] += (globalF -= 1.0, float((sideEffectArray()).length() * 2));
        }
        int i = 0;
        do
        {
            s2.fField = us.fField * us.f2Field.x;
            // Sequence operator and short-circuiting operator with side effects on the right hand side.
        } while ((++i, i < int(us.fField) && ++i <= ui || ++i < ui * 2 - 3));
        // Samplers in structures and integer texture sampling.
        foo += texture(us.sField, us.f2Field) + intBitsToFloat(texture(us.isField, us.f2Field + 4.0));
        my_FragColor = foo * s2.fField * globalF + fooM[ui];
    })";
    
    const char *kTrickyESSL300Id = "TrickyESSL300";
    
    constexpr int kNumIterationsPerStep = 4;
    
    struct CompilerParameters
    {
        CompilerParameters() { output = SH_HLSL_4_1_OUTPUT; }
    
        CompilerParameters(ShShaderOutput output) : output(output) {}
    
        const char *str() const
        {
            switch (output)
            {
                case SH_HLSL_4_1_OUTPUT:
                    return "HLSL_4_1";
                case SH_GLSL_450_CORE_OUTPUT:
                    return "GLSL_4_50";
                case SH_ESSL_OUTPUT:
                    return "ESSL";
                default:
                    UNREACHABLE();
                    return "unk";
            }
        }
    
        ShShaderOutput output;
    };
    
    bool IsPlatformAvailable(const CompilerParameters &param)
    {
        switch (param.output)
        {
            case SH_HLSL_4_1_OUTPUT:
            case SH_HLSL_4_0_FL9_3_OUTPUT:
            case SH_HLSL_3_0_OUTPUT:
            {
                angle::PoolAllocator allocator;
                InitializePoolIndex();
                allocator.push();
                SetGlobalPoolAllocator(&allocator);
                ShHandle translator =
                    sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC, param.output);
                bool success = translator != nullptr;
                SetGlobalPoolAllocator(nullptr);
                allocator.pop();
                FreePoolIndex();
                if (!success)
                {
                    return false;
                }
                break;
            }
            default:
                break;
        }
        return true;
    }
    
    struct CompilerPerfParameters final : public CompilerParameters
    {
        CompilerPerfParameters(ShShaderOutput output,
                               const char *shaderSource,
                               const char *shaderSourceId)
            : CompilerParameters(output), shaderSource(shaderSource)
        {
            testId = shaderSourceId;
            testId += "_";
            testId += CompilerParameters::str();
        }
    
        const char *shaderSource;
        std::string testId;
    };
    
    std::ostream &operator<<(std::ostream &stream, const CompilerPerfParameters &p)
    {
        stream << p.testId;
        return stream;
    }
    
    class CompilerPerfTest : public ANGLEPerfTest,
                             public ::testing::WithParamInterface<CompilerPerfParameters>
    {
      public:
        CompilerPerfTest();
    
        void step() override;
    
        void SetUp() override;
        void TearDown() override;
    
      protected:
        void setTestShader(const char *str) { mTestShader = str; }
    
      private:
        const char *mTestShader;
    
        ShBuiltInResources mResources;
        angle::PoolAllocator mAllocator;
        sh::TCompiler *mTranslator;
    };
    
    CompilerPerfTest::CompilerPerfTest()
        : ANGLEPerfTest("CompilerPerf", "", GetParam().testId, kNumIterationsPerStep)
    {}
    
    void CompilerPerfTest::SetUp()
    {
        ANGLEPerfTest::SetUp();
    
        InitializePoolIndex();
        mAllocator.push();
        SetGlobalPoolAllocator(&mAllocator);
    
        const auto &params = GetParam();
    
        mTranslator = sh::ConstructCompiler(GL_FRAGMENT_SHADER, SH_WEBGL2_SPEC, params.output);
        sh::InitBuiltInResources(&mResources);
        mResources.FragmentPrecisionHigh = true;
        if (!mTranslator->Init(mResources))
        {
            SafeDelete(mTranslator);
        }
    
        setTestShader(params.shaderSource);
    }
    
    void CompilerPerfTest::TearDown()
    {
        SafeDelete(mTranslator);
    
        SetGlobalPoolAllocator(nullptr);
        mAllocator.pop();
    
        FreePoolIndex();
    
        ANGLEPerfTest::TearDown();
    }
    
    void CompilerPerfTest::step()
    {
        const char *shaderStrings[] = {mTestShader};
    
        ShCompileOptions compileOptions = SH_OBJECT_CODE | SH_VARIABLES |
                                          SH_INITIALIZE_UNINITIALIZED_LOCALS | SH_INIT_OUTPUT_VARIABLES;
    
    #if !defined(NDEBUG)
        // Make sure that compilation succeeds and print the info log if it doesn't in debug mode.
        if (!mTranslator->compile(shaderStrings, 1, compileOptions))
        {
            std::cout << "Compiling perf test shader failed with log:\n"
                      << mTranslator->getInfoSink().info.c_str();
        }
    #endif
    
        for (unsigned int iteration = 0; iteration < kNumIterationsPerStep; ++iteration)
        {
            mTranslator->compile(shaderStrings, 1, compileOptions);
        }
    }
    
    TEST_P(CompilerPerfTest, Run)
    {
        run();
    }
    
    ANGLE_INSTANTIATE_TEST(
        CompilerPerfTest,
        CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kSimpleESSL100FragSource, kSimpleESSL100Id),
        CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kSimpleESSL300FragSource, kSimpleESSL300Id),
        CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kRealWorldESSL100FragSource, kRealWorldESSL100Id),
        CompilerPerfParameters(SH_HLSL_4_1_OUTPUT, kTrickyESSL300FragSource, kTrickyESSL300Id),
        CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT, kSimpleESSL100FragSource, kSimpleESSL100Id),
        CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT, kSimpleESSL300FragSource, kSimpleESSL300Id),
        CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT,
                               kRealWorldESSL100FragSource,
                               kRealWorldESSL100Id),
        CompilerPerfParameters(SH_GLSL_450_CORE_OUTPUT, kTrickyESSL300FragSource, kTrickyESSL300Id),
        CompilerPerfParameters(SH_ESSL_OUTPUT, kSimpleESSL100FragSource, kSimpleESSL100Id),
        CompilerPerfParameters(SH_ESSL_OUTPUT, kSimpleESSL300FragSource, kSimpleESSL300Id),
        CompilerPerfParameters(SH_ESSL_OUTPUT, kRealWorldESSL100FragSource, kRealWorldESSL100Id),
        CompilerPerfParameters(SH_ESSL_OUTPUT, kTrickyESSL300FragSource, kTrickyESSL300Id));
    
    }  // anonymous namespace