Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Test of async and synchronous image load timing in Cinder.
#include "cinder/app/App.h"
#include "cinder/app/RendererGl.h"
#include "cinder/gl/gl.h"
#include "cinder/gl/Texture.h"
using namespace ci;
using namespace ci::app;
using namespace std;
struct TextureInfo {
std::string name;
gl::TextureRef texture;
};
class ImageLoadingTestApp : public App {
public:
void setup() override;
void mouseDown( MouseEvent event ) override;
void update() override;
void draw() override;
void loadTestData();
void testLoad( const fs::path &path );
std::map<std::string, ImageSourceRef> sources;
TextureInfo testTexture;
gl::QueryTimeSwappedRef gpuTimer;
bool timeAsync = true;
const int framesToTime = 5;
int framesTimed = 0;
};
void ImageLoadingTestApp::setup()
{
gpuTimer = gl::QueryTimeSwapped::create();
loadTestData();
}
void ImageLoadingTestApp::loadTestData()
{
auto path = getAssetPath("some_image.jpg");
console() << "Testing 1080x1080 image load time: " << endl;
testLoad( path );
}
gl::TextureRef asyncConvert( const ImageSourceRef &surface, const ci::gl::Context *shared_context )
{
Timer t(true);
auto context = gl::Context::create( shared_context );
context->makeCurrent();
auto texture = gl::Texture::create( surface );
t.stop();
app::console() << "Async conversion (in separate thread): " << t.getSeconds() * 1000 << "ms" << endl;
return texture;
}
void ImageLoadingTestApp::testLoad( const fs::path &path )
{
console() << endl;
Timer perfTimer( true );
ImageSourceRef source = loadImage( path );
int width = source->getWidth();
int height = source->getHeight();
perfTimer.stop();
console() << "Create Source: " << ivec2( width, height );
console() << ", Time: " << perfTimer.getSeconds() * 1000 << "ms" << endl;
// probably benefits from some HDD memory caching
Timer surfaceTimer( true );
Surface surface = loadImage( path );
width = surface.getWidth();
height = surface.getHeight();
surfaceTimer.stop();
console() << "Create Surface: " << ivec2( width, height );
console() << ", Time: " << surfaceTimer.getSeconds() * 1000 << "ms" << endl;
// Store surface
sources[path.string()] = source;
Timer textureTimer( true );
gl::TextureRef texture = gl::Texture::create( loadImage( path ) );
width = texture->getWidth();
height = texture->getHeight();
textureTimer.stop();
console() << "Create Texture: " << ivec2( width, height );
console() << ", Time: " << textureTimer.getSeconds() * 1000 << "ms" << endl;
// Load surface from map, start async loading to GPU
// Lets us store all textures in RAM to have faster access
Timer asyncTimer( true );
const auto &s = sources.at( path.string() );
width = s->getWidth();
height = s->getHeight();
auto *ctx = gl::context();
auto future = std::async( std::launch::async, asyncConvert, s, ctx );
asyncTimer.stop();
console() << "Cue Async: " << ivec2( width, height );
console() << ", Time: " << asyncTimer.getSeconds() * 1000 << "ms" << endl;
future.wait();
// We can only test one or the other of sync vs async given how the GPU timer works.
// Both synchronous and asynchronous loaded textures suffer from the same initial draw penalty.
// It is in addition to any loading time.
if( timeAsync ) {
testTexture = { "Async", future.get() };
}
else {
testTexture = { "Sync", texture };
}
framesTimed = 0;
console() << endl;
}
void ImageLoadingTestApp::mouseDown( MouseEvent event )
{
timeAsync = ! timeAsync;
loadTestData();
}
void ImageLoadingTestApp::update()
{
}
void ImageLoadingTestApp::draw()
{
if( framesTimed < framesToTime )
{
gl::clear( Color( 0, 0, 0 ) );
gpuTimer->begin();
gl::draw( testTexture.texture );
gpuTimer->end();
if( framesTimed >= 1 )
{
console() << testTexture.name << " ";
console() << "Draw time: " << gpuTimer->getElapsedMilliseconds() << endl;
}
framesTimed += 1;
}
}
CINDER_APP( ImageLoadingTestApp, RendererGl )
@sansumbrella

This comment has been minimized.

Copy link
Owner Author

sansumbrella commented Apr 11, 2015

Demonstrates first draw hiccup issue experienced by AMD cards (at least).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.