OSDN Git Service

ラスタライザステートを、デバイスリソース から テクスチャ の共通項目(static) へ委譲。
[strokestylet/CsWin10Desktop3.git] / FDK24 / メディア / デバイスリソース.cs
1 using System;
2 using System.Collections.Generic;
3 using System.Diagnostics;
4 using System.Linq;
5
6 namespace FDK.メディア
7 {
8         public class デバイスリソース
9         {
10                 public SharpDX.Size2F 設計画面サイズdpx = new SharpDX.Size2F( 640f, 480f );
11                 public SharpDX.Size2F 物理画面サイズpx = new SharpDX.Size2F( 0, 0 );     // (0, 0) は、サイズ依存リソース無効の印。
12                 public IntPtr ウィンドウハンドル = IntPtr.Zero;
13                 public float 視野角deg { get; set; } = 45f;
14                 public SharpDX.Matrix ビュー変換行列
15                 {
16                         get
17                         {
18                                 var カメラの位置 = new SharpDX.Vector3( 0f, 0f, ( -2f * this.dz( this.設計画面サイズdpx.Height, this.視野角deg ) ) );
19                                 var カメラの注視点 = new SharpDX.Vector3( 0f, 0f, 0f );
20                                 var カメラの上方向 = new SharpDX.Vector3( 0f, 1f, 0f );
21                                 var mat = SharpDX.Matrix.LookAtLH( カメラの位置, カメラの注視点, カメラの上方向 );
22                                 mat.Transpose();  // 転置
23                                 return mat;
24                         }
25                 }
26                 public SharpDX.Matrix 射影変換行列
27                 {
28                         get
29                         {
30                                 float dz = this.dz( this.設計画面サイズdpx.Height, this.視野角deg );
31                                 var mat = SharpDX.Matrix.PerspectiveFovLH(
32                                         SharpDX.MathUtil.DegreesToRadians( 視野角deg ),
33                                         設計画面サイズdpx.Width / 設計画面サイズdpx.Height,  // アスペクト比
34                                         -dz,  // 前方投影面までの距離
35                                         dz ); // 後方投影面までの距離
36                                 mat.Transpose();  // 転置
37                                 return mat;
38                         }
39                 }
40                 public SharpDX.Direct3D11.Device D3DDevice => this.bs_D3DDevice;
41                 public SharpDX.DXGI.SwapChain SwapChain => this.bs_SwapChain;
42                 public SharpDX.Direct3D11.RenderTargetView RenderTargetView => this.bs_RenderTargetView;
43                 public SharpDX.Mathematics.Interop.RawViewportF[] ViewPort => this.bs_ViewPort;
44                 public SharpDX.Direct3D11.Texture2D DepthStencil => this.bs_DepthStencil;
45                 public SharpDX.Direct3D11.DepthStencilView DepthStencilView => this.bs_DepthStencilView;
46                 public SharpDX.Direct3D11.DepthStencilState DepthStencilState => this.bs_DepthStencilState;
47                 public SharpDX.Direct3D11.ShaderResourceView ShaderResourceView => this.bs_ShaderResourceView;
48                 public SharpDX.Direct3D11.SamplerState SamplerState => this.bs_SamplerState;
49                 protected SharpDX.Size2F ShaderResourceViewSize;
50
51                 public void すべてのリソースを作成する( System.Drawing.Size バックバッファサイズ, IntPtr ウィンドウハンドル )
52                 {
53                         this.物理画面サイズpx = new SharpDX.Size2F( バックバッファサイズ.Width, バックバッファサイズ.Height );
54                         this.ウィンドウハンドル = ウィンドウハンドル;
55
56                         this.すべてのリソースを作成する();
57                 }
58                 protected void すべてのリソースを作成する()
59                 {
60                         // これらが呼び出し前に設定されていること。
61                         Debug.Assert( ( 0f < this.物理画面サイズpx.Width ) && ( 0f < this.物理画面サイズpx.Height ) );
62                         Debug.Assert( IntPtr.Zero != this.ウィンドウハンドル );
63
64                         #region " デバイス、スワップチェーンを作成する。"
65                         //----------------
66                         // スワップチェーン desc
67                         var swapChainDesc = new SharpDX.DXGI.SwapChainDescription() {
68                                 BufferCount = 3,
69                                 ModeDescription = new SharpDX.DXGI.ModeDescription(
70                                         (int) this.物理画面サイズpx.Width,
71                                         (int) this.物理画面サイズpx.Height,
72                                         new SharpDX.DXGI.Rational( 60, 1 ),
73                                         SharpDX.DXGI.Format.B8G8R8A8_UNorm
74                                 ),
75                                 IsWindowed = true,
76                                 OutputHandle = ウィンドウハンドル,
77                                 SampleDescription = new SharpDX.DXGI.SampleDescription( 1, 0 ),
78                                 SwapEffect = SharpDX.DXGI.SwapEffect.Discard,
79                                 Usage = SharpDX.DXGI.Usage.RenderTargetOutput,
80                         };
81                         // 機能レベル
82                         var featureLevels = new SharpDX.Direct3D.FeatureLevel[] {
83                                 SharpDX.Direct3D.FeatureLevel.Level_11_0,
84                                 SharpDX.Direct3D.FeatureLevel.Level_10_1,
85                                 SharpDX.Direct3D.FeatureLevel.Level_10_0,
86                         };
87                         // デバイスとスワップチェーンを作成する。
88                         SharpDX.Direct3D11.Device.CreateWithSwapChain(
89                                 SharpDX.Direct3D.DriverType.Hardware,
90                                 SharpDX.Direct3D11.DeviceCreationFlags.None,
91                                 featureLevels,
92                                 swapChainDesc,
93                                 out this.bs_D3DDevice,
94                                 out this.bs_SwapChain );
95
96                         Trace.WriteLine( "D3Dデバイスとスワップチェーンを生成しました。" );
97                         Trace.WriteLine( $"機能レベル: {this.bs_D3DDevice.FeatureLevel.ToString()}" );
98                         //----------------
99                         #endregion
100                         #region " すべての Windows イベントを無視する。具体的には PrintScreen と Alt+Enter 。"
101                         //----------------
102                         using( var factory = this.bs_SwapChain.GetParent<SharpDX.DXGI.Factory>() )
103                         {
104                                 factory.MakeWindowAssociation( ウィンドウハンドル, SharpDX.DXGI.WindowAssociationFlags.IgnoreAll );
105                         }
106                         //----------------
107                         #endregion
108                         #region " 深度ステンシルステート "
109                         //----------------
110                         var DepthSencil = new SharpDX.Direct3D11.DepthStencilStateDescription() {
111                                 IsDepthEnabled = true,  // 深度テストあり
112                                 DepthWriteMask = SharpDX.Direct3D11.DepthWriteMask.All,     // 書き込む
113                                 DepthComparison = SharpDX.Direct3D11.Comparison.Less,   // 手前の物体を描画
114                                 IsStencilEnabled = false,   // ステンシルテストなし。
115                                 StencilReadMask = 0,    // ステンシル読み込みマスク。
116                                 StencilWriteMask = 0,   // ステンシル書き込みマスク。
117
118                                 // 面が表を向いている場合のステンシル・テストの設定
119                                 FrontFace = new SharpDX.Direct3D11.DepthStencilOperationDescription() {
120                                         FailOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
121                                         DepthFailOperation = SharpDX.Direct3D11.StencilOperation.Keep,  // 維持
122                                         PassOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
123                                         Comparison = SharpDX.Direct3D11.Comparison.Never,   // 常に失敗
124                                 },
125
126                                 // 面が裏を向いている場合のステンシル・テストの設定
127                                 BackFace = new SharpDX.Direct3D11.DepthStencilOperationDescription() {
128                                         FailOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
129                                         DepthFailOperation = SharpDX.Direct3D11.StencilOperation.Keep,  // 維持
130                                         PassOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
131                                         Comparison = SharpDX.Direct3D11.Comparison.Always,  // 常に成功
132                                 },
133                         };
134                         this.bs_DepthStencilState = new SharpDX.Direct3D11.DepthStencilState( this.bs_D3DDevice, DepthSencil );
135                         //----------------
136                         #endregion
137                         #region " シェーダーリソースビュー "
138                         //----------------
139                         this.bs_ShaderResourceView = FDK.Utilities.CreateShaderResourceViewFromFile(
140                                 this.D3DDevice, "テスト用テクスチャ画像.jpg", out this.ShaderResourceViewSize );
141                         //D3DX11CreateShaderResourceViewFromFile( g_pD3DDevice, L"texture.png", NULL, NULL, &g_pTextureSRV, &hr );
142                         //----------------
143                         #endregion
144                         #region " サンプラー "
145                         //----------------
146                         var descSampler = new SharpDX.Direct3D11.SamplerStateDescription() {
147                                 Filter = SharpDX.Direct3D11.Filter.Anisotropic,
148                                 AddressU = SharpDX.Direct3D11.TextureAddressMode.Wrap,
149                                 AddressV = SharpDX.Direct3D11.TextureAddressMode.Wrap,
150                                 AddressW = SharpDX.Direct3D11.TextureAddressMode.Wrap,
151                                 MipLodBias = 0.0f,
152                                 MaximumAnisotropy = 2,
153                                 ComparisonFunction = SharpDX.Direct3D11.Comparison.Never,
154                                 BorderColor = new SharpDX.Mathematics.Interop.RawColor4( 0f, 0f, 0f, 0f ),
155                                 MinimumLod = float.MinValue,
156                                 MaximumLod = float.MaxValue,
157                         };
158                         this.bs_SamplerState = new SharpDX.Direct3D11.SamplerState( this.bs_D3DDevice, descSampler );
159                         //----------------
160                         #endregion
161
162                         this.サイズに依存するリソースを作成する();
163                 }
164                 public void すべてのリソースを解放する()
165                 {
166                         // デバイスステートをクリアする。
167                         this.bs_D3DDevice?.ImmediateContext?.ClearState();
168
169                         // スワップチェインをウインドウモードにする。
170                         this.bs_SwapChain?.SetFullscreenState( fullscreen: false, targetRef: null );
171
172                         this.サイズに依存するリソースを解放する();
173
174                         // 取得したインターフェイスの開放
175                         this.bs_DepthStencilState?.Dispose();
176                         this.bs_SamplerState?.Dispose();
177                         this.bs_ShaderResourceView?.Dispose();
178                         this.bs_SwapChain?.Dispose();
179                         this.bs_D3DDevice?.Dispose();
180                 }
181                 public void サイズに依存するリソースを作成する()
182                 {
183                         #region " スワップチェーンのサイズを変更する。"
184                         //----------------
185                         Debug.Assert( null != this.SwapChain ); // スワップチェーンは、デバイスとともに、すでに生成される。
186                         this.SwapChain.ResizeBuffers(
187                                 bufferCount: 2,
188                                 width: (int) this.物理画面サイズpx.Width,
189                                 height: (int) this.物理画面サイズpx.Height,
190                                 newFormat: SharpDX.DXGI.Format.R8G8B8A8_UNorm,
191                                 swapChainFlags: SharpDX.DXGI.SwapChainFlags.AllowModeSwitch );
192                         //----------------
193                         #endregion
194
195                         // 新しいサイズになったバックバッファを取得して、リソースを作成する。
196                         using( var backBuffer = SharpDX.Direct3D11.Texture2D.FromSwapChain<SharpDX.Direct3D11.Texture2D>( this.bs_SwapChain, 0 ) )
197                         {
198                                 #region " RenderTargetView の作成 "
199                                 //----------------
200                                 this.bs_RenderTargetView = new SharpDX.Direct3D11.RenderTargetView( this.bs_D3DDevice, backBuffer );
201                                 //----------------
202                                 #endregion
203                                 #region " 深度ステンシルテクスチャの作成 "
204                                 //----------------
205                                 var descDepth = backBuffer.Description;
206                                 //descDepth.Width = backBuffer.Description.Width;       → backBuffer に同じ
207                                 //descDepth.Height = backBuffer.Description.Height;     → 同上
208                                 descDepth.MipLevels = 1;    // ミップマップレベル数
209                                 descDepth.ArraySize = 1;    // 配列サイズ
210                                 descDepth.Format = SharpDX.DXGI.Format.D32_Float;   // フォーマット(深度のみ)
211                                 descDepth.Usage = SharpDX.Direct3D11.ResourceUsage.Default; // デフォルト使用法
212                                 descDepth.BindFlags = SharpDX.Direct3D11.BindFlags.DepthStencil;    // 深度ステンシル
213                                 descDepth.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None;  // CPUからはアクセスしない
214                                 descDepth.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None;    // その他の設定なし
215
216                                 this.bs_DepthStencil = new SharpDX.Direct3D11.Texture2D( this.bs_D3DDevice, descDepth );
217                                 //----------------
218                                 #endregion
219                                 #region " 深度ステンシルビューの作成 "
220                                 //----------------
221                                 var descDSV = new SharpDX.Direct3D11.DepthStencilViewDescription() {
222                                         Format = descDepth.Format,
223                                         Dimension = SharpDX.Direct3D11.DepthStencilViewDimension.Texture2D,
224                                         Flags = SharpDX.Direct3D11.DepthStencilViewFlags.None,
225                                 };
226                                 descDSV.Texture2D.MipSlice = 0;
227                                 this.bs_DepthStencilView = new SharpDX.Direct3D11.DepthStencilView(
228                                         this.bs_D3DDevice,
229                                         this.bs_DepthStencil,
230                                         descDSV );
231                                 //----------------
232                                 #endregion
233                                 #region " ビューポートの設定 "
234                                 //----------------
235                                 this.bs_ViewPort[ 0 ] = new SharpDX.Mathematics.Interop.RawViewportF() {
236                                         X = 0.0f,
237                                         Y = 0.0f,
238                                         Width = (float) backBuffer.Description.Width,
239                                         Height = (float) backBuffer.Description.Height,
240                                         MinDepth = 0.0f,
241                                         MaxDepth = 1.0f,
242                                 };
243                                 //----------------
244                                 #endregion
245                                 #region " テクスチャの共有リソースの作成 "
246                                 //----------------
247                                 FDK.メディア.テクスチャ.共有リソースを作成する( this );
248                                 //----------------
249                                 #endregion
250                         }
251                 }
252                 public void サイズに依存するリソースを解放する()
253                 {
254                         // 描画ターゲットを解除する。
255                         this.D3DDevice.ImmediateContext.OutputMerger.ResetTargets();
256
257                         FDK.メディア.テクスチャ.共有リソースを解放する();
258                         this.bs_DepthStencilView?.Dispose();
259                         this.bs_DepthStencil?.Dispose();
260                         this.bs_RenderTargetView?.Dispose();
261                         //this.bs_SwapChain?.Dispose(); → スワップチェーンは解放しない(生成・解放はデバイスとセット)。
262
263                         // (0,0)は、サイズ依存リソース無効の印。
264                         this.物理画面サイズpx = new SharpDX.Size2F( 0, 0 );
265                 }
266                 public void D3Dデバイスが消失していれば再構築する( out bool 異常状態なのでアプリを終了せよ )
267                 {
268                         異常状態なのでアプリを終了せよ = false;
269
270                         var 削除理由 = this.bs_D3DDevice.DeviceRemovedReason;
271                         if( 削除理由.Success )
272                                 return;
273
274                         var エラー詳細 = new[] {
275                                         new { Code = SharpDX.DXGI.ResultCode.DeviceHung.Code, Info = SharpDX.DXGI.ResultCode.DeviceHung.ApiCode, Rebuild = true },
276                                         new { Code = SharpDX.DXGI.ResultCode.DeviceReset.Code, Info = SharpDX.DXGI.ResultCode.DeviceReset.ApiCode, Rebuild = true },
277                                         new { Code = SharpDX.DXGI.ResultCode.DeviceRemoved.Code, Info = SharpDX.DXGI.ResultCode.DeviceRemoved.ApiCode, Rebuild = false },
278                                         new { Code = SharpDX.DXGI.ResultCode.DriverInternalError.Code, Info = SharpDX.DXGI.ResultCode.DriverInternalError.ApiCode, Rebuild = false },
279                                         new { Code = SharpDX.DXGI.ResultCode.InvalidCall.Code, Info = SharpDX.DXGI.ResultCode.InvalidCall.ApiCode, Rebuild = false },
280                                 }.First( ( エラー ) => エラー.Code == 削除理由.Code );  // 見つからないなら System.InvalidOperationException 。
281
282                         Trace.WriteLine( $"D3Dデバイスが消失しました: {エラー詳細.Info}" );
283
284                         if( エラー詳細.Rebuild )
285                         {
286                                 this.すべてのリソースを解放する();
287                                 this.すべてのリソースを作成する();
288                         }
289                         else
290                         {
291                                 異常状態なのでアプリを終了せよ = true;
292                         }
293                 }
294
295                 private float dz( float 高さdpx, float 視野角deg )
296                 {
297                         return (float) ( 高さdpx / ( 4.0 * Math.Tan( SharpDX.MathUtil.DegreesToRadians( 視野角deg / 2.0f ) ) ) );
298                 }
299
300                 #region " バックストア。"
301                 //----------------
302                 private SharpDX.Direct3D11.Device bs_D3DDevice = null;
303                 private SharpDX.DXGI.SwapChain bs_SwapChain = null;
304                 private SharpDX.Mathematics.Interop.RawViewportF[] bs_ViewPort = new SharpDX.Mathematics.Interop.RawViewportF[ 1 ];
305                 private SharpDX.Direct3D11.DepthStencilState bs_DepthStencilState = null;
306                 private SharpDX.Direct3D11.ShaderResourceView bs_ShaderResourceView = null;
307                 private SharpDX.Direct3D11.SamplerState bs_SamplerState = null;
308                 private SharpDX.Direct3D11.RenderTargetView bs_RenderTargetView = null;
309                 private SharpDX.Direct3D11.Texture2D bs_DepthStencil = null;
310                 private SharpDX.Direct3D11.DepthStencilView bs_DepthStencilView = null;
311                 //----------------
312                 #endregion
313         }
314 }