協力者募集中!

こんにちわ、Pocolです。
皆さんはCEDECをご存じでしょうか?
そして、その昔Imagire Dayというセッションがあったのをご存じでしょうか?

[CEDEC 2007]最新3D技術論文読みこなしのススメ。2007年注目の「Frequency Domain Normal Map Filtering」とは?
[CEDEC 2008#03]IMAGIRE DAY開幕,トップレンダリストによる最新グラフィックス処理動向
[CEDEC 2009]トップレンダリスト対談:先端を走るゲーム開発者達が次世代の技術を語る

非常に思い出があるセッションでして,当時大学の研究室にいるときに、存在を知りまして,これをきっかけに論文を見るということをはじめ、その習慣は今にも至っています。
物凄く色々な影響を受けていまして,この記事がきっかけでゲーム業界に入るために勉強を色々とするようにもなりました。ShaderXを見始めたり,GPU GemsやGame Programing Gemsを読み漁ったり,C for Graphicsを触り始めたり,ホームページをやり始めたりとか…。

Imagire Dayは本当に良い内容が多く、更に難しい。でも、難しくても為になるからそれがいい。1ランク上に自分を導いてくれる本当に良いセッションばかりです。
殆どImagire Dayに参加するためにCEDECのチケット買っていたといっても差し支えないです。
しかし、いつしかImagire Dayも無くなってしまいました。会場で「今年からImagire Dayは無くなりました」という発言を聞いて残念な気持ちになったのを今も思い出せます。
最近のCEDECはこういう1ランク・2ランク上の世界に導いてくれるセッションが少なくなって、淋しい限りです。

そう常日頃思っていたので、呟いたところ

なんと今給黎先生から、リプライがありまして,尊敬する方にそんなことを言われたらやるしかないか!
…と思いまして,来年のCEDEC 2026に向けてPocol Dayをやれないかなぁーと画策していまして,集団投稿してくれる方を募集しています。
基本的には,普通のCEDEC公募と同じ手続きをとります。単に応募タイトル名の一部に「Pocol Day」を紛れ込ましてもらうだけということを考えています。
なので、普通の公募に応募するだけなので,採択されるかどうかは神のみぞ知るという状態です。一緒に応募しても誰も採択されない可能性は普通に有り得ますので、その点だけご注意いただければと思います。

というわけで,Pocol Dayの協力者を絶賛募集中です!!
ちょっと興味ある!っていう方は是非お声がけください。
また、今年のBBQ会あたりでもどうでしょうか?とこちらからお声がけさせて頂くかもしれませんので、よろしくお願い致します。

またカスタムビルド

どうしてもエディタとしてVisual Studioを使いたいPocolです。

一番簡単なカスタムビルドのメモです。
.vcxprojをテキストエディタで開いて,一番下のほうに次ような感じでコマンドを挿入します。

  </ImportGroup>
  <Target Name="Build">
      <Exec Command="call build.bat" />
  </Target>
  <Target Name="Clean">
      <Exec Command="call clean.bat" />
  </Target>
</Project>

ちなみにExecタスクのドキュメントは下記ですので,細かい設定を追加した場合は下記を参考にしてください.
MSBuildリファレンス > タスクリファレンス > Execタスク
https://learn.microsoft.com/ja-jp/visualstudio/msbuild/exec-task?view=vs-2022

Visual Studio上からリビルドを実行した場合は,Clean —> Build の順番で呼び出しされます。
もしリビルド自体をカスタマイズしたいなら

  <Target Name="Rebuild">
    <Exec Command="call rebuild.bat" />
  </Target>

とやってあれば,自前にリビルドコマンドに変更できます。

実行時のコマンドのカスタマイズは,通常のVCと同じようにプロパティから変更すれば良いと思うので,それでやればよいかと思います。
…というわけでカスタムビルドのメモ書きでした。

どっかで

クリックしてtede-msbuild-2.0.pdfにアクセス

とか

あたりを参考にもうちょいちゃんとしたものを今後改造してみたいと思います。

DREDとAftermathのサンプルプログラムを作りました。

こんばんわんわん、Pocolです。

X(旧Tiwtter)でも書いたのですが,DRED(Device Removed Extended Data)のサンプルプログラムを書きました。
サンプルは以下に置いておきました。
https://github.com/ProjectAsura/D3D12Samples/tree/master/D3D12_DRED

DREDなんですが,意外とまともなドキュメントが無いです。ドキュメントあるんですけども,わかりづらい,「この変数の意味は?」みたいな痒いところに手が届くものが無い感じがしますね。(単純に、ドキュメントみて理解できない私がアホなだけなんですが…)
…というわけで,コードを書いてみました。
仕事で使っているのはちゃんと,Push/Popの入れ子とかも考慮しているやつですけども,まぁええでしょ。こまけぇこたぁいいんっすよ。
結局,DREDのサンプルで困るのは「これちゃんとGPUクラッシュ時に出るの?」という所で,故意にGPUクラッシュさせるようなプログラムがなかなかネットで見つからない。
それだと,動作確認に困るので,GPUクラッシュさせるプログラム書きました。
ここ最近,ずっとGPUクラッシュの調査していたので,どうやれば簡単にGPUクラッシュを引き起こせるかなどのノウハウが溜まったので,その知見を活かして書きました。
一番よくある例,実行中にテクスチャを解放しちゃうやつ。これが一番良くあるので,Tボタン押したら,テクスチャをRelease()するようにしました。これで簡単にPageFaultのGPUクラッシュが発生します。TDRはレジストリいじっている場合は,発生までに時間かかるし,意外とGPU側でちゃんと対処してくれちゃったりする場合もあるので,無理やりやろうとしても意外と発生しなかったりします。サクッといかない。
DirectX-Samplesにはhttps://github.com/microsoft/DirectX-Graphics-Samples/tree/master/Tools/DXGIAdapterRemovalSupportTestというやつもあるみたいですが,こっちは触ったことないんで良く分からんっす(詳しい人教えてください)。

…で馬鹿の一つ覚えみたいな感じなんですが,PageFaultを発生できるようになったので,NVIDIA Aftermathのサンプルも書きました。
一応クラッシュ発生時に,ShaderBinaryとShaderPDBを吐き出して,クラッシュログを調査できる感じにしてみました。私のサンプルの場合は,クラッシュが発生している該当シェーダだけを出力するので,そんなにクラッシュダンプ出力に時間はかからないと思います(仕事でつかっているやつは,別の人が既に実装されたやつなんで,全部のシェーダのバイナリとPDBを出力しやがるんで,時間とディスク容量を食いまくって,困るんですよね。直すのは面倒ですし、時間の余裕もないので直す気はサラサラないです)。
サンプルプログラムは下記にあります。
https://github.com/ProjectAsura/D3D12Samples/tree/master/D3D12_NvAftermath
時間があれば,解説書いてもいいんですが,残念ながら,その時間がないのと,若干仕事のせいで鬱気味なのでやる気が起きないっす。(どうせみんなUEやらUnityつかうでしょ?こういう直叩きするひとがもう日本じゃ少数だから,親切に書いてあげても意味が無いんですよ。見る人いないから…)

…というわけで,リリースして精神的に落ち着いたら,のんびりゆったり解説を書こうかなと思います。
まぁ,そんなの期待する人はほぼいないと居ないと思いますが。

GPUクラッシュが激減した…

こんばんわ、Pocolです。

このところ,仕事でずっとGPUクラッシュを追っていたのですが,なんとなくノウハウが溜まってきました。
ほぼ、毎日のようにGPUクラッシュが何十件もあり,色々な人に手伝ってもらいながら,調査していたんですが,ようやくそれがパッタリ収まりました。

いくつか対策を入れていたのですが,結局どれが効いたのかは正直分からないのですが…
groupsharedで,UINT32_MAXでアクセスして,GPU上でメモリ破壊を発生させるコードがあったので,修正した所,謎に発生していたGPUクラッシュが治まりました。
多分,数年レベルで放置されていたバグなんじゃないかと思います。

NVIDIA AftermathとかでGPUクラッシュダンプを調べても,PageFault,さらにシェーダ情報もでない,挙句の果てにはResourceBarrierを実行するとGPUクラッシュする,定数バッファが壊れて無限ループして,TDRで落ちるなど,過去のクラッシュログを見ても,まったく共通性もなく,しかも結構頻発する。でも全然再現性が無い,手元で全く発生しない…という困ったちゃんで,困りまくった挙句何かないのか?と調べてみたら,NVIDIA Aftermathに,GFSDK_Aftermath_FeatureFlags_EnableShaderErrorReportingというフラグがあるのですが,これを有効にしたところ即クラッシュするようになりました。
何で無効だったのか聞いたんですが,こちらはヘッダファイルにも書かれているようにパフォーマンスペナルティがあるということで,ゲームプレイに支障があるとのことで無効化していたとのことでした。
結局,このフラグを有効にしたところ,先ほど述べたgroupsharedのバグを発見できたのと,他にもクラッシュする原因が見つかって,大いに役立ちました。

今後は,確定で発生しないものはGPU上のメモリ破壊を疑った方が良いという知見が得られました。
基本的にはUAVとかSRVとかのLoad()とかoperator []あたりミスっているんじゃないかって思いがちなんですが,これらはAPIドキュメントを見ると、安全に良しなにしてくれそうなことがあるので,メモリ破壊が発生するのは,CPU上での書き換えか,groupsharedのアクセスミスによる2パターンしかないように思えます(他のパターンがあったら教えてください)。CPU上でのメモリ破壊の可能性がほとんど低いことが分かったなら,groupsharedでの破壊が無いかどうかを調べましょう。
今回のバグは,

groupshared g_Variable[XXX][XXX];
みたいなのが定義されていて,
float temp0 = saturate(XXX);
uint temp1 = temp0 * MAX_VALUE – 1;
uint index = min(temp, MAX_VALUE);
g_Variable[index][XXX] = ….;
っぽいような,謎の計算がされていて(uintをマイナス1する時点でぞわぞわしちゃんですが…)
temp0がゼロになったときに,アボンするみたいケースでした。
よくよく見ると「馬鹿か!」って怒鳴りたくなったっちゃうような,不具合なんですが,変数がごちゃごちゃ定義されていたりとか,ジュニアレベルのエンジニアだとこういうチェックがおざなりになりがちなんで,気を付けた方が良いよ!…という良い事例になりました。

…というわけで,社内でも共有したんですが,この場でも共有してみました。
謎バグに困っている方は,groupsharedで変なことしていないかどうか確認してみると良いかもです。
(※ちなみ1個あったら,他にも絶対あるだろうと思って全シェーダをチェックしてみたのですが,確認した所発生しているのは該当シェーダの1個だけでした。)

パンくずリスト

こんばんわ。Pocolです。

最近ずっとGPUクラッシュ調査の仕事をやっていて疲弊しています。
基本的には,DREDとAftermathを使っています。
DREDを使うと,自動でパンくずリストを作ってくれます。
これ,基本的にはマーカー名とどこまで進んだかを教えてくれます。

GPUクラッシュは大半がTDRかPageFaultだと思います。
TDRでよくあるのは,ループ終了条件を定数バッファのメンバとして渡すパターン。
バッファがどっかで壊れて,終了条件値が想定外の値になって,無限ループ扱いになってクラッシュするとかが良くあります。

で、クラッシュ調査時に欲しいのはどのシェーダ?設定されているのはどのバッファ?中身どうなっている?
…あたりの情報が知りたくなります。

そこで,思いました。
DREDの自動パンくずリストをやめて,自前でカスタムのパンくずリストを作った方が便利なのでは?
そう思ったので,パンくずリストについて調査してみます。

Githubやググったんですが,まともな情報がほぼありません。
FidelityFX Breadcrumbs 1.0が唯一信じられるまともな実装です。
これを調査してみます。
ドキュメントは下記です。
https://gpuopen.com/manuals/fidelityfx_sdk/fidelityfx_sdk-page_techniques_breadcrumbs/

ソースコードは

…あたりを見ると良いです。

基本的な仕組みとしては,
D3D12の場合は,WriteBufferImmedidate() で実行済みフラグを立てていくだけみたいです。
Vulkanの場合は,AMD拡張が使える場合は,vkCmdWriteBufferMaker2AMD()やvkCmdWriteBufferMarkerAMD(),そうでない場合はvkCmdFillBuffer()を使って実行済みフラグを立てていくようです。
現在困っているのは,D3D12環境なので以下D3D12として説明します。

で、WriteBufferImmediate()でどこに書き込むか?なのですが,次のような感じで書き込むメモリを用意するようです。
・VirtualAlloc(nullptr, bufferSize, MEM_COMMIT, PAGE_READWRITE)でメモリを用意。— (A)
・(A)で用意したメモリを引数として,ID3D12Device3::OpenExistingHeapFromAddress() をコールして,ID3D12Heapを取得し,CreatePlacedResource()でID3D12Resourceを生成。 — (B)
・(B)に失敗した場合は,CreateCommittedResource()でID3D12Resourceを生成し,メモリはMap()して取る — (C)
・(B)または(C)にてID3D12Resourceが出来上がるので,ID3D12Resource::GetGPUVirtualAddress()して,BaseAddressを取得 — (D)
・(D)で取得したBaseAddressを開始点として,uint(4byte)で,フラグをWriteBufferImmedidate()で書き込んでいく。

これでコマンドリストに記録されるようになるので,あとはクラッシュした際に(B)または(C)で用意してあるメモリをReadしていきます。これで書き込まれていればフラグが立っていくはずなので,どこまでコマンドが進んだかどうかが判定できます。
マーカー名などのデータはCPU側で管理して,Readしたデータと照合して一致させて,デバッグログなどに表示させれば良いようです。

細かい実装は,FidelityFX Breadcrumbsのソースコードを参照してみてください。

…というわけで,パンくずリストを自前実装する際の基本的な仕組みが分かりました。
あとは,CPU側で管理するデータをリッチにしていけば,色々とデータが取れそうです。

まずは、これらの情報を元にカスタムパンくずリストの実装を始めてみようかなと思いました。
そんなわけで、パンくずリストの話でした。
もし、ノウハウを色々とお持ちの方は是非教えてください。

———————
同僚の方にノウハウを教えてもらいました。
メモリが直接見えるコンソール機では,WriteBufferImmedidate()に対応するような命令が無いことが多く,その場合はタイムスタンプを使って,コマンドがどこまで進んだかを調べると良いそうです。
これは確かに良いなと思いました。

本年もよろしくお願い致します。

Pocolです。
喪中につき、新年のご挨拶は控えさせていただきます。
寒い日が続きますが,どうぞ皆様ご自愛くださいませ。
本年もよろしくお願い致します。

パフォーマンス反省点メモ

120FPS対応を仰せつかった,その時のパフォーマンスについての反省点のメモです。

* ComputeSkinningはEarlyDepthと並列で動作させるべき。
非スキニングメッシュをグラフィックスパイプで描画し,その裏でコンピュートパイプでスキニング処理を実行。完了後にグラフィックスパイプに投入できるように変更すべき。つまり,SkinningメッシュとStaticメッシュはコマンドを分けておかなければならない。

* コンテキストロール回避をあらかじめ仕組みとして用意しておく
シェーダのハッシュ値をもとにソートして,コンテキストロールが発生しづらいように設計しておいたほうが良い。PC版DXCでもハッシュ値が公開されていたはずだと思うので,それを調べてソートする感じ。

* プラットフォームによってコンピュートシェーダが速い
ピクセルシェーダを使うとWaveを使いきれないプラットフォームがあるので,フルスクリーン描画系はすべてコンピュートにしておいたほうが良い。これはとあるカンファレンスでも説明されているので,そちらの資料を参照されたし。どの資料かはお教えできません。

* 深度バッファのダウンサンプルを使いまわせる設計にすべき
何度もダウンサンプルすると遅いので,SSAO, RayMarchShadow, SSR等すべてのスクリーンスペースエフェクトで深度バッファを使いまわせるようにあらかじめ設計すべき。さらにいうとAMD SPDとかみたいな実装でダウンサンプル自体も1パスで実行するべき。

* 非同期コンピュートをフル活用できるようにする
できるだけ非同期コンピュートで実行できるようにレンダリングパスを考えるべき。特にフレームの中盤以降にRTVやUAVの依存関係で,動かせるものがなくなる傾向がある。でも,非同期コンピュートは空いているので,この時間を有効活用できるようにフレーム全体を設計すべき。結局使いどころとしては,コンピュートスキニング,VFX,タイルライトの事前処理や,カリング処理関連になるかと…。

* 半透明重い
おそらく次世代機でも半透明が重いのは変わらないと思われる。縮小バッファやTranslucencyLightingVolumeは先に対応しておき,ON/OFFできるように用意しておくのがよろし。Publisherさんによっては,Hardware-VRSは使わないでとか言われるので,Software-Based Variable Rate Shadingを実装しておくのが良いかもしれない。

* FSR重い
開発終盤にFSRパス全体がボトルネックになりやすい。特に深度を作るパスなどは先行して処理することができるので,FSRのパスの一部を切り分けできるようにしておいたほうが良い。また,とある界隈では最適化されたものが配布されているので,そちらをベースにして各プラットフォーム用に動作するようにカスタマイズするのがおススメ。自分で組み込んだ感じだと0.1ms程度通常版よりも高速化した。

* 16bit専用命令を駆使する
レジスタプレッシャー下げや高速化のために,16bitのhalf floatにすることはよくあると思うのだが,普段そこまでカリカリにチューニングしなくても済んでしまっているので,ノウハウがなかったが,できるだけfloatに戻さずに専用命令で演算し続けたほうが良い。単にhalfにするだけで四則演算するだけじゃだめ。ハードウェア命令を駆使するように。先ほど述べたFSRの最適化もこのあたりを使いまくっている。

* wave32のほうが速いケースがある
PS4なんかはWave64モードしかないので,スレッド数が64になるようにコンピュートシェーダとかで組んでいたと思いますが,最近のハードはwave32ベースで作られていて,wave64で実行する場合はエミュレーションされる命令などもあるっぽい。実際にとあるプラットフォームではシェーダコンパイラがちゃんと警告を出してくれて,wave32で実行したほうが良いことを促してくれる。また,Divergenceの多い複雑なシェーダなどではwave32にするだけで,高速化する場合もある。特にフォーワードレンダリングのシェーダなんかは複雑になりやすい傾向があるので,そういうものはwave32にしたほうが良い。またコンピュートシェーダで起動スレッド数が少ないものもwave32モードにしたほうが良い。

* バリア処理はまとめる
いうまでもないがバリア処理はまとめてバッチングするように。過去にカプコンさんだったりの資料で,そうしたほうが高速化するという実例が出ているので,面倒だけどもちゃんとまとめるように。…というかレンダーグラフとかパスグラフみたいなシステムがちゃんと作ってあるなら,そこで吸収するように作ってあるはず。もしつくっていないなら,今すぐにそうなるようにプログラムを組んだほうが良い。

* 何でもかんでもバインドレスにしない!
レンダーターゲットにもテクスチャにも使用されていない的な警告がグラフィックスデバッガで出ることがあるが,バインドレステクスチャとして使っている場合に,使用していることがスルーされることがあるっぽい。実際にあった事例だと,使っていないから消してOK的な指示があるので,遠慮なく削除したところ,見た目がバグることがあった。で、コードを追って調べたところバインドレステクスチャとして使っている箇所だった。なので,基本的にはバインドレステクスチャにしなくてもいいところは無理にしないほうが,ツールのアシストが効くので最適化に役立つことがある。何でもかんでもバインドレスにしないこと!

* 出力シェーダアトリビュートは4つ以下にする
出力パラメータが4つまでなら,処理負荷がかかることはないが,4つを超えると処理負荷がかかって遅くなる。そのため,頂点シェーダやメッシュシェーダからの出力パラメータは可能な限り4つ(float4が4つ)以内に収まるようにパッキングを行う。とあるプラットフォームだけが特定キーワードを付け足すと自動でパッキングしてくれるが,そのような機能が用意されていないプラットフォームもあるのでfloat16_tを使ってできる限り詰め込むと良い。

* 帯域を下げる
R9G9B9E5フォーマットなどを使い,R16G16B16A16_FLOATなどのフォーマットは避ける。R11G11B10_FLOATがあるが,こちらは過去タイトルで絵的なバグが出た事例を聞いたことがあるのと,あんまり精度がよくないため,お勧めできない。前述のR9G9B9E5フォーマットを使うようにする。この際に,アルファブレンドしているものがあると置き換えに苦労するので,デバッグ系描画などはシェーダ上で手動ブレンドして3チャンネルしか使わないようにするなど,あらかじめ最適化を見越した作りにしておいたほうが良い。

* 頂点シェーダは可能な限り使わない
頂点シェーダを使うだけで重いので,できる限り使わない。メッシュシェーダやコンピュートシェーダで処理できるようにしておく。

* コマンドジャンプを使う
奥の手としてコマンドジャンプを使って色々なことを実装することが可能なので,PipelineStateをGPU上で設定したりなど,PCでは出来ない,コンソールならではのことをやって最適化を行う。こうすることによってCPUのドローコールは減らせるので,CPU処理がネックだった場合は高速化ができる。

* バッファのアロケータはちゃんと作る
CommittedResourceはアライメントが64KiBになるので,例えば16Byteの定数バッファをアロケートしても64KiBでメモリが取られてしまうので,小さいバッファ用に自前でちゃんとアロケータは作っておいたほうが良い。作っていないとメモリ周りで嫌な思いをすることになる。
自分が作ったやつだと,VB or IB or (!UAV && ByteAddressBuffer) or (!UAV && StructuredBuffer)の条件を満たして,64KiBなら同一リソースから切り出して使うという実装にした。!UAVにしているのは1個のResourceの場合,リソースステートが部分的にWriteになったりさせることができないので,基本的にはReadしかしない対象に限定するため。これで数百MB減ったケースがある。

* Decompress処理をしないようにする
Decompress処理が走ると重いので,最近のやつだとDecompressしなくていいようにするためのフラグがあったりするので,そいつを付けておく。

* 最初からWave Instrinsicsを使って最適化しておく
終盤に命令最適化すると,バグで困ることが多々あるので,あらかじめ最適はできるところは最初からやっておく。終盤にしかできない場合は,ちゃんとデグレを検知するための単体テスト環境など,機械的なチェック環境を用意しておくこと。人力によるチェックはすり抜けることが当たり前にある。

* GPUネックになりやすいものは一部処理をCPUに逃がす。
今世代でもGPUネックになりやすい。そのため,CPU側に逃がせるものは逃がすようにする。例えば,オクルージョンカリングはソフトウェアラスタライズのもの使うとか,VFXの計算の一部をCPUでやるとか,メッシュのLOD判定をGPUからCPUに移すとか…。

* 非同期解放処理システムを作っておく
同期させるとやっぱりスパイクなどが発生しやすいので,1フレームでの処理対象を制限するか,そもそも大丈夫なように非同期解放の仕組みをつくっておくかしないと,ロード時・ロード直後に痛い目に会うことになる。

* その場しのぎの適当なコードを書かない
w成分空いているからここに高さデータいれちゃえーとか適当な実装をしていると,前述したパッキングによる最適化を行う際に,都合が悪いケースが出てきて,困ることがある。どこにどのデータが入っているかは,誰から見ても分かるようにしておくこと・そしてきちんと管理しておくこと。そうしないとエンバグが発生しまくって,自分の首を絞めることになる。

* ループ処理を見直す
早い段階で,continueできれば重い処理を回避し,最適化できるケースはちゃんと最適化する。メッシュ描画などは何度も呼ばれるため,意外と大したことがない変更でもめちゃくちゃ速くなることがある。

* デバッグツールは用意する
プログラマー的なグラフィックスデバッガーを使いこなせるアーティストは少ないので,ゲーム上にデバッグツール・可視化ツールは用意しておく。大量生産前に用意しないと,そのあとは忙しさで作られることないと思ったほうが良い。特にオーバードローやシェーダの複雑度あたりは必須。

Direct3D 12 ゲームグラフィックス実践ガイド 増刷決定!!

こんにちわ。Pocolです。
技術評論社様より販売させていただいております『Direct3D 12 ゲームグラフィックス実践ガイド』ですが,おかげさまで増刷が決定しました!

Uneral EngineやUnity等が台頭する時代に逆行する内容の書籍なので,すぐに絶版するのではないか?という不安。
また,DirectX12の魔導書なども既に発売されていて,私の書籍など見向きもされないのではないか?
発売しても売れるのだろうか,そもそも買おうとすら思ってもらえないのではないか?
…など色々な不安を抱えながら,なんとか発売までたどり着いた書籍です。

この本は本当にいろいろな方にご迷惑をお掛けしながら,何とか出せた書籍ですので,増刷が決定したと連絡を受けて嬉しかったです。
本当に皆様のおかげです。本当にありがとうございます。

ただ正直,もっと批判とか苦情に近い意見が多いんだろうなと覚悟はしていたのですが,想像していたよりも少なく,また良かったという意見も全くない状態でして,著者としては書いてよかったのか,書いて悪かったのかが何にも分からない。受け入れられているのか,そうでもないのか判断に困るという状態です。
分かりづらいところがあれば,SNS等で遠慮なく書いていただきたいですし,逆にダメなところは今後の執筆に活かせるチャンスとなるので,忌憚のないご意見を書いていただけると幸いです。また,もっと書いて欲しいものとかあるのであれば,応援の意味を込めて「良かったよ!」など肯定的な意見を頂けると,励みになります。肯定的な意見が無ければ,「これはもう書かないほうがいいな」という執筆を辞める決断にもなってしまいますので,応援していただけるのであれば,応援の声も頂けるとありがたいです。

書籍のほうですが,12月ころから増刷版が市場流通する見込みと伺っておりますので,現在手に入れられていない方はもうしばらくお待ちいただければと思います。
今後ともDirect3D 12ゲームグラフィックス実践ガイドをよろしくお願いいたします。