我的目標是讀取默認OpenGL幀緩衝區的內容並將像素數據存儲在cv::Mat
中。顯然有2種實現這一目標的不同方式:從OpenGL的默認幀緩衝區中讀取像素數據:FBO與PBO的性能
1)同步:使用FBO和glRealPixels
cv::Mat a = cv::Mat::zeros(cv::Size(1920, 1080), CV_8UC3);
glReadPixels(0, 0, 1920, 1080, GL_BGR, GL_UNSIGNED_BYTE, a.data);
2)異步:使用PBO和glReadPixels
cv::Mat b = cv::Mat::zeros(cv::Size(1920, 1080), CV_8UC3);
glBindBuffer(GL_PIXEL_PACK_BUFFER, pbo_userImage);
glReadPixels(0, 0, 1920, 1080, GL_BGR, GL_UNSIGNED_BYTE, 0);
unsigned char* ptr = static_cast<unsigned char*>(glMapBuffer(GL_PIXEL_PACK_BUFFER, GL_READ_ONLY));
std::copy(ptr, ptr + 1920 * 1080 * 3 * sizeof(unsigned char), b.data);
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
根據全部信息我收集了關於這個主題的異步版本2)應該快得多。但是,比較兩種版本的使用時間可以得出差異通常是最小的,有時版本1)的事件優於PBO變體。
出於性能方面的檢查,我已經插入下面的代碼(基於this答案):
std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now();
....
std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now();
std::cout << "Time difference = " << std::chrono::duration_cast<std::chrono::microseconds>(end - begin).count() << std::endl;
我也試驗了使用提示創建PBO時:我沒找到這裏的GL_DYNAMIC_COPY
和GL_STREAM_READ
之間的差別很大。
我很樂意提供如何進一步提高幀緩衝器中像素讀取操作速度的建議。
你的第二個版本並不是非同步的,因爲你在調用'glReadPixels()'調用之後立即阻塞結果。 –
你的意思是調用'std :: copy'?實際上,如果我評論這條線,效果會很小,而版本1有時會更快。 – Schnigges
如果我不將GPU緩衝區映射到CPU內存,這當然是預料之中的,但在此之後必須有相當大的不同,因爲我想將'cv :: Mat'存儲在向量中 – Schnigges