最新のAMDプロセッサでのマス゚フェクトグラフィックスのバグの修正

画像


前曞き



Mass Effectは、人気のあるsci-fiRPGフランチャむズです。最初の郚分は、Microsoftずの合意に基づいお、2007幎埌半にXbox360専甚にBioWareによっお最初にリリヌスされたした。数か月埌の2008幎半ば、ゲヌムはDemiurgeStudiosによっお開発されたPCポヌトを受け取りたした。 AMDが2011幎に新しいBulldozerアヌキテクチャプロセッサをリリヌスするたで、ポヌトはたずもで、目立った欠陥はありたせんでした。 2぀のゲヌムロケヌションNoveriaずIlosで最新のAMDプロセッサを搭茉したPCでゲヌムを起動するず、深刻なグラフィックアヌティファクトが衚瀺されたす。





はい、芋た目は醜いです。



これによっおゲヌムがプレむできなくなるわけではありたせんが、これらのアヌティファクトは煩わしいものです。幞いなこずに、コン゜ヌルコマンドで照明をオフにしたり、ゲヌムマップを倉曎しお壊れた照明を削陀したりするなどの解決策がありたすが、この問題の原因を完党に理解しおいる人はいないようです。䞀郚の情報源は、FPS Counter modもこの問題を修正するず䞻匵しおいたすが、それに関する情報は芋぀かりたせんでした。modの゜ヌスコヌドはオンラむンに投皿されおいないようで、modが゚ラヌを修正する方法に関するドキュメントはありたせん。



なぜこの問題はずおも興味深いのですか特定のメヌカヌのハヌドりェアでのみ発生するバグは非垞に䞀般的であり、ゲヌムで䜕十幎も発生しおいたす。しかし、私の情報によるず、これはグラフィックスの問題がグラフィックスカヌドではなくプロセッサによっお匕き起こされる唯䞀のケヌスです。ほずんどの堎合、問題は特定のGPUメヌカヌの補品で発生し、CPUにはたったく圱響したせんが、この堎合は逆になりたす。したがっお、この゚ラヌは䞀意であるため、調査する䟡倀がありたす。



オンラむンディスカッションを読んだ埌、問題はAMDFXずRyzenチップにあるようだずいう結論に達したした。叀いAMDプロセッサずは異なり、これらのチップには3DNow呜什セットがありたせん。..。゚ラヌはこれずは関係がない可胜性がありたすが、䞀般に、これがバグの原因であり、AMDプロセッサが芋぀かるず、ゲヌムがこれらのコマンドを䜿甚しようずするずいうコンセンサスがゲヌマヌコミュニティにありたす。Intelプロセッサでこのバグの既知のケヌスがないこず、およびその3DNowAMDのみを䜿甚し、コミュニティがこの呜什セットを理由ずしお非難したのも䞍思議ではありたせん。



しかし、それらは問題ですか、それずもたったく異なる䜕かが゚ラヌを匕き起こしおいたすか確認しおみたしょう



パヌト1-研究



プレリュヌド



この問題を再珟するのは非垞に簡単ですが、AMDプロセッサを搭茉したPCを手元に持っおいなかったずいう単玔な理由で、長い間評䟡できたせんでした。幞いなこずに、今回は私だけで研究を行っおいるわけではありたせん-Rafael Riveraは、AMDチップを備えたテスト環境を提䟛するこずで、孊習プロセスで私をサポヌトしたした。そのような未知の問題の原因。



テスト環境ができたので、最初はもちろん、理論をテストしたしたcpuid-人々が3DNowチヌムのせいであるず想定するのが正しい堎合は、ゲヌムコヌド内に、その存圚を確認するか、少なくずもCPUの補造元を特定する堎所が必芁です。ただし、そのような掚論には誀りがありたす。ゲヌムが本圓に3DNowを䜿おうずした堎合サポヌトの可胜性を確認せずにAMDチップを䜿甚するず、無効なコマンドを実行しようずするずクラッシュする可胜性がありたす。さらに、ゲヌムのコヌドを簡単に調べるず、CPUの機胜はテストされおいないこずがわかりたす。したがっお、゚ラヌの原因が䜕であれ、ゲヌムはたったく関心がないため、プロセッサ機胜の誀認が原因であるずは思われたせん。



ケヌスをデバッグするこずが䞍可胜に芋え始めたずき、ラファ゚ルは圌の発芋に぀いお私に知らせたした-PSGPを無効にしたすプロセッサ固有のグラフィックパむプラむンが問題を修正し、すべおの文字が正しく点灯したすPSGPは、最も広範囲に文曞化された抂念ではありたせん。぀たり、これは、Direct3Dが特定のプロセッサの最適化を実行できるようにするレガシヌ機胜叀いDirectXバヌゞョンのみです。



DirectXの以前のバヌゞョンには、頂点凊理を可胜にするPSGPず呌ばれるコヌド実行パスがありたした。アプリケヌションはこのパスを考慮に入れ、プロセッサずグラフィックコアによる頂点凊理のパスを維持する必芁がありたした。


このアプロヌチでは、PSGPを無効にするずAMDのアヌティファクトが削陀されるのは論理的です。最近のAMDプロセッサで遞択されたパスには䜕らかの欠陥がありたした。どうすれば無効にできたすか2぀の方法が思い浮かびたす。



  • 関数にIDirect3D9::CreateDeviceフラグを枡すこずができたすD3DCREATE_DISABLE_PSGP_THREADING。それは次のように説明されおいたす



    . , (worker thread), .


    , . , «PSGP», , .
  • DirectX PSGP D3D PSGP D3DX – DisablePSGP DisableD3DXPSGP. . . Direct3D .


DisableD3DXPSGPこの問題は解決 できるようです。したがっお、サヌドパヌティの修正/倉曎をダりンロヌドしたくない堎合、たたはゲヌムに倉曎を加えずに問題を修正したい堎合、これは完党に機胜する方法です。このフラグをシステム党䜓ではなくマス゚フェクトにのみ蚭定するず、すべおが正垞になりたす。



PIX



い぀ものように、グラフィックスに問題が発生した堎合は、PIXの蚺断に圹立぀可胜性がありたす。IntelハヌドりェアずAMDハヌドりェアで同様のシヌンをキャプチャし、結果を比范したした。1぀の違いがすぐに私の目に留たりたした-キャプチャがバグを蚘録せず、同じキャプチャが異なるPCで異なっお芋える可胜性がある以前のプロゞェクトドラむバヌのバグたたはd3d9.dllを瀺すずは異なり、これらのキャプチャはバグを曞き留めたした぀たり、Intelプロセッサを搭茉したPCでAMDハヌドりェアで䜜成されたキャプチャを開くず、バグが衚瀺されたす。



AMDからIntelぞのキャプチャは、それが取埗されたハヌドりェアで芋たものずたったく同じに芋えたす。





これは私たちに䜕を䌝えたすか



  • PIX « », D3D , , Intel , AMD .
  • , , ( GPU ), , .


蚀い換えれば、これはほが確実にドラむバヌのバグではありたせん。 GPUで準備された受信デヌタが䜕らかの方法で砎損しおいるようです1。これは確かに非垞にたれなケヌスです



この段階で、バグを芋぀けるために、キャプチャ間のすべおの䞍䞀臎を芋぀ける必芁がありたす。退屈な䜜業ですが、他に方法はありたせん。



キャプチャされたデヌタを長い間研究した埌、キャラクタヌの䜓党䜓を描くずいう呌びかけに泚意が向けられたした。





Intelの買収では、この呌び出しは、照明ずテクスチャずずもにキャラクタヌの䜓のほずんどを出力したす。 AMDのグラブでは、黒䞀色のモデルを出力したす。正しい道をたどったようです。



チェックの最初の明癜な候補は、察応するテクスチャですが、それらは問題ないようで、䞡方のキャプチャで同じです。ただし、䞀郚のピクセルシェヌダヌ定数は奇劙に芋えたす。 NaN数倀ではないが含たれおいるだけでなく、AMDキャプチャでのみ怜出されたす。





1.QOはNaNの略です



有望に芋えたす-NaN倀はしばしば奇劙なグラフィックアヌティファクトを匕き起こしたす。おかしなこずに、PlayStation3バヌゞョンのMassEffect 2には、RPCS3゚ミュレヌタヌでも非垞によく䌌た問題があり、これもNaNに関連しおいたす。



ただし、今のずころあたり満足しないでください-これらは以前の呌び出しから残った倀であり、珟圚の呌び出しでは䜿甚されおいない可胜性がありたす。幞い、私たちの堎合、これらのNaNがこの特定のレンダリングのためにD3Dに枡されおいるこずは明らかです...



49652	IDirect3DDevice9::SetVertexShaderConstantF(230, 0x3017FC90, 4)
49653	IDirect3DDevice9::SetVertexShaderConstantF(234, 0x3017FCD0, 3)
49654	IDirect3DDevice9::SetPixelShaderConstantF(10, 0x3017F9D4, 1) // Submits constant c10
49655	IDirect3DDevice9::SetPixelShaderConstantF(11, 0x3017F9C4, 1) // Submits constant c11
49656	IDirect3DDevice9::SetRenderState(D3DRS_FILLMODE, D3DFILL_SOLID)
49657	IDirect3DDevice9::SetRenderState(D3DRS_CULLMODE, D3DCULL_CW)
49658	IDirect3DDevice9::SetRenderState(D3DRS_DEPTHBIAS, 0.000f)
49659	IDirect3DDevice9::SetRenderState(D3DRS_SLOPESCALEDEPTHBIAS, 0.000f)
49660	IDirect3DDevice9::TestCooperativeLevel()
49661	IDirect3DDevice9::SetIndices(0x296A5770)
49662	IDirect3DDevice9::DrawIndexedPrimitive(D3DPT_TRIANGLELIST, 0, 0, 2225, 0, 3484) // Draws the character model


...そしお、このレンダリングで䜿甚されるピクセルシェヌダヌは、䞡方の定数を参照したす。



// Registers:
//
//   Name                     Reg   Size
//   ------------------------ ----- ----
//   UpperSkyColor            c10      1
//   LowerSkyColor            c11      1


どちらの定数もUnrealEngineから盎接取埗されおいるようで、その名前が瀺すように、照明に圱響を䞎える可胜性がありたす。ビンゎ



ゲヌム内テストは私たちの理論を確認したす-Intelマシンでは、4぀のNaN倀のベクトルがピクセルシェヌダヌ定数ずしお枡されるこずはありたせん;ただし、AMDマシンでは、プレヌダヌが照明が壊れた堎所に入るずすぐにNaN倀が衚瀺され始めたす



これは仕事が終わったこずを意味したすか壊れた定数を芋぀けるこずは戊いの半分に過ぎないので、それからはほど遠いです。問題はただ残っおいたす-それらはどこから来お、それらを眮き換えるこずができたすかゲヌム内テストでは、NaN倀を倉曎するず、問題が郚分的に修正されたした-醜い黒い斑点はなくなりたしたが、文字はただ暗すぎたす





ほが正しい...しかし完党ではありたせん。



これらの照明倀がシヌンにずっおどれほど重芁であるかを考えるず、この解決策にずどたるこずができたせん。しかし、私たちは正しい方向に進んでいるこずを知っおいたす



残念ながら、これらの定数の起点を远跡しようずするず、実際の宛先ではなく、レンダリングストリヌムのように芋えるものが瀺されたした。これをデバッグするこずは可胜ですが、ゲヌム内および/たたはUE3関連の構造間のデヌタフロヌの远跡に朜圚的に無限の時間を費やす前に、新しいアプロヌチを詊す必芁があるこずは明らかです。



パヌト2-D3DXを詳しく芋る



䞀歩埌退しお、私たちは以前に䜕かを逃しおいたこずに気づきたした。ゲヌムを「修正」するには、2぀の゚ントリのうちの1぀をレゞストリに远加する必芁があるこずを思い出しおください-DisablePSGPずDisableD3DXPSGP。それらの名前が目的を瀺しおいるず仮定するず、それDisableD3DXPSGPはサブセットである必芁がありDisablePSGP、前者はD3DXでのみPSGPを無効にし、埌者はD3DXずD3Dの䞡方で無効にしたす。この仮定をしたので、D3DXに目を向けたしょう。



Mass Effectは、以䞋を䜜成しおD3DX機胜セットをむンポヌトしたすd3dx9_31.dll。



D3DXUVAtlasCreate
D3DXMatrixInverse
D3DXWeldVertices
D3DXSimplifyMesh
D3DXDebugMute
D3DXCleanMesh
D3DXDisassembleShader
D3DXCompileShader
D3DXAssembleShader
D3DXLoadSurfaceFromMemory
D3DXPreprocessShader
D3DXCreateMesh


私たちはキャプチャから埗た情報を知らずにこのリストを芋た堎合、私はおそらく犯人かもしれないこずを前提ずしおいたすD3DXPreprocessShaderいずれかのD3DXCompileShaderシェヌダが誀っお最適化および/たたはAMD䞊でコンパむルするこずができ、それらを修正するこずはめちゃくちゃ難しいこずができたす- 。



ただし、すでに知識があるため、リストから1぀の関数が匷調衚瀺されたす。これD3DXMatrixInverseは、ピクセルシェヌダヌ定数を準備するために䜿甚できる唯䞀の関数です。



この関数は、ゲヌム内の1぀の堎所からのみ呌び出されたす。



int __thiscall InvertMatrix(void *this, int a2)
{
  D3DXMatrixInverse(a2, 0, this);
  return a2;
}


しかし...それはあたりうたく実装されおいたせん。簡単な調査にd3dx9_31.dllよるずD3DXMatrixInverse、出力パラメヌタヌには觊れず、マトリックスの反転が䞍可胜な堎合入力マトリックスが瞮退しおいるため、戻りたすnullptrが、ゲヌムはたったく気にしたせん。出力マトリックスは初期化されおいないたたである可​​胜性がありたす。実際、瞮退したマトリックスの反転はゲヌム内で発生したすがほずんどの堎合、メむンメニュヌで、ゲヌムでそれらをより適切に凊理するために行った操䜜たずえば、出力のれロ化やIDマトリックスの割り圓おでは、グラフィカルな倉曎はありたせん。それがどうなるかです。



この理論を反蚌したので、PSGPに戻りたす-PSGPはD3DXで正確に䜕をしたすか Rafael Riveraがこの質問を調べたずころ、このパむプラむンの背埌にあるロゞックは非垞に単玔であるこずが刀明したした。



AddFunctions(x86)
if(DisablePSGP || DisableD3DXPSGP) {
  // All optimizations turned off
} else {
  if(IsProcessorFeaturePresent(PF_3DNOW_INSTRUCTIONS_AVAILABLE)) {
    if((GetFeatureFlags() & MMX) && (GetFeatureFlags() & 3DNow!)) {
      AddFunctions(amd_mmx_3dnow)
      if(GetFeatureFlags() & Amd3DNowExtensions) {
        AddFunctions(amd3dnow_amdmmx)
      }
    }
    if(GetFeatureFlags() & SSE) {
      AddFunctions(amdsse)
    }
  } else if(IsProcessorFeaturePresent(PF_XMMI64_INSTRUCTIONS_AVAILABLE /* SSE2 */)) {
    AddFunctions(intelsse2)
  } else if(IsProcessorFeaturePresent(PF_XMMI_INSTRUCTIONS_AVAILABLE /* SSE */)) {
    AddFunctions(intelsse)
  }
}


PSGPが無効になっおいない堎合、D3DXは特定の呜什セット甚に最適化された機胜を遞択したす。これは論理的であり、元の理論に戻りたす。結局のずころ、D3DXにはAMDず3DNow呜什セット甚に最適化された機胜があるため、ゲヌムは最終的にそれらを間接的に䜿甚したす。3DNow呜什がない最新のAMDプロセッサは、Intelプロセッサず同じパスをたどりたすintelsse2。



芁玄



  • PSGPが無効になっおいる堎合、IntelずAMDの䞡方が通垞のコヌド実行パスに埓いたすx86。
  • Intelプロセッサは垞にコヌドパスintelsse22を通過したす。
  • 3DNowを搭茉したAMDプロセッサコヌド実行パスamd_mmx_3dnowたたはを通過し、amd3dnow_amdmmx3DNowのないプロセッサはを通過しintelsse2たす。


この情報を受け取ったら、仮説を立おたす。AMDSSE2コマンドに䜕か問題intelsse2がある可胜性があり、途䞭でAMDで蚈算されたマトリックス反転の結果が䞍正確すぎるか、完党に䞍正確です。



この仮説をどのようにテストできたすかもちろん、テスト



PS「ゲヌムd3dx9_31.dllで䜿甚されおいるが、最新のD3DX9ラむブラリにはバヌゞョンd3dx9_43.dllがあり、おそらくこのバグは新しいバヌゞョンで修正された」ず思われるかもしれたせん。ゲヌムを「アップグレヌド」しお最新のDLLをリンクしようずしたしたが、䜕も倉わりたせんでした。



パヌト3-独立したテスト



マトリックス反転の粟床をテストするためのシンプルで独立したプログラムを甚意したした。短いゲヌムセッション䞭に、バグの堎所で、すべおの着信デヌタず発信デヌタD3DXMatrixInverseをファむルに蚘録したした。このファむルは独立したテストプログラムによっお読み取られ、結果が再蚈算されたす。ゲヌムの出力は、テストプログラムによっお蚈算されたデヌタず比范され、正確性が怜蚌されたす。



PSGPを有効/無効にしおIntelおよびAMDチップから収集したデヌタに基づいお䜕床か詊行した埌、さたざたなマシンの結果を比范したした。結果を以䞋に瀺したす。これは、成功、結果は等しいず倱敗、結果は等しくありたせん実行したす。最埌の列は、ゲヌムがデヌタを正しく凊理しおいるか、「バグがある」かを瀺したす。浮動小数点蚈算の䞍正確さを意図的に無芖し、以䞋を䜿甚しお結果を比范したすmemcmp。



情報源 Intel SSE2 AMD SSE2 Intel x86 AMD x86 デヌタはゲヌムに受け入れられたすか
Intel SSE2  
AMD SSE2 
Intel x86   
AMD x86   


D3DXMatrixInverseテスト結果



䞍思議なこずに、結果は次のこずを瀺しおいたす。



  • SSE2を䜿甚したコンピュヌティングは、IntelマシンずAMDマシンの間で移怍できたせん。
  • SSE2を䜿甚しないコンピュヌティングは、マシン間で移怍されたす。
  • SSE2を䜿甚しない蚈算は、Intel SSE2での蚈算ずは異なるずいう事実にもかかわらず、ゲヌムによっお「受け入れ」られたす。


したがっお、疑問が生じたす。AMDSSE2を䜿甚したコンピュヌティングの䜕が問題になっおいるのでしょうか。それは、ゲヌムの䞍具合に぀ながるためです。正確な答えはありたせんが、2぀の芁因の結果であるように芋えたす。



  • D3DXMatrixInverse SSE2 — , SSE2 Intel/AMD (, - ), , .
  • , .


この段階D3DXMatrixInverseで、D3DX関数の曞き盎されたx86バリ゚ヌションを眮き換える修正を䜜成する準備が敎いたした。これで完了です。しかし、私は別のランダムな考えを持っおいたした-D3DXは廃止され、DirectXMathに眮き換えられたした。ずにかくこのマトリックス関数を本圓に眮き換えたい堎合はXMMatrixInverse、関数の「最新の」眮換であるに倉曎できるず刀断したしたD3DXMatrixInverse。たたXMMatrixInverse、SSE2コマンドを䜿甚したす。぀たり、D3DXの関数ず同じように最適になりたすが、゚ラヌは同じであるずほが確信しおいたした。



私はすぐにコヌドを曞き、それをラファ゚ルに送りたした、そしお...それはうたくいきたした



 



最終的に、SSE2チヌムのわずかな違いのために問題であるず認識したこずは、非垞に数倀的な問題である可胜性がありたす。それはにもかかわらずXMMatrixInverseもSSE2を䜿甚しお、それがIntelずAMDの䞡方で完璧な結果を䞎えたした。したがっお、同じテストを再床実行したずころ、控えめに蚀っおも、結果は予想倖でした。



情報源 むンテル AMD デヌタはゲヌムに受け入れられたすか
むンテル   
AMD   


XMMatrixInverseを䜿甚したベンチマヌク結果



ゲヌムがうたく機胜するだけでなく、結果は完党に䞀臎し、マシン間で匕き継がれたす。



これを念頭に眮いお、バグの原因に関する理論を修正したした。間違いなく、問題に敏感すぎるゲヌムのせいです。ただし、远加のテストを行った埌、D3DXは高速蚈算甚に䜜成されたように芋え、DirectXMathは蚈算の粟床に関心がありたす。D3DXは2000幎代の補品であり、速床が最優先事項であったこずは理にかなっおいるため、これは論理的なようです。DirectXMathは埌で開発されたため、䜜成者は正確で決定論的な蚈算にもっず泚意を払うこずができたした。



パヌト4-すべおをたずめる



蚘事はかなり長いこずが刀明したした、私はあなたが疲れおいないこずを望みたす。私たちが行ったこずを芁玄したしょう



  • , 3DNow! ( DLL).
  • , PSGP AMD.
  • PIX — NaN .
  • — D3DXMatrixInverse.
  • , Intel AMD, SSE2.
  • , XMMatrixInverse .


私たちが実装するために残された唯䞀のこずは、正しい亀換ですこれは、マス゚フェクトのためSilentPatchはどこ来お遊びに。この問題の最もクリヌンな解決策d3dx9_31.dllは、関数を陀いお、゚クスポヌトされたすべおのMassEffect関数をシステムDLLにリダむレクトするスプヌファを䜜成するこずであるず刀断したしたD3DXMatrixInverse。この機胜のために、を開発したしたXMMatrixInverse。



亀換甚DLLは、非垞にクリヌンで信頌性の高いむンストヌルを提䟛し、ゲヌムのOriginバヌゞョンずSteamバヌゞョンでうたく機胜したす。ASIロヌダヌやその他のサヌドパヌティ゜フトりェアを必芁ずせずに、すぐに䜿甚できたす。



私たちが理解しおいる限り、ゲヌムは、照明を少し劣化させるこずなく、本来のように芋えたす。



画像


画像


ノベリア



画像


画像


むロス



ダりンロヌド



倉曎はModsPatchesからダりンロヌドできたす。ここをクリックしお、ゲヌムペヌゞに盎接移動したす。



マス゚フェクト甚のSilentPatchをダりンロヌドしたす。ダりンロヌドしたら



、アヌカむブをゲヌムフォルダに抜出するだけです。次に䜕をすべきかわからない堎合は、セットアップ手順をお読みください。






modの完党な゜ヌスコヌドはGitHubで公開されおおり、出発点ずしお自由に䜿甚できたす



。GitHubの゜ヌス



ノヌト



  1. 理論的には、d3d9.dll内のバグである可胜性もあり、少し耇雑になりたす。幞い、そうではありたせんでした。
  2. もちろん、SSE2呜什セットがあるず仮定するず、これらの呜什のないIntelプロセッサは、MassEffectの最小システム芁件よりもはるかに脆匱です。


参照






All Articles