図面を個別のスレッドでレンダリングする

はじめに

このトピックでは、パフォーマンスを向上させるために、図面を個別のスレッドでレンダリングする方法について説明します。

ODA BimRv SDK は、OdBmMTDrawContext、OdBmMTDraw、および OdBmMTDrawingMgr クラスのマルチスレッド機能を呼び出すためのシンプルな API を提供します。

OdBmMTDraw クラスは、指定されたコンテキストを介して、単一の OdBmDBDrawing 要素に対するスレッドセーフなレンダリング機能を提供します。

OdBmMTDrawingMgr クラスは、指定されたコンテキストを介して、OdBmDBDrawing 要素の配列に対するスレッドセーフなレンダリング機能を提供します。これは、複数の OdBmMTDraw インスタンスを起動して、図面の配列を個別の並行スレッドでレンダリングするだけです。

また、OdBmMTDrawContext またはその派生クラスのインスタンスが必要です。以下の typedef とコンストラクタを参照してください。


typedef std::function<OdGsDevicePtr(const OdBmMTDrawContext*)> OdBmCreateGsDeviceFuncType;
typedef std::function<void(OdBmObjectId, OdGsDevice*, const OdBmMTDrawContext*)> OdBmPostProcessFuncType;

OdBmMTDrawContext(
    OdMutex* pDbAccessMutex,
    long picWidth,
    long picHeight,
    bool bZoomToExtents,
    const OdBmCreateGsDeviceFuncType& deviceCreator,
    const OdBmPostProcessFuncType& postProcessor)

最後の2つのパラメータは、実装する必要がある関数への参照です。

最初の関数は OdBmCreateGsDeviceFuncType プロトタイプを満たし、適切な GS デバイスを作成し、そのポインタを返す必要があります。

2番目の関数は OdBmPostProcessFuncType プロトタイプを満たし、レンダリング結果の後処理を実行する必要があります。

次の例では、GLES2 デバイスを介して DBDrawings をレンダリングし、結果をビットマップ配列に格納します。以下のコードは BmMTDrawingMgrEx の例で見つけることができます。

まず、OdBmMTDrawContext クラスの派生クラスを作成します。

struct OdBmGLES2MTDrawContext : public OdBmMTDrawContext {
  OdBmGLES2MTDrawContext(
    OdMutex* dbAccessMutex,
    long picWidth,
    long picHeight,
    bool bZoomToExtents,
    const OdBmCreateGsDeviceFuncType& createGsDeviceFunc,
    const OdBmPostProcessFuncType& postProcessFunc,
    // discard back faces wile rendering
    bool bDiscardBackFaces,
    // use plot generation
    bool bPlotGeneration,
    // background color of result images
    ODCOLORREF bgColor = ODRGB(255, 255, 255)):
  OdBmMTDrawContext(
    dbAccessMutex, picWidth, 
    picHeight, bZoomToExtents,
    createGsDeviceFunc, postProcessFunc),
    discardBackFaces(bDiscardBackFaces),
    plotGeneration(bPlotGeneration),
    bgColor(bgColor) {
  }

  bool discardBackFaces;
  ODCOLORREF bgColor;
  bool plotGeneration;
};

次に、例えばカバークラスを定義します。

class OdBmMTRenderer {
public:
  // type defenition for rendering results
  typedef std::map Renditions; 
  /* execution params
    param drawings - an array of drawings to be rendered.
    param picWidth - width of result bitmaps in pixels.
    param picHeight - height of result bitmaps in pixels.
    param bZoomToExtents - use zoom to extents.
    param bDiscardBackFaces - discard back faces while rendering.
    param bgColor - result bitmaps background color.
  */
  Renditions run(OdBmDBDrawingPtrArray& drawings,
    long picWidth, long picHeight, bool bZoomToExtents = false,
    bool bDiscardBackFaces = false, ODCOLORREF bgColor = ODRGB(255, 255, 255));
};

次に、それを実装します。まず、必要なすべてのインクルードファイルを取得します。

#include "BmMTRenderer.h"

#include "DynamicLinker.h"
#include "RxVariantValue.h"
#include "Gi/GiRasterWrappers.h"
#include "Database/MTDrawingMgr/BmMTDrawingMgr.h"

#include "MTDrawingMgr/BmMTDraw.h"
#include "BmGLES2MTDrawContext.h"

次に、run() 関数を実装します。これは特殊なプロセスであるため、最初のステップは OdBmCreateGsDeviceFuncType 型の関数を作成することです。

/******************************************************************/
/* GS device creation function                                    */
/******************************************************************/

OdMutex m_createDevice;
auto createDevice = [&m_createDevice](const OdBmMTDrawContext* pContext) {
    TD_AUTOLOCK(m_createDevice);
    const OdBmGLES2MTDrawContext* pToImgContext =
      static_cast(pContext);

    OdGsModulePtr pGsModule = ::odrxDynamicLinker()->loadModule(OdWinGLES2ModuleName);
    OdGsDevicePtr pGsDevice = pGsModule->createBitmapDevice();

    // Enable HLR for Bitmap and WinGDI vectorizers
    OdRxDictionaryPtr pProps = pGsDevice->properties();
    if (pProps->has(OD_T("EnableSoftwareHLR"))) // Check if property is supported
      pProps->putAt(OD_T("EnableSoftwareHLR"), OdRxVariantValue(true));
    if (pProps->has(OD_T("DiscardBackFaces"))) // Check if property is supported
      pProps->putAt(OD_T("DiscardBackFaces"), OdRxVariantValue(pToImgContext->discardBackFaces()));

    OdRxThreadPoolServicePtr pThreadPool = ::odrxDynamicLinker()->loadApp(OdThreadPoolModuleName);
    if (pThreadPool.isNull())
      throw(L"ThreadPool.tx not found.\n");

    OdUInt16 nCPUs = pThreadPool->numCPUs();
    if (pGsDevice->properties()->has(OD_T("MaxRegenThreads")))
      pGsDevice->properties()->putAt(OD_T("MaxRegenThreads"), OdRxVariantValue(nCPUs));

    if (pGsDevice->properties()->has(OD_T("EnableMultithread")))
      pGsDevice->properties()->putAt(OD_T("EnableMultithread"), OdRxVariantValue(true));

    pGsDevice->setLogicalPalette(
      (ODGETRED(pToImgContext->bgColor()) < 140) && (ODGETGREEN(pToImgContext->bgColor()) < 140) && (ODGETBLUE(pToImgContext->bgColor()) < 140) ?
      (::odcmAcadDarkPalette()) : (::odcmAcadLightPalette()), 256);
    pGsDevice->setBackgroundColor(pToImgContext->bgColor());

    return pGsDevice;
};

次に、OdBmPostProcessFuncType 型の関数を作成します。

/******************************************************************/
/* Rendering results processing function                          */
/******************************************************************/

OdMutex m_mutex;
Renditions renditions;
auto postPrecess = [&m_mutex, &renditions](OdBmObjectId id, OdGsDevice* pDevice, const OdBmMTDrawContext* pContext) {
    TD_AUTOLOCK(m_mutex);
    // Create clone of rendered raster image to correctly release all vectorizer resources in current thread
    OdGiRasterImagePtr pRaster = OdGiRasterImageHolder::createObject(
      OdGiRasterImagePtr(pDevice->properties().get()->getAt(OD_T("RasterImage"))));
    renditions[id] = pRaster;
};

最後に、OdBmMTDrawContext のインスタンスを作成します。

/******************************************************************/
/* Instantiate the context and start MT rendering                 */
/******************************************************************/

OdBmGLES2MTDrawContext m_ctx(&m_mutex, picWidth, picHeight, bZoomToExtents,
    (OdBmMTDrawContext::OdBmCreateGsDeviceFuncType)createDevice, 
    (OdBmMTDrawContext::OdBmPostProcessFuncType)postPrecess,
    bDiscardBackFaces, bgColor);
 
OdBmMTDrawingMgr().draw(drawings, &m_ctx);

return renditions;

run() メソッドは、BimRv/Examples/BmMTDrawingMgrEx/BmMTDrawingMgrEx.cpp ファイルに実装されています。

今すぐ始める

ODAソフトウェアを60日間無料でお試しください。
リスクなし、クレジットカード不要。

無料で試す