OSDN Git Service

テクスチャを実装。
[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
48                 public void すべてのリソースを作成する( System.Drawing.Size バックバッファサイズ, IntPtr ウィンドウハンドル )
49                 {
50                         this.物理画面サイズpx = new SharpDX.Size2F( バックバッファサイズ.Width, バックバッファサイズ.Height );
51                         this.ウィンドウハンドル = ウィンドウハンドル;
52
53                         this.すべてのリソースを作成する();
54                 }
55                 protected void すべてのリソースを作成する()
56                 {
57                         // これらが呼び出し前に設定されていること。
58                         Debug.Assert( ( 0f < this.物理画面サイズpx.Width ) && ( 0f < this.物理画面サイズpx.Height ) );
59                         Debug.Assert( IntPtr.Zero != this.ウィンドウハンドル );
60
61                         #region " デバイス、スワップチェーンを作成する。"
62                         //----------------
63                         // スワップチェーン desc
64                         var swapChainDesc = new SharpDX.DXGI.SwapChainDescription() {
65                                 BufferCount = 3,
66                                 ModeDescription = new SharpDX.DXGI.ModeDescription(
67                                         (int) this.物理画面サイズpx.Width,
68                                         (int) this.物理画面サイズpx.Height,
69                                         new SharpDX.DXGI.Rational( 60, 1 ),
70                                         SharpDX.DXGI.Format.B8G8R8A8_UNorm
71                                 ),
72                                 IsWindowed = true,
73                                 OutputHandle = ウィンドウハンドル,
74                                 SampleDescription = new SharpDX.DXGI.SampleDescription( 1, 0 ),
75                                 SwapEffect = SharpDX.DXGI.SwapEffect.Discard,
76                                 Usage = SharpDX.DXGI.Usage.RenderTargetOutput,
77                         };
78                         // 機能レベル
79                         var featureLevels = new SharpDX.Direct3D.FeatureLevel[] {
80                                 SharpDX.Direct3D.FeatureLevel.Level_11_0,
81                                 SharpDX.Direct3D.FeatureLevel.Level_10_1,
82                                 SharpDX.Direct3D.FeatureLevel.Level_10_0,
83                         };
84                         // デバイスとスワップチェーンを作成する。
85                         SharpDX.Direct3D11.Device.CreateWithSwapChain(
86                                 SharpDX.Direct3D.DriverType.Hardware,
87                                 SharpDX.Direct3D11.DeviceCreationFlags.None,
88                                 featureLevels,
89                                 swapChainDesc,
90                                 out this.bs_D3DDevice,
91                                 out this.bs_SwapChain );
92
93                         Trace.WriteLine( "D3Dデバイスとスワップチェーンを生成しました。" );
94                         Trace.WriteLine( $"機能レベル: {this.bs_D3DDevice.FeatureLevel.ToString()}" );
95                         //----------------
96                         #endregion
97                         #region " すべての Windows イベントを無視する。具体的には PrintScreen と Alt+Enter 。"
98                         //----------------
99                         using( var factory = this.bs_SwapChain.GetParent<SharpDX.DXGI.Factory>() )
100                         {
101                                 factory.MakeWindowAssociation( ウィンドウハンドル, SharpDX.DXGI.WindowAssociationFlags.IgnoreAll );
102                         }
103                         //----------------
104                         #endregion
105                         #region " 深度ステンシルステート "
106                         //----------------
107                         var DepthSencil = new SharpDX.Direct3D11.DepthStencilStateDescription() {
108                                 IsDepthEnabled = true,  // 深度テストあり
109                                 DepthWriteMask = SharpDX.Direct3D11.DepthWriteMask.All,     // 書き込む
110                                 DepthComparison = SharpDX.Direct3D11.Comparison.Less,   // 手前の物体を描画
111                                 IsStencilEnabled = false,   // ステンシルテストなし。
112                                 StencilReadMask = 0,    // ステンシル読み込みマスク。
113                                 StencilWriteMask = 0,   // ステンシル書き込みマスク。
114
115                                 // 面が表を向いている場合のステンシル・テストの設定
116                                 FrontFace = new SharpDX.Direct3D11.DepthStencilOperationDescription() {
117                                         FailOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
118                                         DepthFailOperation = SharpDX.Direct3D11.StencilOperation.Keep,  // 維持
119                                         PassOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
120                                         Comparison = SharpDX.Direct3D11.Comparison.Never,   // 常に失敗
121                                 },
122
123                                 // 面が裏を向いている場合のステンシル・テストの設定
124                                 BackFace = new SharpDX.Direct3D11.DepthStencilOperationDescription() {
125                                         FailOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
126                                         DepthFailOperation = SharpDX.Direct3D11.StencilOperation.Keep,  // 維持
127                                         PassOperation = SharpDX.Direct3D11.StencilOperation.Keep,   // 維持
128                                         Comparison = SharpDX.Direct3D11.Comparison.Always,  // 常に成功
129                                 },
130                         };
131                         this.bs_DepthStencilState = new SharpDX.Direct3D11.DepthStencilState( this.bs_D3DDevice, DepthSencil );
132                         //----------------
133                         #endregion
134
135                         this.サイズに依存するリソースを作成する();
136                 }
137                 public void すべてのリソースを解放する()
138                 {
139                         // デバイスステートをクリアする。
140                         this.bs_D3DDevice?.ImmediateContext?.ClearState();
141
142                         // スワップチェインをウインドウモードにする。
143                         this.bs_SwapChain?.SetFullscreenState( fullscreen: false, targetRef: null );
144
145                         this.サイズに依存するリソースを解放する();
146
147                         // 取得したインターフェイスの開放
148                         this.bs_DepthStencilState?.Dispose();
149                         this.bs_SwapChain?.Dispose();
150                         this.bs_D3DDevice?.Dispose();
151                 }
152                 public void サイズに依存するリソースを作成する()
153                 {
154                         #region " スワップチェーンのサイズを変更する。"
155                         //----------------
156                         Debug.Assert( null != this.SwapChain ); // スワップチェーンは、デバイスとともに、すでに生成される。
157                         this.SwapChain.ResizeBuffers(
158                                 bufferCount: 2,
159                                 width: (int) this.物理画面サイズpx.Width,
160                                 height: (int) this.物理画面サイズpx.Height,
161                                 newFormat: SharpDX.DXGI.Format.R8G8B8A8_UNorm,
162                                 swapChainFlags: SharpDX.DXGI.SwapChainFlags.AllowModeSwitch );
163                         //----------------
164                         #endregion
165
166                         // 新しいサイズになったバックバッファを取得して、リソースを作成する。
167                         using( var backBuffer = SharpDX.Direct3D11.Texture2D.FromSwapChain<SharpDX.Direct3D11.Texture2D>( this.bs_SwapChain, 0 ) )
168                         {
169                                 #region " RenderTargetView の作成 "
170                                 //----------------
171                                 this.bs_RenderTargetView = new SharpDX.Direct3D11.RenderTargetView( this.bs_D3DDevice, backBuffer );
172                                 //----------------
173                                 #endregion
174                                 #region " 深度ステンシルテクスチャの作成 "
175                                 //----------------
176                                 var descDepth = backBuffer.Description;
177                                 //descDepth.Width = backBuffer.Description.Width;       → backBuffer に同じ
178                                 //descDepth.Height = backBuffer.Description.Height;     → 同上
179                                 descDepth.MipLevels = 1;    // ミップマップレベル数
180                                 descDepth.ArraySize = 1;    // 配列サイズ
181                                 descDepth.Format = SharpDX.DXGI.Format.D32_Float;   // フォーマット(深度のみ)
182                                 descDepth.Usage = SharpDX.Direct3D11.ResourceUsage.Default; // デフォルト使用法
183                                 descDepth.BindFlags = SharpDX.Direct3D11.BindFlags.DepthStencil;    // 深度ステンシル
184                                 descDepth.CpuAccessFlags = SharpDX.Direct3D11.CpuAccessFlags.None;  // CPUからはアクセスしない
185                                 descDepth.OptionFlags = SharpDX.Direct3D11.ResourceOptionFlags.None;    // その他の設定なし
186
187                                 this.bs_DepthStencil = new SharpDX.Direct3D11.Texture2D( this.bs_D3DDevice, descDepth );
188                                 //----------------
189                                 #endregion
190                                 #region " 深度ステンシルビューの作成 "
191                                 //----------------
192                                 var descDSV = new SharpDX.Direct3D11.DepthStencilViewDescription() {
193                                         Format = descDepth.Format,
194                                         Dimension = SharpDX.Direct3D11.DepthStencilViewDimension.Texture2D,
195                                         Flags = SharpDX.Direct3D11.DepthStencilViewFlags.None,
196                                 };
197                                 descDSV.Texture2D.MipSlice = 0;
198                                 this.bs_DepthStencilView = new SharpDX.Direct3D11.DepthStencilView(
199                                         this.bs_D3DDevice,
200                                         this.bs_DepthStencil,
201                                         descDSV );
202                                 //----------------
203                                 #endregion
204                                 #region " ビューポートの設定 "
205                                 //----------------
206                                 this.bs_ViewPort[ 0 ] = new SharpDX.Mathematics.Interop.RawViewportF() {
207                                         X = 0.0f,
208                                         Y = 0.0f,
209                                         Width = (float) backBuffer.Description.Width,
210                                         Height = (float) backBuffer.Description.Height,
211                                         MinDepth = 0.0f,
212                                         MaxDepth = 1.0f,
213                                 };
214                                 //----------------
215                                 #endregion
216                                 #region " テクスチャの共有リソースの作成 "
217                                 //----------------
218                                 FDK.メディア.テクスチャ.共有リソースを作成する( this );
219                                 //----------------
220                                 #endregion
221                         }
222                 }
223                 public void サイズに依存するリソースを解放する()
224                 {
225                         // 描画ターゲットを解除する。
226                         this.D3DDevice.ImmediateContext.OutputMerger.ResetTargets();
227
228                         FDK.メディア.テクスチャ.共有リソースを解放する();
229                         this.bs_DepthStencilView?.Dispose();
230                         this.bs_DepthStencil?.Dispose();
231                         this.bs_RenderTargetView?.Dispose();
232                         //this.bs_SwapChain?.Dispose(); → スワップチェーンは解放しない(生成・解放はデバイスとセット)。
233
234                         // (0,0)は、サイズ依存リソース無効の印。
235                         this.物理画面サイズpx = new SharpDX.Size2F( 0, 0 );
236                 }
237                 public void D3Dデバイスが消失していれば再構築する( out bool 異常状態なのでアプリを終了せよ )
238                 {
239                         異常状態なのでアプリを終了せよ = false;
240
241                         var 削除理由 = this.bs_D3DDevice.DeviceRemovedReason;
242                         if( 削除理由.Success )
243                                 return;
244
245                         var エラー詳細 = new[] {
246                                         new { Code = SharpDX.DXGI.ResultCode.DeviceHung.Code, Info = SharpDX.DXGI.ResultCode.DeviceHung.ApiCode, Rebuild = true },
247                                         new { Code = SharpDX.DXGI.ResultCode.DeviceReset.Code, Info = SharpDX.DXGI.ResultCode.DeviceReset.ApiCode, Rebuild = true },
248                                         new { Code = SharpDX.DXGI.ResultCode.DeviceRemoved.Code, Info = SharpDX.DXGI.ResultCode.DeviceRemoved.ApiCode, Rebuild = false },
249                                         new { Code = SharpDX.DXGI.ResultCode.DriverInternalError.Code, Info = SharpDX.DXGI.ResultCode.DriverInternalError.ApiCode, Rebuild = false },
250                                         new { Code = SharpDX.DXGI.ResultCode.InvalidCall.Code, Info = SharpDX.DXGI.ResultCode.InvalidCall.ApiCode, Rebuild = false },
251                                 }.First( ( エラー ) => エラー.Code == 削除理由.Code );  // 見つからないなら System.InvalidOperationException 。
252
253                         Trace.WriteLine( $"D3Dデバイスが消失しました: {エラー詳細.Info}" );
254
255                         if( エラー詳細.Rebuild )
256                         {
257                                 this.すべてのリソースを解放する();
258                                 this.すべてのリソースを作成する();
259                         }
260                         else
261                         {
262                                 異常状態なのでアプリを終了せよ = true;
263                         }
264                 }
265
266                 private float dz( float 高さdpx, float 視野角deg )
267                 {
268                         return (float) ( 高さdpx / ( 4.0 * Math.Tan( SharpDX.MathUtil.DegreesToRadians( 視野角deg / 2.0f ) ) ) );
269                 }
270
271                 #region " バックストア。"
272                 //----------------
273                 private SharpDX.Direct3D11.Device bs_D3DDevice = null;
274                 private SharpDX.DXGI.SwapChain bs_SwapChain = null;
275                 private SharpDX.Mathematics.Interop.RawViewportF[] bs_ViewPort = new SharpDX.Mathematics.Interop.RawViewportF[ 1 ];
276                 private SharpDX.Direct3D11.DepthStencilState bs_DepthStencilState = null;
277                 private SharpDX.Direct3D11.RenderTargetView bs_RenderTargetView = null;
278                 private SharpDX.Direct3D11.Texture2D bs_DepthStencil = null;
279                 private SharpDX.Direct3D11.DepthStencilView bs_DepthStencilView = null;
280                 //----------------
281                 #endregion
282         }
283 }