デバイスまたは描画 API に固有のコードを書くことは推奨されませんが、デバイス固有の情報が必要なときにアクセスする必要がある場合があります。この例は、プラグインが GPU の計算を使用していくつかの操作を実行する場合です。
描画 API 固有の情報は、リソースへのハンドルにアクセスすることによって取得できます。ハンドルには、次のレベルでアクセスすることができます。
MTexture): DirectX 11 のシェーダ リソース ビューへのポインタ リファレンスまたは OpenGL のテクスチャ識別子が返されます。MRenderTarget): DirectX のレンダー ターゲット ビューまたは深度ステンシル ビュー(ターゲット タイプに応じる)へのポインタ リファレンスとして公開されます。OpenGL の場合、テクスチャ ID へのポインタとして返されます。お勧めの方法は、プラグインで、API を介して必要なすべてのリソースを作成し、適切な GPU リファレンスを抽出することです。
プラグインが API ラッパーへのリファレンスを保持している限り、このリファレンスが存在し、非表示になることはありません。リソース管理処理のためにハンドルが変更された場合に備えて、ハンドルを再度照会することをお勧めします。リソース ハンドルを単一のフレーム レンダー内で変更することはできません。
GPU 上に直接作成される(API を介さずに)リソースの管理は、プラグイン作成者の責任です。また、このデータを使用して、エクスポーズされた API ラッパー コンストラクトを介してリソースを作成することはできません。
MPxShaderOverride は、一般的に GPU データにアクセスするためのインタフェースです。CgFX および dx11Shader SDK プラグインは、パラメータをシェーダにバインドするために、または描画のジオメトリをバンドするために、未処理データにアクセスする方法の例を示しています。さらに、プラグインには、GPU コンテキストにアクセスして、内部フレームワークによって追跡されていないリソースを作成するコードが含まれます。
DirectCompute の例
GPU の計算を使用して、手続き的に生成されたジオメトリをサポートすることができます。これを設定するには、関連付けられた描画オーバーライド(MPxDrawOverride)とともにカスタム DAG ノード(たとえば、MPxLocatorNode)を追加するプラグインを作成します。オーバーライドの描画ルーチンでは、DirectX 11 デバイスが照会されます。
// Get the device and context
ID3D11Device* dxDevice = NULL;
ID3D11DeviceContext* dxContext = NULL;
MHWRender::MRenderer* theRenderer = MHWRender::MRenderer::theRenderer();
if (theRenderer->drawAPI() == MHWRender::DrawAPI::kDirectX11)
{
// init device
ID3D11Device* dxDevice = (ID3D11Device*)theRenderer->GPUDeviceHandle();
if (!dxDevice) return;
// get context
dxDevice->GetImmediateContext(&dxContext);
if (!dxContext) return;
}
この情報を抽出したら、計算シェーダを使用してテクスチャを塗り潰します。次に、このテクスチャはピクセル シェーダによって使用され、ジオメトリがレンダリングされます。
// Load in a compute shader
MString shaderPath("myComputeShader.hlsl");
ID3D11ComputeShader* aComputeShader = NULL;
ID3D10Blob* pPSBuf = NULL;
HRESULT hr = D3DX11CompileFromFile( shaderPath.asChar(), NULL, NULL, "AComputeShader", "cs_5_0", dwShaderFlags, NULL, NULL, &pPSBuf, NULL, NULL );
hr = dxDevice->CreateComputeShader( ( DWORD* )pPSBuf->GetBufferPointer(), pPSBuf->GetBufferSize(), NULL, &aComputeShader );
pPSBuf->Release();
// The “resource” to update. Filled by the compute shader(s), and
// rendered by the pixel shader.
ID3D11ShaderResourceView* shaderResourceView; // Pixel shader view
ID3D11UnorderedAccessView* computeResourceView; // Compute shader view
Resource pRenderOutput;
ID3D11Texture2D* outputTexture = NULL;
// Create a 2D texture to write into
D3D11_TEXTURE2D_DESC tdesc;
tdesc.Width = g_width;
tdesc.Height = g_height;
tdesc.MipLevels = 1;
tdesc.ArraySize = 1;
tdesc.SampleDesc.Count = 1;
tdesc.SampleDesc.Quality = 0;
tdesc.Usage = D3D11_USAGE_DEFAULT;
tdesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
tdesc.BindFlags = D3D11_BIND_SHADER_RESOURCE | D3D11_BIND_UNORDERED_ACCESS;
tdesc.CPUAccessFlags = 0;
tdesc.MiscFlags = 0;
hr = dxDevice->CreateTexture2D(&tdesc, NULL, &outputTexture);
// Create an unordered access view to the texture which a compute shader
// can write into.
dxDevice->CreateUnorderedAccessView( outputTexture, NULL, &computeResourceView);
// Create a resource view to the texture that will be used by a pixel shader
dxDevice->CreateShaderResourceView( outputTexture, NULL, &shaderResourceView);
// Set inputs
dxContext->CSSetShaderResources( 0, 1, shaderResourceView);
// Set outputs
dxContext->CSSetUnorderedAccessViews(0, 1, computeResourceView, (UINT*)(&computeResourceView));
// Set the compute shader
dxContext->CSSetShader(aComputeShader, NULL, 0 );
// Run the compute shader with 32 x 32 groups (e.g.)
dxContext->Dispatch( 32, 32, 1 );
//...