したらばTOP ■掲示板に戻る■ 全部 1-100 最新50 | |
レス数が1スレッドの最大レス数(1000件)を超えています。残念ながら投稿することができません。

技術情報交換スレ

1管理人★:2004/06/16(水) 20:44
RTXのみならずROや支援ツール全般に関する技術的な情報を交換するスレです。
コーディングに詰まった作者が他力本願的に知恵を増やす目的で設立されましたが、
それだけでなく広く情報交換に使っていただけることを願っています。

管理人の手持ちの情報は少ないですが、RTX/RoTimerの内部動作に関する
御質問などでしたら、できるだけお答えしたいと思います。

規約云々や解析手法の是非などは別スレ/別BBSへ誘導のこと。
水面下に落ちるまではsage縛りで。

2Mystle </b><font color=#FF0000>(M.B.S.4s)</font><b>:2004/06/16(水) 21:51
とりあえず >>1 からネタ振り

21f→21g/h で発生した「特定の環境でタイマーがガクブル問題」ですが、とりあえず
原因となる箇所は判明しました。
DX乗っ取りで実際に書き込みを行うタイミングを変更したのが原因だったようです。

○21f
 2D書き込み:
  窓モードでは DirectDrawSurface->Blt() 、フルスクでは Flip() のタイミングで
  GetDC() してGDIでプライマリサーフェスに直接描画、あるいは自前サーフェスからBlt()
 3D書き込み:
  Direct3DDevice->EndScene() のタイミングで DrawPrimitive() などを投下
  
○21g/h
 3D書き込み:
  EndScene() で (21fと同じ)
 2D書き込み:
  EndScene() で 3D書き込みを行った後に保存しておいたプライマリサーフェスの
  ポインタを使って GetDC() して以下略

というわけで 2D書き込みのタイミングを3Dのそれと一本化したのがまずかったようで。
これがどうしてまずいのかは不明です。

3人柱さん:2004/06/16(水) 23:05
>>2
 
> ○21g/h
> 2D書き込み:
>  EndScene() で 3D書き込みを行った後に保存しておいたプライマリサーフェスの
>  ポインタを使って GetDC() して以下略

EndSceneが非同期で動いてると、その後GDI処理するためにレンダリング終了
まで待つ必要があってRO本体の足を引っ張ってるってことはないでしょうか?

EndSceneでプライマリサーフェイスに書き込んでもFlipかBltでなかったことにな
りませんっけ?バックバッファーに書き込んでるのでしたら、サーフェイスが
VRAM上にあった場合には、GetDCやGDIでほげほげするときにシステムメモリと
VRAM間で転送しまくってて遅い可能性も。

DirectX5〜7ぐらいの期間しかDirectXさわってなかったので、記憶違いだっ
たらすみません。それに、プロファイルとったわけでもないので全部予想に
過ぎません。

4Mystle </b><font color=#FF0000>(M.B.S.4s)</font><b>:2004/06/16(水) 23:55
>>3
21g/h ではこんなふうに書いてたわけですが

// フックした Direct3DDevice->EndScene() 関数
HRESULT WINAPI Nisemono_EndScene(LPDIRECT3DDEVICE7 *lpD3DDevice)
{
  HRESULT hRes1, hRes2;
  hDC hDC;
  
  /*
  // 色々と3Dなお絵かき
  lpD3DDevice->SetRenderState();
  lpD3DDevice->SetTexture();
  lpD3DDevice->DrawPrimitive();
  */
  
  // 本物を呼び出し (ここで3D命令がグラボに飛ぶの?)
  hRes1 = Honmono_EndScene(lpD3DDevice);
  
  // プライマリサーフェス (LPDIRECTDRAWSURFACE7 lpPrimarySurface) は
  // 別箇所 (CreateSurface()のフック関数) で取得・保持しています
  if (lpPrimarySurface)
  {
    hRes2 = lpPrimarySurface->lpVtbl->GetDC(lpPrimarySurface, &hDC);
    
    if (hRes2 == S_OK)
    {
      /*
      // 色々と2Dなお絵かき
      TextOut();
      Ellipse();
      */
      
      lpPrimarySurface->lpVtbl->ReleaseDC(lpPrimarySurface, hDC);
    }
  }
  return hRes1;
}

*lpD3DDevice自体はプライマリサーフェイスから生成されてますから、Honmono_Endscene() を
呼ぶ前に2D描画を試みてもGetDC()自体が成功しません。でこんな順序に。
でもこれだとガクブルするということで

21fでは if (lpPrimarySurface) { ... } のブロックがそっくり 偽Blt() の中にありまして、
Nisemono_EndScene() はRTXの3D描画を終えた後すみやかに
  return Honmono_EndScene(lpD3DDevice);
してますた。これだとガクブルしない、と

5人柱さん:2004/06/17(木) 00:50
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/jpdx8_c/hh/directx8_c/_dx_d3dcaps8_graphics.asp
を見ると

一般的には、BeginScene と EndScene のペアの外側で 2D 処理を実行する
ことを推奨する。2D 処理がBeginScene と EndScene のペアの間で実行される
場合は、D3DCAPS2_NO2DDURING3DSCENE 能力をチェックする必要がある。この
能力が設定されている場合、アプリケーションでは、BeginScene と EndScene
の間にある 2D 処理は破棄されると考えなければならない。

とあるので、GetDCが成功しないのはそういうことなんじゃないのでしょうか?


ところで、ゲームの一般的な処理って

入力読んだりネットワーク通信したりいろいろ情報更新
BeginScene
DrawXXXなんかで描画
EndScene←ここでバックバッファーに画面が作られる
Flip/Blt←ここでバックバッファーからプライマリサーフェイスに転送
適当にSleep

の繰り返しですよね。だとするとEndSceneの直後にプライマリサーフェイスに
いろいろお絵かきしても無駄じゃありませんか?

##なんか私がどっか勘違いしてる気がしてきた。

6人柱さん:2004/06/17(木) 02:12
当方、コンシューマー機畑の人間、オマケにヒッキーなので
DirectX(というよりGefのドライバ)がどうなっているのかは知らないのですが、
調べてみた限りでは、>>3の説が濃厚な気がします。

つまり、EndScene直後ではまれなタイミングでしかGetDCに成功せず、
ほとんどのRTXの2D描画が廃棄されガクブル。
しかし、Blt重あてをしていて、Flip/Bltまでドライバに時間が与えられていれば
GetDCに成功し、概ね描画可能になっている、のだと思います。

問題の発生しない環境だと、VGAにぶちこむディスプレイリストの再構築の間、
プライマリは好きにしてもいいよ、な実装になっていて、直後でもS_OKがもらえるんじゃないでしょうか。

72&5:2004/06/17(木) 03:26
>>6
私の言いたかったのは、GetDCが成功したり失敗したりってそういうことでは
ないです。単純に呼び出しが失敗しているのなら作者さん気がつくでしょうし。

IDirect3DDevice9::EndSceneのドキュメントに

When this method succeeds, the scene has been queued up for rendering
by the driver. This is not a synchronous method, so the scene is not
guaranteed to have completed rendering when this method returns.

って記述がありました。(手元にはDXSDK9しかなく、DirectX 7のドキュメント
はだいぶ前に処分したので実際どうなのかはわからないです。)

また、GetDCするときに内部的にはサーフェイスをLockしているようです。
しかし、Lock後に整合性を保つにはLockの前にレンダリング済ませる必要が
あるはずです。

それらのことから、もしROがEndSceneがすぐ戻ってくることを前提に書かれて
いてEndScene→Flipの間に非同期に何かやろうとしてることがあったとすれば
それを同期的にしか処理できないことでフレームレートが落ちる可能性がある
んじゃなかろうかっていう推測です。

とりあえず、もう寝ます。

87:2004/06/17(木) 03:27
2だと管理人さんじゃん。3と5と7でした。

96:2004/06/17(木) 03:59
GetDCの動作を理解していませんでした。
EndSceneについては自分で調べた通りで、だから6のような妄想をしてしまったわけですが、
なるほどROクライアント本体で何か、という推測は成り立ちますね。

ガクブルの実際の動作がどうなっているのか気になります。

1.ROクラは普通に動作/RTXの3D描画も普通に動作/RTXの2D描画のみがガクブル
2.ROクラは普通に動作/RTXの3D/2D描画ともにガクブル
3.ROクラからRTXから全部ガクブル

外野から想像できるのはこんなところでしょうか。

10人柱さん:2004/06/17(木) 15:44
うちも21gでガクブル(((;゚Д゚))) してましたけど、文字列(2D表示)がちらついてない
ので、GetDC() 自体は成功してるんじゃないかなと思います。

おそらく EndScene() から返ってからその3D描画が実現するまでのレイテンシが、
直後に 2D描画を突っ込むことでロスされる、というのが真実かと。

(2D描画をBlt()部に分離した試作版いただきましたが、正常動作しました)

関係ありませんがここってパケの話とかはOKですか?
ウンバラで最初取引チャイム出なかったのはやっぱ新パケなのかなと

11Mystle </b><font color=#FF0000>(M.B.S.4s)</font><b>:2004/06/17(木) 16:12
>>10
それでビンゴのようです。
とりあえず再びBlt()/Flip()のところに文字列描画を引き離すことで事なきを得ましたが、
最終的には面倒くさがらず2D描画もDIB→動的Texture変更など使ってGDI撲滅の方向へ
いかなければなりませんでしょうか……

今は毎フレームプライマリサーフェイスにTextOut()する、という信じられないようなことをしている
のですが、タイマーって少なくとも1秒ごとに文字列が変わるわけで、画面上に20本のタイマーが
出ていたら、文字列不変をスキップしても、1秒ごとに20個のテクスチャをロックする必要があるわけ
ですよね。今は毎フレームサーフェイスロック1回のみなわけで。
やっぱこれでも3Dに統合した方がパフォーマンス出るのかなぁ


>パケの話
全く問題ありません。
とりあえず、ウンバラの取引要請でしたっけ?

// 取引要請(受)
R 00E5 → R 01F4 <trader's name>.24B <trade id?>.L <LV>.w

// 取引要請(攻)
R 00E7 → R 01F5 <success>.B <trade id?>.L <LV>.w

以降のシークエンスはいままでと同じです。

<trade id>.L は取引中保持され続ける固有値ですが、同じ相手と
再び取引しても同じ値だったり。生成方法は不明。




掲示板管理者へ連絡 無料レンタル掲示板