-
Notifications
You must be signed in to change notification settings - Fork 1.3k
[render-test] Add gfx probe for tracking gpu resource usage #15843
Conversation
9df645f
to
ef1fca5
Compare
include/mbgl/gfx/rendering_stats.hpp
Outdated
struct RenderingStats { | ||
bool isZero() const; | ||
|
||
int numDrawCalls = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: RenderingStats() = default;
?
std::exception_ptr error; | ||
|
||
map.renderStill([&](std::exception_ptr e) { | ||
if (e) { | ||
error = e; | ||
} else { | ||
result = backend->readStillImage(); | ||
result.image = backend->readStillImage(); | ||
result.stats = getBackend()->getContext().renderingStats(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
backend->getContext()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getBackend()
is not a trivial getter function
@@ -17,6 +18,11 @@ class TransformState; | |||
|
|||
class HeadlessFrontend : public RendererFrontend { | |||
public: | |||
struct RenderResult { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shall we add bool isValid() const
here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yeah could be added. In current use std::exception is thrown if an error is encountered
namespace gfx { | ||
|
||
struct RenderingStats { | ||
bool isZero() const; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isEmpty()
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would say that being "empty" is not the right term in this context.
@@ -48,7 +54,7 @@ class HeadlessFrontend : public RendererFrontend { | |||
LatLng latLngForPixel(const ScreenCoordinate&); | |||
|
|||
PremultipliedImage readStillImage(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
shall readStillImage()
return RenderResult
too? (Might be added later)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is an interesting function as it has to be called from the rendering thread. It can be used together with the Map::renderStill(...)
to fetch the still image in the callback.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this could be updated later.
render-test/metadata.hpp
Outdated
@@ -82,13 +88,33 @@ struct NetworkProbe { | |||
size_t transferred; | |||
}; | |||
|
|||
struct GfxProbe { | |||
struct Memory { | |||
int allocated = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
size_t
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Memory tracking between probeGFXStart and probeGFXEnd is relative, ie. these numbers could be negative in a tracking segment where more memory was released than allocated. I might need to rethink the logic :)
render-test/metadata.hpp
Outdated
GfxProbe() = default; | ||
GfxProbe(const mbgl::gfx::RenderingStats&); | ||
|
||
int numDrawCalls = 0; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: no need = 0
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This will lead to uninitialized memory, for example innocent looking initialization GfxProbe probe;
will result in undefined behavior.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course GfxProbes could be initialized like GfxProbe probe {};
but that's really dangerous and error prone code imho.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
GfxProbe() = default;
shall solve it for you
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I solved the issue for now by properly using aggregate initialization GfxProbe probe {}
instead of more traditional GfxProbe probe;
initialization
render-test/runner.cpp
Outdated
@@ -34,6 +34,27 @@ | |||
|
|||
using namespace mbgl; | |||
|
|||
GfxProbe::GfxProbe(const mbgl::gfx::RenderingStats& stats) { | |||
numBuffers = stats.numBuffers; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: use init list
render-test/runner.cpp
Outdated
const char* msg, const std::string& name, const auto& expected, const auto& actual) -> bool { | ||
if (expected != actual) { | ||
char msgBuf[512]; | ||
snprintf(msgBuf, sizeof(msgBuf), msg, name.c_str(), actual, expected); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could std::stringstream
be used instead?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think the c-style printf formatting makes the code more readable (in this case) for the caller.
@@ -206,10 +207,12 @@ UniqueTexture Context::createUniqueTexture() { | |||
if (pooledTextures.empty()) { | |||
pooledTextures.resize(TextureMax); | |||
MBGL_CHECK_ERROR(glGenTextures(TextureMax, pooledTextures.data())); | |||
stats.numCreatedTextures += TextureMax; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
could this statistics population affect the performance? shall we collect it conditionally, e.g. for debug builds only? @alexshalamov @astojilj
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Incrementing one integer value wont have any visible effect on performance :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
true, but I mean the whole stats collecting in general, e.g. std::chrono::steady_clock::now()
might not be that lightweight
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it's good idea to collect general rendering stats (in gl::Context). Frame time tracking in headless frontend could be collected conditionally, but impact on performance is neglectable nevertheless.
render-test/runner.cpp
Outdated
auto check = [&metadata]( | ||
const char* msg, const std::string& name, const auto& expected, const auto& actual) -> bool { | ||
if (expected != actual) { | ||
char msgBuf[512]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe use string stream instead of hardcoded buffer?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unfortunately snprintf requires a fixed buffer. C-style formatting is used here for more readable code.
render-test/runner.cpp
Outdated
const auto& expectedValue = expected.second; | ||
const auto& actualValue = actual->second; | ||
|
||
if (!check("Number of draw calls at probe \"%s\" is %i, expected is %i", |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think it would be better to check all probes and return 'false' if one of probe fails. Also, are all expected values (probes) mandatory?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Very good point!
e4278e1
to
de9bfb1
Compare
src/mbgl/gl/context.cpp
Outdated
@@ -647,6 +666,7 @@ void Context::performCleanup() { | |||
} | |||
} | |||
MBGL_CHECK_ERROR(glDeleteBuffers(int(abandonedBuffers.size()), abandonedBuffers.data())); | |||
stats.numBuffers -= (int)abandonedBuffers.size(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: better int(..) or static_cast()
render-test/runner.cpp
Outdated
return false; | ||
} | ||
|
||
auto check = [&metadata]( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this still needed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good catch, not anymore!
render-test/runner.cpp
Outdated
std::stringstream ss; | ||
ss << "Number of textures at probe \"" << probeName << "\" is " << actualValue.numTextures | ||
<< ", expected is " << expectedValue.numTextures; | ||
if (metadata.errorMessage.length()) ss << "\n"; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
std::endl
de9bfb1
to
d641af1
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
lgtm % comments
render-test/runner.cpp
Outdated
std::stringstream ss; | ||
ss << "Number of textures at probe \"" << probeName << "\" is " << actualValue.numTextures | ||
<< ", expected is " << expectedValue.numTextures; | ||
if (metadata.errorMessage.length()) ss << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
should it be checked before adding the new error message?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
All failed test cases of a probe are reported in a single message. Should this behavior be changed?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I mean, should std::endl
be added first i.e. as a separator between the different probe reports?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if (!metadata.errorMessage.empty()) ss << std::endl;
ss << "Number of textures at probe \"" << probeName << "\" is " << actualValue.numTextures
<< ", expected is " << expectedValue.numTextures;
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
True, metadata is shared between different operations.
render-test/runner.cpp
Outdated
std::stringstream ss; | ||
ss << "Number of textures at probe \"" << probeName << "\" is " << actualValue.numTextures | ||
<< ", expected is " << expectedValue.numTextures; | ||
if (metadata.errorMessage.length()) ss << std::endl; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: !metadata.errorMessage.empty()
3b8d19f
to
192fcc5
Compare
192fcc5
to
0cc9452
Compare
No description provided.