Open2

C-WebGL: DirectX11バックエンドの計画

okuokuokuoku

あまりにもIntelのVulkanが言うことを聞いてくれないので、ちょっとデバッグを諦めてDirectX11をターゲットすることに。。Vulkanに比べてDirectX11はかなりハイレベルなAPIなのでトラブルも少いんじゃないかと期待している。

更に、VulkanはOpenGL ES2に比べて制約が多いが、その制約の大半はDirectX由来なのでVulkanのために書いた Depth範囲変換 のようなシェーダパッチはそのまま流用できる。

DirectX12にはDXILという専用の中間言語が存在するものの、これはDirectX11では使用できないので、(MetalやWebGPUと同様、)一旦システムのシェーダコンパイラ D3DCompiler_47.dll が受け入れるHLSLに変換し、バイトコードにコンパイルしてから使うことになる。( D3DCompilerのバージョン自体は大量にあって 超ややこしい。特に、UWPをサポートしていないWindows7ではシステム標準では含まれないため手動でインストールするか再配布する必要がある。

資料あつめ

前書いた

https://zenn.dev/okuoku/scraps/e362f5867899b1

みたいな表を書きたい。DirectX11とか最後に触ったのが昔過ぎてまったく覚えてないんで。。

Vulkan Decoder Ring とか MSDNの移植チャプタ が参考になる。

DirectXは COM のAPIを伝統的に採用しているため、たとえばGLで言うところの glDrawElements はデバイスのメソッド ID3D11DeviceContext::DrawIndexed となる。

DirectX11 ドキュメンテーションの目次Vulkanと違って仕様書PDFが一本あったりしないので。。 よく探したらあった https://microsoft.github.io/DirectX-Specs/

okuokuokuoku

描画系コマンド

WebGL DirectX11
cwgl_drawArrays, cwgl_drawElements Draw, DrawIndexed
cwgl_clear ClearRenderTargetView, ClearDepthStencilView
cwgl_readPixels CopySubresourceRegion してから Map してコピー
cwgl_renderbufferStorage , cwgl_checkFramebufferStatus ID3D11RenderTargetViewID3D11DepthStencilView を用意して OMSetRenderTargets で設定
cwgl_finish なし
cwgl_flush Flush
cwgl_generateMipmap GenerateMips

Vulkan同様、Clearはscissorやviewportを処理しない(常に全面クリア)。

固定機能の殆どは廃止されているが、generateMipmapに相当するGenerateMipsはDirectX11でも残っている。これはDirectX12で廃止された。

オブジェクト

DirectX11はResourceとViewを分離している。このため多くのGet/Set系インターフェースはViewの方を取ることになる。

WebGL DirectX11
Buffer ID3D11Buffer
Shader ID3D11VertexShader, ID3D11PixelShader
Program なし
Texture ID3D11Texture2DID3D11SamplerState
Renderbuffer ID3D11RenderTargetViewID3D11DepthStencilView
VertexArrayObject (エミュレートする)

DirectXでは、事前にBufferの用途を確定させてからバッファを作成する必要がある。 CreateBuffer, D3D11_BIND_FLAG, How to: Create a Vertex Buffer, Index, Constant 。また、Constant bufferはGLES2には無いがVulkanやDirectX11では逆にdefault uniform が存在しないため必要になる。