2

QT4で、OpenGLレンダリングを実行し、その結果をWebSocketを介してネットワーク経由で送信するヘッドレスコンソールアプリケーションの作成に取り組んでいます。すべてのレンダリングとネットワークコードを実行していますが(GUIがあると仮定)、ヘッドレスアプリケーションへの移行に問題があります。ウィンドウなしでQGLContextを作成することは可能ですか?

Webでの読み取りはそれほど多くはありませんが、私が収集したものから、有効なQPaintDeviceであるQGLPixelBufferを作成できます。ハードウェアアクセラレーションによる描画に使用する独自のプライベートQGLContextを作成しているようです。このルートで発生している問題は、別のスレッド(レンダリングされたシーンからの高速DMAテクスチャ転送用のネットワークスレッド)と共有できるように、基になるQGLContextにアクセスする必要があることです。以下に含まれているのは小さなプロトタイプです。何か案は?

Application.h

/**
@file
@author     Nikolaus Karpinsky
*/

#ifndef _APPLICATION_H_
#define _APPLICATION_H_

#include <QCoreApplication>
#include <QTimer>

#include "MainController.h"

#endif  // _APPLICATION_H_

Application.cpp

#include "Application.h"

int main(int argc, char **argv)
{
//  Setup our console application with an event loop
QCoreApplication app(argc, argv);

//  Create and initialize our controller
MainController controller;
controller.Init();
QObject::connect(&controller, SIGNAL( Finished() ), &app, SLOT( quit() ), Qt::QueuedConnection);

//  This will put start on top of the event loop
QTimer::singleShot(0, &controller, SLOT( Start() ));

// Finally start up the event loop
return app.exec(); 
}

MainController.h

/**
 @file
 @author        Nikolaus Karpinsky
 */

#ifndef _MAIN_CONTROLLER_H_
#define _MAIN_CONTROLLER_H_

#include <QObject>
#include <QGLWidget>
#include <QGLPixelBuffer>
#include <QGLFramebufferObject>
#include <memory>

using namespace std;

class MainController : public QObject
{
  Q_OBJECT

private:
  unqiue_ptr<QGLPixelBuffer> m_mainBuffer;
  //unique_ptr<QGLContext> m_mainContext;

public:
  MainController();
  void Init(void);

public slots:
  void Start(void);
  void Close(void);

signals:
  void Finished(void);
};

#endif  // _MAIN_CONTROLLER_H_

MainController.cpp

#include "MainController.h"

MainController::MainController() : QObject()
{ }

void MainController::Init(void)
{
  m_mainBuffer = unique_ptr<QGLPixelBuffer>(new QGLPixelBuffer(800, 600));
  bool has      = buffer->hasOpenGLPbuffers();
  bool current  = buffer->makeCurrent();
  bool valid    = buffer->isValid();

  //  Now I need to get access to the context to share it with additional threads
  // m_mainContext = unique_ptr<QGLContext>(new QGLContext(buffer.getContext()));
}

void MainController::Start(void)
{
}

void MainController::Close(void)
{
  //  This will tell the event loop that we are done and close the app
  emit( Finished() );
}
4

2 に答える 2

2

ウィンドウなしでQGLContextを作成することは可能ですか?

はい、でも落とし穴があります…</ p>

Webでの読み取りはそれほど多くはありませんが、私が収集したものから、有効なQPaintDeviceであるQGLPixelBufferを作成できます。

はい。ただし、そのPBufferはGPUと通信する必要があります。Linuxでは、GPUと通信する通常の方法はXサーバーを使用することです。したがって、実際には、GPUドライバーを使用してXサーバーを起動、PBufferがGPUで動作できるようにアクティブなVTが必要です。

うまくいけば、GPUへの新しいABI / APIが間もなく登場します。これにより、Xサーバーを使用せずにGPUでオフスクリーンレンダリングコンテキストを作成できます。

このルートで発生している問題は、別のスレッド(レンダリングされたシーンからの高速DMAテクスチャ転送用のネットワークスレッド)と共有できるように、基になるQGLContextにアクセスする必要があることです。

残念ながら、Qt開発者はOpenGLについて限られた知識しか持っていないようです。OpenGLで完全に可能であり、明確に指定されているいくつかのことは、明白な理由なしにQtでは不可能です。たとえば、単一のドローアブルを使用して、任意の数のコンテキストを持つことができます。ただし、再バインドすることで、任意の数の(互換性のある)ドローアブルで単一のコンテキストを使用することもできます。どちらもQtと明確な設計上の欠陥によってサポートされていません。私は今、これに苦労しています。

于 2013-01-15T21:36:40.770 に答える
1

さて、いくつか遊んだ後、私は十分な解決策を見つけました。現在、アプリケーションをQApplicationとQCoreApplicationとして実行しています。ここから、GUIスレッドでQGLWidgetを作成し、すぐにウィジェットでupdateGL()を呼び出して、OpenGLコンテキストを作成して初期化します。アプリを表示しないと仮定すると、アプリは「ヘッドレス」で実行されますが、XまたはExplorerからQTに必要なウィンドウハンドルを取得します。

もう少し深く掘り下げて、他のスレッドで共有QGLContextを取得する必要もありました。QGLWidgetからコンテキストのコピーを作成するには、非推奨のコンストラクターを使用してQGLWidgetを作成します。ここで、ペインター(QGLWidget)を指定してから、QGLWidgetsコンテキストを使用して作成します。以下に例を掲載しました。これを使用して、アプリを「ヘッドレス」に保ちながら、あるスレッドでテクスチャを記述し、別のスレッドで処理することができます。助けてくれてありがとうdatenwolf。

shared_ptr<QGLContext> MainController::MakeSharedContext(void)
{
  shared_ptr<QGLContext> sharedContext(nullptr);

  if(nullptr != m_mainContext)
  {
    // m_mainContext is: shared_ptr<QGLWidget>
    sharedContext = shared_ptr<QGLContext>( new QGLContext(m_mainContext->format(), m_mainContext.get( ) ) );
    bool created = sharedContext->create( m_mainContext->context( ) );
    Utils::AssertOrThrowIfFalse(created, "Unable to create a shared OpenGL context" );
  }

  return sharedContext;
}
于 2013-01-17T21:03:58.080 に答える