今更ですがディファードレンダリングのコードを書いていました。ポイントライトをたくさんおける仕組みなのがいいですね。
古いタイプのレンダリングコードとはまた違った感じで、入力は既に描画したテクスチャを参照してデータが入ってくるのは新鮮でした。
そのときに、既に描画済みのデプスバッファを参照しつつも、デプステストは有効にしたいというようなケースでワーニングに出遭ってしまいました。
リソースハザードの発生
今回の場合では、デプスバッファがシェーダーへの入力と、パイプラインの出力(出力マージャー)に設定されているために、リソースハザードの警告が発生しました。
デプスステンシルステートで、 D3D11_DEPTH_WRITE_MASK_ZERO を設定して、書き込まれないようにしていてもこの警告は発生します。
ピクセルシェーダーで ShaderResource として読み込む設定だったため、以下の警告が VisualStudio で表示されました。
D3D11 WARNING: ID3D11DeviceContext::PSSetShaderResources: Resource being set to PS shader resource slot 3 is still bound on output! Forcing to NULL. [ STATE_SETTING WARNING #7: DEVICE_PSSETSHADERRESOURCES_HAZARD]
この警告への対応を考えます。
対応策
今回の例では ID3D11DepthStencilView をもう1つ作成することになりました。
読み込み専用としての ID3D11DepthStencilView を作成します。これは以下のようにして作成します。
フラグに D3D11_DSV_READ_ONLY_DEPTH を設定するのがポイントです。難点はこのフラグの存在に気付きにくいことでしょうか。
D3D11_DEPTH_STENCIL_VIEW_DESC descDSVRO; ZeroMemory(&descDSVRO, sizeof(descDSVRO)); descDSVRO.Format = DXGI_FORMAT_D32_FLOAT; descDSVRO.ViewDimension = D3D11_DSV_DIMENSION_TEXTURE2D; descDSVRO.Flags = D3D11_DSV_READ_ONLY_DEPTH;
今更ですが、デプスバッファをテクスチャとして読み込むためには、デプステクスチャ作成時に BindFlags を D3D11_BIND_DEPTH_STENCIL | D3D11_BIND_SHADER_RESOURCE で作成します。このとき、フォーマットは DXGI_FORMAT_D32_FLOAT ではなく、 DXGI_FORMAT_R32_TYPELESS を使って作成しておく必要がありました。
DXGI_FORMAT_R32_FLOAT, DXGI_FORMAT_D32_FLOAT のフォーマットを指定して、各ビューの作成を行います。
感想
現時点においては簡単なものしか入れていないため、まだデプスバッファをINにもOUTにも設定して有効活用するといったところまでは到達していません。やろうと思ったら今までに説明した内容に出遭ってしまったので記事にしてみました。
デプスバッファを出力マージャーに設定しておきたいのはデプステストや Depth Bounds Test とかを活用したいという狙いです。
あとは、デプスを入力として参照したかったのは SSAO や ワールド位置の復元をこのバッファから出来れば、G-buffer に出さなくていい(削減できる)と考えたからです。