mirror of
https://github.com/godotengine/godot-angle-static.git
synced 2026-01-06 02:09:55 +03:00
perf tests: Record perf counter metrics.
This adds a new command line argument that will allow the user to specify perf counters to record into the test output. Bug: angleproject:4918 Change-Id: Ia7432ff96eadf13ef681f67d2d503d00fd83e06e Reviewed-on: https://chromium-review.googlesource.com/c/angle/angle/+/3516970 Reviewed-by: Lingfeng Yang <lfy@google.com> Reviewed-by: Charlie Lao <cclao@google.com> Reviewed-by: Yuxin Hu <yuxinhu@google.com> Commit-Queue: Jamie Madill <jmadill@chromium.org>
This commit is contained in:
committed by
Angle LUCI CQ
parent
24ad581e7e
commit
3739a195c2
@@ -90,6 +90,8 @@ struct SaveFileHelper
|
||||
};
|
||||
|
||||
// AMD_performance_monitor helpers.
|
||||
constexpr char kPerfMonitorExtensionName[] = "GL_AMD_performance_monitor";
|
||||
|
||||
struct PerfMonitorCounter
|
||||
{
|
||||
PerfMonitorCounter();
|
||||
|
||||
@@ -18,62 +18,12 @@
|
||||
|
||||
#include "test_utils/gl_raii.h"
|
||||
#include "util/random_utils.h"
|
||||
#include "util/shader_utils.h"
|
||||
|
||||
using namespace angle;
|
||||
|
||||
namespace
|
||||
{
|
||||
constexpr char kExtensionName[] = "GL_AMD_performance_monitor";
|
||||
|
||||
using CounterNameToIndexMap = std::map<std::string, GLuint>;
|
||||
|
||||
CounterNameToIndexMap BuildCounterNameToIndexMap()
|
||||
{
|
||||
GLint numCounters = 0;
|
||||
glGetPerfMonitorCountersAMD(0, &numCounters, nullptr, 0, nullptr);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
std::vector<GLuint> counterIndexes(numCounters, 0);
|
||||
glGetPerfMonitorCountersAMD(0, nullptr, nullptr, numCounters, counterIndexes.data());
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
CounterNameToIndexMap indexMap;
|
||||
|
||||
for (GLuint counterIndex : counterIndexes)
|
||||
{
|
||||
static constexpr size_t kBufSize = 1000;
|
||||
char buffer[kBufSize] = {};
|
||||
glGetPerfMonitorCounterStringAMD(0, counterIndex, kBufSize, nullptr, buffer);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
|
||||
indexMap[buffer] = counterIndex;
|
||||
}
|
||||
|
||||
return indexMap;
|
||||
}
|
||||
|
||||
void UpdatePerfCounter(const CounterNameToIndexMap &counterIndexMap,
|
||||
GLuint *counterOut,
|
||||
const char *name,
|
||||
std::vector<angle::PerfMonitorTriplet> &triplets)
|
||||
{
|
||||
auto iter = counterIndexMap.find(name);
|
||||
ASSERT(iter != counterIndexMap.end());
|
||||
GLuint counterIndex = iter->second;
|
||||
|
||||
for (const angle::PerfMonitorTriplet &triplet : triplets)
|
||||
{
|
||||
ASSERT(triplet.group == 0);
|
||||
if (triplet.counter == counterIndex)
|
||||
{
|
||||
*counterOut = triplet.value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
class VulkanPerformanceCounterTest : public ANGLETest
|
||||
{
|
||||
protected:
|
||||
@@ -213,33 +163,12 @@ class VulkanPerformanceCounterTest : public ANGLETest
|
||||
|
||||
angle::VulkanPerfCounters getPerfCounters()
|
||||
{
|
||||
GLuint resultSize = 0;
|
||||
glGetPerfMonitorCounterDataAMD(0, GL_PERFMON_RESULT_SIZE_AMD, sizeof(GLuint), &resultSize,
|
||||
nullptr);
|
||||
EXPECT_GL_NO_ERROR();
|
||||
EXPECT_GT(resultSize, 0u);
|
||||
|
||||
std::vector<angle::PerfMonitorTriplet> perfResults(resultSize /
|
||||
sizeof(angle::PerfMonitorTriplet));
|
||||
glGetPerfMonitorCounterDataAMD(0, GL_PERFMON_RESULT_AMD,
|
||||
perfResults.size() * sizeof(perfResults[0]),
|
||||
&perfResults.data()->group, nullptr);
|
||||
|
||||
if (mIndexMap.empty())
|
||||
{
|
||||
mIndexMap = BuildCounterNameToIndexMap();
|
||||
}
|
||||
|
||||
angle::VulkanPerfCounters counters;
|
||||
|
||||
#define ANGLE_UNPACK_PERF_COUNTER(COUNTER) \
|
||||
UpdatePerfCounter(mIndexMap, &counters.COUNTER, #COUNTER, perfResults);
|
||||
|
||||
ANGLE_VK_PERF_COUNTERS_X(ANGLE_UNPACK_PERF_COUNTER)
|
||||
|
||||
#undef ANGLE_UNPACK_PERF_COUNTER
|
||||
|
||||
return counters;
|
||||
return GetPerfCounters(mIndexMap);
|
||||
}
|
||||
|
||||
CounterNameToIndexMap mIndexMap;
|
||||
@@ -261,7 +190,7 @@ class VulkanPerformanceCounterTest_MSAA : public VulkanPerformanceCounterTest
|
||||
// Tests that texture updates to unused textures don't break the RP.
|
||||
TEST_P(VulkanPerformanceCounterTest, NewTextureDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
|
||||
|
||||
@@ -311,7 +240,7 @@ TEST_P(VulkanPerformanceCounterTest, NewTextureDoesNotBreakRenderPass)
|
||||
// Tests that RGB texture should not break renderpass.
|
||||
TEST_P(VulkanPerformanceCounterTest, SampleFromRGBTextureDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Texture2D(), essl1_shaders::fs::Texture2D());
|
||||
glUseProgram(program);
|
||||
@@ -354,7 +283,7 @@ TEST_P(VulkanPerformanceCounterTest, SampleFromRGBTextureDoesNotBreakRenderPass)
|
||||
// Tests that RGB texture should not break renderpass.
|
||||
TEST_P(VulkanPerformanceCounterTest, RenderToRGBTextureDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
|
||||
glUseProgram(program);
|
||||
@@ -393,7 +322,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderToRGBTextureDoesNotBreakRenderPass)
|
||||
// Tests that changing a Texture's max level hits the descriptor set cache.
|
||||
TEST_P(VulkanPerformanceCounterTest, ChangingMaxLevelHitsDescriptorCache)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
GLColor kInitialData[4] = {GLColor::red, GLColor::blue, GLColor::green, GLColor::yellow};
|
||||
|
||||
@@ -445,7 +374,7 @@ TEST_P(VulkanPerformanceCounterTest, ChangingMaxLevelHitsDescriptorCache)
|
||||
// Tests that two glCopyBufferSubData commands can share a barrier.
|
||||
TEST_P(VulkanPerformanceCounterTest, IndependentBufferCopiesShareSingleBarrier)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr GLint srcDataA[] = {1, 2, 3, 4};
|
||||
constexpr GLint srcDataB[] = {5, 6, 7, 8};
|
||||
@@ -491,7 +420,7 @@ TEST_P(VulkanPerformanceCounterTest, IndependentBufferCopiesShareSingleBarrier)
|
||||
// used
|
||||
TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleResolveWithBlit)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr int kSize = 16;
|
||||
glViewport(0, 0, kSize, kSize);
|
||||
@@ -544,7 +473,7 @@ TEST_P(VulkanPerformanceCounterTest_ES31, MultisampleResolveWithBlit)
|
||||
// Ensures a read-only depth-stencil feedback loop works in a single RenderPass.
|
||||
TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr GLsizei kSize = 4;
|
||||
|
||||
@@ -634,7 +563,7 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthStencilFeedbackLoopUsesSingleR
|
||||
// - Scenario: invalidate, disable, draw
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDisableDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -682,7 +611,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDisableDraw)
|
||||
// - Scenario: disable, invalidate, draw
|
||||
TEST_P(VulkanPerformanceCounterTest, DisableInvalidateDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -730,7 +659,7 @@ TEST_P(VulkanPerformanceCounterTest, DisableInvalidateDraw)
|
||||
// - Scenario: disable, draw, invalidate, enable
|
||||
TEST_P(VulkanPerformanceCounterTest, DisableDrawInvalidateEnable)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -789,7 +718,7 @@ TEST_P(VulkanPerformanceCounterTest, DisableDrawInvalidateEnable)
|
||||
// - Scenario: invalidate
|
||||
TEST_P(VulkanPerformanceCounterTest, Invalidate)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -828,7 +757,7 @@ TEST_P(VulkanPerformanceCounterTest, Invalidate)
|
||||
// whole framebuffer.
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateSub)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -869,7 +798,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateSub)
|
||||
// - Scenario: invalidate, draw
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -913,7 +842,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDraw)
|
||||
// - Scenario: invalidate, draw, disable
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisable)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
// http://anglebug.com/6857
|
||||
ANGLE_SKIP_TEST_IF(IsLinux() && IsAMD() && IsVulkan());
|
||||
@@ -967,7 +896,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisable)
|
||||
// - Scenario: invalidate, disable, draw, enable
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDisableDrawEnable)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+0), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1020,7 +949,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDisableDrawEnable)
|
||||
// - Scenario: invalidate, disable, draw, enable, draw
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDisableDrawEnableDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1075,7 +1004,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDisableDrawEnableDraw)
|
||||
// - Scenario: invalidate, draw, disable, enable
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisableEnable)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1131,7 +1060,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisableEnable)
|
||||
// - Scenario: invalidate, draw, disable, enable, invalidate
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisableEnableInvalidate)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+0), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1189,7 +1118,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisableEnableInvalidate)
|
||||
// - Scenario: invalidate, draw, disable, enable, invalidate, draw
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisableEnableInvalidateDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1251,7 +1180,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDrawDisableEnableInvalidateDraw)
|
||||
// - Scenario: invalidate, disable, enable, draw
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDisableEnableDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1303,7 +1232,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDisableEnableDraw)
|
||||
// Tests that an in renderpass clear after invalidate keeps content stored.
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateAndClear)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1353,7 +1282,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateAndClear)
|
||||
// content stored.
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateAndMaskedClear)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+1, Load+0, Stores+1)
|
||||
@@ -1414,7 +1343,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateAndMaskedClear)
|
||||
// - Scenario: invalidate, detach D/S texture and modify it, attach D/S texture, draw with blend
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDetachModifyTexAttachDrawWithBlend)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+1)
|
||||
@@ -1504,7 +1433,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDetachModifyTexAttachDrawWithBlen
|
||||
// - Scenario: invalidate
|
||||
TEST_P(VulkanPerformanceCounterTest, InvalidateDrawAndDeleteRenderbuffer)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+1), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -1549,7 +1478,7 @@ TEST_P(VulkanPerformanceCounterTest, InvalidateDrawAndDeleteRenderbuffer)
|
||||
// Tests that even if the app clears depth, it should be invalidated if there is no read.
|
||||
TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthAfterClear)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
ANGLE_GL_PROGRAM(redProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Red());
|
||||
|
||||
@@ -1574,7 +1503,7 @@ TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthAfterClear)
|
||||
// Tests that masked color clears don't break the RP.
|
||||
TEST_P(VulkanPerformanceCounterTest, MaskedColorClearDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
GLTexture texture;
|
||||
glBindTexture(GL_TEXTURE_2D, texture);
|
||||
@@ -1614,7 +1543,7 @@ TEST_P(VulkanPerformanceCounterTest, MaskedColorClearDoesNotBreakRenderPass)
|
||||
// Tests that masked color/depth/stencil clears don't break the RP.
|
||||
TEST_P(VulkanPerformanceCounterTest, MaskedClearDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr GLsizei kSize = 64;
|
||||
|
||||
@@ -1695,7 +1624,7 @@ TEST_P(VulkanPerformanceCounterTest, MaskedClearDoesNotBreakRenderPass)
|
||||
// Tests that clear followed by scissored draw uses loadOp to clear.
|
||||
TEST_P(VulkanPerformanceCounterTest, ClearThenScissoredDraw)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
uint32_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
|
||||
uint32_t expectedDepthClears = getPerfCounters().depthClears + 1;
|
||||
@@ -1768,7 +1697,7 @@ TEST_P(VulkanPerformanceCounterTest, ClearThenScissoredDraw)
|
||||
// Tests that scissored clears don't break the RP.
|
||||
TEST_P(VulkanPerformanceCounterTest, ScissoredClearDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr GLsizei kSize = 64;
|
||||
|
||||
@@ -1866,7 +1795,7 @@ TEST_P(VulkanPerformanceCounterTest, ScissoredClearDoesNotBreakRenderPass)
|
||||
// Tests that draw buffer change with all color channel mask off should not break renderpass
|
||||
TEST_P(VulkanPerformanceCounterTest, DrawbufferChangeWithAllColorMaskDisabled)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
ANGLE_GL_PROGRAM(program, essl1_shaders::vs::Passthrough(), essl1_shaders::fs::UniformColor());
|
||||
glUseProgram(program);
|
||||
@@ -1925,7 +1854,7 @@ TEST_P(VulkanPerformanceCounterTest, DrawbufferChangeWithAllColorMaskDisabled)
|
||||
// Tests the optimization that a glFlush call issued inside a renderpass will be skipped.
|
||||
TEST_P(VulkanPerformanceCounterTest, InRenderpassFlushShouldNotBreakRenderpass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
uint32_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
|
||||
|
||||
GLTexture texture;
|
||||
@@ -1952,7 +1881,7 @@ TEST_P(VulkanPerformanceCounterTest, InRenderpassFlushShouldNotBreakRenderpass)
|
||||
// Tests that depth/stencil texture clear/load works correctly.
|
||||
TEST_P(VulkanPerformanceCounterTest, DepthStencilTextureClearAndLoad)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
// TODO: http://anglebug.com/5329 Flaky test
|
||||
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
|
||||
@@ -2065,7 +1994,7 @@ TEST_P(VulkanPerformanceCounterTest, DepthStencilTextureClearAndLoad)
|
||||
// Tests that multisampled-render-to-texture depth/stencil textures don't ever load data.
|
||||
TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilTextureShouldNotLoad)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
// http://anglebug.com/5083
|
||||
ANGLE_SKIP_TEST_IF(IsWindows() && IsAMD() && IsVulkan());
|
||||
@@ -2193,7 +2122,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureDepthStencilRenderbufferShou
|
||||
ANGLE_SKIP_TEST_IF(IsWindows7() && IsNVIDIA() && IsVulkan());
|
||||
|
||||
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -2316,7 +2245,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureInvalidate)
|
||||
|
||||
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
|
||||
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
@@ -2442,7 +2371,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureUninitializedAndUnusedDepthS
|
||||
|
||||
ANGLE_SKIP_TEST_IF(!EnsureGLExtensionEnabled("GL_EXT_multisampled_render_to_texture"));
|
||||
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, no depth/stencil clear, load or store.
|
||||
@@ -2508,7 +2437,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderToTextureUninitializedAndUnusedDepthS
|
||||
// Ensures we use read-only depth layout when there is no write
|
||||
TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr GLsizei kSize = 64;
|
||||
|
||||
@@ -2577,7 +2506,7 @@ TEST_P(VulkanPerformanceCounterTest, ReadOnlyDepthBufferLayout)
|
||||
// invalidate)
|
||||
TEST_P(VulkanPerformanceCounterTest, RenderPassAfterRenderPassWithoutDepthStencilWrite)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+0, Loads+0, Stores+0), stencil(Clears+0, Load+0, Stores+0)
|
||||
@@ -2636,7 +2565,7 @@ TEST_P(VulkanPerformanceCounterTest, RenderPassAfterRenderPassWithoutDepthStenci
|
||||
// etc) don't break the render pass.
|
||||
TEST_P(VulkanPerformanceCounterTest, ClearAfterClearDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
uint32_t expectedRenderPassCount = getPerfCounters().renderPasses + 1;
|
||||
|
||||
constexpr GLsizei kSize = 6;
|
||||
@@ -2780,7 +2709,7 @@ TEST_P(VulkanPerformanceCounterTest, ClearAfterClearDoesNotBreakRenderPass)
|
||||
// Ensures that changing the scissor size doesn't break the render pass.
|
||||
TEST_P(VulkanPerformanceCounterTest, ScissorDoesNotBreakRenderPass)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
constexpr GLsizei kSize = 16;
|
||||
|
||||
@@ -3026,7 +2955,7 @@ TEST_P(VulkanPerformanceCounterTest, ScissorDoesNotBreakRenderPass)
|
||||
// Tests that changing UBO bindings does not allocate new descriptor sets.
|
||||
TEST_P(VulkanPerformanceCounterTest, ChangingUBOsHitsDescriptorSetCache)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
// Set up two UBOs, one filled with "1" and the second with "2".
|
||||
constexpr GLsizei kCount = 64;
|
||||
@@ -3155,7 +3084,7 @@ void main()
|
||||
// waiting for the GPU access to complete before returning a pointer to the buffer.
|
||||
TEST_P(VulkanPerformanceCounterTest, MappingGpuReadOnlyBufferGhostsBuffer)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
// 1. Create a buffer, map it, fill it with red
|
||||
// 2. Draw with buffer (GPU read-only)
|
||||
@@ -3252,7 +3181,7 @@ void main()
|
||||
// Verifies that BufferSubData calls don't trigger state updates for non-translated formats.
|
||||
TEST_P(VulkanPerformanceCounterTest, BufferSubDataShouldNotTriggerSyncState)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::Green());
|
||||
glUseProgram(testProgram);
|
||||
@@ -3294,7 +3223,7 @@ TEST_P(VulkanPerformanceCounterTest, BufferSubDataShouldNotTriggerSyncState)
|
||||
// Verifies that rendering to backbuffer discards depth/stencil.
|
||||
TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthStencil)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+0), stencil(Clears+1, Load+0, Stores+0)
|
||||
@@ -3323,7 +3252,7 @@ TEST_P(VulkanPerformanceCounterTest, SwapShouldInvalidateDepthStencil)
|
||||
// Verifies that rendering to MSAA backbuffer discards depth/stencil.
|
||||
TEST_P(VulkanPerformanceCounterTest_MSAA, SwapShouldInvalidateDepthStencil)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
angle::VulkanPerfCounters expected;
|
||||
|
||||
// Expect rpCount+1, depth(Clears+1, Loads+0, Stores+0), stencil(Clears+1, Load+0, Stores+0)
|
||||
@@ -3352,7 +3281,7 @@ TEST_P(VulkanPerformanceCounterTest_MSAA, SwapShouldInvalidateDepthStencil)
|
||||
// Tests that uniform updates eventually stop updating descriptor sets.
|
||||
TEST_P(VulkanPerformanceCounterTest, UniformUpdatesHitDescriptorSetCache)
|
||||
{
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kExtensionName));
|
||||
ANGLE_SKIP_TEST_IF(!IsGLExtensionEnabled(kPerfMonitorExtensionName));
|
||||
|
||||
ANGLE_GL_PROGRAM(testProgram, essl1_shaders::vs::Simple(), essl1_shaders::fs::UniformColor());
|
||||
glUseProgram(testProgram);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "common/debug.h"
|
||||
#include "common/mathutil.h"
|
||||
#include "common/platform.h"
|
||||
#include "common/string_utils.h"
|
||||
#include "common/system_utils.h"
|
||||
#include "common/utilities.h"
|
||||
#include "test_utils/runner/TestSuite.h"
|
||||
@@ -467,6 +468,43 @@ double ANGLEPerfTest::printResults()
|
||||
mReporter->AddResult(".total_steps", static_cast<size_t>(mTotalNumStepsPerformed));
|
||||
}
|
||||
|
||||
for (const auto &iter : mPerfCounterInfo)
|
||||
{
|
||||
const std::string &counterName = iter.second.name;
|
||||
std::vector<GLuint> samples = iter.second.samples;
|
||||
|
||||
size_t midpoint = samples.size() >> 1;
|
||||
std::nth_element(samples.begin(), samples.begin() + midpoint, samples.end());
|
||||
|
||||
{
|
||||
std::stringstream medianStr;
|
||||
medianStr << "." << counterName << "_median";
|
||||
std::string medianName = medianStr.str();
|
||||
|
||||
mReporter->AddResult(medianName, static_cast<size_t>(samples[midpoint]));
|
||||
}
|
||||
|
||||
{
|
||||
std::string measurement = mName + mBackend + "." + counterName + "_median";
|
||||
TestSuite::GetInstance()->addHistogramSample(measurement, mStory, samples[midpoint],
|
||||
"count");
|
||||
}
|
||||
|
||||
const auto &maxIt = std::max_element(samples.begin(), samples.end());
|
||||
|
||||
{
|
||||
std::stringstream maxStr;
|
||||
maxStr << "." << counterName << "_max";
|
||||
std::string maxName = maxStr.str();
|
||||
mReporter->AddResult(maxName, static_cast<size_t>(*maxIt));
|
||||
}
|
||||
|
||||
{
|
||||
std::string measurement = mName + mBackend + "." + counterName + "_max";
|
||||
TestSuite::GetInstance()->addHistogramSample(measurement, mStory, *maxIt, "count");
|
||||
}
|
||||
}
|
||||
|
||||
return retValue;
|
||||
}
|
||||
|
||||
@@ -835,6 +873,8 @@ void ANGLERenderTest::SetUp()
|
||||
// between calibration measurements.
|
||||
calibrateStepsToRun(RunLoopPolicy::FinishEveryStep);
|
||||
}
|
||||
|
||||
initPerfCounters();
|
||||
}
|
||||
|
||||
void ANGLERenderTest::TearDown()
|
||||
@@ -865,6 +905,73 @@ void ANGLERenderTest::TearDown()
|
||||
ANGLEPerfTest::TearDown();
|
||||
}
|
||||
|
||||
void ANGLERenderTest::initPerfCounters()
|
||||
{
|
||||
if (!gPerfCounters)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!IsGLExtensionEnabled(kPerfMonitorExtensionName))
|
||||
{
|
||||
fprintf(stderr, "Cannot report perf metrics because %s is not available.\n",
|
||||
kPerfMonitorExtensionName);
|
||||
return;
|
||||
}
|
||||
|
||||
CounterNameToIndexMap indexMap = BuildCounterNameToIndexMap();
|
||||
|
||||
std::vector<std::string> counters =
|
||||
angle::SplitString(gPerfCounters, ":", angle::WhitespaceHandling::TRIM_WHITESPACE,
|
||||
angle::SplitResult::SPLIT_WANT_NONEMPTY);
|
||||
for (const std::string &counter : counters)
|
||||
{
|
||||
auto iter = indexMap.find(counter);
|
||||
if (iter == indexMap.end())
|
||||
{
|
||||
fprintf(stderr, "Counter '%s' not in list of available perf counters.\n",
|
||||
counter.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
{
|
||||
std::stringstream medianStr;
|
||||
medianStr << '.' << counter << "_median";
|
||||
std::string medianName = medianStr.str();
|
||||
mReporter->RegisterImportantMetric(medianName, "count");
|
||||
}
|
||||
|
||||
{
|
||||
std::stringstream maxStr;
|
||||
maxStr << '.' << counter << "_max";
|
||||
std::string maxName = maxStr.str();
|
||||
mReporter->RegisterImportantMetric(maxName, "count");
|
||||
}
|
||||
|
||||
GLuint index = indexMap[counter];
|
||||
mPerfCounterInfo[index] = {counter, {}};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void ANGLERenderTest::updatePerfCounters()
|
||||
{
|
||||
if (mPerfCounterInfo.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
std::vector<PerfMonitorTriplet> perfData = GetPerfMonitorTriplets();
|
||||
ASSERT(!perfData.empty());
|
||||
|
||||
for (auto &iter : mPerfCounterInfo)
|
||||
{
|
||||
uint32_t counter = iter.first;
|
||||
std::vector<GLuint> &samples = iter.second.samples;
|
||||
samples.push_back(perfData[counter].value);
|
||||
}
|
||||
}
|
||||
|
||||
void ANGLERenderTest::beginInternalTraceEvent(const char *name)
|
||||
{
|
||||
if (gEnableTrace)
|
||||
@@ -933,6 +1040,7 @@ void ANGLERenderTest::step()
|
||||
// command queues.
|
||||
if (mSwapEnabled)
|
||||
{
|
||||
updatePerfCounters();
|
||||
mGLWindow->swap();
|
||||
}
|
||||
mOSWindow->messageLoop();
|
||||
|
||||
@@ -122,6 +122,13 @@ class ANGLEPerfTest : public testing::Test, angle::NonCopyable
|
||||
int mIterationsPerStep;
|
||||
bool mRunning;
|
||||
std::vector<double> mTestTrialResults;
|
||||
|
||||
struct CounterInfo
|
||||
{
|
||||
std::string name;
|
||||
std::vector<GLuint> samples;
|
||||
};
|
||||
angle::HashMap<GLuint, CounterInfo> mPerfCounterInfo;
|
||||
};
|
||||
|
||||
enum class SurfaceType
|
||||
@@ -190,6 +197,7 @@ class ANGLERenderTest : public ANGLEPerfTest
|
||||
void endGLTraceEvent(const char *name, double hostTimeSec);
|
||||
|
||||
void disableTestHarnessSwap() { mSwapEnabled = false; }
|
||||
void updatePerfCounters();
|
||||
|
||||
bool mIsTimestampQueryAvailable;
|
||||
|
||||
@@ -204,6 +212,8 @@ class ANGLERenderTest : public ANGLEPerfTest
|
||||
|
||||
bool areExtensionPrerequisitesFulfilled() const;
|
||||
|
||||
void initPerfCounters();
|
||||
|
||||
GLWindowBase *mGLWindow;
|
||||
OSWindow *mOSWindow;
|
||||
std::vector<const char *> mExtensionPrerequisites;
|
||||
|
||||
@@ -29,6 +29,7 @@ bool gEnableAllTraceTests = false;
|
||||
bool gRetraceMode = false;
|
||||
bool gMinimizeGPUWork = false;
|
||||
bool gTraceTestValidation = false;
|
||||
const char *gPerfCounters = nullptr;
|
||||
|
||||
// Default to three warmup loops. There's no science to this. More than two loops was experimentally
|
||||
// helpful on a Windows NVIDIA setup when testing with Vulkan and native trace tests.
|
||||
@@ -171,5 +172,10 @@ void ANGLEProcessPerfTestArgs(int *argc, char **argv)
|
||||
gTestTrials = 1;
|
||||
gMaxTrialTimeSeconds = 600.0;
|
||||
}
|
||||
else if (strcmp("--perf-counters", argv[argIndex]) == 0 && argIndex < *argc - 1)
|
||||
{
|
||||
gPerfCounters = argv[argIndex + 1];
|
||||
argIndex++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ extern bool gEnableAllTraceTests;
|
||||
extern bool gRetraceMode;
|
||||
extern bool gMinimizeGPUWork;
|
||||
extern bool gTraceTestValidation;
|
||||
extern const char *gPerfCounters;
|
||||
|
||||
inline bool OneFrame()
|
||||
{
|
||||
|
||||
@@ -42,6 +42,7 @@ Several command-line arguments control how the tests run:
|
||||
* `--enable-all-trace-tests`: Offscreen and vsync-limited trace tests are disabled by default to reduce test time.
|
||||
* `--minimize-gpu-work`: Modify API calls so that GPU work is reduced to minimum.
|
||||
* `--validation`: Enable serialization validation in the trace tests. Normally used with SwiftShader and retracing.
|
||||
* `--perf-counters`: Additional performance counters to include in the result output. Separate multiple entries with colons: ':'.
|
||||
|
||||
For example, for an endless run with no warmup, run:
|
||||
|
||||
|
||||
@@ -1418,6 +1418,8 @@ void TracePerfTest::drawBenchmark()
|
||||
mTraceLibrary->replayFrame(mCurrentFrame);
|
||||
stopGpuTimer();
|
||||
|
||||
updatePerfCounters();
|
||||
|
||||
if (mParams.surfaceType == SurfaceType::Offscreen)
|
||||
{
|
||||
if (gMinimizeGPUWork)
|
||||
|
||||
@@ -303,6 +303,8 @@ def main():
|
||||
default=DEFAULT_CALIBRATION_TIME)
|
||||
parser.add_argument(
|
||||
'--show-test-stdout', help='Prints all test stdout during execution.', action='store_true')
|
||||
parser.add_argument(
|
||||
'--perf-counters', help='Colon-separated list of extra perf counter metrics.')
|
||||
|
||||
args, extra_flags = parser.parse_known_args()
|
||||
|
||||
@@ -407,10 +409,15 @@ def main():
|
||||
'--trials',
|
||||
str(args.trials_per_sample),
|
||||
]
|
||||
|
||||
if args.smoke_test_mode:
|
||||
cmd_run += ['--no-warmup']
|
||||
else:
|
||||
cmd_run += ['--warmup-loops', str(args.warmup_loops)]
|
||||
|
||||
if args.perf_counters:
|
||||
cmd_run += ['--perf-counters', args.perf_counters]
|
||||
|
||||
with common.temporary_file() as histogram_file_path:
|
||||
cmd_run += ['--isolated-script-test-perf-output=%s' % histogram_file_path]
|
||||
exit_code, output = _run_and_get_output(args, cmd_run, env)
|
||||
|
||||
@@ -34,11 +34,59 @@ namespace angle
|
||||
{
|
||||
namespace
|
||||
{
|
||||
std::string GetUnitAndDirection(proto::UnitAndDirection unit)
|
||||
std::string UnitAndDirectionToString(proto::UnitAndDirection unit)
|
||||
{
|
||||
ASSERT(unit.improvement_direction() == proto::SMALLER_IS_BETTER);
|
||||
ASSERT(unit.unit() == proto::MS_BEST_FIT_FORMAT);
|
||||
return "msBestFitFormat_smallerIsBetter";
|
||||
std::stringstream strstr;
|
||||
|
||||
switch (unit.unit())
|
||||
{
|
||||
case proto::MS_BEST_FIT_FORMAT:
|
||||
strstr << "msBestFitFormat";
|
||||
break;
|
||||
case proto::COUNT:
|
||||
strstr << "count";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
strstr << "error";
|
||||
break;
|
||||
}
|
||||
|
||||
switch (unit.improvement_direction())
|
||||
{
|
||||
case proto::NOT_SPECIFIED:
|
||||
break;
|
||||
case proto::SMALLER_IS_BETTER:
|
||||
strstr << "_smallerIsBetter";
|
||||
break;
|
||||
default:
|
||||
UNREACHABLE();
|
||||
break;
|
||||
}
|
||||
|
||||
return strstr.str();
|
||||
}
|
||||
|
||||
proto::UnitAndDirection StringToUnitAndDirection(const std::string &str)
|
||||
{
|
||||
proto::UnitAndDirection unitAndDirection;
|
||||
|
||||
if (str == "count")
|
||||
{
|
||||
unitAndDirection.set_improvement_direction(proto::NOT_SPECIFIED);
|
||||
unitAndDirection.set_unit(proto::COUNT);
|
||||
}
|
||||
else if (str == "msBestFitFormat_smallerIsBetter")
|
||||
{
|
||||
unitAndDirection.set_improvement_direction(proto::SMALLER_IS_BETTER);
|
||||
unitAndDirection.set_unit(proto::MS_BEST_FIT_FORMAT);
|
||||
}
|
||||
else
|
||||
{
|
||||
UNREACHABLE();
|
||||
}
|
||||
|
||||
return unitAndDirection;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
@@ -54,9 +102,7 @@ void HistogramWriter::addSample(const std::string &measurement,
|
||||
std::string measurementAndStory = measurement + story;
|
||||
if (mHistograms.count(measurementAndStory) == 0)
|
||||
{
|
||||
proto::UnitAndDirection unitAndDirection;
|
||||
unitAndDirection.set_improvement_direction(proto::SMALLER_IS_BETTER);
|
||||
unitAndDirection.set_unit(proto::MS_BEST_FIT_FORMAT);
|
||||
proto::UnitAndDirection unitAndDirection = StringToUnitAndDirection(units);
|
||||
|
||||
std::unique_ptr<catapult::HistogramBuilder> builder =
|
||||
std::make_unique<catapult::HistogramBuilder>(measurement, unitAndDirection);
|
||||
@@ -102,7 +148,7 @@ void HistogramWriter::getAsJSON(js::Document *doc) const
|
||||
js::Value description(histogram.description(), allocator);
|
||||
obj.AddMember("description", description, allocator);
|
||||
|
||||
js::Value unitAndDirection(GetUnitAndDirection(histogram.unit()), allocator);
|
||||
js::Value unitAndDirection(UnitAndDirectionToString(histogram.unit()), allocator);
|
||||
obj.AddMember("unit", unitAndDirection, allocator);
|
||||
|
||||
if (histogram.has_diagnostics())
|
||||
|
||||
@@ -135,6 +135,28 @@ void KHRONOS_APIENTRY DebugMessageCallback(GLenum source,
|
||||
callbackChain(source, type, id, severity, length, message, gCallbackChainUserParam);
|
||||
}
|
||||
}
|
||||
|
||||
void GetPerfCounterValue(const CounterNameToIndexMap &counterIndexMap,
|
||||
std::vector<angle::PerfMonitorTriplet> &triplets,
|
||||
const char *name,
|
||||
GLuint *counterOut)
|
||||
{
|
||||
auto iter = counterIndexMap.find(name);
|
||||
ASSERT(iter != counterIndexMap.end());
|
||||
GLuint counterIndex = iter->second;
|
||||
|
||||
for (const angle::PerfMonitorTriplet &triplet : triplets)
|
||||
{
|
||||
ASSERT(triplet.group == 0);
|
||||
if (triplet.counter == counterIndex)
|
||||
{
|
||||
*counterOut = triplet.value;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
UNREACHABLE();
|
||||
}
|
||||
} // namespace
|
||||
|
||||
GLuint CompileShader(GLenum type, const char *source)
|
||||
@@ -372,6 +394,98 @@ void EnableDebugCallback(GLDEBUGPROC callbackChain, const void *userParam)
|
||||
glDebugMessageCallbackKHR(DebugMessageCallback, reinterpret_cast<const void *>(callbackChain));
|
||||
}
|
||||
|
||||
CounterNameToIndexMap BuildCounterNameToIndexMap()
|
||||
{
|
||||
GLint numCounters = 0;
|
||||
glGetPerfMonitorCountersAMD(0, &numCounters, nullptr, 0, nullptr);
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<GLuint> counterIndexes(numCounters, 0);
|
||||
glGetPerfMonitorCountersAMD(0, nullptr, nullptr, numCounters, counterIndexes.data());
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
CounterNameToIndexMap indexMap;
|
||||
|
||||
for (GLuint counterIndex : counterIndexes)
|
||||
{
|
||||
static constexpr size_t kBufSize = 1000;
|
||||
char buffer[kBufSize] = {};
|
||||
glGetPerfMonitorCounterStringAMD(0, counterIndex, kBufSize, nullptr, buffer);
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
indexMap[buffer] = counterIndex;
|
||||
}
|
||||
|
||||
return indexMap;
|
||||
}
|
||||
|
||||
std::vector<angle::PerfMonitorTriplet> GetPerfMonitorTriplets()
|
||||
{
|
||||
GLuint resultSize = 0;
|
||||
glGetPerfMonitorCounterDataAMD(0, GL_PERFMON_RESULT_SIZE_AMD, sizeof(GLuint), &resultSize,
|
||||
nullptr);
|
||||
if (glGetError() != GL_NO_ERROR || resultSize == 0)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
std::vector<angle::PerfMonitorTriplet> perfResults(resultSize /
|
||||
sizeof(angle::PerfMonitorTriplet));
|
||||
glGetPerfMonitorCounterDataAMD(
|
||||
0, GL_PERFMON_RESULT_AMD, static_cast<GLsizei>(perfResults.size() * sizeof(perfResults[0])),
|
||||
&perfResults.data()->group, nullptr);
|
||||
|
||||
if (glGetError() != GL_NO_ERROR)
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
return perfResults;
|
||||
}
|
||||
|
||||
angle::VulkanPerfCounters GetPerfCounters(const CounterNameToIndexMap &indexMap)
|
||||
{
|
||||
std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
|
||||
|
||||
angle::VulkanPerfCounters counters;
|
||||
|
||||
#define ANGLE_UNPACK_PERF_COUNTER(COUNTER) \
|
||||
GetPerfCounterValue(indexMap, perfResults, #COUNTER, &counters.COUNTER);
|
||||
|
||||
ANGLE_VK_PERF_COUNTERS_X(ANGLE_UNPACK_PERF_COUNTER)
|
||||
|
||||
#undef ANGLE_UNPACK_PERF_COUNTER
|
||||
|
||||
return counters;
|
||||
}
|
||||
|
||||
CounterNameToIndexMap BuildCounterNameToValueMap()
|
||||
{
|
||||
CounterNameToIndexMap indexMap = BuildCounterNameToIndexMap();
|
||||
std::vector<angle::PerfMonitorTriplet> perfResults = GetPerfMonitorTriplets();
|
||||
|
||||
CounterNameToValueMap valueMap;
|
||||
|
||||
for (const auto &iter : indexMap)
|
||||
{
|
||||
const std::string &name = iter.first;
|
||||
GLuint index = iter.second;
|
||||
|
||||
valueMap[name] = perfResults[index].value;
|
||||
}
|
||||
|
||||
return valueMap;
|
||||
}
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
|
||||
@@ -8,9 +8,11 @@
|
||||
#define SAMPLE_UTIL_SHADER_UTILS_H
|
||||
|
||||
#include <functional>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "common/angleutils.h"
|
||||
#include "util/util_export.h"
|
||||
#include "util/util_gl.h"
|
||||
|
||||
@@ -51,6 +53,14 @@ ANGLE_UTIL_EXPORT GLuint LoadBinaryProgramES3(const std::vector<uint8_t> &binary
|
||||
|
||||
ANGLE_UTIL_EXPORT void EnableDebugCallback(GLDEBUGPROC callbackChain, const void *userParam);
|
||||
|
||||
using CounterNameToIndexMap = std::map<std::string, GLuint>;
|
||||
using CounterNameToValueMap = std::map<std::string, GLuint>;
|
||||
|
||||
ANGLE_UTIL_EXPORT CounterNameToIndexMap BuildCounterNameToIndexMap();
|
||||
ANGLE_UTIL_EXPORT angle::VulkanPerfCounters GetPerfCounters(const CounterNameToIndexMap &indexMap);
|
||||
ANGLE_UTIL_EXPORT CounterNameToValueMap BuildCounterNameToValueMap();
|
||||
ANGLE_UTIL_EXPORT std::vector<angle::PerfMonitorTriplet> GetPerfMonitorTriplets();
|
||||
|
||||
namespace angle
|
||||
{
|
||||
|
||||
|
||||
Reference in New Issue
Block a user