Archives

2008 の記事

テレビ売り場に足を踏み入れて、いかに自分が取り残されているか実感。
何を今更という感じでしょうが、最近のテレビは進化してるなと。
全然知りませんでした。


・機能

何でもつながる?ありとあらゆるコネクタが付いてる。
豊富な映像入出力だけでなく、
LAN コネクタは当たり前、NAS 専用の LAN 端子とか USB やら iLINK の 1394 やら
電話線とか中には eSATA まで。

インターネットブラウザも入ってて、ダウンロードしたアプリが動いたりもするらしい。
テレビに USB キーボードもつながる。
HDD 内蔵とか SD カードとか、自分で再生したり録画したり。
どうやって作っているんだろうと思ったら、どのメーカーもマニュアルにも
GPL と使用した Linux kernel の記載があった。

携帯電話のように、今できる機能は何でも入ってるといった感じです。


・画像補整競争

解像度もフルHDで、技術革新によりパネルの性能も向上しています。
でも入力データはフォーマットが決まっており、モニタが対応したからといって急に
変えるわけにもいかず。

そんな中差別化を図る手段が、限られた入力リソースをいかにきれいに見せるか。
デジカメの現像のようにさまざまな画像処理を経て、それぞれメーカー毎の絵作りが行われています。

色の補正、解像度変換、残像を減らすため工夫。中間フレームを生成してフレーム
レートを数倍にして、フィルタで映像内のモーションブラーを除去したり。
それだけハードウエアの処理性能が向上しているということです。


業務用の高度なモニタだと、キャリブレーション調整後のガンマ補正や色域を
一定にするために演算精度を上げています。パネルの多階調化も正確さのため。

一方家庭用テレビの場合は、同様の演算能力をきれいに見せるために使います。
カタログによると内部演算は 10~18 ビットで行われているそうです。

DeepColor というのはこのように従来より多階調の色情報を扱うこと。
入力信号は HDMI v1.3 以降で対応しているので、DeepColor 対応はモニタ側が直接
多階調の情報を受け取れるかどうかを意味しているようです。
実際に使われている液晶パネルも 10bit のものが増えています。

従来フルカラーは 1pixel あたり 24bit (24bpp) で、1ch あたり 8bit = 256階調でした。
10bit の場合は 1024 階調。1pixel あたり 30bit (30bpp) となります。

同じようにカタログに出てくる xv.Color は、色の段階の細かさを表す DeepColor
と違って、色の広さ方向の拡張を表しているようです。

入力情報が最初から多階調に対応しているならともかく、現状ほとんど無いため
その差を埋める技術が画質の差につながるわけです。


昔 Xbox1 の時代でも、ビュアでテレビに出した絵の色がシーンによって違うと
デザイナーに呼び出されることがありました。
まだ CRT だったけど、入力の情報にあわせて動的にトーンコントロールが行われていたためです。
あらかじめテレビ側の設定を変えておかないと、明るいシーンと暗いシーンでトーンが
変わってしまいます。
今だとそれ以上に、テレビで絵が変わってしまう可能性がありそうです。


HDMI 1.3a や DisplayPort では、信号自体 DeepColor に対応しています。

Wikipedia High-Definition Multimedia Interface
Wikipedia DisplayPort

 ・24 bpp ( 8 bit x 3)
 ・30 bpp ( 10 bit x 3)
 ・26 bpp ( 12 bit x 3)
 ・48 bpp ( 16 bit x 3)

GPU の PixelShader も今では当たり前のように内部演算は 32bit 浮動小数で行われています。
1pixel あたり 3ch で数えると 96bit です。

フレームバッファもより深い深度を持つことが可能です。
HDR で 16fp (64bpp) も使われているし、同じ 10bit 階調なら 32bpp の
R10G10B10A2 もあります。

今更ながら、Direct3D 10.1 で 16bit (64bit) 整数バッファへのブレンディングが
サポートされたのはこのためだったのかと気がつきました。

今後 DisplayPort が普及したら、PC もフルカラー = 24bit ではなく
より色数が増えて 30bit 以上になりそうです。
例えば下記スライド。

WinHEC 2008
  ・Display Technologies - pptx



前回 はポータブルの無線ルータ LAN-PWG/APR を使いましたが、試しに据え置きの
WHR3-AG54 を使ってみました。
PSP ブラウザも結構快適に使えるようになりました。

TouchDiamond PS3 Wii PSP

機材リスト

・PSP-2000 (5.02)
・BUFFALO WHR3-AG54
・HTC Touch Diamond (S21HT) + WMWifiRouter 1.25

接続方法や設定は 前回 とほぼ同じです。
ブラウザで読み出しの反応が速くなり、待たされる感じが減っています。
回線速度や設定は同じはずなので、単にルータの処理能力の差なのか、最適化など
機能の差なのか、何らかの違いがあるのでしょう。

でもこれを持ち歩くわけにはいかないので、移動を考えたら結局
ノートPC + AP機能付き USB無線LANアダプタ の方が実用的だという結果になりそうです。

せっかくなので他のゲーム機も EMOBILE 経由で接続してみました。

PS3/Wii ともに 11g なので回線自体 PSP より速いはずですが、もともと EMOBILE で
500Kbps しか出てない場所なのでそんなに変わらないかも。
ちなみに E-MOBILE 開始直後、サービス対象圏外だった頃からずっと 500Kbps。

PS3 では一応ブラウザ、YouTube、PlaystationStore、Home など。
Home はアップデートやゾーン移動時のダウンロードはかなり遅い。でも一応入れる。
LittleBigPlanet のオンラインステージは、読み込みに少々時間がかかる。
不安定になったのでオンラインは断念。

S21HT のバッテリーが持たないので Wii の USB ポートからの給電に切り替え。
Wii はまず本体の更新から。でも時間がかかりすぎて断念。その他チャンネルなど
使えるけどやっぱり遅いかも。


関連エントリ
PSP / Eye-Fi と EMOBILE Touch Diamond S21HT をつなぐ (WMWifiRouter + LAN-PWG/APR)
EMOBILE 経由で PSP ブラウザ



キーボードがない Touch Diamond に Wireless Keypad つないで QWERTY キーボード化

ps3keypadwm

ps3keyapdwm は WindowsMobile の携帯電話や PDA で ワイヤレスキーパッド を
使うためのソフトです。v1.30 では各端末のキー配列の違いを吸収できるように
なりました。

ps3keypadwm v1.30 ダウンロードはこちら

対応しているキーレイアウトは 3種類

 ・日本語配列と認識するタイプ
 ・英語配列と認識するタイプ
 ・Touch Diamond 系独自の配列

それぞれキーボードの刻印通りに記号入力できて、日本語入力モード (IME) の切り替え
もできて、さらにキーボードだけで操作できるよういくつかの機能を割り振っています。

ps3keypadwm
↑これは WindowMobile 版 ps3keypadwm 専用の配列です

  ・キーレイアウト認識の違いを吸収 (3タイプ)
  ・WindowsMobile ではほぼ使わない ESC キーを Ctrl キーに変更
     → Ctrl+X/C/V の Copy & Paste などに使える
  ・[/] キーを日本語入力で多用する ハイフンキー [-] に入れ替え
  ・ワイヤレスキーパッドの [あ/A] ボタンで日本語モード切替
  ・Ctrl +数字キー等で WindowsMobile の操作

Ctrl キーとの組み合わせで下記の操作ができます。
ワイヤレスキーパッドでは ESC ボタンが Ctrl なので、ESC を押しながらの操作になります。

Ctrl + [0] = 起動しているアプリ(タスク) を順次切り替える
Ctrl + [6] = Win ボタン (スタートメニューを呼び出す)
Ctrl + [7] = 左ソフトキー
Ctrl + [8] = 右ソフトキー
Ctrl + [9] = OK ボタン相当

Ctrl + [1] = 画面回転 縦 (Touch Diamond だと本来の位置)
Ctrl + [2] = 画面回転 横
Ctrl + [3] = 画面回転 縦 (上下逆)
Ctrl + [4] = 画面回転 横

Ctrl + [あ/A] = ↑ カーソルキー
Ctrl + [/]    = ↓ カーソルキー
Ctrl + [,]    = ← カーソルキー
Ctrl + [.]    = → カーソルキー

ps3keypadwm は RBK-2100BTJ など他の日本語キーボードの配列補正にも使えます。

文字入力しやすくなりました。
Advanced Wnn だと問題が多いので、 MS-IME に切り替えて imekeyset5 で
Phone Style も追加して使っています。

ただ一般的な 5方向カーソルがないので、片手だけで手探りで操作できない点は
少々マイナス。

画面が離れていても操作可能ですが、結局キーを見ないと打てないので QWERTY キー
内蔵端末のようにすぐ近くに持ちながら打つことになります。

Bluetooth の認識は便利で、自動で電源が切れても何らかのキー操作するだけで
すぐに接続が復活します。常に文字入力しているわけではないので、必要なときだけ
キーボードを出して使えます。

しばらく使っていて、片手だけで見ないで操作できるカーソルキーやテンキーだけの
Bluetooth Keyboard があっても良いんじゃないか、と思いました。
用途に合わせて QWERTY キーと組み合わせたり好みで使い分けたり。

それにしても WindowsMobile の日本語 IME 周りや文字入力の互換性の無さは
何とかして欲しいです。キーボード付きの WindowsMobile 端末が出るようになって
から、ずっと同じことばかりしてた気がします。

標準化されてるわけでなく各端末が独自に実装してたりするので、新商品が出るたびに
その場限りの対応になってしまうことが問題です。


関連エントリ
HTC Touch Diamond とキー入力、MS-IME への切り替え
WindowsMobile6 で imekeyset5 を使う
WindowsMobile IME FSKAREN / ATOK
EMONSTER lite S12HT IME FSKAREN
EMONSTER lite S12HT の文字入力を MS-IME に切り替える




●日本語入力の切り替え

Touch Diamond (S21HT) の日本語変換は Advanced Wnn です。
外部キーボードを接続した場合に一部の記号入力ができなかったり、文字を取りこぼし
たりと互換性の面で問題があるようです。

WindowsMobile6.1 には MS-IME も入っているので、EMONSTER lite S12HT と同じ方法で
MS-IME に切り替えることができます。下記エントリで解説しています。
 ・EMONSTER lite S12HT の文字入力を MS-IME に切り替える
 ・EMONSTER lite (S12HT) 対応 ctrlswapmini lite v1.00

直接ダウンロードできるファイルも置きました。
 ・s12ht_msime.txt(reg)
 ・s12ht_msime.txt(reg)
s12ht_msime.txt をレジストリに登録して再起動(長押しで電源入れ直し)すると
MS-IME になります。s12ht_wnn.txt で元に戻ります。

MS-IME のキーマップ切り替えやカスタマイズは、WindowsMobile5.0/6.0 と同じように
imekeyset5 を使うことができます。
imekeyset5


●その他の IME

パネルやキーボードなどの入力方法を自前で何とかするという前提で ATOK が
使えるようです。gesture10key など。

FSKAREN は正式に対応したバージョンが販売されているとのことです。
残念なのは、ほんの数ヶ月前に発売された FSKAREN と別バージョン扱いで、新たに買い直さなければならないということ。発売後わずか 3ヶ月。機種乗り換えで使えなくなりました。
アップグレードなどで既存ユーザーにもきちんとサポートして欲しいところです。


●外付けキーボードのキー配列

↓ Bluetooth Keyboard x4 + Touch Diamond S21HT
BluetoothKeyboard
 左上ワイヤレスキーパッド、右上 RBK-2000BT2
 左下ワイヤレスキーパッド改、右下 RBK-2100BTJ


Touch Diamond S21HT の外部キーボード認識は独自の配列となるようです。
基本的には日本語キー配列ですが、一部キーの認識が異なっています。

キー配列の認識については Bluetooth Keyboard
Reudo RBK-2100BTJ/RBK-2000BTII のページがたいへん参考になります。
携帯電話キーボード Rboard for Keitai RBK-2000シリーズ

対応機種一覧で日本語配列/英語配列/独自配列 の違いがわかります。
Touch Diamond / Touch Pro はどれも独自配列です。

調べてみました

TouchDiamond のキーコード (相違点のみ)
[\|]        → Code  0 / 106 (0x6A)
[@`]        → [[{]
[[{]        → []}]
[]}]        → [\|]
[半/全漢字] → [@`]
[カナ/かな] → Code  0 /  19 (0x13)
[Pause]     → Code  0 / 119 (0x77)
[無変換]    → Code  0 / 103 (0x67)
[変換]      → Code  0 / 100 (0x64)
[ _]        → Code  1 /  51 (0x33)
[ _]        → Code  1 /  81 (0x51)


関連エントリ
WindowsMobile6 で imekeyset5 を使う
WindowsMobile IME FSKAREN / ATOK
EMONSTER lite S12HT IME FSKAREN
EMONSTER lite S12HT の文字入力を MS-IME に切り替える



PSP と Eye-Fi Share を EMOBILE 経由でネットにつないでみました。
WMWifiRouter + アクセスポイントでの接続は、EM・ONE (S01SH2) で試したときは
だめだったけど Touch Diamond だとうまくいきます。

EM・ONE の無線LAN は特殊なようで、WMWifiRouter で設定を変えると固まることがあります。
Touch Diamond (S21HT) の場合設定した通りに動くのでいろいろ実験できそうです。

試した機材は下記の通り。

・PSP-2000 (5.02)
・Logitec LAN-PWG/APR モバイルブロードバンドルータ (ファーム 1.03)
・HTC Touch Diamond (S21HT) + WMWifiRouter 1.25

Touch Diamond PSP


●設定手順

とにかくつながればよいのでさまざまな設定方法があります。
今回は PC を使わず、上記の機器だけで設定を行いました。
下記の手順で。


●ルータ LAN-PWG/APR の初期化

(1) 電源が入ってるときにリセットを長押しして工場出荷時の設定に戻す。
(2) 裏のスライドスイッチを AP にする (アクセスポイントモード)


●PSP でルータにつないで設定を行う

ルータの設定を変更するためにブラウザでアクセスします。
Touch Diamond を使っても構いませんが PSP でやってみます。

(1) 設定 → ネットワーク設定 → インフラストラクチャモード → [新しい接続の作成]
(2) ワイヤレスLAN設定の画面で「検索する」
(3) ルータのデフォルトSSID "LAN-PWG_APR" が見えるのでそれを選ぶ
(4) SSID は「 LAN-PWG_APR 」のまま
(5) ワイヤレスLANセキュリティ設定は初期設定なので「なし」のまま
(6) アドレス設定は「かんたん」 (初期状態では DHCP サーバーが有効)
(7) 接続名を適当につける
(8) 設定を保存 (テストは不要)

以後ブラウザから

(9) メニューからネットワーク→インターネットブラウザ
(10) 「利用する接続を選択してください。」のリストから (8) で保存した設定を選ぶ。
  DNS 等でエラーが出ても無視して構わない。

(11) (△) でメニューを出して十字キー [↑] で画面上の「アドレス」にカーソルを合わせる
(12) アドレスバーに「 http://192.168.1.200 」と入力
(13) ユーザーID とパスワードをきかれるので、両方とも「 admin 」といれる

以後設定画面

(14) ルータの設定画面が開くので「基本設定」のボタン
(15) 暗号化方式を WEP に変更し、WEPキー の入力形式を「ASCII」に切り替える
(16) WEPキーの 1番に、半角アルファベット 5文字で任意の文字列を入れる
(17) 「設定」ボタンを押して保存。再起動のため 80 秒ほど待つ。
  この間ルータが再起動するのでいったん接続が切れる。
  ブラウザを終了。

メニューで再びネットワーク設定へ

(18) 設定 → ネットワーク設定 → インフラストラクチャモード → (8)で保存した設定
(19) 「手動で入力する」を選ぶ
(20) SSID はそのまま
(21) ワイヤレスLANセキュリティ設定を「WEP」に変更
(22) WEPキーに (16) で登録した文字列を入れる
(23) アドレス設定「かんたん」のまま
(24) 保存し終了 (テスト不要)

再びブラウザへ

(25) メニューからネットワーク→インターネットブラウザ
(26) (11)~(13) と同じように入力して再び設定画面を開く (URL の入力履歴を使うと簡単)
(27) IPアドレス設定を選ぶ
(28) 無線側の「DHCPサーバー」が有効になっているので「無効」に変更する。
(29) 「設定」ボタンを押します。
  再びルータの再起動で接続が切れます。ブラウザを終了します。


● Touch Diamond (S21HT) 側の設定

あらかじめ WMWifiRouter をインストールしておきます。
また電源が勝手に切れないようにしておきます。
 設定→電源→詳細設定 から「次の時間経過後、電源を切る」のチェックを外す。

(31) WMWifiRouter を起動する。
(32) Options → Configuration → Wifi network...
   Dynamic (Safer) → None (advanced) に変更
(33) Options → Configuration → IP range...
   「192.168.1.x」に変更する。
(34) いったん WMWifiRouter を終了する。

(35) 設定 → 接続 → Wi-Fi のアイコン → ネットワークの検索
(36) LAN-PWG_APR がみつかったら、社内ネットワーク設定 → データ暗号化を WEP にする
  「自動的に提供されるキーを使用する」のチェックを外して
  PSP 上で設定した (16) の WEP キーを入れる
(37) "LAN-PWG_APR" が接続中のままになるけどそのまま

(38) WMWifiRouter を起動する。
(39) 3G → Wifi ボタン (Cellular to Wifi) で接続を開始する。
(40) Wifi に「Network: LAN-PWG_APR」と表示されたら完了。
  もし再び WEP キーをきかれたら (36) と同じように入れる。

これで終わりです。


●PSP から利用する

これで PSP から EMOBILE 経由でネットにつながるようになります。
(8) で保存した設定でつなぎます。
一応試したもの。

・インターネットブラウザ
・PlayStation Store でまいにちいっしょの 12/15 更新をダウンロード
・まいにちいっしょポータブル の トロステ更新
・インターネットラジオの再生 64kbps のもの

一通りできますがレスポンスが遅いので、設定をもう少し吟味した方がよいかもしれません。
以前 ZEROProxy を使用したときはブラウザだけでしたが、WMWifiRouter だとブラウザ以外も
使用できます。
どこでも まいにちいっしょ が見れます。


●Eye-Fi

Eey-Fi も PSP 同様に無線 LAN の設定さえしておけば、EMOBILE (Touch Diamond) 経由で
アップロードできました。
それなりに時間がかかるので、上りが高速な HSUPA 対応端末の方が良いかもしれません。


関連エントリ
Eye-Fi Share 無線LAN内蔵 SDカード(2) 実験など、簡単な解析
Eye-Fi 無線LAN内蔵 SDカード
EMOBILE 経由で PSP ブラウザ



1年ほど前に作った WbalanceGE が窓の杜対象にノミネートされていました。
Balance Board を使って Google Earth 上を歩くソフトです。

窓の杜 2008年 ノミネート一覧 作品部門

結果はごらんの通り

窓の杜 2008年 窓の杜大賞 結果発表

入賞していないのでどれだけ票が入ったのか、入っていないのかわかりませんが
投票してくださった方がいましたらお礼申し上げます。
ありがとうございました。

プログラムを書いたのは自分ですが、アイデア出したのは HYPERでんち
トップにあるモデルを作ったアクリルさんです。


関連エントリ
バランスWiiボード で地球を歩く WbalanceGE v1.10
地球上を歩き回る GoogleEarth 対応 WbalanceGE v1.00



試してきました。メディアポート UP300
Nikon MEDIA PORT UP 300x

ただの単眼式のヘッドマウントディスプレイかと思ったら違いました。
iPod など最近の「多機能メディアプレイヤーにヘッドホンとモニタが一体化しているもの」
といった方が正しいようです。

単体でメモリを 4~8GB 内蔵しており、音楽、画像、ムービーといった各種プレイヤー
機能が含まれています。
特に安い方のモデルには外部入力端子がなく、ディスプレイとして利用することが
できないあたりにこの商品の狙う位置が見えます。


本体は意外に軽く普通のヘッドホン感覚で使えます。
最初に行うのはディスプレイ部の位置あわせとピント調整です。

ダイヤルを回しきってもなかなかうまくあわなかったけれど、目よりも若干下で
ぴったり合う位置を発見。アームはかなり柔軟に動きます。

画面は思ったほど大きいものではなく、視界の中に PinP の小画面が浮いている感じ。
カタログの表現を借りると「1m 先に 17インチ相当」です。

単眼式なので、大迫力というよりは他のことしながら情報ウィンドウが片側に開いている
イメージでしょうか。解像度は VGA。

最初は片目の方が見やすいですが、設定がうまくいって慣れてくると両目をあけたままで
見えるようになりました。


WiFi も内蔵しており、ストリームでメディアを再生したり内蔵ブラウザで web 閲覧も可能。

ブラウザの操作はヘッドホン横のスクロールホイール+カーソルキーで行います。
解像度は 640x480 ながらサイズが小さいためフォントも大きめ。
制限されたボタン操作かつ描画や転送が重いので、残念ながら快適というほどでは
ありません。一応赤外線リモコンが用意されているようです。

たぶん携帯電話の方が速くて快適でしょう。
もし携帯電話の出力を表示できるならば、ワイヤレスキーパッド のようなワイヤレスの
Bluetooth キーボードも使って携帯メールなども快適に書けるだろうなと。

きっと歩きながら下を見て携帯の画面を注視し続けるよりも、
こんな感じで視界に浮いている方がまだ安全だと思います。見た目はともかく。


ヘッドホン内側には WindowsCE 5.0 のシールが貼られていました。
CE5 は WindowsMobile5~6 等にも使われているものです。

無線 LAN 内蔵で WindowsCE を採用したメディアプレイヤーといえば
Toshiba Gigabeat や Microsoft の Zune があります。
でも WindowsMobile のロゴではなかったことと、独自のメニュー構造に見えたので
これらと同じプラットフォームを利用しているわけではなさそうです。
アプリが作れたり XNA が動いたりしたら楽しいのですが無理っぽい。


あくまで多機能メディアプレイヤーであって、モニタとしての用途は限られています。
1万円高い UP300x にしか外部入力端子が無く、用意されているケーブルは iPod 用
などミニジャックのものだけ。

コネクタさえあわせればビデオ入力(コンポジット)は可能と思われますが、
他にどんな入力が可能かは明記されていませんでした。
(本体側はマルチコネクター端子という特殊なもの)
例えば S端子入力に対応しているかなど、ショールームのスタッフも問い合わせた
サポートの方も、わからないという以前に質問の意味や意図を理解していない様子でした。

PSP もインターレースに対応した PSP-3000 ならつながるとは思いますが、
反応速度等がわからないのでどこまでゲームに使えるかどうかは不明です。
携帯電話も以前は TV出力機能付きがありましたが今もあるかどうかわかりません。


メディア再生よりも、歩行ナビのような情報表示とかメール着信表示とか、
いつでも取れるテキストメモやメールとか、
ツールとしての活用の方がおもしろそうに見えました。

内蔵ブラウザではくっきりしたデジタル表示なのに、入力がもしビデオ端子のみ
だとしたら少々残念なところです。


またモーションセンサーも入っていますがあまり活用されていないようです。
スタッフの方も機能を知りませんでした。
頭の動きを感知できるので、情報を取り出してコントローラにしたりとかできたら
おもしろそう。(でもおそらくできない)

商品コンセプトもターゲットもメディアプレイヤーとして一般向けを狙っているようです。
でも一発目だし値段を考えても、もう少し新しい物好きの人に向けた深いところも
用意した方が良かったのではないかと感じます。
何でもやってくれる機能ではなく 何かできそうな機能が欲しい。

おもしろいし かなり欲しかったので 今後に期待します。



●普通の SD カードリーダーが使える

Eye-Fi 付属の USB カードリーダーではなく、他のカードリーダーを使ってもソフトウエアの
インストールや無線 LAN 設定ができます。
実際に GREEN HOUSE の GH-CRHC35-U2 や ELECOM MR-C11BK で
インストールと設定変更ができました。
(ファームウエアの更新は未確認)

無線設定など Eye-Fi カードの機能アクセスのために、専用の USB アダプタを使用
しているわけではないようです。

ただしノート PC 内蔵のカードリーダーを使うと、PC 内蔵の無線 LAN アダプタと
電波が干渉するのかネット接続が切断されました。外付けのカードリーダーを使って
できるだけ本体から離した方が良いようです。


●マネージャー

Eye-Fi Manager は複数の PC にインストールできます。
同じアカウントでログインしておけば OK。
カードを差し込んで設定変更できますし、転送先 PC を切り替えながら使えます。


●転送の組み合わせ

転送先の組み合わせは次の 3種類です。

(1) Eye-Fi カード ==> インターネット共有サイト
(2) Eye-Fi カード ==> パソコンの指定フォルダ
(3) Eye-Fi カード ==> インターネット共有サイト + パソコンの指定フォルダ

一見ネットと関係ない (2) の場合でも、インターネットに接続してログイン
できなければ転送が行われませんでした。

純粋に認証のためかもしれないし他に理由があるのかもしれません。
例えば USB カードリーダーを使った Eye-Fi カードへのアクセスは無線 LAN 設定
だけであって、それ以外の設定はサーバーを経由している可能性があります。
つまり

 1. PC 設定をサーバーに書き込む
 2. Eye-Fi カードはサーバーから設定情報を受け取って動作を決定する

といった仕組み考えられます。
実際に複数の PC で無線 LAN 以外の設定は共有されていました。
メール通知のためかもしれません。


●隠しフォルダ

Eye-Fi カードのルートには EyeFi というフォルダがあり、中に

REQC
REQM
RSPC
RSPM

と 4つのファイルがあります。すべて 16KB 固定です。
このうち RSPM ファイルは直前の操作によって中身が上書きされています。
ログ取得を行った直後はログファイルの一部が書き込まれているし、無線LAN 一覧が
列挙されていることもあります。
カード内部にアクセスするための I/O ファイルのような感じ。

・設定された無線LANの列挙
・検出された無線LANの列挙(電波強度などの情報付き)
・テキストログ

アップロード履歴はログを元に Eye-Fi Manager で生成しているだけかもしれません。


●DHCP エラー

やはり自分の環境だと DHCP のエラーでつながらないことが多いようです。
つながるときもあります。今のところもう 1つのルータなら大丈夫。
回避用に固定 IP の設定も欲しいところです。


関連エントリ
Eye-Fi 無線LAN内蔵 SDカード 設定や感想やらはこちら



無線LANによる自動アップロード機能付き SD カード、Eye-Fi を手に入れました。
Eye-Fi

容量は 2GB。
デジカメでこのカードを使用すれば、写真を撮るとすぐにパソコンに転送してくれます。

データ転送のためにいちいちカメラからメモリカードを抜かなくてもいいし、
専用の USB ケーブルでつながなくてもいい。
それどころかカメラを専用の通信モードに切り替える必要すらなく、撮影状態のままでも
手間無く転送が行われます。


利用するにはパソコンが必須で、まずは Eye-Fi カードのセットアップを行います。
無線 LAN の設定など。

初期設定は非常に丁寧に作り込まれていますが、ウィザードに従い一通りの手順を
体験しなければなりません。

パッケージには Eye-Fi カード本体と、専用の USB カードリーダーがセットになっています。
親切にも最初からカードリーダーに差し込まれた状態です。そのまま PC へ。
必要なソフトウエアもカードに書き込まれており、ドライバ CD 等はありません。
表示される指示に従うだけで準備は完了します。

(1) 最初にアカウントを作ります。PC側の通信でサーバーに登録されるようです。

(2) ファームウエアの更新が行われます。

(3) 次にカード側の無線 LAN でネットにつながるか確認します。
  DHCP が必須で、IP アドレス等の手動設定はありません。
  実際にインターネットにつながっているかどうか、Eye-Fi のサーバーまで
  到達できるかどうかもチェックします。

(4) オンラインの共有サービスに自動でアップロードするか設定します。
  PC への転送だけが目的なら設定しなくても構いません。

(5) PC の保存フォルダの確認など。

(6) カードを抜いてデジカメへ。実際に最初のアップロードが行われるかテストします。

これらを全部クリアして初めて完了します。
使用した PC は WindowsVista x64。


(3) の無線 LAN 設定ではまりました。無線はつながるものの DHCP でタイムアウトし、
アドレスを受け取れない状態が続きました。

構築してあるルータの設定を変更したくはないし、
先に他の設定だけ済ませてからゆっくり原因を探すこともできないし、
手動で IP 設定することもできないし、
親切なウィザードがあだとなる何もできない状態。

別のルータを用意してセキュリティを落としてテストするとつながったので、
一通り初期化を済ませてまずは登録。
それから設定を何度か変更しつつ本来の無線 LAN アクセスポイントにも接続できました。


●気がついたことなど

一度転送した写真は再転送しない。
最後に転送したファイルのタイムスタンプか撮影日をチェックしているように見えます。

転送してもデータの削除は行われません。
カードが勝手にファイルを削除すると本来のホスト(デジカメなど)と同期が
取れなくなるのでおそらく無理。


データの転送確認はデジカメでなくてもできます。初期化をこれで済ませました。
他のノート PC にカードを挿して DCIM フォルダを作成。さらにその中に適当な
フォルダを作って jpg ファイルをコピーします。
しばらくたつと勝手に転送が始まるはず。

例えば

  \DCIM\A

の中に拡張子 .jpg で画像を保存するだけ。

4文字拡張子 .jpeg はだめ。
ファイルの中身が別のフォーマットだったりすると、最初転送しようとしますが
受け取る PC 側ではじかれます。


付属のカードリーダーは普通の SD カードリーダーとして使えます。
16G SDHC もいけました。

逆に普通の SD カードリーダーに Eye-Fi を入れてもマネージャーが認識します。
ただし設定やファーム更新の安定性を考えると純正のものを使った方が良いと思われます。


●使用感

使い始めたばかりですが非常に快適です。
完全なワイヤレスであり、さらにモードレスでもあります。

添付ソフトや設定もわかりやすいので、本来ならトラブルもなく完了するはず。

外では直接インターネットへアップロードすることを想定しているようですが、
ポータブルのルータがあればノートPC にその場で保存することもできそうです。



EMOBILE Touch Diamond S21HT で軽く動作確認しました。

ワイヤレスキーパッド CECHZK1JP

Bluetooth に関しては、EMONSTER lite S12HT のように再接続後に通信が極端に
不安定になることもなく EM・ONE 同様に使えました。
ただ認識されるキー配列が異なっており、EM・ONE や S12HT とも別物。
ps3keypadwm v1.00 だとうまく使えないかもしれません。


関連エントリ
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (5)
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (4)
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (3)
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (2)
Bluetooth Keyboard として使える PS3 のワイヤレスキーパッド



EeePC901-X (初代 12GB) の内蔵 SSD を交換し、Vista install のその後。
(前回: EeePC 901 の SSD 交換 BUFFALO SHD-DI9M 32G と Vista)

SSD 4G へ install した Vista より重く感じたのは、やはり設定の差だったようです。
今回は機能を削らないでそのまま install したため。
軽量化します。

とりあえずサービスの停止

・ReadyBoost 停止
・SuperFetch 停止
・TabletPC Input Services 停止
・Windows Backup 停止

これでだいぶ変わりました。
その他自分は使わないと思うもの。

・Human Interface Device Access 停止
・Windows Image Acquisition 停止

使わないデバイスも一応無効にしておく

・web camera 無効

Aero Glass は絶対に無効にしない。

電源設定はスリープのみ。休止状態は使わない。

フル充電ならスリープ放置で 3日くらいは平気。

待機時の消費電力がかなり小さい + EeePC901 のバッテリー容量が大きいおかげで、
電源を切らずにスリープのみで運用できています。
PDA (携帯) のように常に待機してる感じで非常に便利。
SSD であることとバッテリー容量が大きいことが EeePC901 の強みだと感じます。
これだと SSD 容量が小さく休止状態が使えないことがデメリットになりません。

使える環境になったと思います。
あとはしばらく使ってみてから。


関連エントリ
EeePC 901 の SSD 交換 BUFFALO SHD-DI9M 32G と Vista
EeePC 901 のその後
EeePC 901 に WindowsVista (5)
EeePC 901 に WindowsVista (4)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista


ASUS EeePC 901 (初代 12GB) の内蔵 SSD を交換しました。

BUFFALO Inspiron Mini9専用 MLC 搭載 内蔵SSD SHD-DI9M シリーズ

Dell の Inspiron Mini9 専用ですが EeePC 901 でも使えるとのこと。
参考にしたページはこちらです。取り付け方なども丁寧に解説されています。

x-gadget:blog  「BUFFALO SHD-DI9MをEee PC 901-Xへ装着する」を公開


購入したモデルは 32GB SHD-DI9M32G。BUFFALO 直販サイトでは 8800円となっています。

EeePC 901-X では内蔵 4GB SSD の代わりに取り付けます。
基板を取り出すまで分解が必要ですが、上記サイトの PDF で非常に丁寧に詳しく
解説されています。おかげでスムーズに交換できました。

引っかかったのはタッチパッドのフラットケーブルコネクタだけ。
  外し方が甘く、パームレスト部を外すときにつながったままだったのと、
  取り付け後、差し込みが甘くて最初タッチパッドが使えなかったこと。
  OS インストール時に気がつきました。

これで容量は内蔵 32GB + 8GB へと大幅に強化されました。
BUFFALO の EeePC 用 32GB/64GB との違いは、C ドライブ側に装着可能なことと
比較的高速なこと。
PC Watch 本城網彦のネットブック生活研究所 第5回 Inspiron mini 9+αをSSD交換で容量アップ! バッファロー「SHD-DI9M32G」

早速 WindowsVista をインストールしてみます。

以前 EeePC 901 に Vista Business をインストールしたときの結果は次の通り。

・内蔵 8GB MLC 側
  最小 6GB なので、一応そのまま install できるが更新すると空きがなくなる。
  インストールも動作も極めて低速で、継続利用はあきらめた。

・内蔵 4GB SLC 側
  vLite でぎりぎりまで削ったインストーラで導入可能。
  インストールにかなり時間かかる。その後容量をあけるために多くのファイルを
  D: (8GB) に逃がしたのでその分遅くなっているはず。Aero Glass さえ有効に
  すれば速度は十分で今まで常用していました。が、容量とメンテが厳しい。

詳しくは関連エントリを参照してください。


● SHD-DI9M32GB に Vista Business install

容量に余裕があるので、そのまま install DVD から OS をインストールできます。
Vista の場合インストールしたドライブが常に C: になるため、ドライブの順番とか
あまり気にしなくてすみます。

インストール中に長時間固まることもなく、以前よりずっと短い時間でインストール
できました。SSD 速度の差というより、容量に余裕があるためだと思われます。

インストール直後の消費容量はおよそ 9GB。20GB がフリーとなっています。
SP1 + 更新適用後も 19GB 以上フリーのまま。

eeepc 901 vista

ドライバの導入や設定などは以前と同じです。

・ほとんどのドライバは付属のものが使える。Vista 用も含まれている。
 AsusSetup.exe だと OS チェックではじかれるので直接 Setup.exe を実行する。
 Chipset, LAN, WLAN, ACPI (起動時に毎回 ACPI のエラーが出るようになる)

・VGA ドライバは intel サイトから 945GM Vista 用を落として入れる。
 Aero Glass は必ず有効にする。

・Bluetooth は Windows 標準のままでも使える。A2DP 等、Windows Stack で未対応の
 プロファイルが必要ならドライバを入れる必要あり。

・ドライバが一通り入ったら、Windows エクスペリエンスインデックスを計測し直す。
  コントロールパネル→システム→ Windows エクスペリエンス インデックス
 正しく VGA ドライバが入っていれば スコアは 2.7 になります。

・RAM 2GB なので仮想メモリなしに。復元ポイントもなしへ。自動デフラグ停止。
 インデックスをなしに。

RAMDISK を設定する。
 容量を 512MB、W: に設定。Vista は頻繁に TEMP に書き込むので、環境変数 TEMP
 と TMP をどちらも W:\TEMP にする。

・IE7 のインターネットオプションから「インターネット一時ファイル」のフォルダを
 C:\TEMP\Temporary Internet Files に変更。

・IE7 以外のブラウザも入れる。同様にキャッシュを RAMDISK に変更。

SymbolicLink で他のドライブにファイルを逃がす必要もなく、アプリケーションも
デフォルトのパスに入れられるし普通の PC になりました。
実際に使用してみての速度などについてはこれから。
操作のレスポンスなど若干遅くなった印象がありますが、
vLite を使っていないためサービス等が多数動いているせいかもしれません。

続き>Vista 設定 その2

関連エントリ
EeePC 901 に WindowsVista (5)
EeePC 901 に WindowsVista (4)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista



● WindowsXP/Vista 版 ps3keypad v1.10

足りないキーを補う ps3keypad を更新しました。

ps3 wireless keypad

このプログラムを組み込むと、上図の通り 左側のメッセージボタンを [Func] キーに、
右側のフレンドリストボタンを [Ctrl] キーにします。

また Func キーとの組み合わせで Alt, Home, End, PageDown, PageUp, F1~F12, Alt,
Win を入力できるようにします。Func + [/?] でハイフン(長音) の入力もできます。

ダウンロードはこちら
ps3keypad v1.10


● WindowsMobile 版 ps3keypadwm v1.00

このプログラムを使うと、英語のキーボード配列として認識してしまう WindowsMobile
端末でもキーボードの刻印通り文字入力できるようになります。
Ctrl キーの追加やハイフンの直接入力が可能です。

ダウンロードはこちら
ps3keypadwm v1.00

EMONSTER lite S12HT や Touch Diamond 系 (S21HT 等)、英語配列と認識してしまう
端末でも使えます。
日本語モードの切り替えにも対応。(IME によって若干差異が生じる可能性があります)

WindowsMobile ではメッセージボタン、フレンドリストボタンを認識しません。
その代わり、WindowsMobile ではまず使用しない ESC キーを Ctrl に割り当てます。


●まとめ

Playstation3 用に発売されている小型の Bluetooth キーボードです。
ワイヤレスキーパッド CECHZK1JP
パッケージには PS3 専用と書かれていますが、実際は汎用の Bluetooth キーボードで
マニュアルにも他の Bluetooth 対応機器とペアリングして使用できると書かれています。
PS3 コントローラにつける必要はなく、単独でも使用できます。

  ・非常に小型で薄くて軽い
  ・Bluetooth のワイヤレスキーボードとして使える
  ・タッチパッドの代わりにもなる (ワイヤレスマウス相当)
  ・充電式バッテリー内蔵。USB 端子で充電できる。

スマートフォン内蔵の QWERTY キーボードのようなものです。
  ◎キーボードを持っていないスマートフォンと組み合わせて
  ◎サブ PC 用に
  ◎PC のリモコン代わり
など、さまざまな使い方が考えられます。


・ペアリング方法
  1. 左上のブルーボタンを押しながら、スライドスイッチで 電源を ON
  2. LED が点滅し出すまでブルーボタンを押しっぱなしにする
  3. 3つの LED がちかちか点滅してる状態がペアリングモード

  パスキーの入力を求められたら、キーパッドの数字キーでそのまま打ち込みます。
  最後に Enter を押す。

詳しくは付属の紙マニュアルを参照してください


・タッチパッドモード

 SONY ロゴ真下のタッチパッドボタンで、タッチパッドモードに切り替わります。
 緑色の LED が点灯している状態がこれ。

 キーボードの上を指でスライドするとマウスカーソルが動きます。
 ノート PC のタッチパッドと思って操作するとやりやすい。


・初期化(キャリブレーション) について

 タッチパッドを正しく使うには初期化(キャリブレーション)が必要です。

   タッチパッドモード(緑色 LED が付いている状態)で、
   ブルーボタンとオレンジボタンを長押しします。
     → LED が一回点滅したら完了。

 初期化をしないとカーソルが飛んだり、キーに触れていないのに反応したりします。

 環境が変わると感度も変わるので、反応がおかしいと思ったら再び初期化
 (キャリブレーション) した方がよいです。


●問題など

Bluetooth の相性かどうかわかりませんが、EMONSTER lite S12HT ではキーパッドの
電源を入れ直したあとの再接続が行われると、キーの反応が悪くなることがあります。
通信が途切れがちになっている感じ。

ペアリングしたあと電源を切るまでは全く問題なく動作しますし、同じ WindowsMobile
端末の EM・ONE S01HT では、再接続後でも問題なく動いています。
個体差かもしれないし原因はわかっていません。


●雑感

サイズや使った感じは、スマートフォン等に組み込まれている小型の QWERTY キー
ボードそのままです。

キートップが小さく、ボタンを斜めに押してしまうことがないため取りこぼしも
ありません。使いやすい方です。
個人的には 初代 W-ZERO3(WS003SH) には負けるけど [es](WS007SH) より上。

クリック感も適度で [F] と [J] には触ってわかるポジションマークがあります。
カーソル左右移動がスペースバーの両脇にあるのは思ったより使いやすい。

単独で使った場合は、ボタンがどうこうよりも形状による持ちにくさの方が方が気になります。
ブルーやオレンジボタンの位置を考えてもコントローラにつけたままの方が
操作しやすいです。

タッチパッドモードはキートップ間隔のせいなのか、細かな微調整が苦手です。
スクロール機能と真ん中ボタンが欲しいところ。


下記の関連エントリも参照してください。


関連エントリ
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (4)
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (3)
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (2)
Bluetooth Keyboard として使える PS3 のワイヤレスキーパッド



さらに裏の出っ張りも削ってストラップをつけたもの

ps3 wireless keypad

薄くなりました。机の上に置いて使えます。
厚みはこれくらい

ps3 wireless keypad

↑上が EMONSTER lite S12HT、下が ワイヤレス キーパッド

ps3 wireless keypad

↑上が ワイヤレスキーパッド、下が EMONSTER lite S12HT

見えている USB 端子は、PS3 とのペアリングと充電に使用します。
USB ケーブルを使わずに、PLAYSTATION3 XMB のメニューから手動でペアリングしても使えます。

薄くて小型なので、キーボードを内蔵していない EMONSTER lite S12HT や
S21HT など Touch Diamond 系にぴったりかもしれません。

2008/12/20 8:22 追記 S12HT ではキーパッドの電源を入れ直して再接続すると反応が悪くなる症状がありました。ペアリング直後や EM・ONE S01SH では大丈夫でした。原因不明。


英語配列と認識する WindowsMobile でのキー配列に関しては、
これから解決方法を探るつもりです。


ps3 wireless keypad

↑削っていない(使っていない)方の中身


タッチパッドモードは、環境が変わると反応に差が出ることがあるようです。
カーソルが飛ぶようになったりキーに触れていないのに反応する場合は、再び初期化
(キャリブレーション)を実行すると安定します。


この キーパッド は解析も覚悟で購入したものだったので、こんなにあっさり
つながるとは思いませんでした。

Playstation3 がもともと汎用的なインターフェースを採用しており、PC 等の周辺機器
がそのまま使えるからこそできること。
これまで閉じていることが多かったゲーム機だけど、いろんなものがあっさりつながり、
互換性のある PS3 は大変良い傾向だと思います。

ワイヤレスキーパッド CECHZK1JP


関連エントリ
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (3)
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (2)
Bluetooth Keyboard として使える PS3 のワイヤレスキーパッド



削ってしまいました

ps3 wireless keypad
ps3 wireless keypad

↑クリップ部分を削る前のキーボードと比較


前回 は PC への接続が中心だったので、今度はスマートフォン WindowsMobile です。

ps3 wireless keypad

↑キーボード比較

日本語配列として認識する WindowsMobile 端末ではそのままの配列で使えます。
[あ/A] ボタンで日本語切り替えもできました。
上の EM・ONE など、QWERTY キーボードを搭載している端末は日本語配列のものが
多いようです。
EM・ONE だとマウスカーソルが出るのでタッチパッドモードも使えます。


Ctrl キーがないのがちょっと不便なのと、PC と違い [メッセージボックス]
[フレンドリスト] ボタンを認識できませんでした。

ps3 wireless keypad


↑ キーボードを持っていない端末でも QWERTY キーボード

上の EMONSTER lite S12HT のように、英語キーボードとして認識する端末では
キーの刻印と入力される記号に相違が生じます。

これは他の日本語配列の Bluetooth キーボードでも同じなので、たまたまインストール
していた Reudo RBK-2100BTJ 用のサポートソフトが利用できました。
サポートソフトを RBK-2100BTJ の設定にすると配列通りの文字入力になります。

Reudo RBK-2100BTJ

でもこれだけでは [あ/A] で日本語の切り替えができませんでした。
さらに別のソフトでカスタマイズする必要がありそうです。


WindowsPC 向け接続と、Ctrl キーなどのカスタマイズについては 前回 の記事を参考にしてください。


関連エントリ
PS3 ワイヤレスキーパッド を スマートフォン と PC で使う (2)
Bluetooth Keyboard として使える PS3 のワイヤレスキーパッド



PLAYSTATION3 の周辺機器として発売された小型のキーボード
ワイヤレスキーパッド CECHZK1JP は汎用の Bluetooth キーボードとして活用可能です。

特徴は

・非常に小型で薄くて軽い
・Windows PC や PDA、スマートフォンなどで使える
・タッチパッドモードがあるのでマウス操作もできる
・Bluetooth Keyboard としては安価
・日本語入力もワンタッチで切り替えられる
・充電バッテリー内蔵で、USB で充電できる
・PS3 コントローラがなくても単独で使える

などなど。

ps3 wireless keypad
ps3 wireless keypad

てっきり PS3 コントローラの USB ポートにつなぐのかと思ったら、独立した
汎用の Bluetooth Keyboard でした。しかも慣れればマウス操作もできる。

ワイヤレスかつ小型なので場所をとらず、離れた場所の PC やサブマシン用、
リビングPC のリモコン代わり、持ち歩いてスマートフォンの文字入力などに
・・・これから使ってみます。


●QWERTY キーボード

文字キーは一通りそろっており、左右の肩にある「●ブルーボタン」と
「◎オレンジボタン」を併用して記号の入力を行います。

ブルー、オレンジ、シフトキーは同時押しと連続押しどちらにも対応しています。
QWERTY キー付きのスマートフォンと同じです。

例えば [Shift] を押しながら [1] だと「!」になりますが、
[Shift] を押して離したあと [1] を押しても「!」になります。
直後のキーにだけ有効です。

"{" や "}" もあるし、入力できない記号も特になさそうです。

[Enter] の左にある [あ/A] が漢字キー相当になっています。
日本語入力の On/Off もワンタッチです。

SONY ロゴの下にあるアイコンボタンは左から下記の順。

・メッセージボックスボタン
・タッチパッドモード切替
・フレンドリストボタン

メッセージボックスボタン と フレンドリストボタン はファンクションキー F24/F23
相当でした。カスタマイズに使えそうです。

カーソルキーはスペースバーの左右に分かれています。
上下はブルーボタン併用なので少々操作しづらいかもしれません。

SELECT, START, PS ボタンの 3つは、コントローラ (SIXAXIS) に取り付けたとき
だけ使うものです。電気的につながっているものではありません。

PS ボタンやコントローラに固定するためのフック部分は邪魔ですが、
構造的に切り取ってしまっても動作には支障ないかもしれません。


●タッチパッド

キーボードがそのままタッチパッドになります。

タッチパッドモードでは、キーの上をなぞるように指をスライドさせると
マウスカーソルが動きます。

初めて使うときは初期化(キャリブレーション)が必要で、タッチパッドモードに切り替えた
状態で ブルー+オレンジを長押しします。

購入直後のキャリブレーション前だと、キーから指が大胆に浮いた状態でも反応してしまいます。
静電容量方式かもしれません。
初期化重要、きちんと説明書を読んでおかないとはまります。

操作感はノートPC のタッチパッドに近く、そのつもりで触ると納得。
でもキートップが離れているせいか、細かい操作には向いていないようです。

左右のカーソルキーがマウスの左右ボタンになります。
真ん中ボタン相当はありませんでした。


●カスタマイズ

不満点はハイフンがオレンジボタン併用なところ。日本語入力時の長音で少々不便。
また [Ctrl] キーがないので コピー&ペースト とかできません。

em1key を使って、
メッセージボタンを [Ctrl] キー
フレンドリストボタンを ハイフン「-」
[Shift] + [BS] を [Delete] キーに割り当ててみました。

動作確認は次の環境で行いました。
WindowsVista SP1 (x64)

em1key 用スクリプト ps3keypad v1.00

アーカイブ内の scriptcommand.txt を、em1keypc.exe または em1keypc.exe と同じ
場所に入れてから em1key を起動するだけです。
これでコピー&ペーストなど Ctrl キーを使った操作もできます。
(このスクリプトは現在 WindowsMobile では使用できません)


●その他

右サイドにスライド式電源ボタンがあります。オートパワーオフ(スタンバイ)もあり。
一度ペアリングしておけば、電源を入れたあと何らかの操作で勝手につながります。
このあたりは一般的な Bluetooth Keyboard と同じです。

ブルーボタンを押しながら電源を入れてそのままブルーボタンを押し続けると
ペアリングモードになります。

ペアリング時のパスキーは、キーボードから任意の数字を入れられます。
4桁入力したあと Enter を押すのを忘れずに。
(これも他の Bluetooth Keyboard と同じ)

Bluetooth キーボードは 1万前後のものが多いので、このワイヤレスキーパッドは
かなり安価に見えます。
調べてみると、これらのキーボードも PLAYSTATION3 に対応と書かれていました。

IO DATA CPKB/BT 15700円
ロジクール diNovo Mini 18800円
RBK-2000BT2 9800円


関連エントリ
Bluetooth Keyboard として使える PS3 のワイヤレスキーパッド



PS3
oga at 10:04
本日発売の PS3 のコントローラにつけるタイプのミニキーボード、
PLAYSTATION3 ワイヤレスキーパッド CECHZK1JP を買ってきました。

周辺機器 PLAYSTATION3
PLAYSTATIONR3専用「ワイヤレスキーパッド」2008年の年末商戦期に向けて日米欧にて発売

コントローラと合体しているのは単に固定のためでした。
キーパッド自身がバッテリーを内蔵しており、単独で Bluetooth Keyboard として
動作します。
つまり PS3 コントローラが無くても使えます。

マニュアルにもきちんと、PS3 以外の機器とペアリングする方法が載っており
Bluetooth 対応製品と一緒に使えると明記されています。
実際に WindowsPC (Vista x64) とペアリングできました。

キー入力だけでなく、マウス代わりのタッチパッドモードもそのまま使えます。
非常におもしろいデバイスだと思います。いろいろ試してみます。



2008/12/17
テラバイト

1.5TB HDD を買ってみました。
ギガの時は "GB" なのに、容量の単位がなぜか "テラバイト" (カタカナ) 。

terabyte

WindowsVista



投影されるスクリーンのピクセル長から TessFactor を求めるように変更。
これを曲率で補正します。
前回の頂点形式の tscale はそのまま曲率を意味するようになりました。
この値を無視すれば直線部分も分割可能。

tess font 90

拡大してもフォントが荒れず、同一フォント内でもエッジの長さや奥行きに応じて変わります。
ただし分割数は GS だと限界があります。
GeometryShader の出力は最大 1024 float なので、仮に出力が最小の float4
SV_Position のみとしても 1エッジあたり 21 分割まで。
21 * 3 vertex * 4 edge = 252
252* 4 float = 1008
↑負荷は軽くなったけど TessFactor の求め方はまだまだ改良の余地あり。

tess font 91

↑直線部も均等に割ってランダムな振動を加えたもの。(WARP)
2D のディスプレースメントマップのような感じ。
エッジをじりじり動かせます。手書きアニメーション風の表現とかできるかも。
コンバータにはかなり苦労したけど、実際に画面が出て動くようになるとさまざまな
応用ができて楽しい。

描画が軽いうちは WARP デバイス (D3D_DRIVER_TYPE_WARP) はかなり使えます。
ステートの組み合わせを間違えても GPU がハングアップすることがないので、
いろいろ実験したりテストするとき 精神的 に楽です。

GPU がハングアップすると画面が停止して何もできない状態に陥ります。
たいていはドライバがタイムアウトすると GPU をリセットするので
しばらく待っていれば復活します。
でもうっかりミスだったりするとこの待ち時間が後悔の時間。万が一復活しない場合は
たとえ内部で正常に動いていてもリセットが必要というプレッシャーも。
短時間でも画面のフリーズは無い方がよいです。


関連エントリ
Direct3D11/DirectX11 (17) GPU を使ったアウトラインフォントの描画の(5)
Direct3D11/DirectX11 (16) GPU を使ったアウトラインフォントの描画の(4)
Direct3D11/DirectX11 (15) GPU を使ったアウトラインフォントの描画の(3)
Direct3D11/DirectX11 (14) GPU を使ったアウトラインフォントの描画の(2)
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など


やっとフォントデータ丸ごとコンバータを通るようになりました。

tess font 82
tess font 81

表示は Direct3D11 beta + RADEON HD4850
ハードウエアで動かすために GeometryShader 4.0 を使っています。
Reference Driver なら GeometryShader ではなくテセレータを使用可能。

fps 表示もアウトラインフォント

tess font 80

プロポーショナルフォントの処理が無いので字間が少々おかしい。

CPU Rendering の WARP Driver でも 30fps くらいは出ます。
Reference Driver だと 2.4fps 程度。
(WindowsVista x64 Core2 Duo)

頂点形式は float2 x4、これを 4頂点で 1パッチとして描画しています。
4頂点なら LINELIST_ADJ で GeometryShader に渡せます。

px py  c0x c0y  c1x c1y  tscale cx
px py  c0x c0y  c1x c1y  tscale cy
px py  c0x c0y  c1x c1y  tscale 0
px py  c0x c0y  c1x c1y  tscale 0

1頂点が 1エッジに相当します。tscale はテセレータに対する係数。
係数が 0 だと分割しないので直線部分に使用します。
カーブが急な部分、エッジが長い部分は係数を大きくするなどの調整も可能です。

cx cy はパッチの中心座標を埋め込んだもの。


フォントデータは SVG か FXG を使用しています。glyph や path 等。
パス情報自体はほぼ同じ形式なのでデコード処理は共通化できます。
使用していませんが XAML も attribute に埋め込まれたパスの書式は同一でした。
内外判定は NonZero 相当。自己交差したパスは未対応。

Paths SVG 1.1
FXG 1.0 Public Specification
パス マークアップ構文


関連エントリ
Direct3D11/DirectX11 (16) GPU を使ったアウトラインフォントの描画の(4)
Direct3D11/DirectX11 (15) GPU を使ったアウトラインフォントの描画の(3)
Direct3D11/DirectX11 (14) GPU を使ったアウトラインフォントの描画の(2)
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作


前回 は通信を避けてほぼ待ち受け状態でした。
今回は連続通信です。

・E-MOBILE EM・ONEα (S01SH2) WindowsMombile 6.0
・3400mAh のスーパー大容量バッテリー
WMWifiRouter 1.25
MachiukeIdle

Windows NotePC から接続して音楽のストリーム再生 (128kbps) 流しっぱなし。
結果はおよそ 4時間30分。

電波状況 LED off、miniSD 入れたまま、常駐ソフトなし、Today 画面もなし、
警告とサウンドもできるだけ無しに設定。

EM・ONE をフル充電伝電源 ON → WMWifiRouter を起動 &接続 → MachiukeIdle
4時間 38分後に再生停止、バッテリーの赤ランプ点灯で、WMWifiRouter がバッテリー
警告で停止していました。

まとめ
・待ち受け状態 (通信しない状態) で 7時間半
・通信し続ける (下り128Kbps連続) で 4時間半

Bluetooth だと待ち受けだけなら 20時間くらい生きていた気がするので
やはり無線LAN の方がバッテリーを消耗するようです。

スーパー大容量バッテリーを付けると EM・ONE だけでも 300g を超えてサイズもかなり
かさばります。欠点は
・でかさと重さ
・シャットダウン状態から電源を入れると1分くらいかかること
・アドホック接続のみ

WMWifiRouter はルータなので、起動しておけばアドホック接続限定とはいえ複数台から
接続できます。IP も正しく割り振られており、iPod touch と EeePC 両方同時に使用できました。
あとはいつも EMONE を立ち上げておくだけ。


関連エントリ
iPod touch + EM・ONE WMWifiRouter
EMOBILE EM・ONE の Bluetooth モデム化2
EMOBILE EM・ONE を Bluetooth モデムにする
EMOBILE EM・ONE スーパー大容量バッテリー



最近 iPod touch を使っているので EM・ONE に WMWifiRouter を導入しました。

・EMOBILE EM・ONEα (S01SH2)
・3400mAh のスーパー大容量バッテリー
WMWifiRouter 1.25
MachiukeIdle

この組み合わせで待ち受け状態にし、およそ 7時間30分。

条件は割といい加減
・購入時から時間がたっているバッテリー
・通信状態は不定 (地下鉄に乗ったりした)
・まれにメールチェックで接続&生存確認
・iPod touch は近くで音楽再生しっぱなし。
 (通信しなくても無線LAN を見に行ってるかもしれない)
・miniSD カード入れっぱなしだった
・電波状態ランプは消灯

フル充電+シャットダウン状態から起動し、WMWifiRouter で接続したのち
MachiukeIdle を立ち上げてそのままかばんの中へ。常駐アプリ無し。
条件が不定で通信もできるだけ控えたので、あんまり参考にならないかもしれません。
7時間30分後が最後の生存確認で、その後 7:35~7:40 くらいに赤ランプでバッテリーが
落ちました。


● WMWifiRouter 1.25

WMWifiRouter は WindowsMobile 端末をルータとして使えるようにするソフト(有料)です。
例えば iPod touch のネット接続が、EMOBILE 経由でできるようになります。
利点は無線 LAN を使うため Bluetooth がなくてもワイヤレスで接続できるということと、
EMONE の場合は Bluetooth 経由よりも高速に通信できます。
ただしクライアントを想定している WM 端末はアクセスポイント機能を持たないので、
EM・ONE と直接接続する場合アドホック通信のみとなります。
iPod touch は OK ですが、PSP/DS 等は直接接続できません。

他の無線 LAN 接続設定が残っていると不安定になることがあったので、導入前に完全に
初期化を行いました。ルータとして使うと割り切るならその方が確実なようです。
起動前に無線 LAN を ON にしておきます。

(1) EM・ONE をフォーマット (購入時状態に戻す)
(2) 輝度を落としたり音を消したり常駐物を減らすなど最低限の設定
(3) 無線LAN を ON
(4) WMWifiRouter をインストール、起動してダイアログに従い初期設定
(5) MachiukeIdle をインストール

バッテリーの消耗を防ぐ意味もあり、使わないときはシャットダウンしておいた方が良いようです。
電源投入後

(1) 本体起動まで待つ
(2) WMWifiRouter を起動して「3G→Wifi」(Cellular to Wifi) の接続ボタンを押す
(3) MachiukeIdle を起動する

MachiukeIdle は 画面OFF とキーロック、オートパワーオフの無効化を行い、ずっと
稼働し続ける状態にします。
切断時は、キーロック解除 → MachiukeIdle EXIT、WMWifiRouter の切断アイコンを
押して通信が切れたらアプリ終了ボタンを押す。
アプリが終了したらシャットダウン。


関連エントリ
EMOBILE EM・ONE の Bluetooth モデム化2
EMOBILE EM・ONE を Bluetooth モデムにする
EMOBILE EM・ONE スーパー大容量バッテリー


結局 GeometryShader だけで描画できました。
これだと D3D11 でもハードウエアアクセラレートかかるので
回転アニメーションとかも余裕。

tess font gs

入力頂点は、最後の1つを複製して 6頂点単位に変更。
それぞれが float2 × 4 なのは変わらず。

・エッジ x4
・中心座標
・ダミー

描画 TOPOLOGY は D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ に変更。
これを triangleadj で受け取れば 6 頂点入力ができます。

HS/DS を NULL にして代わりに GS を設定するだけ。

iContext->RSSetState( iRS_WIREFRAME );
UINT	stride= sizeof(float)*2*4;
UINT	offset= 0;
iContext->IASetVertexBuffers( 0, 1, &iVBuffer, &stride, &offset );
iContext->IASetInputLayout( iLayout );
iContext->VSSetShader( iVS, NULL, 0 );
iContext->GSSetConstantBuffers( 0, 1, &iBufferV );
iContext->GSSetShader( iGS, NULL, 0 );
iContext->PSSetShader( iPS, NULL, 0 );
iContext->OMSetRenderTargets( 1, &iRenderTargetView, iDepthStencilView );
iContext->IASetPrimitiveTopology( D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST_ADJ );
iContext->Draw( vdata0_size*sizeof(float)/(sizeof(float)*2*4), 0 );

各エッジを最大 8 分割と仮定すると最大
8 triangle × 3 × 4edge = 96 頂点出力される可能性があります。

各シェーダーを vs_4_0 gs_4_0 ps_4_0 向けにコンパイルすると
RADEON HD4850 で HARDWARE 動作しました。API は D3D11 のまま。

// gs_4_0
struct VS_OUTPUT {
	float2	vPos0	:	VSPOS0;
	float2	vC0	:	VSPOS1;
	float2	vC1	:	VSPOS2;
	float2	vPos1	:	VSPOS3;
};

cbuffer pf {
	float4x4	WVP;
};

struct DS_OUTPUT {
	float4	vPos	: SV_Position;
};

void addv( float2 pos, inout TriangleStream<DS_OUTPUT> stream )
{
	DS_OUTPUT	dout;
	dout.vPos= mul( float4( pos.xy, 0, 1 ), WVP );
	stream.Append( dout );
}

float2 UVtoPositionB( const VS_OUTPUT p, float t )
{
	float	t2= 1.0-t;
	float4	u= float4( t2*t2*t2, t2*t2* t*3, t2* t* t*3, t* t* t );
	return	 u.x*p.vPos0.xy +u.y*p.vC0.xy +u.z*p.vC1.xy +u.w*p.vPos1.xy;
}

void Curve4( float2 center, const VS_OUTPUT v,
			inout TriangleStream<DS_OUTPUT> stream )
{
	const int	step= 8; // = TessFactor
	float	t= 0;
	float	tstep= 1.0/step;
	float2	prevpos= UVtoPositionB( v, 0 );
	for( int i= 0 ; i< step ; i++ ){
		t+= tstep;
		float2	pos= UVtoPositionB( v, t );
		addv( prevpos, stream );
		addv( pos, stream );
		addv( center, stream );
		stream.RestartStrip();
		prevpos= pos;
	}
}

void Edge( float2 center, const VS_OUTPUT v,
			inout TriangleStream<DS_OUTPUT> stream )
{
	if( v.vC0.x > -1e4 ){
		Curve4( center, v, stream );
	}else{
		// 直線の場合
		addv( v.vPos0, stream );
		addv( v.vPos1, stream );
		addv( center, stream );
		stream.RestartStrip();
	}
}

// step(8) x 3 x 4 = 96
[maxvertexcount(96)]
void main(
	triangleadj VS_OUTPUT input[6],
	inout TriangleStream<DS_OUTPUT> stream )
{
	Edge( input[4].vPos0, input[0], stream );
	Edge( input[4].vPos0, input[1], stream );
	Edge( input[4].vPos0, input[2], stream );
	Edge( input[4].vPos0, input[3], stream );
}

最適化していないので、四隅と中心の頂点の計算が重複したままです。


関連エントリ
Direct3D11/DirectX11 (15) GPU を使ったアウトラインフォントの描画の(3)
Direct3D11/DirectX11 (14) GPU を使ったアウトラインフォントの描画の(2)
Direct3D11/DirectX11 (13) TessFactor とシェーダーリンクの補足など
Direct3D11/DirectX11 (12) テセレータのレンダーステート他
Direct3D11/DirectX11 (11) 互換性とシェーダーの対応表など
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分



↓手書きのフォントもベクタ表示
tess font 40

続きです。
前回表示したアウトラインフォント のシェーダー側の動作となります。

入力データは quad のエッジ情報です。通常は VertexShader に頂点情報を渡しますが、
接続する 2頂点+2コントロールポイント座標を一組としてシェーダーに渡します。

1つの quad を描画するためには 4辺分+中心座標が必要なので、これが 5組あります。
よって描画データは下記の通り。

// 1 quad 分
v0 c0 c1 v1
v0 c0 c1 v1
v0 c0 c1 v1
v0 c0 c1 v1
g0 0  0  0

 v0= x,y 頂点
 c0= x,y コントロールポイント
 g0= x,y 中心座標
 0= 0,0 未使用

ラインの場合コントロールポイントが不要なので c0, c1 は使いません。
中心座標は x,y のみなので、残りは全部 0 です。

カーブの場合: v0 c0 c1 v1
ラインの場合: v0 -1e5 0 v1

例
249.593597f,395.421600f,  302.652008f,346.582397f,  341.562408f,290.375214f,  366.312805f,226.812805f,
366.312805f,226.812805f,  -1e5f,0,  0,0,  324.124786f,219.500000f,
324.124786f,219.500000f,  298.250397f,282.316803f,  263.750397f,333.031189f,  220.624802f,371.656006f,
220.624802f,371.656006f,  -1e5f,0,  0,0,  249.593597f,395.421600f,
293.008575f,305.777374f,  0,0, 0,0, 0,0,


IA に渡す頂点の定義は次の通り。float2 × 4

D3D11_INPUT_ELEMENT_DESC	ldesc[]= {
{  "VPOS", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 0,
				D3D11_INPUT_PER_VERTEX_DATA, 0	},
{  "VPOS", 1, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float)*2,
				D3D11_INPUT_PER_VERTEX_DATA, 0	},
{  "VPOS", 2, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float)*4,
				D3D11_INPUT_PER_VERTEX_DATA, 0	},
{  "VPOS", 3, DXGI_FORMAT_R32G32_FLOAT, 0, sizeof(float)*6,
				D3D11_INPUT_PER_VERTEX_DATA, 0	},
};

これが 5 個なので D3D11_PRIMITIVE_TOPOLOGY_5_CONTROL_POINT_PATCHLIST
で描画します。

Vertex Shader は素通り

struct VS_INPUT {
	float2	vPos0	: VPOS0;
	float2	vC0	: VPOS1;
	float2	vC1	: VPOS2;
	float2	vPos1	: VPOS3;
};
struct VS_OUTPUT {
	float2	vPos0	: VSPOS0;
	float2	vC0	: VSPOS1;
	float2	vC1	: VSPOS2;
	float2	vPos1	: VSPOS3;
};

VS_OUTPUT main( VS_INPUT idata )
{
	VS_OUTPUT	odata;
	odata.vPos0= idata.vPos0;
	odata.vPos1= idata.vPos1;
	odata.vC0= idata.vC0;
	odata.vC1= idata.vC1;
	return	odata;
}


Hull Shader はカーブかラインか区別して異なる TessFactor を設定します。

#define	MAX_POINTS	5

struct VS_OUTPUT {
	float2	vPos0	: VSPOS0;
	float2	vC0	: VSPOS1;
	float2	vC1	: VSPOS2;
	float2	vPos1	: VSPOS3;
};

struct HS_OUTPUT {
	float2	vPos0	: HSPOS0;
	float2	vC0	: HSPOS1;
	float2	vC1	: HSPOS2;
	float2	vPos1	: HSPOS3;
};


struct HS_DATA {
	float	Edge[4]		: SV_TessFactor;
	float	Inside[2]	: SV_InsideTessFactor;
};

HS_DATA func( InputPatch<VS_OUTPUT,MAX_POINTS> ip )
{
	HS_DATA	pdata;
	const float	tf= 8.0;
	const float	lineFlag= -1e4;
	// ラインを区別する
	pdata.Edge[3]= ip[0].vC0.x > lineFlag ? tf : 1.0f;
	pdata.Edge[2]= ip[1].vC0.x > lineFlag ? tf : 1.0f;
	pdata.Edge[1]= ip[2].vC0.x > lineFlag ? tf : 1.0f;
	pdata.Edge[0]= ip[3].vC0.x > lineFlag ? tf : 1.0f;
	// 内部は 2固定
	pdata.Inside[0]= 2.0;
	pdata.Inside[1]= 2.0;
	return	pdata;
}

[domain("quad")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(5)]
[patchconstantfunc("func")]
HS_OUTPUT main(
	InputPatch<VS_OUTPUT,MAX_POINTS> ip,
	uint id : SV_OutputControlPointID
	)
{
	HS_OUTPUT	odata;
	odata.vPos0= ip[id].vPos0;
	odata.vPos1= ip[id].vPos1;
	odata.vC0= ip[id].vC0;
	odata.vC1= ip[id].vC1;
	return	odata;
}


Doman Shader は生成された頂点がどのエッジか区別して、それぞれ異なるパラメータ
補間を適用します。
InsideTessFactor が 2.0 なので、Tessellator で分割されるのはエッジだけです。
上下左右のエッジは

・u が 0.0
・u が 1.0
・v が 0.0
・v が 1.0

で区別することができます。上のどれでもない場合は中心座標です。

例として 1辺だけ TessFactor[0] = 4 の場合を考えます。
このとき生成される頂点の uv は下記の 8点となります。

四隅
(0.0, 0.0)
(1.0, 0.0)
(0.0, 1.0)
(1.0, 1.0)

中心
(0.5, 0.5)

分割で挿入された点
(0.0, 0.25)
(0.0, 0.50)
(0.0, 0.75)

よって u が 0.0 の場合を区別すれば必要なエッジだけ取り出せることがわかります。

#define	CONTROL_POINT	5

struct HS_DATA {
	float	Edge[4]		: SV_TessFactor;
	float	Inside[2]	: SV_InsideTessFactor;
};

struct HS_OUTPUT {
	float2	vPos0	: HSPOS0;
	float2	vC0	: HSPOS1;
	float2	vC1	: HSPOS2;
	float2	vPos1	: HSPOS3;
};

struct DS_OUTPUT {
	float4	vPos	: SV_Position;
};

cbuffer pf {
	float4x4	WVP;
};

// カーブの場合
float2 UVtoPositionB( const HS_OUTPUT p, float t )
{
	float	t2= 1.0-t;
	float4	u= float4( t2*t2*t2, t2*t2* t*3, t2* t* t*3, t* t* t );
	return	 u.x*p.vPos0.xy +u.y*p.vC0.xy +u.z*p.vC1.xy +u.w*p.vPos1.xy;
}

// 直線の場合
float2 UVtoPositionL( const HS_OUTPUT p, float ux )
{
	return	p.vPos0 * (1-ux) + p.vPos1 * ux; // 実際は不要
}

float2 UVtoPosition( const HS_OUTPUT p, float ux )
{
	if( p.vC0.x < -1e4 ){
		return	UVtoPositionL( p, ux );
	}
	return	UVtoPositionB( p, ux );
}

[domain("quad")]
DS_OUTPUT main(
		HS_DATA ip,
		float2 uv : SV_DomainLocation,
		const OutputPatch<HS_OUTPUT,CONTROL_POINT> bpatch
	)
{
	DS_OUTPUT	dout;
	const float	EPC= 0.0f; // 誤差が問題になるなら増やす
	float2	pos= float2( 0, 0 );
	// 各エッジを切り分ける
	if( uv.y >= 1.0-EPC ){
		pos= UVtoPosition( bpatch[0], uv.x );
	}else if( uv.y <= 0.0+EPC ){
		pos= UVtoPosition( bpatch[2], 1-uv.x );
	}else if( uv.x >= 1.0-EPC ){
		pos= UVtoPosition( bpatch[1], 1-uv.y );
	}else if( uv.x <= 0.0+EPC ){
		pos= UVtoPosition( bpatch[3],   uv.y );
	}else{
		pos= bpatch[4].vPos0.xy; // 中心
	}
	dout.vPos= mul( float4( pos.xy, 0, 1 ), WVP );
	return	dout;
}

エッジの切り分けは、四隅の頂点が共有されている点に注意です。
どの uv 値をどのエッジに割り当てるのかは任意で構いませんが、四隅が共有されている
関係上、エッジの並びが連続していなければカーブが不連続になります。

またエッジ単位に Tess Factor のスケールを入れれば、長い辺など必要な場所のみ
より細かく分割するなどの応用ができるでしょう。


前回のアルゴリズムはまだ完全に形状を分割できるとは限らず、いくつか問題が生じる
ケースがあります。

(1) 分割時に対応する頂点が見つけられない場合がある
(2) アウトラインからはみ出さない位置に中心頂点を配置できない場合がある

このような状態に陥った場合、対象のプリミティブのエッジを分割して
頂点(アンカー)を追加することで対処可能です。

シェーダーを書き出していて気がつきましたが、これ GeometryShader だけでも実現
できそうですね。GeometryShader には 5 頂点入力がないので、頂点数さえ合わせれば
ハードウエアで実行できそうです。


関連エントリ
Direct3D11/DirectX11 (14) GPU を使ったアウトラインフォントの描画の(2)
Direct3D11/DirectX11 (13) TessFactor とシェーダーリンクの補足など
Direct3D11/DirectX11 (12) テセレータのレンダーステート他
Direct3D11/DirectX11 (11) 互換性とシェーダーの対応表など
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver


Direct3D 11 の Tessellator を使って、GPU だけでアウトラインフォントの描画を
行ってみました。
↓左からそれぞれ TessFactor (分割数) = 1, 2, 12

tess font 20

改良しました。

(1) 事前の変換処理を自動化した。
(2) isoline ではなく quad プリミティブを使ったテセレートを行っており、
  必要に応じて任意のエッジをテセレートできる。

まだ (1) がやっとなのであまり最適化していません。

前回
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など

tess font 21

↑左が前回のもの。2点 X-Y を挿入し、赤 (B-C-X-Y) と 緑 (D-E-X-Y) の 2つの
プリミティブに分解。

右が今回のもの。B-C-D-E で 1つの quad で表現され、必要なエッジのみ分割。
中央の X の位置は事前に求めておく


塗りつぶしたフォントの描画のために、事前にプリミティブに分割します。
思ったよりも難しい処理で、特に細長い三角形ができてしまうとアウトラインから
はみ出します。

tess font 22

↑では波線が本来のカーブです。A の上のエッジが沈み込んで対角線に重なっています。
カーブが極端になると対角線エッジの直線部分が表に出てしまいます。
(前回はこれをうまく解決できなかったので手作業だった)

いろいろと試行錯誤した結果がこれ↓です。

tess font 24
↑ましになったもの。

元↓はこちら。

tess font 23
↑だめな分割 (はみ出ているのはバグ)。

(白線=カーブ、青線=直線、ピンクの点=中心の頂点、水色の点=コントロールポイント)


(1) 角度が一番開いた頂点を求める。
(2) (1) の頂点から直線を引ける他の頂点を探す。
  (エッジと交差しない、かつ隣接でない、かつ文字の外側ではない)
(3) (2) の条件を満たす頂点の中で一番近い頂点と結ぶ。エッジを挿入して領域を分ける
(4) 4 頂点以下の領域ができたら取り除く。

すべての領域が取り除かれるまで再帰的に繰り返します。
比較的細長い領域への分割を避けてぶつ切りになります。

内外判定のために方向をそろえる必要があるため挿入したエッジは両面分必要です。

循環している可能性があるので、(3) で単一のエッジを挿入しても 2つの領域が
できるとは限りません。

(4) の場合くりぬいた領域が裏返しで繋がっている可能性があるため、4頂点以下の
パスのループでも閉じているかどうか判定が必要です。(対角線の可視など)
上の「だめな分割」の図は失敗しています。

領域毎に、アウトラインをじゃましない位置に中心座標を配置します。(上の図のピンクの点)
ただしアンカーが少なくカーブが極端な場合、最適な中心座標は求まらない可能性が
あります。まだ完全には解決していません。

tess font 25
↑ TessFactor = 8 のワイヤー表示です。


●データの準備

xml で対応ツールが比較的多いことと参照しやすいため、SVG / FXG フォーマットを
使用しています。
Scalable Vector Graphics (SVG) 1.1 Specification

含まれるカーブの種類は複数あり、直線部分も Line で出力されるので、変換時に
情報を保存しておきます。
現在エッジ情報は 座標ペア × 4 (Cubic Bezier時) で、Arc は未対応です。

v0.xy, c0.xy, c1.xy, v1.xy

Line 時は c0.xy, c1.xy は未使用。c0.x に範囲外の値を入れて、シェーダー内で
未使用(直線)かどうか判断できるようにしています。

(1) カーブの種類をを考慮してパスデータを 4 パラメータに変換
(2) エッジの方向をノーマライズする

(2) は内外判定のため。進行方向 v0 → v1 に向かって右側が必ず文字の外側など、
どちらかに統一されていれば OK。

次回に続きます。


関連エントリ
Direct3D11/DirectX11 (13) TessFactor とシェーダーリンクの補足など
Direct3D11/DirectX11 (12) テセレータのレンダーステート他
Direct3D11/DirectX11 (11) 互換性とシェーダーの対応表など
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver


●TessFactor と方向の対応

テセレータによる分割数は Hull Shader で指定します。

float	Edge[4]  : SV_TessFactor;
float	Index[2] : SV_InsideTessFactor;

quad の場合上記 6パラメータで指定します。このとき各 TessFactor とテセレータ
出力の uv 値との対応は下記の通り。

                    u          v
SV_TessFactor[0]    0.0        0~1.0
SV_TessFactor[1]    0~1.0     0.0
SV_TessFactor[2]    1.0        0~1.0
SV_TessFactor[3]    0~1.0     1.0

例えば u方向を右向き → 、v方向を上向き ↑ として 2D でレンダリングすると
TessFactor[0][1][2][3] は 左、下、右、上 の順番となります。

 (0,1)  [3]   (1,1)
  ┌─────┐
  │     │
  │     │
 [0]│     │[2]
  │     │
  │     │
  └─────┘
 (0,0)  [1]   (1,0)

InsideTessFactor は下記の通り。

SV_InsideTessFactor[0] uの分割 (u=0~1.0)
SV_InsideTessFactor[1] vの分割 (v=0~1.0)


● Dynamic Shader Linkage の補足

Dynamic Shader Linkage には 2つの大きな変更があります。

(1) シェーダー内の命令の分岐先を外部から切換えられるようになった
(2) HLSL の記述で java 風の class 定義ができるようになった

表面的には (2) の方が大きいように見えますが、本来の目的は動的シェーダーリンク
という名前の通り (1) の方です。
むしろ (1) を実現するために、さまざまな候補の中から (2) の実装方法を選択した
だけだといえるかもしれません。
(詳しくはこちら Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage)


シェーダーによって、ハードウエアのレンダリング動作を自分で記述することが
できるようになりました。
自由度が高まる反面、動作の種類毎に個別の異なるシェーダープログラムを用意
しなければならないという問題も生じました。

例えばライティングアルゴリズムによって数種類。基本的なものだけでも

・環境光源
・スカイライト
・平行光源
・点光源
・スポットライト

等複数存在します。
複数光源を照射する場合、オブジェクトの配置位置によって光源の組み合わせが変わる
かもしれません。例えば屋外だと平行光源が必要ですが屋内だと必要なかったりします。

・屋外用光源シェーダー
 太陽平行光源+環境スカイライト+エフェクト点光源

・屋内用光源シェーダー
 環境光源+点光源×1~4

など。

マテリアルによってはテクスチャをレイヤーで複数重ねたり、それぞれのブレンド式
を変えるかもしれません。
ノーマルマップやレリーフマップを持つ場合、付随して頂点に必要な情報も増えます。

他にも各レイヤー毎に独立した Texcoord (uv) を持たせるのか、テクスチャによって
は共有するのか、パラメータで生成するのかなど。

ゲームで実際に使うことを考えると、法線マップを圧縮したり、アルファチャンネルの
用途をマテリアルによって使い分けたり、場面によって精度を落としたり復号したり、
半透明やテクスチャアルファによる抜きの扱いでシェーダーを分けたり。
影のレンダリングのありなしや、ライトスペースの求め方の違い、フィルタリングの
種類による変更など。

VertexShader でもアニメーションによって、頂点ウエイトの個数、ビルボード化、
ジオメトリインスタンシングへの対応など種類が必要です。

これらをすべて自由に組み合わせられるような汎用的な描画の仕組みを作ると
シェーダーの数は爆発的に増えます。

もちろんシェーダープログラムも外部の情報へアクセスはできますし、分岐やループ
命令もありました。しかしながらシェーダーの組み合わせをによるバリエーション数を
減らすために用意された機能ではなかったことが問題でした。

マテリアル(描画命令)単位で大きな処理の切換えをしたいだけなのに、コード内で
分岐を行うのは少々大げさでです。
最適化の妨げになるし条件判断コードの実行によるパフォーマンスへの影響もあった
ので、どちらを取るか選択を迫られます。
(シェーダーを切換えるための負荷が減るメリットはあります)

Direct3D 11 (Shader Model 5.0) の Dynamic Shader Linkage の導入は
これらの問題を解決するために設けられたものです。
シェーダーのバリエーションを減らして管理しやすくすることが目的で、プログラム内
の命令ジャンプの飛び先を外部から切換えることが可能になりました。

分岐切り替えの粒度も不必要に細かくなく適切で、レンダリング命令単位(マテリアル単位)
で決められるし、その条件判断もシェーダーの外部で一度だけやればいいわけです。

期待が大きい反面、気になる点もあります。

・動的リンクで切換え可能なコードは予め 1つのシェーダーにコンパイルされている必要がある
・最適化への影響

オブジェクトのインスタンスも単なる Buffer へのマッピングに過ぎず、すべて静的に
決まってなければなりません。
非常に巨大な単一のシェーダープログラムができあがる可能性があります。

分岐先の決定は描画時まで遅延されるため、その分 HLSL コンパイラでできる最適化は
減少します。間接ジャンプはインライン化を阻害しますし、結局サブルーチン分の
消費レジスタも予めアロケートしておかなければならないのではないか、との疑問も
生じます。

シェーダーの単なる分岐と本当に違うのか、効果があるのかどうか、
動的リンクによるパフォーマンスの影響はどの程度なのか、
実ハードが出てからあらためて検証する必要がありそうです。

ちなみに D3D11 付属の HLSL コンパイラでは、class 定義だけなら ShaderModel 4.0
以前をターゲットにしても使えます。あくまで表記上の違いだけなので、できることは
今までと変わりません。
動的な飛び先の切り替え (interface 経由の呼び出し) は ShaderModel 5.0 以降のみ
となります。


関連エントリ
Direct3D11/DirectX11 (12) テセレータのレンダーステート他
Direct3D11/DirectX11 (11) 互換性とシェーダーの対応表など
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver



●レンダーステート

テセレータにはレンダーステートがありません。
ID3D11DeviceContext::TSSet~ 等の命令は一切無し。
その代りになるのが Hull Shader のたくさんある attribute です。

[domain("tri")]
[partitioning("fractional_even")]
[outputtopology("triangle_ccw")]
[outputcontrolpoints(4)]
[patchconstantfunc("func")]
float4 main(
	InputPatch<VS_OUTPUT,MAX_POINTS> ip,
	uint id : SV_OutputControlPointID
	) : TSPOS
{
   ...
}

HullShader の attribute は単なるヒントではなく、Tessellator の動作そのものを
決定しています。
テセレータの動作を変えるにはシェーダーまるごと置き換える必要があり、レンダー
ステートとシェーダーが一体化しているともいえます。

今までのシェーダーからは少々特殊ですが、管理するオブジェクトが減るので扱いは
楽です。他のシェーダーでも、シェーダーとペアで使うことがわかりきったステートなら
シェーダーに含めてしまって構わないのかもしれません。


●Effect

ShaderModel 5.0 にはまだ Effect ( .fx, fx_5_0 ) が無いようです。
現在のベータ SDK では、core API を使って各シェーダーを個別に生成したり管理する
必要があります。
Effect (ID3D10Effect) を core API 化してしまった Direct3D10 と比べると
何となくトーンダウンしているようにも見えます。

これが方針転換なのか、単に未完成で beta に含まれていないだけなのかまだわかりません。
シェーダー数が増えて大変そうだし後者のような気もします。
だけど Shader Compiler の分離もあるので、D3D10 の反省を踏まえての仕様変更の可能性もあります。
ツールやゲームエンジン等の設計にも関わってくるので、今後どうなるのか気になるところです。


●Tessellator と Triangle patch

Tessellator が扱える patch のタイプには isoline tri quad の 3種類あります。
(Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など)

quad / isoline はこれまでなんどか取り上げたとおり、テセレータは
float2 の DomainLocation (uv) を出力します。
tri の場合は 3次元の uvw を返します。

この u v w はそれぞれ、Triangle の 3頂点に対する割合(距離)を示して
います。(barycentric coordinates)

float3 v1, v2, v3;
pos= v1*uvw.x + v2*uvw.y + v3*uvw.z;

↓左から TessFactor = 222-2、333-3、444-4

tess tri

中 (InsdeTessFactor) を 2に固定して外側だけ割った場合。
↓左から TessFactor = 111-2、888-2、181-2

tess tri

右端(181-2)は、1 つのエッジだけ 8分割したものです。
以前アウトラインフォントの描画では quad あたり 1辺の分割に限定して isoline
を使いました。事前処理でこのようなプリミティブにきちんと分解できれば、
一度に複数のエッジを分割対象とすることも可能です。
まだまだ効率化はできるでしょう。


関連エントリ
Direct3D11/DirectX11 (11) 互換性とシェーダーの対応表など
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver



・D3D11 の方が対応ハードウエアのカバー範囲が広い。
・D3D10 専用ソフトは動かなくても、D3D11 対応ソフトなら動く可能性がある。
・逆に D3D11 対応ソフトは、D3D10 専用ソフトよりも絵がきれいとは限らない。

シェーダー対応をまとめるとこんな感じでしょうか。

              FIXED  SM1  SM2  SM3  SM4  SM5 
DirectX7/D3D7   ○   ×   ×   ×   ×   ×
DirectX8/D3D8   ○   ○   ×   ×   ×   ×
DirectX9/D3D9   ○   ○   ○   ○   ×   ×
DirectX/D3D10   ×   ×   ×   ×   ○   ×
DirectX/D3D11   ×   ×   △   ○   ○   ○

(SM1~5 は ShaderModel1.0~5.0)

Direct3D11 で ShaderModel2.0 が △ なのは、ShaderModel2.0 の固定機能が使えない
可能性があるからです。
例えば 2.0 世代のフォグはハードの固定機能で、RenderState で設定していました。
D3D11 にはこの手のステートがないため同等のブレンドを実現するためにシェーダーに
追加コードが必要です。
その分 Direct3D9 以前を使うよりも速度が落ちる可能性があるからです。


Direct3D10 以降、GeometryShader や HullShader + Tessellator + DomainShader
など、注目すべき新機能がジオメトリに移ってきました。
DirectX8 から始まったシェーダーの拡張は、しばらくはピクセルが中心だったといえます。
固定少数だったピクセルが世代を重ねて完全な 32bit になり、テクスチャルックアップも
制限が無くなり、定数レジスタが増えて実行可能命令数も増加しました。

PixelShader1  固定少数
PixelShader2  浮動小数 16~24bit
PixelShader3  浮動小数 32bit、動的分岐
PixelShader4  Unified化

必要な面積しか演算しなくて済むので効率がよいし、見た目の効果も大きいし、
大量の並列化による演算は CPU には真似ができない分野です。
GPU の力を一番実感しやすかったのかもしれません。

Shader の区別が無くなるところまで行き着いた今、流れはジオメトリに向いています。
単一の描画パイプラインの中で、頂点の生成やプリミティブの削除など自由自在です。
CPU の追い上げもありますが、GPU ならではの活用やさまざまな技法がこれから
生まれてくるものと期待できます。


関連エントリ
Direct3D11/DirectX11 (10) テセレータの補間
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分




isoline を使うと線分の分割だけでなく 2次元方向にも数を増やすことが出来ます。
おそらく髪の毛の表現などに使われる機能だと考えられます。
uv の u 方向のみライン描画されるので、u が毛の滑らかさ(丸み)、v が密度(本数)
を表します。

出力トポロジの line は domain("isoline") の場合のみ使用できるようです。
前回の記事で tri/quad の出力にも line を含ませていたのは間違いでした。
訂正致します。


テセレータを使うと、かなり簡単に頂点を増やすことができます。
特に isoline は uv 方向に任意に頂点を生成できるため使い勝手が良さそうです。
outputtopology を point にして GeometryShader でオブジェクトを配置すれば、
草むらなどの表現に使えるかもしれません。LOD も容易です。


テセレータは partitioning の指定によってテセレータの各段階を補間できるように
なります。一番シンプルな isoline の 1 line だけで調べてみました。

共通事項として、TessFactor のどれかに 0 が含まれているとプリミティブは表示
されないようです。無関係の固定図形を GeometryShader で描画している場合も
出力されないので、描画が完全に捨てられていると判断できます。

integier の場合、TessFactor が 1.0 の時分割数が 1 です。
isoline で頂点のみ出力すると両端の 2点が表示されます。(点を '*' で表します)

1.0=   *              *

TessFactor= 2.0 の時、線分は 2分割されて 3頂点が表示されます。

2.0=   *      *       *

同じように各 partitioning タイプ毎に TessFactor を変えて調べてみました。

fractional_odd
1.0= *              * 1分割
1.5= * *          * *
2.0= *  *        *  *
2.5= *   *      *   *
3.0= *    *    *    * 3分割

fractional_even
1.0= *       *       *
2.0= *       *       * 2分割
2.5= *      ***      *
3.0= *     * * *     *
3.5= *    *  *  *    *
4.0= *   *   *   *   * 4分割

integer == pow2
1.0= *               * 1分割
1.5= *       *       * 切り上げ
2.0= *       *       * 2分割
2.5= *    *     *    * 切り上げ
3.0= *    *     *    * 3分割
4.5= *   *   *   *   * 切り上げ
4.0= *   *   *   *   * 4分割

fractional_odd は奇数の時が基準です。
1.0 で 1分割、3.0 で空間が 3分割されており、その間は補間するように頂点が
移動しています。

fractional_even も同じように偶数時が基準となっています。
2分割と 4分割の中間の図形が生成されています。

integer では中間状態はなく、常に整数値で分割された値になります。
ここで興味深いのは、integer の TessFactor は切り捨てではなく切り上げになる
ことです。1.0 を少しでも超えると 2分割相当となります。

この挙動は他の fractional_even , fractional_odd と見比べると納得できます。
間を補間する場合は、1.0 を少しでも超えると補間のための頂点が生成されて移動を
始めるからです。

今回のテストでは pow2 の動作は integer と同じ結果で違いを発見できませんでした。

tess quad odd

上の図は、domain("quad") で partitioning("fractional_odd") の場合の様子を
表示したものです。
それぞれ左上から TessFactor = 1.0、1.5、2.0、3.0 を表しています。

isoline の場合と同じように、quad でも 1.0(1分割) と 3.0(3分割) の間が補間
されていることがわかります。
またその動きも 2次元になっているだけで、基本的には isoline と変わりません。
両端から生成された線分が次の分割状態に近づくよう中心に徐々に移動しています。


テセレータの挙動は想像よりもずっとわかりやすいものでした。テセレータ部だけ
固定機能と言われていたため、もっと決まった動作しかできないかと思ってましたが
HullShader DomainShader のおかげで十分な自由度もあります。
正直かなり使いやすいと思います。

CPU の core 数も増えて、CPU と GPU の違いも少なくなりつつあります。
複雑で特別な仕様の GPU や API をいちいち覚えるくらいなら、必要な機能だけ
CPU で直接書いた方が速いんじゃないかと思ってましたが見直しました。


関連エントリ
Direct3D11/DirectX11 (9) テセレータによるアウトラインフォントの描画など
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver



●Tessellator のタイプ

Tessellator の出力には 3種類のタイプがあります。

[domain(type)]:
 isoline  TessFactor[2]                           出力 point line
 tri      TessFactor[3]   InsideTessFactor[1]     出力 point line triangle
 quad     TessFactor[4]   InsideTessFactor[2]     出力 point line triangle

2008-11-17追記:間違いを修正しました。上記赤字と、tri/quad では line を出力できませんでした。

quad, tri はそれぞれ四角パッチ、三角パッチを意味しています。
isoline は面を均等に割った 2次元頂点を出力するようです。
TessFactor[1] が 1.0 の場合、線分の分割に相当します。

例えば isoline で、TessFactor=8,4 を与えると下記の点を出力します。

isoline point

Tessellator が出力するプリミティブの形状は次の4種類です。

[outputtopology(type)]:
 point
 line
 triangle_cw
 triangle_ccw

これらは Hull Shader のアトリビュートで指定します。
出力トポロジの影響を直接受けるのは Geometry Shader 以降ですが、その設定も
Domain Shader ではなく HullShader が行うので注意。

ちなみに DomainShader は、プリミティブの形状 (outputtopology) を判別する
手段がありません。
DomainShader は TessFactor を参照できるため、上の domain のみ指定する必要
があります。

isoline では triangle を出力できません。
line を指定すると、単なる横線が複数出力されました。


●TessFactor の種類

partitioning は TessFactor による分割方法を指定します。

[partitioning(type)]:
 integer
 fractional_even
 fractional_odd
 pow2

fractional だと、TessFactor が実数値の場合間を補間します。
LOD のつながりがよりスムーズになると考えられます。

outputtopology も、partitioning もマニュアルに書いてあることと違います。
まだまだ間違いが多いようです。


●アウトラインフォントの描画

テセレータパイプラインは、HullShader と DomainShader のおかげでかなり自由度が
高くなっています。固定機能の制限は小さく、さまざまな応用が考えられます。

以前「3D だけでなく、ベクタフォントを GPU で直接描画するなど 2D 面でも応用できる
かもしれません。」
などと書いてしまったので実際にやってみました。

tessellator font step 1
tessellator font step 8

拡大とワイヤー表示は次の通り

tessellator font step 8
tessellator font wire

実際の補間は DomainShader が行っているため、分割したポリゴンのエッジだけ
細分化することは思ったより簡単にできそうです。
quiad や triangle で特定のエッジだけ割っても良いのですが、内部に出来た頂点が
無駄になるし、割ったエッジに影響が出ないよう一点に集めないといけないので
少々複雑です。

isoline があるので、テセレータの段階では輪郭をそのまま割るだけにします。
ポリゴン化は GeometryShader で行います。

簡単にするため、データは前処理で専用のものを用意します。
3次ベジェ のアウトラインを使っています。

tess_font point

各区間、A-B や B-C はそれぞれ 2点の頂点座標(アンカー)+ハンドル2点 で表現
できます。各区間を 4点の制御座標でデータ化します。
このとき隣接するアンカーポイント(頂点)は共有可能です。

A-B :  頂点A, 制御点A0, 制御点A1, 頂点B
B-C :  頂点B, 制御点B0, 制御点B1, 頂点C


これをそのまま D3D11_PRIMITIVE_TOPOLOGY_4_CONTROL_POINT_PATCHLIST
で渡し、domain("isoline")、outputtopology("line") で描画すれば容易にアウトラインの
線描画ができます。DomainShader でベジェカーブを求めるだけです。
フォントのアウトラインそのままで追加情報は不要です。


塗りつぶしは少々手間がかかります。上図の X, Y のように前処理で描画用の
追加点が必要です。

A-B は A-X-B の 3角形、B-C は B-X-Y-C の 4角形を描画します。
処理を簡単にするため、A-X-B は X が2頂点重なってると見なしてすべて四角形で行います。

これらの追加頂点を分割面 (A-X-B や B-X-Y-C) 毎に保持し、GeometryShader まで
情報が届くようにします。

必要な座標は 2次元 x,y のみです。
float4 にすると z,w にもう 1つ座標を入れられます。
アンカーポイントは共有される可能性があるため、面の情報はハンドル(制御点)側の
頂点 zw に入れます。

B-C の例、4頂点

 pointB.xy = 頂点B
 pointB.zw = 未使用

 ctrlB0.xy = 制御点B0
 ctrlB0.zw = 追加の頂点、追加点X

 ctrlB1.xy = 制御点B1
 ctrlB1.zw = 追加の頂点、追加点Y

 pointC.xy = 頂点C
 pointC.zw = 未使用

頂点フォーマットは単純な float4 のみ

D3D11_INPUT_ELEMENT_DESC	ldesc[]= {
{ "VPOS", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, 0,
	D3D11_INPUT_PER_VERTEX_DATA, 0	},
};
iDevice->CreateInputLayout( ldesc, 1, codeblob->GetBufferPointer(),
				codeblob->GetBufferSize(), &iLayout );

VertexShader はデータにスケーリング補正してるだけでそのまま流します。

// vs.hlsl
struct VS_INPUT {
	float4	vPos	: VPOS;
};

float4 main( VS_INPUT idata ) : VSPOS
{
	float4	pos= idata.vPos;

	const float	SCALE= 0.08;
	const float2	CENTER= float2(137,212);
	pos-= CENTER.xyxy;
	pos*= SCALE.xxxx;
	return	pos;
}

HullShader もテセレータの設定のみ。
分割は線分で行うので domain("isoline") を使い、GeometryShader で 2点のつながり
が必要なので出力は outputtopology("line")。
コントロールポイントはそのままスルーで DomainShader に任せます。

// hs.hlsl
struct VS_OUTPUT {
	float4	vPos	: VSPOS;
};

struct HS_DATA {
	float	Edge[2]	: SV_TessFactor;
};

HS_DATA func()
{
	HS_DATA	pdata;
	pdata.Edge[0]= 8.0;	// ここで分割数の決定、値が大きいとなめらか
	pdata.Edge[1]= 1.0;
	return	pdata;
}

[domain("isoline")]
[partitioning("integer")]
[outputtopology("line")]
[outputcontrolpoints(4)]
[patchconstantfunc("func")]
float4 main( InputPatch<VS_OUTPUT,4> ip,
	uint id : SV_OutputControlPointID ) : TSPOS
{
	return	ip[id].vPos;
}

DomainShader で分割点のベジェ補間を行い、GeometryShader に渡すための頂点を
構築します。
追加点は 2番目と 3番目の zw に入っているので、それらも取り出して頂点に入れます。
uv は Geometry Shader で線分の最後かどうか判断するために使います。

// ds.hlsl
struct HS_DATA {
	float	Edge[2]		: SV_TessFactor;
};

struct HS_OUTPUT {
	float4	vPos	: TSPOS;
};

cbuffer perFrame {
	float4x4	WVP;
};

float4 Bezier0( float t )
{
	float	t2= 1.0-t;
	return	float4( t2*t2*t2, t2*t2* t*3, t2* t* t*3, t* t* t );
}

float2 UVtoPosition( const OutputPatch<HS_OUTPUT,4> p, float2 uv )
{
	float4	u= Bezier0( uv.x );
	return	 u.x*p[0].vPos.xy
		+u.y*p[1].vPos.xy
		+u.z*p[2].vPos.xy
		+u.w*p[3].vPos.xy;
}

struct DS_OUTPUT {
	float4	nPos[2]	: NPOS;
	float	uv	: UV;
	float4	vPos	: SV_Position;
};

[domain("isoline")]
DS_OUTPUT main(
	HS_DATA ip,
	float2 uv : SV_DomainLocation,
	const OutputPatch<HS_OUTPUT,4> bpatch )
{
	DS_OUTPUT	dsout;

	float2	pos= UVtoPosition( bpatch, uv );
	dsout.vPos= mul( float4( pos.xy, 0, 1 ), WVP );

	// 追加点 2つを各頂点に埋め込む
	dsout.nPos[0]= mul( float4( bpatch[1].vPos.zw, 0, 1 ), WVP );
	dsout.nPos[1]= mul( float4( bpatch[2].vPos.zw, 0, 1 ), WVP );

	dsout.uv= uv.x; // Geometry Shader で使う
	return	dsout;
}

GeometryShader は頂点情報から Triangle を作ります。

// gs.hlsl
struct DS_OUTPUT {
	float4	nPos[2]	: NPOS;
	float	uv	: UV;
	float4	vPos	: SV_Position;
};

[maxvertexcount(6)]
void main(
	line DS_OUTPUT input[2],
	inout TriangleStream<DS_OUTPUT> stream )
{
	stream.Append( input[0] );
	stream.Append( input[1] );

	DS_OUTPUT	dout2= input[0];
	dout2.vPos= input[0].nPos[0];
	stream.Append( dout2 );

	stream.RestartStrip();

	if( input[1].uv >= 0.9998f ){
		DS_OUTPUT	dout3= input[1];
		dout3.vPos= input[0].nPos[1];

		stream.Append( input[1] );
		stream.Append( dout2 );
		stream.Append( dout3 );
		stream.RestartStrip();
	}
}

uv で判断しているのは最後だけ 1ポリゴン追加する必要があるためです。
下図でいう 4 番。

tess font

描画自体は簡単にできました。
元となるデータを準備する方が大変です。
中心に位置する追加点を求める何らかの手段が必要となりそうです。


関連エントリ
Direct3D11/DirectX11 (8) テセレータの動作
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver


●固定機能テセレータ

DomainShader で、Tessellator の出力 uv のみを WIRE 描画したものです。

TessFactor = 1, 1, 1, 1
InsideTessFactor = 1, 1
Tessellator1111_11

TessFactor = 3, 3, 3, 3
InsideTessFactor = 3, 3
Tessellator3333_33

TessFactor = 3, 3, 3, 3
InsideTessFactor = 8, 8
Tessellator3333_88

パッチ毎に分割数が異なる可能性があるため内部とエッジの係数を個別に指定します。
上の 3333-33 と 3333-88 は繋がります。
固定機能であるテセレータは、TessFactor に応じて上記の uv パターンを生成し、
必要分の頂点を出力しているだけだと考えられます。
実際の曲面を作るのは HullShader と DomainShader の仕事です。

struct DS_OUTPUT {
	float4	vPos	: SV_Position;
};

[domain("quad")]
DS_OUTPUT main(
		HS_POINT_DATA ip,
		float2 uv : SV_DomainLocation,
		const OutputPatch<HS_OUTPUT,4> bpatch )
{
	DS_OUTPUT	dout;
	uv+= float2( -0.5, -0.5 );
	uv*= float2( 0.5, 0.5 );
	dout.vPos= float4( uv.x, -uv.y, 0, 1 );
	return	dout;
}


●ベジェ

実際にシンプルなベジェ曲面を生成してみます。
単純化するため入力はすべてコントロールポイントとします。

Tessellator32

VertexShader は 16個のコントロールポイント定義のみ。
// vs.hlsl
float4 main( uint vid : SV_VertexID ) : VSPOS
{
	const float4	v[]= {
		{	-2,  2,		2,	1,	},
		{	-1,  2,		0,	1,	},
		{	 1,  2,		0,	1,	},
		{	 2,  2,		2,	1,	},
		{	-2,  1,		0,	1,	},
		{	-1,  1,		0,	1,	},
		{	 1,  1,		0,	1,	},
		{	 2,  1,		0,	1,	},
		{	-2, -1,		0,	1,	},
		{	-1, -1,		0,	1,	},
		{	 1, -1,		0,	1,	},
		{	 2, -1,		0,	1,	},
		{	-2, -2,		2,	1,	},
		{	-1, -2,		0,	1,	},
		{	 1, -2,		0,	1,	},
		{	 2, -2,		2,	1,	},
	};
	return	v[vid];
}


HullShader は TessFactor 設定以外に特にやることがありません。
VS からの出力をスルーし、もう 1つは TessFactor を定義します。

// hs.hlsl
struct VS_OUTPUT {
	float4	vPos	: VSPOS;
};

struct HS_OUTPUT {
	float3	vPos	: TSPOS;
};

struct HS_DATA {
	float	Edge[4]		: SV_TessFactor;
	float	Inside[2]	: SV_InsideTessFactor;
};

HS_DATA func(
	InputPatch<VS_OUTPUT,16> ip,
	uint patchID : SV_PrimitiveID )
{
	HS_DATA	pdata;
	pdata.Edge[0]= 32.0;
	pdata.Edge[1]= 32.0;
	pdata.Edge[2]= 32.0;
	pdata.Edge[3]= 32.0;
	pdata.Inside[0]= 32.0;
	pdata.Inside[1]= 32.0;
	return	pdata;
}

[domain("quad")]
[partitioning("integer")]
[outputtopology("triangle_cw")]
[outputcontrolpoints(16)]
[patchconstantfunc("func")]
HS_OUTPUT main(
	InputPatch<VS_OUTPUT,16> ip,
	uint id : SV_OutputControlPointID,
	uint patchID : SV_PrimitiveID )
{
	HS_OUTPUT	odata;
	odata.vPos= ip[id].vPos.xyz; // そのまま渡すだけ
	return	odata;
}


DomainShader で、生成された頂点の実際の座標を求めます。
同時に View Projection の変換もします。

// ds.hlsl
struct HS_DATA {
	float	Edge[4]		: SV_TessFactor;
	float	Inside[2]	: SV_InsideTessFactor;
};

struct HS_OUTPUT {
	float3	vPos	: TSPOS;
};

struct DS_OUTPUT {
	float4	vPos	: SV_Position;
};

cbuffer perFrame {
	float4x4	WVP;	// View Projection
};

float4 Bezier0( float t )
{
	float	t2= 1.0-t;
	return	float4( t2*t2*t2, t2*t2* t*3, t2* t* t*3, t* t* t );
}

float3 UVtoPosition( const OutputPatch<HS_OUTPUT,16> p, float2 uv )
{
	float4	u= Bezier0( uv.x );
	float4	v= Bezier0( uv.y );
	float3	r;
	r = v.x*(u.x*p[ 0].vPos+u.y*p[ 1].vPos+u.z*p[ 2].vPos+u.w*p[ 3].vPos);
	r+= v.y*(u.x*p[ 4].vPos+u.y*p[ 5].vPos+u.z*p[ 6].vPos+u.w*p[ 7].vPos);
	r+= v.z*(u.x*p[ 8].vPos+u.y*p[ 9].vPos+u.z*p[10].vPos+u.w*p[11].vPos);
	r+= v.w*(u.x*p[12].vPos+u.y*p[13].vPos+u.z*p[14].vPos+u.w*p[15].vPos);
	return	r;
}

[domain("quad")]
DS_OUTPUT main(
	HS_DATA ip,
	float2 uv : SV_DomainLocation,
	const OutputPatch<HS_OUTPUT,16> bpatch )
{
	DS_OUTPUT	dout;
	float3	pos= UVtoPosition( bpatch, uv );
	dout.vPos= mul( float4( pos.xyz, 1 ), WVP );
	return	dout;
}


呼び出し側。GeometryShader は使用していません。

iContext->RSSetState( iRS_WIREFRAME );
iContext->VSSetShader( iVS, NULL, 0 );
iContext->HSSetShader( iHS, NULL, 0 );
iContext->DSSetConstantBuffers( 0, 1, &iPerFrame );
iContext->DSSetShader( iDS, NULL, 0 );
iContext->PSSetShader( iPS, NULL, 0 );
iContext->IASetPrimitiveTopology(
		D3D11_PRIMITIVE_TOPOLOGY_16_CONTROL_POINT_PATCHLIST );
iContext->Draw( 16, 0 );



関連エントリ
Direct3D11/DirectX11 (7) テセレータの流れの基本部分
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver


PS3
oga at 23:12
● Yellow Dog Linux

PS3 Linux インストールでは何度も世話になった FIXSTARS
あの Yellow Dog Linux を買収!

フィックスターズ、米Terra Soft Solutionsから「Yellow Dog Linux」を含む全事業を買収

YDL は PS3 対応 Linux として話題になったものです。
個人的にかなり驚いたニュースでした。


● LittleBigPlanet

はまっています。きっと正月越せる。
非常に良くできているだけに、気になる点もいくつか。

・スコア?が増えない

 インフォプラネットの自分の上にある3つの数値。
 プレイ、クリエイト、シェア がずっとゼロのままです。
 ベータの時はたまに増えたり減ったりしていた気がします。
 製品版になったらずっとゼロ。

・タグが付かない

 アップロードしたステージにタグが付かなくなりました。
 発売直後しばらくは、ちゃんとタグが反映されていた気がします。
 最近はさっぱり。

・クリエイトモードのツール設定

 ツールを配置した直後のプロパティで設定した内容が保存されない。
 一端選択ツールに戻って、選択し直してから□ボタンで設定し直すと反映される。
 最初チュートリアルではまります。ベータ時から変わってない。

・クリエイトモードの床からはがすで、関係ないところもばらばらになる

 複数のパーツで構成されたオブジェクトを床にのり付けする。
 その後オブジェクトを床からはがすと、再生時に各パーツもはがれた状態になってる。
 エディット中の選択ツールではくっついたままに見えるので、一端すべての
 パーツをはがす→のり付け し直さないと元には戻りません。


● HDD交換

PS3 の内蔵 HDD を交換しました。
60GB モデルと 20GB モデルの 2台とも 320GB へ換装です。
2.5インチ 9.5mm SATA 対応の HDD が使用できます。

HDD の内容は、PS3 本体が持っているバックアップ機能を使えば、
セーブデータなどもそのまま移行することが出来ます。
この辺は Linux インストール時に散々やったので慣れたもの。

バックアップは XMB のメニューから

 設定 → 本体設定 → バックアップユーティリティー

・バックアップ時の注意

 バックアップを取れるだけの、USB 接続の大容量メディアが必要です。
  例えば USB の外付け HDD や、USB メモリ、カードリーダーなど。
  FAT32 フォーマットのみ。60GB モデルはカードリーダー内蔵なので、
  SD/CF/MS 等のメモリカードも直接使えます。
  HDD タイプの iPod も使えるかもしれません。

 バックアップやリストアは結構時間がかかります。
  再ダウンロード可能な体験版やムービー、ゲームのインストールデータなどは
  あらかじめ消しておいた方が良いです。

 複数のメディアにとっておけるなら、2つバックアップしておくと確実です。



● ComputeShader 用の Append Buffer 作成

何度も DebugLayer に怒られつつテストしてみました。

Buffer
 D3D11_USAGE_DEFAULT
 D3D11_BIND_UNORDERED_ACCESS
 D3D11_RESOURCE_MISC_BUFFER_STRUCTURED
 StructureByteStride= 4
UAV
 DXGI_FORMAT_UNKNOWN
 D3D11_BUFFER_UAV_FLAG_APPEND

AppendStructuredBuffer<uint>	a;
[numthreads(1,1,1)]
void main( uint3 tid : SV_DispatchThreadID )
{
	a.Append( tid.x );
}

バッファ内容の変化が観測できず、まだ動作がつかめていません。
うまく動いていないところや使い方の疑問点もあります。

・ID3D11DeviceContext::CSSetUnorderedAccessViews() に 2つ以上の UAV を渡すと
 シェーダーが落ちる。サンプル HDRToneMappingCS11 では 1つしか渡していない。
・CSSetUnorderedAccessViews() の 3 番目の引数の意味がわからない。
 サンプルでは 2番目のリストのアドレスを UINT* で渡しているが、これが正しい
 とは思えない。


●テセレータ

これも D3D11 での大きな追加機能の一つです。

HullShader と DomainShader を設定することで、その間を繋ぐ Tessellator は
勝手に呼び出されるようになります。
VertexShader と PixelShader の間に、暗黙のうちに Rasterizer が呼ばれるのと
よく似ています。機能も似ています。

GS と HS → DS はオプションなので、パイプラインは下記の 4 通り (+2) です。

  VS → (Rasterizer) PS
  VS → GS → (Rasterizer) PS
  VS → HS → (Tessellator) DS → (Rasterizer) PS
  VS → HS → (Tessellator) DS → GS → (Rasterizer) PS

StreamOutput:
  VS → GS → SO
  VS → HS → (Tessellator) DS → GS → SO

Tessellator を Enable にした場合使用できるプリミティブは Patch のみとなります。
PATCH は新しく追加された Primitive Topology で、1~32 までの頂点を入力可能です。

・Point     List
・Line      List, Strip, ListAdj, StripAdj
・Triangle  List, Strip, ListAdj, StripAdj
・Patch     1~32

Patch の入力頂点は、主に分割時のカーブを求めるためのコントロールポイントとして
使われます。
従来 TriangleListAdj でも最大 6頂点までだったので、入力頂点数は大幅に増えました。
試していませんが DebugLayer のメッセージを見ると GeometryShader で
Patch を直接受け取れる可能性があります。もし使えるなら汎用の多入力頂点としても
応用できそうです。

HullShader は Tessellator に渡すパラメータの生成を行います。
入力された頂点 (コントロールポイント) 毎に走る関数と、パッチ単位で一回だけ走る
関数の 2つエントリポイントがあります。

VertexShader と GeometryShader がセットになったような感じですが、どちらも
1プリミティブ(patch) 分の全頂点に自由にアクセスすることが可能です。

(1) VertexShader が頂点単位に走る
(2) Patchを構成する全頂点(ControlPoint)がキャッシュされたら HullShader を
  呼び出す。
(3) HullShader は 2つの関数が存在する
  - Patch 単位で走る × 1
  - 頂点(ControlPoint) 単位で走る × 頂点数

HullShader が出力すべき必須パラメータは SV_TessFactor と SV_InsideTessFactor
です。これは Path 単位で走る "patchconstantfunc" が設定するようです。

Rasterizer の前に SV_Position が確定していなければならないのと同じように、
Tessellator の前に TessFactor も必須です。

(4) Tessellator が頂点を生成する。
(5) Tessellator の出力頂点毎に DomainShader が走る

DomainShader は、Tessellator の出力である SV_DomainLocation と、
HullShader の出力パラメータをそのまま受け取ります。
DomainShader の役割は、HullShader の出力と Tessellator の出力を元に、正しい
頂点を生成することのようです。

HullShader と違って、Tessellator の実行が完了してから走るわけではありません。
平行して生成される毎にストリームとして呼び出されるようです。
その点 VertexShader に近いといえます。

(6) 1プリミティブ分頂点が生成されたら GeometryShader を呼び出す。


まだ詳しく使い込んでない&調べてませんが、HullShader とテセレータは若干
並列動作しているのかもしれません。
ただし DomainShader が走る前には、依存している HullShader は完了している
必要があります。

─┬ per control point HS ────────→ DomainShader
 └ PatchConstantFunc HS → Tessellator → DomainShader


全コントロールポイントの情報が集まってから各シェーダーに渡されるなど、
シェーダー間で受け渡すデータ量が大幅に増えていることがわかります。
ComputeShader で追加された Append / Consume Buffer の仕組みは、このように
シェーダー間で複雑なデータを受け渡す必然性から設けられたものかもしれません。

単体で見たときはいまいち機能や用途が思い浮かばなかったのですが、HS, DS, GS の
流れを見ていると Append / Consume Buffer の存在意義が見えてきた気がします。

パイプラインが複雑で扱うデータも増えました。
それでも GPU / シェーダーで実行するメリットは、メインメモリを介さず、
CPU を介さずに頂点の増減をストリーム内で閉じたまま扱えることです。


関連エントリ
Direct3D11/DirectX11 (6) D3D11 の ComputeShader を使ってみる
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver



ComputeShader の使い方はドキュメントも少なくまだよくわかっていません。
使用できる機能の共通性などから、PixelShader に近いか PixelShader の改良版
ではないかと予想していました。でも思ったより違いは多そうです。
Technical Preview (Beta) の段階なので、まだこれから仕様が変わる可能性もあります。


●作成と実行

シェーダーの生成はこれまでの PixelShader 等と同じです。
ShaderLinkage を指定できる点も同じ。

ID3D11Device*		iDevice;
ID3D11ComputeShader*	iCS;
iDevice->CreateComputeShader( blob, blobsize, NULL, &iCS );

ステート設定は CS~ 系の命令を使います。

ID3D11DeviceContext*	iContext;
iContext->CSSetShaderResources( 0, 1, srvlist );
iContext->CSSetShader( iCS, NULL, 0 );
UINT	uavcount= 256;
iContext->CSSetUnroderdAccessViews( 0, 1, &iUAV0, &uavcount );

他のシェーダーとの違いは、任意のアドレスに書き込み可能なリソース UAV を
設定する専用命令 CSSetUnroderdAccessViews() があることです。

UAV (UnorderdAccessView) は、RWBuffer や RWTexture2D 等の書き込み可能な
リソースへのアクセスを意味しています。

ComputeShader はストリーム出力を持たないので Shader は void 宣言されます。
値を返すには必ず出力先として UAV の設定が必要となるようです。

UAV は PixelShader でも使えるはずなのに SetUnorderdAccessView 相当の命令は
ありません。この辺の仕様は要調査です。
将来 10 世代 GPU 対応の ComputeShader 4.0/4.1 が使えるようになった場合も
出力先の扱いがどうなるか気になるところです。

ComputeShader の実行は Draw() ではなく専用命令 Dispatch() を使います。

iContext->Dispatch( 1, 1, 1 );

引数はマニュアルに載ってませんが、走らせるスレッドの数と考えられます。
おそらく CUDA や AMD Stream SDK の thread や block、domain 等に相当する
パラメータでしょう。


●ウィンドウレス実行

ComputeShader は描画とは関係なく実行できるはずです。
そこで Window も DXGI も使わずにシェーダーを走らせてみました。

D3D11CreateDevice(
		NULL,
		//D3D_DRIVER_TYPE_HARDWARE,
		//D3D_DRIVER_TYPE_WARP,
		D3D_DRIVER_TYPE_REFERENCE,
		NULL,
		D3D11_CREATE_DEVICE_DEBUG,
		NULL,
		0,
		D3D11_SDK_VERSION,
		&iDevice,
		NULL,
		&iContext
	);
// hlsl 読み込みは省略 → memory
ID3DBlob*	codeblob;
D3DCompile(
		memory,
		(size_t)size,
		fname,
		NULL,	// macro
		NULL,	// include
		"main",
		"cs_5_0",
		D3D10_SHADER_ENABLE_STRICTNESS,
		0,
		&codeblob,
		&errblob
	);
iDevice->CreateComputeShader(
		codeblob->GetBufferPointer(),
		codeblob->GetBufferSize(),
		NULL, &iCS );
codeblob->Release();


// 出力先
ID3D11Buffer*	iBufferC;
D3D11_BUFFER_DESC	bdesc;
bdesc.Usage= D3D11_USAGE_DEFAULT;
bdesc.BindFlags= D3D11_BIND_SHADER_RESOURCE|D3D11_BIND_UNORDERED_ACCESS;
bdesc.CPUAccessFlags= 0;
bdesc.MiscFlags= 0;
bdesc.ByteWidth= sizeof(float)*4*256;
bdesc.StructureByteStride= sizeof(float);
iDevice->CreateBuffer( &bdesc, NULL, &iBufferC );

ID3D11UnorderedAccessView*	iUAView;
D3D11_UNORDERED_ACCESS_VIEW_DESC	uavdesc;
uavdesc.Format= DXGI_FORMAT_R32_UINT;
uavdesc.ViewDimension= D3D11_UAV_DIMENSION_BUFFER;
uavdesc.Buffer.FirstElement= 0;
uavdesc.Buffer.NumElements= 256;
uavdesc.Buffer.Flags= 0;
iDevice->CreateUnorderedAccessView( iBufferC, &uavdesc, &iUAView );

// CPUアクセス用バッファ
ID3D11Buffer*	iBufferC2;
D3D11_BUFFER_DESC	bdesc;
bdesc.Usage= D3D11_USAGE_STAGING;
bdesc.BindFlags= 0;
bdesc.CPUAccessFlags= D3D11_CPU_ACCESS_WRITE|D3D11_CPU_ACCESS_READ;
bdesc.MiscFlags= 0;
bdesc.ByteWidth= sizeof(float)*4*256;
bdesc.StructureByteStride= sizeof(float);
iDevice->CreateBuffer( &bdesc, NULL, &iBufferC2 );

// 初期データ書き込み
D3D11_MAPPED_SUBRESOURCE	mapres;
iContext->Map( iBufferC2, 0, D3D11_MAP_WRITE, 0, &mapres );
unsigned int*	ptr= reinterpret_cast<unsigned int*>( mapres.pData );
ptr[0]= 0;
iContext->Unmap( iBufferC2, 0 );
iContext->CopyResource( iBufferC, iBufferC2 );

// 実行
for( int i= 0 ; i< 4 ; i++ ){
	iContext->CSSetShader( iCS, NULL, 0 );
	UINT	uavcount= 256;
	iContext->CSSetUnorderedAccessViews( 0, 1, &iUAView, &uavcount );
	iContext->Dispatch( 10, 2, 1 );
}

// 結果読み込みと表示
iContext->CopyResource( iBufferC2, iBufferC );
D3D11_MAPPED_SUBRESOURCE	mapres;
iContext->Map( iBufferC2, 0, D3D11_MAP_READ, 0, &mapres );
unsigned int*	ptr= reinterpret_cast<unsigned int*>( mapres.pData );
printf( "%d\n", ptr[0] );
iContext->Unmap( iBufferC2, 0 );

下記のシェーダーを実行すると結果は「360」。(45 x 2 x 4)
Windows や Present() とか無しにシェーダーが走りました。

// cs.hlsl
RWBuffer<uint>	a;

[numthreads(1,1,1)]
void main( uint3 tid : SV_DispatchThreadID )
{
	InterlockedAdd( a[0], tid.x );
}

Reference では InterlockedAdd でなく直接 a[0]+= tid.x と書いても同じ値に
なってしまいます。要注意です。
実際は Query 等を使って GPU の実行を待つ必要があるかもしれません。


●リソースの受け渡し

GPU が書き込めるリソースは D3D11_USAGE_DEFAULT だけなので、UAV は全部
D3D11_USAGE_DEFAULT になります。D3D11_USAGE_DEFAULT だと CPU で直接
読み出せないため、システム側に D3D11_USAGE_STAGING のミラーバッファを用意し
アクセスの度に CopyResource() しています。
初期化手順も多く、あまり簡単とはいえません。

CPU 側との連携やデータの読み書きの容易さを考えると、CUDA や AMD Stream SDK
を直接使った方が便利だと思います。おそらく CopyResource 相当の転送も自動で
やってくれています。

ComputeShader を使うメリットは、GPU 毎の SDK の違いを吸収できることと
Direct3D との連携の容易さでしょう。

Structured Buffer や Append Buffer も試そうとしましたが、フラグ設定や
組み合わせが複雑でなかなかうまくいきませんでした。


関連エントリ
Direct3D11/DirectX11 (5) WARP の試し方、Dynamic Shader Linkage
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver


DirectX SDK November 2008 Technical Preview 5回目です。
WARP の試し方の補足と、D3D11 の大きな目玉のひとつである
「動的なシェーダーリンク」について。


● Direct3D 11 が Direct3D 10 より多くのハードで動く理由

  (1) Direct3D 9 世代の GPU に対応した
  (2) ソフトレンダラ WARP が追加された

(1) ShaderModel 2.0~3.0 でも API 自体は動きます。
ただし固定パイプライン用機能が存在しないため Shader 必須。
D3D11 になったからといって GPU の能力を超えて出来ることが増える訳じゃないので、
使えない機能多数。逆に使用できないステートなど制限が生じる可能性あり。

(2) GPU に必要な 3D 機能が無くても WARP を使えば CPU だけで動作します。
DirectX SDK November 2008 現在 10.1 相当で、Reference Driver よりずっと高速。


●手っ取り早く WARP を試す方法

install したサンプルの DXUT.cpp 2907行あたりに
pDeviceSettings->d3d11.DriverType= D3D_DRIVER_TYPE_WARP;
を挿入します。下記の赤い行。WARP Driver で起動するようになります。

// DXUT.cpp 2902行~
        if( GetDXUTState().GetOverrideForceREF() )
            pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_REFERENCE;
        else if( GetDXUTState().GetOverrideForceHAL() )
            pDeviceSettings->d3d11.DriverType = D3D_DRIVER_TYPE_HARDWARE;

        pDeviceSettings->d3d11.DriverType= D3D_DRIVER_TYPE_WARP;


起動直後 = WARP
オプション画面から REFERENCE or HARDWARE に切り替え可能。(WARP には戻せない)

WARP device も FeatureLevel 10.1 なので、10.1 で動かないサンプルは動きません。
DirectX SDK November 2008 現在、動くのは MultithreadedRendering11 だけです。

実行速度は CPU 速度に依存します。


● Dynamic Shader Linkage

Direct3D 11 の大きな特徴の一つがこの Dynamic Shader Linkage です。

動的なリンクというと、複数のシェーダーバイナリをリンクし相互参照を解決する
イメージがありますが・・違います。

わかりやすく言えば「シェーダー内で関数ポインタが使えるようになった」ということ。

インスタンス自体は静的に生成されており、単一のシェーダーバイナリにすべての
インスタンス及びエントリポイントが含まれていなければなりません。

一つのシェーダープログラムの中に複数の関数を作成することが出来、その飛び先を
動的に切換えることができるわけです。

これらの仕組みは HLSL 上では class と interface の形で用いられます。

interface Base {
	float4	GetColor();
};

class Red : Base {
	float4	effect;
	float4	GetColor()
	{
		return	float4( 1, 0, 0, 1 );
	}
};

class Green : Base {
	float4	effect;
	float4	GetColor()
	{
		return	float4( 0, 1, 0, 1 );
	}
};

cbuffer ibuf {
	Red	cbRed;
	Green	cbGreen;
};

Base	color;	// この宣言はポインタ相当で実体を持たない

float4 main() : SV_Target
{
	return	color.GetColor();
}

上の例では Green と Red が interface Base を継承して作られています。
実行は Base で宣言された color を経由して行われており、どのメソッドが
呼び出されるのかコンパイル時にはわかりません。

Green 及び Red のインスタンスは cbRed, cbGreen として ConstantBuffer 上に
静的に作られています。外部の C++ 側からは、このインスタンス化された "cbRed"、
"cbGreen" を参照することが出来ます。

実際にどのインスタンスを color に割り当てるのか、レンダリング時に C++ 側で
いつでも切換えられるわけです。


シェーダー内のインスタンス参照には ID3D11ClassLinkage::GetClassInstance()
を使います。

ID3D11ClassLinkage* iClassLinkage;
iDevice->CreateClassLinkage( &iClassLinkage );
iDevice->CreatePixelShader( blob, size, iClassLinkage, &iPS );

ID3D11ClassInstance* iClassRed;
ID3D11ClassInstance* iClassGreen;
iClassLinkage->GetClassInstance( "cbRed", 0, &iClassRed );
iClassLinkage->GetClassInstance( "cbGreen", 0, &iClassGreen );

ID3D11DeviceContext::PSSetShader() で、シェーダーと同時に使用する
インスタンスのリストを渡します。

// Green を呼び出す場合
iContext->PSSetShader( iPS, &iClassGreen, 1 );


Shader 内には複数の interface が宣言されている可能性があるので、必ずしも
上のように単純になりません。Reflection を参照して、PSSetShader() に渡す
インスタンスリストの何番目がどの interface 呼び出しに対応するのか調べる
必要があります。

class に変数が含まれている場合、ConstantBuffer 内のメモリ配置との対応付けも
必要です。(この場合 Effect ではないのでバッファの作成も必要)

Dynamic Shader Linkage の仕組みは、このようにパフォーマンスに影響が出ないよう
慎重に作られているため扱いは必ずしも簡単ではないようです。
今後 Direct3D11 対応の Effect fx_5_0 が完成したらある程度自動で行ってくれる
ようになるかもしれません。


出力されたコードを見ると fcall 命令が使われています。label の値 (おそらく
オフセット) を用いてサブルーチン呼び出しを行う仕組みだと考えられます。

ps_5_0
dcl_globalFlags refactoringAllowed 
dcl_function_body fb0
dcl_function_body fb1
dcl_function_table ft0 = {fb0}
dcl_function_table ft1 = {fb1}
dcl_interface fp0[1][1] = {ft0, ft1}
dcl_output o0.xyzw
dcl_temps 1

fcall fp0[0][0]
mov o0.xy, r0.xyxx
mov o0.zw, l(0,0,0,1.000000)
ret 

label fb0
mov r0.xy, l(0,1.000000,0,0)
ret 

label fb1
mov r0.xy, l(1.000000,0,0,0)
ret

上記のように飛び先と種類はコンパイル時に決定しており、おそらく外部参照はできません。
このことは次の例を見てもわかります。

interface Base {
	float4	GetColor();
};

class Blue : Base {
	float4	GetColor()
	{
		return	float4( 0, 0, 1, 1 );
	}
};

Base	color;

float4 main() : SV_Target
{
	return	color.GetColor();
}

この場合 interface を利用しつつも、継承されたエントリが Blue しかありません。
驚くことに HLSL コンパイラは Blue 以外が決して呼ばれないことを認識し、
間接呼び出しを取り除きます。
つまり main の中には Blue::GetColor() がインライン展開されてしまいます。


class の宣言自体は ShaderModel 4.1 (FeatureLevel 10.1) 以前でも使えます。
ただし間接呼び出しは出来ないので、interface からの呼び出しはエラーとなります。
上の例だと「Base color;」を「Blue color;」に書き換えればコンパイル可能です。

ちなみに従来の 4.1 以前のシェーダーにもサブルーチン呼び出しの機能自体は存在
していました。しかしながら HLSL コンパイラはすべてをインライン展開し尽くすので
実際に使われることはほとんどありません。
自分が知る限り、実際に関数呼び出しのコードが出力されるのは switch 文の
attribute に [call] を指定した場合だけでした。

Direct3D11 になってようやくシェーダー内のサブルーチン呼び出しが意味を持つ
ようになりました。


関連エントリ
Direct3D11/DirectX11 (4) FeatureLevel と旧 GPU の互換性、テクスチャ形式など
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver


DirectX SDK November 2008 Technical Preview 4回目です。

●DirectX SDK November 2008 の隠れた変更 (D3D10)

以前作成した D3D10 用プログラムのコンパイルが通らなくなったため調べたところ
今回から D3DX10DisassembleEffect() が無くなってるようです。
Compiler 改良のため core API でなく D3DX になったのは良いのですが
仕様が変わるのは困ります。

D3D11 では HLSL コンパイラは D3DCompiler.h に統合され、バージョンに関係ない
共通 API に進化しているようです。blob 等の API は D3D10 のまま。
こちらの方に D3DX10DisassembleEffect() の後継らしき

D3DDisassemble10Effect()

がありました。でも D3DCompiler.h は d3d11shader.h を include しているので
D3D10 ではコンパイルが通りませんでした。


●FeatureLevel 一覧

Driver (device type) 毎の FeatureLevel を調べてみました。

・RADEON HD4850 (8.10)

HARDWARE  = 10.1 (a100)
REFERENCE = 11.0 (b000)
NULL      = 11.0 (b000)
WARP      = 10.1 (a100)


・GeForce GTX260 (178.24)

HARDWARE  = 10.0 (a000)
REFERENCE = 11.0 (b000)
NULL      = 11.0 (b000)
WARP      = 10.1 (a100)


・GeForce 7900GTX (178.24)

HARDWARE  =  9.3 (9300)
REFERENCE = 11.0 (b000)
NULL      = 11.0 (b000)
WARP      = 10.1 (a100)


・Intel 945/GMA950 (7.14.10.1461)

HARDWARE  =  9.3 (9300)
REFERENCE = 11.0 (b000)
NULL      = 11.0 (b000)
WARP      = 10.1 (a100)

予想通り、D3D_DRIVER_TYPE_HARDWARE の場合のみ異なっています。
Reference と Null Reference はどちらも 11.0 です。
WARP は現在 10.1 までの対応でした。

上記よりわかるのは GeForce でも WARP を使えば 10.1 のテストが出来ること。
また 11.0 の動作を確認するには現状 Reference を使うしかないようです。

それにしても D3D11 になって、テスト用に GeForce7900 を復活させることに
なるとは思いませんでした。

付属 Direct3D11 サンプルの MultithreadedRendering11 は GeForce7900GTX でも
動作しました。(Direct3D10 はいったい何だったのか)

ちなみにサンプルは WARP に対応していないので、FeatureLevel が合わない場合
強制的に Reference Driver になります。
これは DXUT の問題なので、WARP に対応させる場合は DXUT を書き換える必要が
あります。

EeePC 901 (Vista) の Intel 945 (ShaderModel2.0) もなぜか FeatureLevel 9.3 を
返します。MultithreadedRendering11 は動作しませんでした。
D3D11_FEATURE_THREADING が未サポートなためかもしれません。


● D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS

マニュアルに載ってない FEATURE オプションとして
D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS があるようです。
これは D3D10 デバイス (FeatureLevel 4.0 or 4.1) でも、FeatureLevel 11.0 相当の
機能を一部有している場合に用いられるようです。

前回 fxc のプロファイルで ComputeShader 4.0 , 4.1 が存在していることを指摘
しました。D3D11_FEATURE_D3D10_X_HARDWARE_OPTIONS はまさに、D3D10 デバイス
でも ComputeShader が使えるかどうか調べるために用いられます。

現在 D3D11_FEATURE_DATA_D3D10_X_HARDWARE_OPTIONS のメンバは
ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x
だけです。

10.1 デバイスである WARP も FALSE でした。
よって今現在 ComputeShader を試すには Reference しか無いようです。

その他調べた FueatureSupport は下記の通り。
Reference と Null Reference で CheckFeatureSupport() の結果が異なるのが
気になります。cpas とどこが違うんだろうという気にならなくもないです。

REFERENCE 11.0
 thread DriverConcurrentCreates= 0
 thread DriverCommandLists= 0
 double DoublePrecisionFloatShaderOps= 0
 ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x= 1

NULL REFERENCE 11.0
 thread DriverConcurrentCreates= 1
 thread DriverCommandLists= 1
 double DoublePrecisionFloatShaderOps= 1
 ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x= 1

WARP 10.1
 thread DriverConcurrentCreates= 0
 thread DriverCommandLists= 0
 double DoublePrecisionFloatShaderOps= 0
 ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x= 0

HARDWARE 9.3 (GeForce7900GTX)
 thread DriverConcurrentCreates= 0
 thread DriverCommandLists= 0
 double DoublePrecisionFloatShaderOps= 0
 ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x= 0

HARDWARE 10.1 (RADEON HD4850)
 thread DriverConcurrentCreates= 0
 thread DriverCommandLists= 0
 double DoublePrecisionFloatShaderOps= 0
 ComputeShaders_Plus_RawAndStructuredBuffers_Via_Shader_4_x= 0

10.0 / 10.1 ハードウエアも、将来ドライバの更新でこれらの対応状況が変化すると
思われます。


●新テクスチャ形式

マニュアルには記載されてませんが、D3D11 の新しいテクスチャ形式はすでに
DXGIFormat.h に追加されています。
増えたフォーマットは下記の通り。

DXGI_FORMAT_R10G10B10_XR_BIAS_A2_UNORM  = 89,
DXGI_FORMAT_B8G8R8A8_TYPELESS           = 90,
DXGI_FORMAT_B8G8R8A8_UNORM_SRGB         = 91,
DXGI_FORMAT_B8G8R8X8_TYPELESS           = 92,
DXGI_FORMAT_B8G8R8X8_UNORM_SRGB         = 93,
DXGI_FORMAT_BC6H_TYPELESS               = 94,
DXGI_FORMAT_BC6H_UF16                   = 95,
DXGI_FORMAT_BC6H_SF16                   = 96,
DXGI_FORMAT_BC7_TYPELESS                = 97,
DXGI_FORMAT_BC7_UNORM                   = 98,
DXGI_FORMAT_BC7_UNORM_SRGB              = 99,

lib に dxgi_beta.lib が存在しているので、おそらく dxgi.lib の代わりに
こちらをリンクすれば新フォーマットが使えそうです。

help 内の扱いが変わったことから予想してましたが、やはり DXGI は共通のままで
(DXGI2 のような) 新インターフェースに分岐しませんでした。
もしかしたら D3D10 でも使えるようになるのかもしれません。

追加された B8G8R8A8 (ARGB) 系は以前からある
DXGI_FORMAT_B8G8R8A8_UNORM = 87 の追加バリエーションとなります。

これ D3D10 の一般的なフォーマット R8G8B8A8 (ABGR) と逆順です。
Direct3D9 以前ではこっちの方が標準でした。
(D3D関連 DDSテクスチャの取り扱い)

仕様として隅に追いやられてたはずのフォーマットを正式な扱いに戻したのは、
やはり D3D9 ShaderModel3.0 以前の GPU に対応するために、必要だったからでは
ないでしょうか。

BC6/BC7 が新しい圧縮テクスチャ形式です。
詳細はまだわかりませんが、F16 が使われている BC6 の方が HDR 圧縮形式だと
考えられます。


Preview (beta) とはいえ、1つの SDK に 3世代のバージョンが同居しているのは
Direct3D で初めてです。
DXGI は D3D10 でも D3D11 でも共通に用いられますし、HLSL コンパイラは全世代で
共有されています。
アップデートの単位が徐々に細分化しているため、バージョンの区切りはこれから
ますます曖昧になっていくかもしれません。


関連エントリ
Direct3D11 (DirectX11) シェーダーの書き込み RWBuffer 他
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver

Direct3D11 シェーダーの動的リンクやテクスチャ
Direct3D11 マルチスレッドのための機能
Direct3D11 テセレータとシェーダー
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11



引き続き DirectX SDK Novemver 2008 より、Direct3D 11 の Technical Preview です。
今まで取り上げたことがないもの中心。


●リソースサイズ

仕様として扱えるリソースの上限が拡張されています。
4GByte (32bit) を超えるリソースも扱えるらしく、内部的には 64bit で管理されて
いるようです。すでに VRAM 2GB の製品は存在しているので、4GB を超えるのも
時間の問題と思われます。

リソースサイズが 32bit を超えていても、データアクセス時の index は 32bit までに
制限されます。shader に double は追加されたものの 64bit int 型はまだ無いので
当然かもしれません。


●64bit 整数

HLSL では long/ulong 型が 64bit 整数となるようです。
double 対応前の HLSL コンパイラでは double 型を使うと float 相当の扱いでした。
(D3D10/DX10 シェーダーと64bit浮動少数)
新しい fxc で long/ulong を使うと未サポートエラーになります。

: error X3653: 'v': ps_5_0 does not support 64-bit integers
: error X3653: 'v': cs_5_0 does not support 64-bit integers


●fxc プロファイル

付属の fxc.exe は単一で、d3d9/d3d10/d3d11 共通になっています。
fxc の対応プロファイルを見ると、ComputeShader は ShaderModel 4.0/4.1 でも
使えそうです。

fx_2_0
fx_4_0
fx_4_1

cs_4_0  // ← ComputeShader 4.0?
cs_4_1  // ← ComputeShader 4.1?
cs_5_0

gs_4_0
gs_4_1 
gs_5_0

ds_5_0  // DomainShader

hs_5_0  // HullShader

ps_2_0
ps_2_a  // NVIDIA拡張
ps_2_b  // ATI拡張
ps_2_sw
ps_3_0
ps_3_sw
ps_4_0 
ps_4_0_level_9_1   // D3D11 の ShaderModel2.0
ps_4_0_level_9_3   // D3D11 の ShaderModel3.0
ps_4_1
ps_5_0

vs_1_1
vs_2_0 
vs_2_a  // NVIDIA拡張
vs_2_sw
vs_3_0
vs_3_sw
vs_4_0
vs_4_0_level_9_1   // D3D11 の ShaderModel2.0
vs_4_0_level_9_3   // D3D11 の ShaderModel3.0
vs_4_1
vs_5_0 

tx_1_0

前前回 FeatureLevel 9.1 と 9.2 の違いがわからないと書いたけど、これを見ると
本当にわかりません。


● RW Buffer

読み書き可能リソースが追加されています。
ついに、シェーダーが直接リソースに書き込みできるようになりました。
ストリーム以外の出力ができます。

RWBuffer
RWByteAddressBuffer
RWStructuredBuffer
RWTexture1D
RWTexture1DArray
RWTexture2D
RWTexture2DArray
RWTexture3D

書き込みできるのは PixelShader と ComputeShader のみ。
Load() メソッドではなく基本的に operator[] を使用します。
例えば Buffer では Load() と両方使えるものの RWBuffer は必ず operator[] を
使う必要があります。

Atomic 命令が使えるのは RWByteAddressBuffer だけで、こちらは逆に operator[] が
使えません。Load()/Store() や Interlocked 命令を使用します。

RWBuffer	a;
RWByteAddressBuffer	b;
Buffer		c;

float4
main() : SV_Target
{
	a[1]= 3;
	b.Store( 0, 4 );
	b.InterlockedAdd( 0, 1 );
	return	a[0]+ c.Load( 0 );
}

下記のようにコンパイルされました。(fxc /Tps_5_0)

ps_5_0
dcl_globalFlags refactoringAllowed 
dcl_resource_buffer (float,float,float,float) t0
dcl_uav_typed_buffer (float,float,float,float) u1
dcl_uav_raw u2
dcl_output o0.xyzw
dcl_temps 2
store_uav_typed u1.xyzw, l(1, 1, 1, 1), l(0x40400000, 0x40400000, 0x40400000, 0x40400000)
store_raw u2.x, l(0), l(4)
atomic_iadd u2, l(0), l(1)
ld_uav_typed r0.xyzw, l(0, 0, 0, 0), u1.xyzw
ld_indexable(buffer)(float,float,float,float) r1.xyzw, l(0, 0, 0, 0), t0.xyzw
add o0.xyzw, r0.xyzw, r1.xyzw
ret 

store_ 、atomic_ 命令が存在しておりやっと実感がわきます。
シェーダーが本当に書き込んでいます。

dcl_uav や ld_uav など、uav と付くのが読み書き可能な RW リソースを指している
ようです。t レジスタではなく u レジスタが使われています。
ちなみに 4.0 をターゲットにすると UAV をサポートしていないとのエラーが出ます。

// Resource Bindings:
//
// Name                   Type  Format         Dim Slot Elements
// ---------------- ---------- ------- ----------- ---- --------
// c                   texture  float4         buf    0        1
// a                       UAV  float4         buf    1        1
// b                       UAV    byte          rw    2        1

UAV は Unordered Access View (ID3D11UnorderedAccessView) の略だそうです。


● Append/Consume Buffer

RW Buffer や Atomic 命令だけでなく、もう少し便利な同期機能も追加されています。

AppendStructuredBuffer
AppendByteAddressBuffer
ConsumeStructuredBuffer
ConsumeByteAddressBuffer

Append がバッファの最後に追加、Consume がバッファの最後から取り出します。
LIFO として機能するようです。

RW Buffer と違い、読み込み専用、書き込み専用とそれぞれ個別に定義します。
送信側と受け側を明確にし、同期を単純化しているものと思われます。


使用可能なのはやはり PixelShader と ComputeShader のみ。
マニュアルでは一部全シェーダーで使えるかのような表記もありますがおそらく間違いでしょう。

使い方がよくわからなかったのでコンパイルのみ試したところ、PixelShader だとたまに
Internal Compiler Error が出るようです。
やはり主な用途は ComputeShader だと思われます。

ConsumeStructuredBuffer	c;
AppendStructuredBuffer	a;

[numthreads(1,1,1)]
void main()
{
	uint	t= c.Consume();
	a.Append( t );
}

コンパイルした結果は下記の通りです。(fxc /Tcs_5_0)

cs_5_0
dcl_globalFlags refactoringAllowed 
dcl_uav_structured u0, 4
dcl_uav_structured u1, 4
dcl_temps 1
dcl_thread_group 1, 1, 1
imm_atomic_consume r0.x, u0
imm_atomic_alloc r0.y, u1
ld_structured r0.x, r0.x, l(0), u0.x
store_structured u1.x, r0.y, l(0), r0.x
ret 

imm_atomic_consume / imm_atomic_alloc は、このペアを使って load や store を
行うと、atomic な操作でかつバッファサイズも増減することを意味しているようです。
例えば uint を float4 に変更すると次の通り。

ConsumeStructuredBuffer	c;
AppendStructuredBuffer	a;

[numthreads(1,1,1)]
void main()
{
	float4	t= c.Consume();
	a.Append( t );
}


cs_5_0
dcl_globalFlags refactoringAllowed 
dcl_uav_structured u0, 16
dcl_uav_structured u1, 16
dcl_temps 2
dcl_thread_group 1, 1, 1
imm_atomic_consume r0.x, u0
ld_structured r0.y, r0.x, l(0), u0.x
ld_structured r0.z, r0.x, l(4), u0.x
ld_structured r0.w, r0.x, l(8), u0.x
ld_structured r0.x, r0.x, l(12), u0.x
imm_atomic_alloc r1.x, u1
store_structured u1.x, r1.x, l(0), r0.y
store_structured u1.x, r1.x, l(4), r0.z
store_structured u1.x, r1.x, l(8), r0.w
store_structured u1.x, r1.x, l(12), r0.x
ret 

Append / Consume 操作は必ずスカラー単位で行われているようです。
これだけだと、float4 の間に他の Append/Consume が割り込んでしまいそうな
気がしますが、offset も同時に指定しているし、まだよくわかりません。

// Name                   Type  Format         Dim Slot Elements
// ---------------- ---------- ------- ----------- ---- --------
// c                       UAV  struct     consume    0        1
// a                       UAV  struct      append    1        1

バッファとしては UAV の一種で、Dim が consume 及び append となっています。


関連エントリ
Direct3D11 の遅延描画、スレッド対応機能、シェーダー命令
Direct3D11 Technical Preview D3D11の互換性、WARP Driver

Direct3D11 シェーダーの動的リンクやテクスチャ
Direct3D11 マルチスレッドのための機能
Direct3D11 テセレータとシェーダー
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11


Direct3D11 (DirectX11) はマルチスレッドを意識した設計が行われています。
この場合のスレッドとは CPU 側の話で、複数 core CPU が効率よく D3D API を
使用できるようになっています。

D3D10 以前のスレッド対応機能は、複数のスレッドから呼び出してもとりあえず
問題が起こらない、というレベルのものでした。
ハードウエアスレッドでの速度効率はあまり考えられていなかったといえます。

D3D11 では次の点が改良されています。

・描画やステート変更などの命令発行を複数持てる。CommandList と呼ばれる。
 Push バッファをコンテキスト毎に複数持てる。(deferred context)

・描画スレッド以外でも GPU リソースを作成できる。

従来は単一のコマンドバッファに API 単位で同期しつつアクセスが行われていた
ためスレッド間でブロックします。D3D11 はバッファリングで不要なブロッキングと
コンテキストの矛盾を回避します。

個別の CommandList (Display List) の実行には新しい GPU やドライバの機能を
必要としますが、命令の記録を API でエミュレートできるため、低い FeatureLevel
でも動作するようです。エミュレートは実行時にメモリコピーが発生する可能性が
あるため、single core CPU の場合はおそらくあまりメリットがないと思われます。
実際 D3D11_CREATE_DEVICE_SINGLETHREADED を指定すると
CreateDeferredContext() は失敗するようです。


これらの機能に対応するため D3D の Device Interface は Context が分離されました。

(1) ID3D11Device
(2) ID3D11DeviceContext

(1) の ID3D11Device 自体は Create 命令だらけになっています。
描画やステート変更は (2) の ID3D11DeviceContext に移動しました。

言ってしまえば、スレッドセーフでシェア可能な API とスレッドローカルな API に
分かれたわけです。
ID3D11Device を使ったリソースの作成はスレッドセーフであり特別な管理は不要です。
ID3D11DeviceContext は API 呼び出しを行うスレッド毎に所有する必要があります。

ID3D11DeviceContext の生成には次の命令を使います。

ID3D11Device::GetImmediateContext()
ID3D11Device::CreateDeferredContext()

ImmediateContext は従来の API 呼び出しと同等で、プッシュバッファに記録された
命令は必要に応じて kick されます。
DeferredContext の呼び出しは CommandList (ID3D11CommandList) に記録され、
ExecuteCommandList() を実行するまで保留します。
ExecuteCommandList() の呼び出しは、ImmediateContext() が行います。

●描画メインスレッド
 1. GetImmediateContext() で作成した ID3D11DeviceContext を使う。
 2. 他のスレッドが作成した CommandList を ExecuteCommandList() する。

●サブスレッド
 1. CreateDeferredContext() で作成した ID3D11DeviceContext を使用する。
 2. FinishCommandList() で ID3D11CommandList を受け取る。


シェーダーの種類も増えたので、ID3D11DeviceContext の命令も増えています。

CS~ CoputeShader
DS~ DomainShader
GS~ GeometryShader
HS~ HullShader
IA~ InputAssembler
OM~ OutputManager
PS~ PixelShader
RS~ Rasterizer
VS~ VertexShader
SO~ StreamOutput
OM~ OutputManager

HS DS GS VS PS の 6種類のシェーダーそれぞれに次の 8命令が用意されています。

~GetConstantBuffers()
~SetConstantBuffers()
~GetSamplers()
~SetSamplers()
~GetShader()
~SetShader()
~GetShaderResource()
~SetShaderResource()

CS のみ CSGetUnorderdAccessViews()/CSSetUnorderdAccessViews() の特殊な
2命令があります。
これだけで 6 x 8 + 2 = 50命令


関連エントリ
Direct3D11 Technical Preview D3D11の互換性、WARP Driver



DirectX SDK Novemver 2008 には DirectX11 (D3D11) の beta SDK が含まれています。
Direct3D11 API の機能や詳細が明らかになってきました。

Direct3D10 で大幅に変更された API の路線は継承されていますが
さらに現実的な改良がいくつも施されています。
中でも驚いたのが、D3D10 の時よりも間口を広げたこと。

手持ちの RADEON HD4850 でも D3D11 サンプルが動作しました。
(Windows Vista x64 + HD4850 CATALYST 8.10)
サンプルによっては、Reference でなくアクセラレートが利いているものもあります。
D3D9 GPU では一切動かなかった D3D10 とはえらい違いです。
信じられないくらい。


■D3D9 → D3D10 の場合

・Preview SDK が出ても当時は Vista 発売前だったため Reference Driver ですら
 動かなかった。
・D3D10 専用 GPU (ShaderModel 4.0 以上) が無いと一切ハードウエアアクセラレータ
 が利かなかった。(Reference のみ)


■D3D10 → D3D11 の場合

・Vista 上なら旧ビデオカードでも Reference Device で動く。
・D3D10 GPU でも D3D11 API が使えた。Feature Level が制限されるだけで API
 自体は置き換えられる。未対応の機能さえ使わなければアクセラレートされるらしい。
・さらに WARP Driver (WARP Device) が使える。(詳細は後述)


D3D9 以前は CAPS 情報があったため、旧 GPU でも使えない機能が判別できました。
D3D10 はデバイスの性能を特定する仕組みが無く、D3D10 の全機能が必須となり
 旧 GPU は切り捨てられました。
D3D10.1 では FeatureLevel が導入され、10.0 と同居可能となりました。
D3D11 では同じように FeatureLevel で各 GPU のレベルを判別します。

Feature Level
  11.0 = ShaderModel 5.0
  10.1 = ShaderModel 4.1
  10.0 = ShaderModel 4.0
   9.3 = ShaderModel 3.0
   9.2 = ShaderModel 2.0
   9.1 = ShaderModel 2.0

上記 FeatureLevel の定義を見ると、D3D10 GPU どころか D3D9 世代、
ShaderModel 2.0~3.0 にも対応しているように見えます。
もしこれが本当なら、Direct3D10 よりも Direct3D11 の方が対応 GPU の範囲が広い
ことになります。
Direct3D10 は動かないけど Direct3D11 なら動く可能性があるということ。

Direct3D9 の固定パイプライン(HW T&L) が使えないだけで、従来の D3D9Ex も
D3D11 API に統合可能なのかもしれません。

互換性を保った API の置き換えは D3D9 以前の DirectX では当たり前だったため、
元に戻っただけともいえます。
それでも D3D10 の仕様を考えると非常に大きな路線変更です。

Direct3D10 へ移行するのはものすごい骨が折れるし敷居も高かったので良い傾向です。

FeatureLevel 9.2 と 9.1 の違いは不明です。
ShaderModel は vs3.0/vs2.0 ではなく、vs_4_0_level_9_1 等 4.0 の制限版と
なるようです。


●Device Type (Driver Type)

Device Type が増えました。
目新しいのは Null Reference Device と WARP Device です。

・Hardware Device (HAL)
・Null Reference Device
・Reference Device
・Software Device
・WARP Device


Null Reference Device は Reference Device 同様ソフトウエア動作しますが
レンダリング機能が無いようです。API 呼び出しだけソフトウエアでシミュレート
することで、現実的な速度でデバッグを行うのが目的のようです。

WARP Device (Windows Advanced Rasterizer) は高速なソフトウエアラスタライザ
のようです。Multi Core CPU が当たり前になり GPU との差が埋まりつつあるため、
ソフトウエアラスタライザが復活といったところでしょうか。
WARP Device は D3D11/D3D10.1 の置き換えが出来るそうです。
詳しい説明がないため中身はわかりませんが、RAMP とか MMX RGB Driver が存在
していた D3D5~D3D6 あたりを思い出します。

実際に D3D_DRIVER_TYPE_WARP を使ってみたところ、D3D10WARP_beta.dll が
読み込まれているのを確認しました。
Dual Core CPU で試したためあまり参考にならないかもしれませんが、確かに動作は
REFERENCE Driver より高速でした。
Reference で 0.3fps 程度のサンプルが、数fps 程度には向上しています。
Quad 以上ならもっと効果が顕著だと思われます。

これから CPU の core 数は増加していきます。例えば Core i7 は Quad + HT で
ハードウエア 8 スレッドらしいので、今後はさらに期待できそうです。


DirectX11 に関しては下記関連エントリも参考にしてください。


関連エントリ
Direct3D11 シェーダーの動的リンクやテクスチャ
Direct3D11 マルチスレッドのための機能
Direct3D11 テセレータとシェーダー
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11



リリースされたようです。

DirectX SDK November 2008
DirectX Software Development Kit

予告通り Direct3D11 の Technical Preview が含まれています。




PS3
oga at 06:53
βの時にアップロードしたステージデータが残っていました。
同じアカウントならダウンロード(コピー)出来るので再編集も可能です。

ベータとの違いで大きいのが、ジェットパックのはずしかた。
○ボタンだけで簡単に外せるようになってます。
その他気がついたところ

・ジェットパックがボタンだけで簡単に外せる(ベータはコントローラを振る)
・コミュニティのページが増えている(ベータは10ページだった)
・アップロードできるステージ上限が4倍に増えている
・テンプレートはストーリーモードのステージをクリアして手に入れる必要あり

ジェットパックでシェイク不要になったので、センサーが無くても基本操作は
可能となりました。これで純正以外のコントローラも使えるかと思ったけど、
手持ちの PC 向け USB コントローラは XMB では使えるのに LBP では
動きませんでした。


発売直後はサーバーの不調かネットにログインできないことが何度かありました。
それでもストーリーモードとエディットは出来ます。

ストーリーモードのボリュームはかなり増えているし、それぞれ凝っていて
良く作り込まれています。
先にエディットを経験しておけば、ステージの仕掛けがどうやって作られているのか
考えたり、仕組みを再現してみる楽しみ方もあり。


リトルビッグプラネットのエディットは良くできていて強力です。
かえってゲーム経験が豊富な人の方が、「エディット=難しい」と先入観があって、
軽視してしまうかもしれません。だとしたらもったいない。


スクリプトでもなく、状態遷移グラフでもない。
物理法則だけでさまざまな仕掛けを作れてしまう、ゲームの新しいプログラミング
スタイル(?)といえるかもしれません。

言ってしまえばゲーム自体が電子ロジックではなく「機械仕掛け」でできています。
その機械仕掛けをわざわざコンピュータでシミュレートしているわけです。


フラグとか演算とか、そんな概念は何も無し。
スイッチと配線が出来るため、がんばれば論理回路が作れます。
でも物理的なスイッチを動かすモーター(ぶらぶらボルト、ピストン)とマグネット
スイッチを経由するのでリレー式です。


このゲーム(アプリケーション)のジャンルはきっと、機械式ゲームのエミュレータ。


使いやすくてびっくりした!

YouTube gesture10key改造版(g10k3)デモ on 03
↑大変わかりやすいです。


詳細は下記から
gesture10key/gesture10keyr

様々なバリエーション
gesture10key改造ファイル


●他の sip データも探してみました。
どれも工夫されたものばかりで良く作り込まれています。


hp49g+
とあるhx2490bユーザーのメモ hp49g+
  ダウンロードはこちらから


ニコタッチ (2タッチ/ポケベル入力)
ときどきもばいる p905i_nt_sip


タイ語、HTC Touch Dual 風
El Camino Real 英語 日本語 タイ語 入力 スクリプト
El Camino Real HTC Touch Dual 風 各種入力パネル


emonsip
Desire for wealth emonsip

emonsip バリエーション
C_andY の iPHONE + WINDOWSMOBILE メモ emonsip★ネイル用スキン完成\(*^▽^*)/
>C_andY の iPHONE + WINDOWSMOBILE メモ emonsipスキン<iPhone系>
  C_andY の冷蔵庫

emonsip バリエーション 英語キーボード対応
Smart Phone memo emonsipのキーコードをX01HT仕様に変更成功!


ページ送りキー
伊藤浩一のW-ZERO3応援団 pageupdownsip3color


srkeyboardsip 改良版
小人閑居為不善 SIPローマ字変換用スクリプト改変(続)


フルキータイプ
モバイル日記(旧ほぼW-ZERO3[es]日記?) TouchKeySip用自分カスタマイズキーボードV1.2 [WM(自作ツール未満・・・)]


他にもあるかと思います。抜けていたらごめんなさい。



x86 (IA32) の命令は Prefix を追加し op code 長を増やすことで拡張されてきました。
SSE の命令は 2byte escape 0F + 1byte opcode の空間に割り当てられています。
例えば ADDPS は 0F 58 です。バリエーションであるスカラー ADDSS は Prefix と
して F3 が追加され、SSE2 の倍精度命令はさらに 66 と F2 も加わります。

ADDPS     0F 58 ~
ADDSS  F3 0F 58 ~
ADDPD  66 0F 58 ~
ADDSD  F2 0F 58 ~


x64 (AMD64/Intel64/EM64T) の拡張レジスタ xmm8~xmm15 にアクセスするには
上記にさらに REX Prefix が追加されます。
40~4F が REX Prefix で、4bit 分のオプション bit を持っています。

ADDPS     45 0F 58 ~
ADDSS  F3 45 0F 58 ~
ADDPD  66 45 0F 58 ~
ADDSD  F2 45 0F 58 ~


IA32 命令のレジスタフィールドは 3bit しかなく、レジスタ上限は 8個でした。
64bit モードでは REX Prefix 内の機能 bit を追加して、レジスタフィールドを
4bit とみなすことができます。
これで最大 16個のレジスタを指定可能です。

REX Prefix
H---------------L
[0|1|0|0|W|R|X|B]


REX.RXB の 3bit がレジスタ/Index フィールド拡張用です。
残り 1bit REX.W が 64bit オペランドサイズの指定に使われます。

SSE4.x ではさらに opcode が拡張されて 3byte escape の 0F 38 や 0F 3A で
始まるスペースが割り当てられています。(SSE5 は 0F 24)

// SSE4.1
DPPS      66 [REX] 0F 3A 40 ~
BLENDPS   66 [REX] 0F 3A 0C ~
EXTRACTPS 66 [REX] 0F 3A 17 ~

// SSE4.2
CRC32     F2 [REX] 0F 38 F0 ~


追加命令が増える度に命令は長くなる一方です。

AVX でも命令を区別するために、さらに VEX Prefix が定義されています。
今までの命令 Prefix と違うのは、最初から 2~3byte の長さを確保したことと、
その中に従来使われていた Prefix や opcode を組み込んでしまったことです。

例えば SSE 命令の前に付く 66/F2/F3 Prefix は無印を含めて 4通りしかありません。
これは 2bit にエンコードできます。

最初から REX も opcode の機能 bit に組み込んでしまえば 8bit フルに割り
当てる必要もなくなります。

必ず 0F が含まれるとわかっているなら、これを命令から取り除くことが可能です。

2byte-VEX (C5+1byte)
H---C5---L  H---------------L
[11000101]  [R|V|V|V|V|L|P|P]

3byte-VEX (C4+2byte)
H---C4---L  H---------------L   H---------------L
[11000100]  [R|X|B|M|M|M|M|M]   [W|V|V|V|V|L|P|P]


2bit の PP がまさに Prefix の有無を表しています。
 0= なし
 1= 66
 2= F3
 3= F2

L は 256bit (ymm) モードの指定です。0 なら 128bit (xmm)

R X B W は REX Prefix に含まれていた機能 bit です。

4bit の VVVV は追加のレジスタフィールドです。
AVX は 3オペランド命令で source/destination が分離されているので、増えた
レジスタオペランドの指定にここが使われます。

5bit の MMMMM は拡張命令用フィールドでその多くが予約されています。
現在定義されているのは次の 3パターンのみ。
 1= 0F (2byte escape)
 2= 0F 38 (3byte escape)
 3= 0F 3A (3byte escape)

2byte-VEX には MMMMM は含まれていませんが、無条件で 0F とみなします。

これで上で紹介した多くの命令が VEX Prefix で置き換えられることがわかります。
VEX Prefix 以降の 1byte opcode や ModR/M 等のフィールドには互換性があります。

また MMMMM の多くが余っているので、例えば、まず無いとは思いますが

MMMMM: 4= 0F 24

と定義してしまえば AMD SSE5 の VEX 化も可能でしょう。
今後はおそらく命令が長くなることもなく ぐっすり眠れます。


Intel AVX は IA64 のような全く新しい互換性のない命令セットではなく、
x86 (IA32) の命令を圧縮してエンコードしたものです。

追加されたレジスタフィールド以外はこれまでの命令や prefix と同じもの。
従来の命令形式にデコード可能な互換性を保っています。

命令長は必ずしも短くなるわけではなく、ADDPS などは VEX 化することで 1byte
増えそうです。
ただし x64 拡張レジスタへアクセスする場合は長さは変わらず、source と
destination を別指定できるため場合によっては MOV 命令を減らすことができるでしょう。


関連エントリ
Intel AVX その2 転送
Intel AVX



やはり、上位 128bit と下位 128bit を横断する命令は限られているようです。
基本的には 128bit 4要素の SSE 命令を、一度に 2個演算できるのが AVX の
256bit 命令です。

Intel AVX
Intel-AVX-Programming-Reference-319433003.pdf

上下 128bit への任意転送は 128bit 単位のものが多く、SHUFPS/SHUBPD のような
32/64bit 単位で任意に入れ替えたり転送する命令がみあたりません。
float 8個や double 4個の演算時でも、値を入れ替える場合に 128bit 転送命令を
組み合わせる必要がありそうです。

256/128bit 間の転送には VEXTRACTF128, VINSERTF128 が使えます。
上位下位どちらの 128bit を使用するか選択します。
以下 256bit レジスタの ymm.low を下位 128bit、ymm.hi を上位 128bit と表記します。

VEXTRACTF128  xmm1, ymm2, 0   // xmm1= ymm2.low
VEXTRACTF128  xmm1, ymm2, 1   // xmm1= ymm2.hi

VINSERTF128 ymm1, ymm2, xmm3, 0 // ymm1.low= xmm3,  ymm1.hi= ymm2.hi
VINSERTF128 ymm1, ymm2, xmm3, 1 // ymm1.low= ymm2.low,  ymm1.hi= xmm3

VINSERTF128 は VMOVSS 系の部分更新命令なので、合成用の追加のレジスタが増えて
います。
実際は ymm2 に dest (ymm1) と同じレジスタを指定するケースが多いかもしれません。

128bit 単位の入れ替え命令として VPERM2F128 があります。
2つのソース ymm2,ymm3 の任意の 128bit を組み合わせて ymm1 に代入できます。

VPERM2F128  ymm1, ymm2, ymm3, 0  // ymm1.low= ymm2.low,  ymm1.hi= ymm2.low
VPERM2F128  ymm1, ymm2, ymm3, 1  // ymm1.low= ymm2.hi,   ymm1.hi= ymm2.low
VPERM2F128  ymm1, ymm2, ymm3, 2  // ymm1.low= ymm3.low,  ymm1.hi= ymm2.low
VPERM2F128  ymm1, ymm2, ymm3, 3  // ymm1.low= ymm3.hi,   ymm1.hi= ymm2.low
~

VBROADCAST は、唯一 32,64,128bit の任意の値を 256bit に転送できます。
複製されます。

VBROADCASTSS   xmm1, m32   // xmm1 32bit x4= m32, 上位 128bit は 0
VBROADCASTSS   ymm1, m32   // ymm1 32bit x8= m32
VBROADCASTSD   ymm1, m64   // ymm1 64bit x4= m64
VBROADCASTF128 ymm1, m128  // ymm1 128bit x2= m128

F128 は SS, SD, PD, PS に相当し、128bit を表すようです。
(Larrabee では F256 がありそう)

これ以外の命令はほぼ 128bit SSE ×2 個分に相当します。
その他特殊な命令は次の通り。

VZEROALL
VZEROUPPER

VZEROALL は、ymm0~15 レジスタすべてをゼロクリアします。
VZEROUPPER はすべてのレジスタの上位 128bit のみクリア。
これらの命令は、レジスタの部分書き換えが発生してしまう Legacy SSE 命令の
レジスタ依存を断ち切ることが出来ます。

メモリとレジスタ間で条件付き転送が出来るようになっています。
転送単位は 32bit or 64bit で、転送するかどうか mask レジスタで指定します。
mask 値は転送データと同じサイズで、最上位 bit (符号) で判断します。
つまり負なら転送。

VMASKMOVPS  xmm1, xmm2, m128  // 32bit x4, xmm2 が mask
VMASKMOVPS  ymm1, ymm2, m256  // 32bit x8, ymm2 が mask
VMASKMOVPD  xmm1, xmm2, m128  // 64bit x2, xmm2 が mask
VMASKMOVPD  ymm1, ymm2, m256  // 64bit x4, ymm2 が mask
VMASKMOVPS  m128, xmm1, xmm2  // 32bit x4, xmm1 が mask
VMASKMOVPS  m256, ymm1, ymm2  // 32bit x8, ymm1 が mask
VMASKMOVPD  m128, xmm1, xmm2  // 64bit x2, xmm1 が mask
VMASKMOVPD  m256, ymm1, ymm2  // 64bit x4, ymm1 が mask


例えば xmm の各 32bit をシェーダーのように .x .y .z .w で表現すると

xmm2.x= -1
xmm2.y= 0
xmm2.z= -1
xmm2.w= 0

の場合

VMASKMOVPS xmm1, xmm2, m128

は次の転送を行います。

xmm1.x= m128[0]
xmm1.y= 0
xmm1.z= m128[2]
xmm1.w= 0

選択しながら読み出せるため便利ですが、mask レジスタを用意する必要があります。
命令も 3byte 長 VEX (0F38) に含まれています。


積和命令 FMA は AES と同じように別カテゴリに分かれています。
命令フィールドも 0F3A の 3byte VEX で独自のものです。

AVX は基本的に SSE をカバーしていますが SSE1~SSE4.1 までです。
SSE4.2 と AMD SSE5 は含まれていないようです。
積和命令 FMA~ FNMA~ は SSE5 と名称も機能も似通っています。
ちょうど SSE5 を VEX 拡張したかのような位置づけですが、opecode 等を見ても
関連性はありませんでした。


関連エントリ
Intel AVX




2008/10/13
Intel AVX

Intel の新しい拡張命令セットです。基本的には SSE と同じようなもの。

Intel AVX

その特徴は

・256bit になった
・積和命令
・ソース非破壊の 3オペランド命令
・命令 Prefix の圧縮
・メモリアライメント制限の緩和

など。

CPU core 数が増えて性能が向上するように、演算並列度を上げるために SIMD で
扱える bit 幅が拡張されるようです。
x64 の 64bit RAX~ レジスタのように、128bit XMM レジスタが 256bit YMM
レジスタに拡張されています。

256bit = 32bit×8 なので float×8個の演算を一度に行うことができます。
とはいえ GPU の Shader でも xyzw までで、8要素の演算には普段あまり馴染みが
ありません。むしろ 256bit = 64bit×4 と、double で一度に 4要素扱えることに
意義があるのかもしれません。

以前 SSE5 の記事を見たときに勘違いしたのが "3オペランド命令の採用" です。
てっきりソース非破壊で演算可能になったのかと思ったら積和命令のことでした。
(AMD SSE5 Shader のような新しい命令)

今度は本当です。
AVX は単なる 256bit 拡張ではなく、従来の 128bit SSE 命令も含まれています。
VEX Prefix を使った SSE 互換命令はレジスタフィールドが拡張されていて
source operand と destination operand が分離されています。
例えば ADDPS 命令の場合次の通りです。

ADDPS   xmm1, xmm2/m128        // SSE
VADDPS  xmm1, xmm2, xmm3/m128  // AVX
VADDPS  ymm1, ymm2, ymm3/m256  // AVX

積和系 FMA 命令だと 4 operand です。

VFMADDPS  xmm0, xmm1, xmm2/m128, xmm3
VFMADDPS  xmm0, xmm1, xmm2, xmm3/m128
VFMADDPS  ymm0, ymm1, ymm2/m256, ymm3
VFMADDPS  ymm0, ymm1, ymm2, ymm3/m256

SSE3 の HADDPS や SSE4.1 の DPPS もありました。

HADDPS   xmm1, xmm2/m128        // SSE
VHADDPS  xmm1, xmm2, xmm3/m128  // AVX
VHADDPS  ymm1, ymm2, ymm3/m256  // AVX
DPPS     xmm1, xmm3/m128, imm8        // SSE
VDPPS    xmm1, xmm2, xmm3/m128, imm8  // AVX
VDPPS    ymm1, ymm2, ymm3/m256, imm8  // AVX

256bit の VHADDPS も隣接 2値ごとの加算で、機能的には同じ。

問題の 256bit VDPPS ですが、8個全部の内積ではなく上位 128bit と下位 128bit
同士をそれぞれ内積した結果を返すようです。
つまり AVX の 256bit 命令とは、8個の float 演算と言うよりも 4要素の SSE 演算
自体をさらに 2つ同時に実行できると考えた方が理解しやすいようです。

残念なのが VDPPD 命令。
double×4 の内積ではなく 128bit 分 double×2 の内積を 1セット返すのみでした。
float x4 → double x4 への置き換えは簡単ではないようです。

VSHUFPS/VSHUPD も同様に上位 128bit 下位 128bit それぞれの範囲でのみ入れ替え
られます。256bit 全部入れ替えられるわけではないようです。

上位 128bit / 下位 128bit 間の転送には VINSERTF128/VEXTRACTF128 命令が使えます。
任意の xmm レジスタを ymm の上下 128bit どちらに転送するか、
または ymm のどちらの 128bit を xmm に転送するか選択できます。
ちなみに AVX では xmm レジスタへ転送を行うと上位 128bit は 0 クリアされます。

ソース非破壊だとソースを保存のための無駄な転送が減るし、3オペランドだと
演算が MOV を兼ねることが出来ます。
これらは単に命令数が減るメリットだけでなく、レジスタの部分更新が無くなるので
レジスタリネーミングの効率にも貢献するものと考えられます。

例えば MOVSS と MOVPS は AVX では次のように変化します。(m128/m256 は省略)

MOVAPS    xmm1, xmm2    // SSE
VMOVAPS   xmm1, xmm2    // AVX
VMOVAPS   ymm1, ymm2    // AVX

MOVSS   xmm1, xmm2        // SSE
VMOVSS  xmm1, xmm2, xmm3  // AVX

MOVPS は単なる転送命令なので 2 operand のみ。

MOVSS は bit0~bit31 のスカラーを転送する命令です。
SSE では xmm1 の bit32~bit127 は置き換えず保持します。

AVX では dest は全書き換えが原則なので、機能互換性のため bit32~bit127 を
入力する operand が追加されています。(VINSERTF128 も同様)

MOVSS    xmm1, m32    // SSE
VMOVSS   xmm1, m32    // AVX

メモリから読み込む場合 xmm1 の余った bit は 0 クリアされます。
AVX では xmm への転送は上位 128bit をクリアすることになっているため、
bit32~bit255 すべてが 0 になります。
AVX 対応 CPU で SSE 命令を使うと ymm の上位 128bit は非更新です。


Larrabee ではさらに SIMD が 512bit に拡張されるようです。
float だと 16個分ですが、256bit AVX の例を見ると 128bit SSE × 4 相当で
構成されている可能性があります。
また演算毎にレジスタの mask を指定できるようです。
mask の指定はおそらく入力側だと考えられます。shader のような書き込み mask だと、
AVX のルールで考えると VMOVSS のようなもの。そうでなければ GPU のように
内部でスカラー単位に分割して依存を管理しているのかもしれません。


関連エントリ
AMD SSE5 Shader のような新しい命令
SSE についてのメモ(2) SSE4など



PS3
oga at 06:16
Playstation 3 の Little Big Planet ベータをしばらくやってました。
(もうすぐ時間切れ)

little big planet

このゲーム、ほぼすべての画面で複数人同時にプレイできます。

(1) オンラインで繋ぐ
(2) コントローラを複数繋ぐ

合計 4人までです。

オンラインモードや複数人モードなどが分かれておらずシームレスです。

PS3 にローカルに繋いだコントローラからは常に参加可能で、
ポッド(メインメニュー) でも、ゲームモードで「ひとりで遊ぶ」を選んでも、
エディットモードでも付いてきます。
もともと単一のカメラなので、画面分割しなくても矛盾しません。

ゲームの「ひとりで遊ぶ」とは厳密にはプレイ人数のことではなく、
「オンライン接続の禁止=オフラインモード」を意味しているようです。


・ポッド
  メインメニューであり、個人毎のホームやロビーも兼ねています。
  フレンド登録しているプレイヤーがオンラインなら直接行くことが出来ます。
 
・ストーリー
  あらかじめ組み込まれているステージをプレイします。
  操作を覚えたりエディットで使える素材集めもここ。
  複数人で参加可能で、ネットに繋ぎたくないときは「ひとりで遊ぶ」を選びます。
  「オンライン」を選んだときはホストになります。

・クイックマッチ
  「オンライン」でプレイしているユーザーにランダムでつながるようです。
  ステージが終わるとホストの人のポッドに連れて行かれます。
  
・コミュニティ
  ユーザーが作った無数のステージを遊ぶことが出来ます。
  特に組み込みのステージとの違いもなく、複数人で同じように遊べます。

・ぼくの惑星
  自分でステージを自由に作ることが出来ます。
  アップロードすればコミュニティに登録されて誰でも遊べるようになります。

  アップロードしなくても、自分がホストの場合はポッドにいるユーザーで一緒に
  プレイすることが出来るようです。

  エディット時はオンラインユーザーは入れません。
  コントローラを複数繋いでいる場合は、最大4人まで同時にエディットできます。
  複雑なものとか大きなものは協力して作っていくことが可能で、
  二人以上でないとクリアできないトラップなども確認しながら作れます。


途中参加受け付け終了を意味するゲートロック・ポストをマップに配置しない限り
オンラインではいつでも参加出来てしまうようです。
クイックマッチで入った瞬間ゴールだったことが何度かありました。

ロードは速いので、ほとんどバックグラウンドで行われているのかもしれません。
たまに待たされることがありましたが、どちらかと言えばネット側の問題だった
ようです。


エディットもかなり力が入っていて、ツール1つ1つに丁寧なチュートリアルがあります。
裏で勝手に説明ムービーが流れているだけなので、すでに理解している場合は
さっさと先に進めることが可能。

エディット系ツールでは素材から自由に形を作ることが出来ます。
3D オブジェクトのペンで、絵を描くようにモデルが作られます。
基本的にマテリアルは使う素材によって決まっていて、見た目だけでなく
重さや滑りやすさ、つかめるかどうかといった特性も素材で決まります。

見た目を変えるにはステッカーを貼ります。いわゆるテクスチャ。
エディットモードだけでなくプレイ中もステージ内のオブジェクトにステッカーを
貼り替えできます。
USB カメラがあれば、取り込んでステッカーを作ることも可能です。

エディット中も物理シミュレートは有効になっており、空中に置いたものは落ちるし
ぶつかると倒れます。
動くと困るときは、十字キーの上で物理シミュレートを一時停止します。
巻き戻しのような操作でいつでも Undo/Redo 可能なのも便利。

画面は 3D ですが、画面の奥行きには制限があります。
使えるのは 3 ラインまでで、厚みの幅も固定。
コリジョンは 3D だけどオブジェクトの移動は 2D。

オブジェクトは組み合わせてのり付けしたり、ボルトや紐で組み合わせて形状を
作り上げていきます。

機能的なコネクタもあって、回転するモーターや伸び縮みするピストンなど
スイッチで切換えられます。

ジョイントで繋がれた物体の物理シミュレートや、スイッチの配線だけで様々な
ものが連動し、仕組みを作り上げていくことが可能です。
どう使うかは決められたものではなく、どれもこれも工夫次第。

フラグ管理とかスクリプト等といったゲームの都合による設定は極力排除されていて、
身の回りに近い理解しやすい世界が徹底されています。

エディット自体、一歩引いた次元の違う無機質なツールでは無く、
1つの世界として繋がっており、同じように楽しめるゲームの一部といったところ。


これらはベータ版を元にしているので製品版では変更される可能性があります。



2008/10/09
Little Big Planet

PS3
oga at 00:44
ここずっと PS3 の Little Big Planet ベータやってます。はまっています。
道路標識をチェックポイント(コンティニューポイント)と見間違えたくらい。

オンラインにあがっている様々なステージをプレイするだけでも延々遊べそうなのに、
エディットが非常に楽しいです。

自由度が高く、シンプルな物理ルールで出来ているので、
工夫次第で出来そうなことがいくらでもあります。
いかにもゲームっぽいお約束な決まり事にとらわれないのがいい。

littlebigplanet




Windows の Interlocked 系 API は atomic な操作に使われます。
例えば InterlockedIncrement() は load と store を含みますが、その間に他の
スレッドが同じメモリを書き換えることなく処理が完了するよう調整されます。

x64 でコンパイルするとこれらの Interlocked API はインライン展開されるようです。
下記のように同機能の intrinsic 命令が用意されおり、x64 では単なる別名として
定義されていました。

InterlockedCompareExchange Function
_InterlockedCompareExchange Intrinsic Functions

x86 でも直接 _InterlockedCompareExchange() を使えば組み込み命令として機能します。
実際のコードは下記の通り。

x64:
 lock cmpxchg dword ptr [mem32],edx  // InterlockedCompareExchange
 lock cmpxchg qword ptr [mem64],rdx  // InterlockedCompareExchange64

x86:
 lock cmpxchg dword ptr [mem32],edx   // InterlockedCompareExchange
 lock cmpxchg8b qword ptr [mem64]     // InterlockedCompareExchange64

InterlockedIncrement() + x64 の場合

// 返値参照あり
mov ecx,1
lock xadd    dword ptr [mem],ecx
inc ecx

// 返値参照無し
lock add     dword ptr [mem],1

返値を参照するかどうかによって、命令そのものも置き換わっています。
単なる関数や asm 文の inline ではなく、組み込み命令であることがよくわかります。

以前紹介した Gamefest2008 のスライドによると DirectX11 の Compute Shader
には下記の命令が追加されるようです。

 InterlockedAdd()
 InterlockedMin()
 InterlockedMax()
 InterlockedOr()
 InterlockedXor()
 InterlockedCompareWrite()
 InterlockedCompareExchange()

Gamefest 2008 Presentations
「Direct3D 11 Computer Shader More Generality for Advanced Techniques」

InterlockedMin()/InterlockedMax() は Win32 API に無い命令です。
書いてみるとこんな感じでしょうか。(厳密な動作は未検証)

template<typename T>
void InterlockedMin( T volatile* mem, T val )
{
    union {
        T      fval;
        long   ival;
    }	cur;
    do{
        cur.fval= *mem;
        if( cur.fval <= val ){
            break;
        }
    }while( _InterlockedCompareExchange(
                reinterpret_cast<long volatile*>( mem ),
                *reinterpret_cast<unsigned long*>( &val ),
                cur.ival ) != cur.ival );
}


関連エントリ
Direct3D11 Compute Shader など
SSE3 の monitor mwait 命令



SSE3 で monitor / mwait 命令が追加されています。
HT やマルチコアなど、ハードウエアスレッドの同期効率を上げるために有効
らしいですが、使ったことがないので調べてみました。

monitor で監視アドレスを与えた後、mwait 命令は監視アドレスに何らかの
書き込みがあるまで待機します。
メモリの更新をハード的に検出する動作は RISC 系の atomic 命令 ll/sc に
似ています。

イベント待ちのような動作なので様々な通知に使えそうです。ただこれが OS では
なく CPU そのものの命令で実行されるため、いくつかの疑問も生じます。
CPU レベルの命令でアプリケーションがこのような動作を行って問題無いのか、
割り込みやコンテキストスイッチ等でどのように振る舞うのか、
mwait に復帰できるのか、monitor の状態がリストアされるのか、など。

intrin.h を include するだけで、_mm_monitor() / _mm_mwait() の
intrinsic 命令が使えます。
実際に x86 でも x64 でもコンパイルは可能ですが、無効な命令となり実行は
出来ませんでした。
CPUID を調べると、MONITOR/MWAIT に対応していることは確認できます。

Intel 64 and IA-32 Architectures Software Developer's Manuals
日本語技術資料のダウンロード

マニュアルによるとどうやら特権命令らしく、無条件で使えるのはレベル 0
の場合のみ、特権レベル 1~3 での動作も可能だけど、そのためには何らかの
条件がいるそうです。
また MONITOR/WAIT が使えるかどうかは MSR IA32_MISC_ENABLES (1a0) の
bit18 の設定にも依存し、この値が 0 だと CPUID のフラグも落ちるとのこと。
この値も設定されており問題はなさそうです。

Manual の Volume 3A 7.11.3 で、特権レベル 1 以上の場合でこれらの命令が
使えるかどうか判定する方法が載っています。intrinsic で書くと次の通り。

__try{
    _mm_monitor( memory, 0, 0 );
}
__except( 1 ){
   // 使用できない
}

つまり Illegal Instruction が発生するのは特権レベル 0 以外は使えないことを
意味しているようです。何らかの設定で無効にされているのか、それとも
もともと使えないものなのか、その条件はわかりませんでした。

マニュアルを見ると mwait の動作は、割り込み等によって頻繁に解除される
ようです。mwait に復帰することはなく、監視したメモリの値を調べて解除原因を
判断する必要があるようです。

また監視メモリの領域は CPU 依存で、CPUID の 0x05 で調べることが出来ます。
手持ちの CPU では下記の通り。最小も最大も 0x40 == 64 でした。

CPUID (CPU-Z によるレジスタダンプ)
・Atom N270
 0x00000005 0x00000040 0x00000040 0x00000003 0x00020220
・Core2 Duo E6600
 0x00000005 0x00000040 0x00000040 0x00000003 0x00000020

よって何らかの変数を監視するよう割り当てても、同じ 64byte 以内に
割り当てられた他の変数へアクセスによって解除される可能性もあります。

(1) 判定用メモリ領域 64byte (CPUIDで判定) を用意して初期値を入れる
(2) monitor 実行
(3) monitor 命令実行中に書き換えられている可能性があるので判定する。
  書き換わっていたら値によって適切な分岐。
(4) 書き換わっていなければ mwait
(5) 解除されたらその要因を調べる。
  値が書き換わっていたら値によって分岐。
  書き換わっていなければ (2) へ戻る。

もし使うならこのような手順になるようです。
つまりスピンロック時に監視アドレスを与えて停止させられるため、
ループ中に導入することでバスアクセスを減らし、効率を上げることが出来ます。
でも使えませんでした。



以前こちら で触れたように 対応機種一覧 で非対応と書いてありますが 購入してみました。

ATOK for WindowsMobile

EMONSTER lite S12HT へもインストールは可能で、一応 ctrlswapmini lite を
使って、2タッチ/ポケベル入力を行うことが出来ました。トグル入力も可能ですが
キーだけで文字種切り替えが出来ないので難があります。

「非対応」と書かれている理由は、やはり ATOK だけではテンキーによる文字入力が
出来ないためでしょう。
外部でトグル入力やポケベル入力出来るソフトなどを組み込めば、テンキーでも
それなりに使用できるものになると思われます。

また今まで他の機種に内蔵されていた ATOK とほぼ同じで、キーコマンドへの対応
状況や反応も同じ。ソフトからの制御も同じように出来そうです。

例えば Wnn や FSKAREN ではできなかった、確定のみで改行しないキーコードが
使えるため ctrlswapmini との相性も良いです。
ただし ctrlswapmini lite 1.02 は、Wnn 対応のためにこの動作を省いているので
今のところ恩恵がありません。

ATOK 設定の「バージョン番号」のタブにも、特にバージョン番号らしきものが
無いので、手持ちの EM・ONE 内蔵のものと完全に同じかどうかはわかりません。

現在 EMONSTER lite S12HT には、これで 4つの IME が同居しています。
同時に使えるのは一つだけで切り替えは再起動を伴うため、メモリ的にも特に
問題はなさそうです。

使用できる IME のまとめ

    確定のみ テンキー文字入力 外付けキーボード
MS-IME   ○      ×        ○
内蔵Wnn   ×      ○        △(スライドで切換え)
FSKAREN   ×      ○        ×
ATOK    ○      ×        ○


テンキーによるトグル入力処理は、サポートソフトを何も入れない単体の状態だと
Wnn と FSKAREN のみ可能です。
ただし IME 自体が自前でテンキーのトグル処理を行っているので、それぞれ
持っている機能や細かい操作性が異なります。このあたりは好みの問題も出てくる
でしょう。2タッチ/ポケベル入力はそのままでは出来ません。

テンキーの文字入力処理に対応すると数字キーを乗っ取ってしまうために QWERTY
キーボードとの同居が出来なくなります。外付けキーボードを使った場合などに
問題が生じます。
上の表でも、テンキー入力と外付けキーボード対応はほぼ排他です。

唯一 FSKAREN のみ、テンキーのスライドに応じてモードを切換えてくれるので、
一応両方使うことが出来ます。
テンキー専用機種とそうでない機種との違いは、FSKAREN 自体のバイナリを
個別に分けることで対応しているようです。


●外付けキーボードとの相性で問題が生じる原因

・テンキーによる文字入力に対応していると、数字キーが乗っ取られてしまう
  IME 側でテンキー入力処理を一時的に解除する機能が必要

・変換操作がスペースや変換キーでできない(カーソルキーのみなど)
  操作キーをカスタマイズできる機能が必要
  または外付けキーボードを考慮したキーバインドをあらかじめ行っておく

・変換や文字入力モードを切り替えできない
  テンキーに特化した IME だと、漢字、全/半、ひらカタキーなどで文字種を
  切換えられないものがある。


●ctrlswapmini との相性で問題が生じる原因

・キーストロークだけで文字種を変更できないものがある
   そのため IME 制御を行って、IME の on/off だけで英数とかな入力を
   切換えなければならない。

・変換バッファの確定だけ行って改行しないキー操作が必要
   IME 制御を行う場合、未確定バッファを捨てないで済むために必要。
   IME 制御をしなくても良いなら無くても何とかなる。

・一時かなモードの使用
   ローマ字入力モードでありながら、かな入力のシミュレートが出来る
   特殊なキーシーケンス。英語キーボードと見なす端末だとそもそも
   かな入力自体ができないようです。

プログラム側から見ると、MS-IME + 日本語キーボードとみなす場合が一番問題が
少ないです。次はおそらく ATOK だと思いますが、単独でテンキー入力出来ないし
まだほとんど調べていないため、まだ何ともいえません。


関連エントリ
WindowsMobile IME FSKAREN / ATOK
EMONSTER lite S12HT IME FSKAREN




バグ報告をいただいたので修正しました。
定数の値数で、-129 ~ -32768 の範囲の場合のみ符号が失われてしまいます。
値から一目瞭然ですが 1byte、2byte、4byte のそれぞれの範囲で定数の扱いを
区別しており、2byte の場合のみ符号が考慮されていなかったことが原因でした。

touchkeysip v1.07



●シェーダーの動的リンク

もともと Shader はマテリアルやライティング、アニメーションなど、組み合わせに
応じてすぐに数が増加する傾向があります。
加えて SM2.0~4.0 と徐々に固定機能が廃止され、有効な RenderState が減ると
さらに必要なシェーダー数が増えています。

シェーダー内の分岐もできますが、やはり大規模な並列実行でクリティカルな部分
なので、速度への影響が大きいマテリアルでは慎重になります。

もう1つ心配なのがコンパイル速度です。
シェーダーのコード量が増えるに従って、急激にコンパイルに時間がかかるように
なってきた印象があります。
シェーダーは CPU のコンパイラよりも比較的大胆な最適化が行われているので、
総当たりで比較しているのではないかとたまに思う時があります。

Direct3D11 ではこのような問題を解決するため、動的にシェーダーの Link が
できるようになるとのことです。
SetShader() 時に参照が解決されますが、HW native に変換されたコードで処理が
行われるため、リンクの操作も軽く、実行時の動作も速いそうです。
詳しい仕組みやパフォーマンスへの影響はまだわかりませんが、
分割コンパイルできるし組み合わせによる数の増加が抑えられるので、
管理はかなり便利になると思われます。

逆に、すでにシェーダー管理の仕組みを構築している場合は、D3D10→D3D11 への
移行時にいろいろと修正が必要になるかもしれません。
またいろいろ考えることが増えそうです。


●圧縮テクスチャ BC6/BC7

新しい圧縮テクスチャ BC6 は、HDR テクスチャの圧縮に使われるようです。
16 bpc RGB、つまり R16G16B16 相当を 1/6 = 1byte に圧縮するものと考えられます。

圧縮率 1/6 と書かれていますが、DXGI のフォーマットには 6byte = 48bit
の形式はないため、R16G16B16A16 との対比では alpha が無くなるものの
実質 1/8 のメモリ効率が得られそうです。

圧縮方法は従来の BC1~BC5 (DXT) によく似ています。
4x4 のブロックを単位にエンコードしますが、その手法はより複雑になっているようです。
格納するベースカラーに Alpha が無い代わりに HDR なこと、
ブロック毎にアルゴリズムを柔軟に変更できること、
エリアを分割して複数のパーティションとし、それぞれが異なるカラー補間テーブルを
参照できること、などなど。
これ以上の詳細はわからないので、DirectX11 SDK のリリースを待つ必要があるでしょう。


同じように BC7 は、HDR ではないカラー値の圧縮をより改良したものです。
BC6 同様にブロック毎にアルゴリズムを変更でき、RGB や RGBA の両方に対応できます。
RGB 比 1/3、RGBA で 1/4 とのことなので、やはり 1byte/texel となるようです。
これは BC2~3 (DXT3/DXT5) 等と同じです。

BC7 で完全に置き換えられるなら、BC2/3 は使われなくなるかもしれません。

テクスチャの最大サイズは 16384x16384 まで拡張されるようです。
16384x16384 32bit RGBA 相当で 1GByte
BC1(DXT1)/BC4 で 128MByte
BC2~3(DXT3/5),BC5~7 で 256MByte


関連エントリ
Direct3D11 マルチスレッドのための機能
Direct3D11 テセレータとシェーダー
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11



PC もマルチコア CPU が当たり前となり、マルチスレッド化がパフォーマンス向上の
鍵となっています。
Gamefest2008 の D3D11 関連のスライドによると、Direct3D11 ではようやく
本格的にマルチスレッドへの対応が行われるとのことです。

Gamefest 2008 Presentations

これまでは、原則としてレンダリング用の単一のスレッドがリソースアクセスや
描画を行う必要がありました。

D3D11 では非同期のリソース読み込みや複数スレッドからの描画が行えるようです。
またこれらに対応したため、個別に作成された Display List を使った描画も
実質的にできるようになっています。
ゲーム専用ハードでは当たり前のものですが、PC 側にフィードバックされる形と
なったようです。

概念としては現在の Device Interface (ID3D10Device) が、複数の Interface に
分割されます。

 (1) Device
 (2) Immediate Context
 (3) Deferred Context

リソースの作成は従来通り (1) の Device を通して行います。
Thread 対応となり、複数のスレッドで呼ばれても問題が起こりません。

(2) の Immediate Context は従来の ID3D10Device 等での描画に相当し、
レンダリング用スレッドで命令をすぐに発行できます。

(3) の Deferred Context は他のスレッドで描画命令を使用する場合に用いられます。
描画命令はバッファリングされます。いわば内部的に Display List が作られ、
最終的にレンダリングスレッドで Immediate Context と同じように描画命令を発行
できます。
API によっては DispalyList へ乗らないものもあるので、多少の制限は存在します。

基本的に各種ステートがそれぞれの Context 間で干渉することはないようです。
独立して管理し、Display List の描画を行ったあとにステートをリセットした方が
速いとのこと。
この辺の仕組みが具体的にどのような実装になっているのかまだわかりません。


D3D11 は上位互換性があり、D3D10 用の今の GPU でも動作することになっています。
現在の GPU ドライバはスレッド対応になっていないため、呼ばれた API を
バッファに記録して擬似的に Display List をエミュレートする形になるそうです。

リソースアクセスも、使用できるものの lock の粒度が荒くなるため効率は
それなりに落ちるとのこと。
将来的には Direct3D10 世代の GPU でも、ドライバの更新によってスレッド対応化が
行われてパフォーマンスが改善されるようです。


ちなみに現在の D3D9~10 でも、デバイス作成時のフラグで API 呼び出しを
Multi Thread 対応にすることが出来ました。
これは古いやり方で作られており効率悪いため、指定しない方がよいとのことです。


これまでは、使用する Direct3D SDK を次々と乗り換えてきたのは GPU の新しい
機能を使うためであって、GPU の都合によるものでした。

今回の更新は、今のマルチコア CPU を最大限活用するためにも必要となるかも
しれません。


関連エントリ
Direct3D11 テセレータとシェーダー
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11



細かい使い方まではわかりませんが、様々な用例から構造が少しずつ見えてきています。
プログラマブルなシェーダー Hull Shader と Domain Shader に挟まれた形で
Tessellator が入ります。

このテセレータというのは、位置的にも機能的にもラスタライザに非常に近いもの
なのかもしれません。
そう思えば固定機能であることも納得できます。

DomainShader はラスタライズ後に走る Pixsel Shader に相当し、規模も走る
スレッド数も動的に変化します。

テクスチャによってエフェクトが入る点も似ています。
DomainShader は Displacement Map を読み込むので、Pixsel Shader に次いで
テクスチャアクセスを多用するシェーダーとなりそうです。

そもそも、動的にサイズが変化するユニットだからこそイメージマップを利用する
意味があるわけで、必然というか当たり前のことなのかもしれません。


単一のパイプライン中に Tessellator と Rasterizer の 2ヶ所でデータの増幅が
行われます。本当は Geometry Shader でも可能なので 3ヶ所です。

逆にポリゴン減らすのは、生成後のプリミティブ単位で実行される Geometry Shader
でしか出来ないと思われます。
もしマップによってメッシュに穴を開けたいなら、GeometryShader でもテクスチャを
サンプリングするか、Domain Shader からパラメータを渡すことになるのでしょう。

ピクセルを減らすこと自体は PiselShader でも clip (discard) で可能です。


Vertex 単位で走る VertexShader や、Pixel 単位で走る PixelShader を考えると、
GeometryShader は PrimitiveShader といった方が理解しやすいかもしれません。
となると HullShader は PatchShader です。

DomainShader は Post Vertex Shader といった位置づけで、Tessellation 後の
VertexShader に相当します。
本来の VertexShader は Pre Vertex Shader。

VS Vertex Shader   →  Pre Vertex Shader
HS Hull Shader     →  Patch Shader (Pre Primitive Shader)
TS [[Tessellator]]
DS Domain Shader   →  Post Vertex Shader
GS Geometry Shader →  Primitive Shader
RS [[Rasterizer]]
PS Pixel Shader

だいぶすっきりしました。
でも全部略称が PS になって区別できないからやっぱりだめです。


Tessellator や Displacement Map によって 3D データの作り方は今後変わっていく
と思われます。
3D だけでなく、ベクタフォントを GPU で直接描画するなど 2D 面でも応用できる
かもしれません。


関連エントリ
Direct3D11 のパイプライン
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11



今日も Gamefest2008 の資料を参考に、D3D11 関連をいろいろ見てみます。
Gamefest 2008 Presentations


D3D11 ではテセレータと共に新しくシェーダーステージが追加されています。
Direct3D 11 の目玉機能の一つです。

新しく Patch プリミティブが導入されるようです。
Quad で指定可能で、かつ隣接する頂点情報を入力できます。

D3D10 GeometryShader の Triangle Adjacency に少々似てますが、
Triangle Adj は最大6頂点まででした。

Patch は最大 32 頂点まで入力できるようです。
たとえば単純で均等な Quad mesh なら、それぞれの隣接 Quad を1つ受け取ると
12頂点です。
これをコントロールポイントとして使います。

GeometryShader ではプリミティブ毎に 1つのシェーダーが走る形式でした。
HullShader は周囲の頂点情報を受け取りつつも、各入力頂点 (ControlPoint)
毎にシェーダー (Thread) を走らせることが可能となるようです。

頂点シェーダーと違うのは、それぞれのシェーダーが同じパッチ内のすべての
コントロールポイントにアクセス出来るということ。


また HullShader は、GS のようにパッチ毎に 1つだけ走らせることもできそうです。
おそらく、パッチ単位で走る HullShader 関数と、コントロールポイント毎に
走る HullShader 関数の両方を指定出来るのではないかと思われます。


HullShader はテセレータの前段階です。
テセレータの後に位置するのが DomainShader と呼ばれます。

DomainShader はテセレータで生成された頂点毎にシェーダーが走るようです。
この場合もパッチ単位で、入力されたコントロールポイントすべての情報を
受け取ることができます。


このように細切れで ShaderStage が増えているのは、入出力情報のグループ化に
よるものでしょうか。

とりあえずまとめてみました

VertexShader   頂点毎に走る。  入力情報はその1頂点のみ。
HullShader     パッチ毎。      パッチのコントロールポイントを全部参照できる。
HullShader     コントロールポイント毎。パッチのコントロールポイントを全部参照できる。
DomainShader   生成された頂点毎。 パッチの入力コントロールポイントを全部参照できる。
GeometryShader 生成されたプリミティブ毎 。プリミティブを構成する頂点を全部参照できる。
  テセレータがプリミティブとして Adjacency を生成できるかどうかは不明。
PixelShader    ラスタライズされたピクセル毎。GS or VS 出力から補間された値が入力となる。


関連エントリ
Direct3D11 Compute Shader など
Gamefest2008 と Direct3D 11



再び Gamefest2008 のあたりから D3D11 関連。

Gamefest 2008 Presentations


●Compute Shader

ポストフィルタなど Compute Shader の想定されている用途や、
RWTexture2D/RWBuffer が PixelShader でも使えることなどから、
Compute Shader は Pixel Shader に近いものだと考えられます。

実際に現在の GPU でも、AMD Stream SDK の CAL で走るプログラムは
PixelShader 相当だったため一致しています。

Compute Shader は 32KByte のシェアドメモリにアクセス可能です。
2048 float4 = 8192 float = 32KByte

共有メモリと言うよりも、スレッド間で共有されるレジスタ Shared Register と
表現されているようです。

RADEON HD4870 の CAL を使った global buffer (shared local) は実測で
2048 vector、ちょうど 32KByte でした。
これが Shared Memory (Register) 相当と考えられるためほぼ一致しています。

任意の読み書きと Shared Register 以外の特徴として Atomic 命令があります。
32bit 値の read-modify-write に対応しているようです。
命令も Windows のような Interlocked~()

これを利用してスレッド同期が可能となり、排他的なメモリへアクセスなどが
できるようです。
AMD CAL では見あたりませんでしたが、CUDA では 32/64bit の Atomic 命令を
備えているようです。

AMD CAL でも Global Buffer へのアクセス、たとえば
「add g[0].x, g[0].x, r1.x」が Atomic なら代用できますが
そうではないようです。

il_ps_2_0
dcl_input_position_interp(linear) v0.xy
dcl_output_generic o0
dcl_literal l0, 1, 1, 0, 0
itof r1.x, l0.x
add g[0].x, g[0].x, r1.x
ret_dyn
end

g[0].x は毎回異なる値となりました。


● API

Direct3D11 は Direct3D10 とほぼ同じ API セットを持ち、機能拡張されている
ものとなるそうです。
詳細は SDK のリリースを待たないといけませんが、おそらく Direct3D8 と
Direct3D9 の関係に近いものだと考えられます。

DirectX7 までのベースとなる DirectDraw を捨てて、Direct3D8 は作り直されました。
その後の Direct3D9 は完全に互換性があるとはいえないものの、考え方や設計は
Direct3D8 とほとんど同じものでした。

Direct3D11 は Direct3D10 の GPU でも動作するそうです。
11 専用の機能を使用することは出来ませんが、9→10 よりはスムーズな移行が
できそうです。

でもこれは Direct3D9 以前は当たり前のことでした。
DirectX7 世代の GPU でもシェーダーなど未対応機能が走らないだけで DirectX8
が使えるし、ShaderModel1.x の Direct3D8 世代 GPU でも Direct3D9 がそのまま
使えます。

Direct3D9 から Direct3D10 への切り替えがあまりに特殊すぎました。
GPU も OS も新しくしなければならず互換性も無かったので。


関連エントリ
Gamefest2008 と Direct3D 11
AMD Stream SDK



Gamefest 2008 のスライドが落とせるようになっているようです。

DirectX Developer Center から GDC 2008 Presentations Now Available
へ飛び、Microsoft XNA Developer Presentations の一番上にある
Gamefest 2008 Presentations をクリックします。

Gamefest 2008 Presentations

DirectX 11 関連のスライドも多数あって参考になります。
まだしっかり目を通してないですが、いくつか気になったところなど。


●書き込み

D3D11 の ShaderModel 5.0 では、新たに書き込み可能なリソースが追加
されるようです。RWTexture2D や RWBuffer など。

従来のシェーダーと違ってランダムな位置に書き込み可能なこの機能は、
最近の GPGPU 向け言語 (CUDA, AMD CAL 等) に設けられています。

Compute Shader だけかとおもったら、Pixel Shader でも使えるようです。

書き込みはオフセット付きで配列のように扱えます。

またテクスチャロードも配列形式の書式が使えるようになっています。
前はテクスチャオブジェクトに対するロード命令だったので、
ちょうど同等の機能が operator[] で定義されているものと思われます。


●HLSL

HLSL で class 定義できるようです。interface の宣言も可能。
ShaderModel 4.0 向け HLSL でも、Texture のロード命令や型宣言のみそれっぽい
書式でしたが、次は本当に class として扱えるようです。

double や long 型は、今度こそ本当に使えるようになります。
D3D10/DX10 シェーダーと64bit浮動少数


●コンパイラ

HLSL もいろいろ拡張されており、コンパイラも複雑になっていると考えられます。

D3D9 の FX (HLSL) コンパイラは D3DX9 に含まれており単なるライブラリでした。

D3D10 では core API に含まれましたが、SDK の途中から扱いが変わっています。
SDK 側で更新がはいったものの、core API 経由だと従来の 古いコンパイラ が
使われ、D3DX の API だと更新されたコンパイラが呼ばれます。

以前この辺の挙動を調べました
Direct3D 10 Shader4.0 APIによってコンパイラが違う
Direct3D 10 Shader4.0 シェーダーのコンパイル

core に含めてしまうとおいそれと更新できなくなるため失敗だったのでしょう。
D3D11 ではコンパイラの改良や修正ができるよう再び D3DX のライブラリ扱いに
戻っています。


●新しいテクスチャ形式

テクスチャ圧縮形式として新たに BC6、BC7 が追加されています。
具体的にどのような構造でどのようなアルゴリズムなのか詳細まではわかりませんが
これまでの DXT/BC の欠点を克服したものになりそうです。

ちなみに BC1~ は従来 DXT と呼ばれていたものです。

・D3D10
BC1 = DXT1
BC2 = DXT3
BC3 = DXT5
BC4 = 1チャンネルの圧縮
BC5 = ATI の法線圧縮形式 3Dc/ATI2

・D3D11
BC6
BC7


● Direct3D 11 SDK

かなり情報が多いので、D3D11 の登場は意外に早いのかもしれません。
以前 こちら で触れたように DXGI の扱いが微妙に変わっています。
DXGI は共通のコンポーネントなので、D3D10 と並列に D3D11 を持ってくることが
目的なのかもしれません。


関連エントリ
DirectX11 へ (D3D11)
Direct3D 10 Shader4.0 APIによってコンパイラが違う
Direct3D 10 Shader4.0 シェーダーのコンパイル
D3D10/DX10 シェーダーと64bit浮動少数



FSKAREN に続いて ATOK for WindowsMobile も登場します。
ダウンロード版や優待版もあるみたいだし、これで S12HT に入れれば
MS-IME、Advanced Wnn、FSKAREN、ATOK の 4 IME 環境ができるかと思ったら

動作確認済み機種 ATOK for Windows Mobile

の下の方「非対応機種」に

”以下の機種では、日本語での文字入力が正常に行えません。現在のところ回避方法はありません”
EMONSTER LITE (S12HT) / HT1100

ATOK はテンキー入力に対応していないようです。
ctrlswapmini lite で何とかなるかもしれませんが、IME の種類が増えると
それはそれで大変。

ほぼ同時期の登場で、一見かぶると思われた FSKAREN とは少々方向性が違うようです。
こちらは機種毎のバイナリを用意してまでテンキーに対応しています。
ちょうど良いかも。

関連エントリ
EMONSTER lite S12HT IME FSKAREN



キーボードが 15パズル になっていて、自由にキー入れ替えできる
ソフトウエアキーボード (sip) です。

puzzlesip v1.00

スライドして入れ替え。

puzzlesip

WindowsMobile touchkeysip 用です。



FSKAREN は WindowsMobile 用の日本語入力&漢字変換ソフト (IME) です。
自作ソフトの関係で質問を頂いたので試しに使ってみました。

FSKAREN for Windows Mobile 富士ソフト

上記の公式ページを見ても、対応機種も載ってないし すっきりしない説明でかなり
わかりにくくなっています。
ダウンロード販売のページに飛ぶと、やっと対応機種一覧を見ることが出来ます。

・Windows Mobile 5.0/6 Standeard/6 Professional
・Softbank X01HT
・Softbank X02HT
・Softbank X03HT
・Softbank X01T
・NTT Docomo hTc Z
・EMOBILE EMONSTER S11HT
・EMOBILE EMONSTER lite S12HT

要は IME の一種で、ATOK 等と同じように WindowsMobile 端末にインストールして
MS-IME の代わりに使用することが可能です。
実際に購入してみると、対応機種にインストールすべき CAB ファイルが分かれていました。

FSKAREN_HT1100-S12HT.CAB
FSKAREN_hTcZ.CAB
FSKAREN_S11HT.CAB
FSKAREN_X01HT.CAB
FSKAREN_X01T.CAB
FSKAREN_X02HT.CAB
FSKAREN_X03HT.CAB

よく見ると対応機種一覧に載っていないはずの Docomo HT1100 があります。
pdf のマニュアルにも HT1100 としっかり書かれています。
HT1100 と S12HT は機能的に同じ端末と見なして良いのかもしれません。
(ctrlswapmini lite も HT1100 でそのまま動く可能性があります)

ニュース: 富士ソフト

上記ニュースリリースの段階では S12HT も対象機種に含まれていませんでしたし、
「※上記以外の端末も、今後順次ご提供予定」と書かれていますので、今後さらに
対象機種が増える可能性があります。


実際に EMONSTER lite S12HT に FSKAREN_HT1100-S12HT.CAB をインストールしてみました。
ちなみに S12HT は標準で Advanced Wnn が入っています。

現在の使用環境は下記の通りです。

・Today プラグイン無し、標準の HTC のプラグインも全部外してまっさらな状態
・常駐ソフトは em1key のみ
・SIP として touchkeysip + eckeyboardsip を組み込み

em1key はテンキーの文字入力と干渉するので、FSKAREN 利用時は外しました。
FSKAREN を使って、テンキーで文字入力できるようになりました。

設定は \Windows の FSKAREN.cfg に保存されているようです。


●FSKAREN によるテンキー文字入力

Advanced Wnn とほぼ同じキーアサインになっています。

・文字種切り替えは [*] キー
・[#] キーで逆トグル可能

文字入力の直後は [*] キーで濁点半濁点変換と大文字小文字変換になります。
標準の Advanced Wnn だと大文字小文字変換できなかったので、この点は FSKAREN
の方が優れています。
ctrlswapmini でいえば後変換キー相当で、au 系端末に近い操作です。

キー長押しはトグル操作のキーリピートになってしまい意味がありません。
文字種切り換えメニューも出ず、数字入力にもなりません。
この点は Advanced Wnn より劣ります。

同じキーの文字を連続入力する場合、[→] キーによる確定操作に補正がかかりません。
カーソルキーを左に戻してから、同じ文字を挿入しようとして [→] を押すと
カーソルが右に移動してしまいます。
この点は一般の携帯電話よりも操作性が劣ります。
Advanced Wnn も同じ問題を抱えています。

pdf のマニュアルは不完全で、テンキーを使った文字入力方法の説明が載って
いませんでした。


●外付け Bluetooth キーボードによる入力

Advanced Wnn と違い、スライドキーボードを開いた状態でも特に入力を取りこぼす
ことはなく普通に入力出来ました。
ただし数字入力に問題があります。
外付けキーボードの [0]~[9] のキーを押しても、テンキーと同じように文字の
トグル入力が行われてしまいます。

Advanced Wnn と違ってスライドキーボードを閉じても直りません。
外付けキーボード向けに、入力モードを変更する機能が欲しいところです。


●操作に限定した FSKAREN のメリット (Advanced Wnn との比較)

・[*] で大文字小文字変換が出来るようになる
 ただしトグル自体にも小文字を含むので、ショートトグルが好みなら合わないかも


●Advanced Wnn と同じ問題点

・テンキーだけで単独改行は出来ない。決定キーが必要なので、決定を改行以外の
 用途で使うソフトだと改行入力出来ないことがあります。

・[→]キーでトグル入力状態だけ解除したいのにカーソルも移動してしまう。


●FSKAREN の問題点

・長押しで数字入力出来ない。

・キーリピート速度を最速に設定していると、トグル入力のリピートが発生して
 入力ミスが起こりやすい。

・外付けキーボードから入力する場合に問題あり。
 数字キーがテンキーとして取られてしまう。


●ソフト

touchkeysip は一応動きますが文字種切り換えの問題が生じます。
IME が off になると入力モードが英字 [A] に戻ってしまいます。
キーボード側で文字種を切り換えなければなりません。
ただし数字入力は衝突せず、ソフトキーから [0]~[9] を入力しても文字トグルに
ならずに入力可能でした。

ctrlswapmini lite は一応動作しますが、ほぼ Advanced Wnn 同様の問題が
あります。文字種切り替えできず、高速に連続入力した場合に IME 切り替えを伴う
ケースで、判定タイミングのずれが発生します。
IME の種類が増えるとますます対応が困難になりそうです。


●変換その他

他の IME では必ず予測変換などの候補ウィンドウを off にして使っていました。
FSKAREN は確かに表示が速いようです。
今回はこのままデフォルトの設定で使ってみます。

要望点
・テンキーのキーリピートを無視して欲しい (長押しはできれば数字入力に)
・外付けキーボード用に、数字キーの判定モードを切り換えられるように
・IME のキーバインドを変更したい
・未確定バッファを確定するけど、未確定バッファが空でも改行しない操作が欲しい



2008/08/24
AMD Stream SDK (2)

Global Buffer は Shader には無い機能で自由に書き込めますが、同時アクセスで
衝突します。2つの入力値を比較し、相違があった場合だけ値を書き込むような
使い方だと、1回の実行で結果を一カ所に集約できます。
コリジョン判定などに使えるかもしれません。

il_ps_2_0
dcl_input_position v0.xy
dcl_resource_id(0)_type(2d,unnorm)_fmtx(float)_fmty(float)_fmtz(float)_fmtw(float)
dcl_resource_id(1)_type(2d,unnorm)_fmtx(float)_fmty(float)_fmtz(float)_fmtw(float)
dcl_output_generic o0
sample_resource(0)_sampler(0) r0, v0.xy
sample_resource(1)_sampler(0) r1, v0.xy
eq r2.x, r0, r1
cmov g[0], r2.x, v0
mov o0, r2.x000
ret_dyn
end

コンパイル時のエラーは calclGetErrorString() で返ってきますが、
エラー行もわからずあまり意味のある情報が含まれていないので慣れるまで
デバッグは少々大変。

HLSL を使うには utilities\amdhlslCompiler を使います。
HLSL コンパイラ自体はただの lib で、amdhlslCompiler 以下でそのまま
実装されているようです。

関連エントリ
AMD Stream SDK



oyayubiwm による親指シフト定義ファイルでは、デフォルトで JISかな
入力のキーストロークをシミュレートしています。

例えば "か" を入力する場合 [かな]+[T] となります。

親指入力時に、ローマ字でしか入力出来ない文字を定義したいとの質問があったので
ローマ字入力をシミュレートする方法を試しました。

「か」の入力の場合 script 内で下記のように定義されています。

### かな入力シミュレートの場合
func TABLE_FUNC _kana_KA
	SETMODIFIER	MOD_KANA
	SENDKEY	'T'	# か
	ifsw CSW_COUNT
		CALL	_subCount2
	endif
	RETURN	0
endfunc

これを次のように変更すると、JISかな入力ではなくローマ字入力のキーストロークで
文字入力を行うようになります。

### ローマ字入力シミュレートの場合
func TABLE_FUNC _kana_KA
	SENDKEY	'K'	# か
	SENDKEY	'A'	#
	ifsw CSW_COUNT
		CALL	_subCount2
	endif
	RETURN	0
endfunc

ローマ字入力で定義するメリットは、キーボード配列に依存しないことと
かなキー入力でキーボードにマップされていない文字を入力出来る可能性があることです。
デフォルトでローマ字入力になっていないのは、WindowsMobile は描画が遅いため
子音のエコーバック遅延が生じるのを避けたかったためです。

oyayubiwm v1.45
em1key v1.27
em1keypc v1.32


2008/08/23
AMD Stream SDK

コメント欄で、Vista で走らせる方法を教えて頂きました。
WindowsVista x64 SP1 + RADEON HD 4850 を使用しています。

AMD Stream SDK

(1) AMD Stream SDK 1.01.0_beta を install
(2) Folding@home GPU2 6.20 を install
(3) C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\lib\xp32
  内の amdcalcl.dll, amdcalrt.dll の代わりに、
  C:\Users\<USER>\AppData\Roaming\Folding@home-gpu
  に入っている dll を使う。

(2) の注意点
すでに NVIDIA GPU 上で Folding@home を走らせたことがある場合は下記の手順で
 1. Folding@home を uninstall
 2. C:\Users\<USER>\AppData\Roaming\Folding@home-gpu を削除
 3. \C:\Program Files (x86)\Folding@home\Folding@home-gpu を削除
 4. Folding@home を再び install

例えば C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\bin\xp32 に
入っているサンプルは、上記 dll と同じ場所にあれば実行できます。
サンプルのコンパイルは VisualStudio2008 でも大丈夫でした。

CAL の使い方は
C:\Program Files (x86)\AMD\AMD CAL 1.01.1_beta\doc
の ProgrammingGuide.pdf に従います。

GPU 上で走らせるプログラム kernel はほぼシェーダー相当の機能を持っています。
入出力用のリソースを確保し、context に割り当てて、シェーダー内のレジスタに渡します。

最初少々はまったのは PixelShader 相当だということ。
入力リソースは dcl_input に渡すわけではなく、あくまで texture のように
リソース扱いで sampler 経由で読み込みます。
4096 vector 以下なら constant buffer を使うことも可能です。

dcl_input で受け取るのはラスタライザの補間パラメータ相当です。
CAL の場合はこれを自分自身の ID と見なすことが出来ます。
いわゆるシステム値の SV_Position で、出力位置を指しています。

dcl_input の詳しい説明が載ってませんが、ほぼ次のような宣言の仕方で
使われています。

dcl_input_position v0.xy
dcl_input_interp(linear) v0.xy

例えば実行時の CALdomain が 0,0 から 128,128 までなら
0.5~127.5 のように 0.5 offset された値が入ります。
上の 2つの宣言の違いは特にありませんでした。

CALdomain は出力範囲の指定に相当します。RenderTarget の書き込み範囲です。
実行するプログラムの数や dcl_input のパラメータにも影響します。

シェーダーと違うのは、自由に読み書きできる共有メモリ Global Buffer を持っていることです。
Global Buffer (g[]) は Constant Buffer (cb[]) と同じように、命令内で直接
アドレッシング出来ます。書き込みも出来ます。

mad g[0], r0, g[1], r1

o0~ を使ったストリーム出力と違い書き込み制限がありません。

マニュアルに詳細が書かれていませんが、実際に試したところ 4850/4870 では
最大 2048 vector 使用することが出来ました。

常に 128bit = 4要素単位となるため、8192 float 相当 = 32KByte 分と考えられます。
特に同期などの仕組みがないので、同じ Global Buffer への書き込みが発生した場合、
値は不定となるようです。

実際に Global Buffer から値を読んで Global Buffer に書き込むプログラムを
走らせてみるとわかります。
同じタイミングで実行されているスレッドでは同じ初期値が読み込まれます。
実行スレッド数を増やしていくと、そのうち書き込んだ値を読み出している
スレッドも含まれるようになります。

実行はほぼ ID 順ですが、リソース読みだしを行うと順番が崩れてきます。
リソースアクセス待ち間のスケジューリングのためと考えられます。

DirectX11 の Compute Shader では同期アクセスがサポートされるらしいので、
同じメモリに書き込みを行って合計値を求めるような使い方ができるみたいですが
CAL ではおそらく出来ません。

RADEON HD 4850
##calDeviceGetInfo()
target=5  RV770
maxResource1DWidth=8192
maxResource2DWidth=8192
maxResource2DHeight=8192

##calDeviceGetAttribs()
target=5
localRAM=512
uncachedRemoteRAM=2047
cachedRemoteRAM=2047
engineClock=625
memoryClock=337
wavefrontSize=64
numberOfSIMD=10
doublePrecision=1
memExport=1

関連エントリ
AMD Stream Computing



●まとめ

・Animation 無しの場合

 ■ Transform Shader
  + in VertexStream 0 ( _LL_geometry00 ) M3+P
  + in ShaderResourceView ( _LL_geometry00 ) M3+P
  + in ConstantBuffer ( "GRoot" = _LL_rootWorld ) M4
  + out StreamOutput ( _LL_geometryWorld ) M3

・Animation ありの場合

 ■Animation Shader ( Animation Data がある場合のみ )
  + in VertexStream 0 ( _LL_geometry00 ) M3+P
  + in ShaderResourceView ( "GAnimation" = _LL_Anim00 ) M3
  + in ConstantBuffer ( "GTime" )
  + in ConstantBuffer ( "GBind" )
  + out StreamOutput ( _LL_geometryAnimation ) M3+P

 ■Transform Shader
  + in VertexStream 0 ( _LL_geometryAnimation ) M3+P
  + in ShaderResourceView ( _LL_geometryAnimation ) M3+P
  + in ConstantBuffer ( "GRoot" = _LL_rootWorld ) M4
  + out StreamOutput ( _LL_geometryWorld ) M3

 ■Bone Shader ( Bone Matrix を持っている場合のみ)
  + in VertexStream 0 ( _LL_geometry00 ) M3+P // 後半の BoneMatrix のみ
  + in ShaderResourceView ( _LL_geometryWorld ) M3
  + out StreamOutput ( _LL_geometryWorldB ) M3

M3 = Matrix:float4x3
M4 = Matrix:float4x4
P = Index:int4


・描画

 ■Draw IndexedInstanced (single)
  + in VertexStream 0 ( VertexBuffer )
  + in VertexStream 1 ( _LL_geometryWorld )
  + in ConstantBuffer ( "GCamera" )
  + in ConstantBuffer ( "GLight" )

 ■Draw Bone Indexed
  + in VertexStream 0 ( VertexBuffer )
  + in ShaderResourceView ( _LL_geometryWorldB )
  + in ConstantBuffer ( "GCamera" )
  + in ConstantBuffer ( "GLight" )



●Animation なしのまとめ

 ■ Transform Shader
 + in VertexStream 0 ( _LL_geometry00 )
 + in ShaderResourceView ( _LL_geometry00 )
 + in ConstantBuffer ( _LL_rootWorld ) 描画時に CPU が与える
 + out StreamOutput ( _LL_geometryWorld )


●Animation ありの場合

準備
 1. 頂点に Geometry の node 番号と weight 値を埋め込んであります。
 2. Animation データは plot した値をバッファにつめて格納します。
 3. 描画単位のノード毎に、参照する bone の逆行列をあらかじめ求めておいて
   GeometryMatrix の後ろに格納しています。
 4. データを読み込み、モデルに Animation データを Bind します。
   ノードとの対応表を作っておきます。

(1) Aniamtion の取り出し

単純化するため plot した値をそのままバッファに格納しています。
外部から描画すべき frame を与えて、そのフレームの Animation ノードを取り出します。
フレーム補間は容易に実現できますがここでは行っていません。

単に frame 値による値の選択なので、独立した描画パスに分ける必然性はありません。
ただし、モデルのノードとアニメーションのノードをマッピングする必要があります。

・アニメーションデータの n 番が、実モデルの何番の node に対応するのか
・対応するノードがモデルに存在しているかどうか

これらのノード対応表をデータを読み込んだあと、Animation を bind するときに
作成しておきます。

アニメーションデータのバッファ定義は下記の通り。

// 実際のアニメーションデータ
Buffer	_LL_Anim00
Usage	IMMUTABLE
Cpu	0
Bind	SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
 ~

ノード毎の frame 単位の値を、単一バッファにパックしています。
ノード対応表にはただの番号ではなく、バッファ内のオフセット値を入れておきます。

例えば index0~31 が node 3 のデータ、index 32~63 が node 1 に bind され
たとします。ノード→Animation の対応表は次のようになります。

 0: 無し
 1: 32
 2: 無し
 3: 0

ここでのセットアップ情報

// Shader Setup
Vertex			_LL_geometry00
CBuffer 		"GBind"= マップデータ
ShaderResourceView 	"GAnimation"= _LL_srv_Anim00
StreamOut		_LL_geometryAnimation
Draw	POINTLIST

その他のバッファは下記の通りです。

// アニメーション参照用
ResourceView	_LL_srv_Anim00
Link	_LL_Anim00
Format	32x4F BUFFER
Element	151110

// 出力バッファ
Buffer _LL_geometryAnimation
Usage	DEFAULT
Cpu	0
Bind	STREAM_OUTPUT SHADER_RESOURCE VERTEX_BUFFER
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	INDEX:32x4UI

出力は、アニメーションを適用した _LL_geometry00 の置き換えとなります。

// Animation Shader
struct TBindMap {
	uint	Remap;
	uint	reserved0;
	uint	reserved1;
	uint	reserved2;
};

cbuffer cb_GBind
{
	TBindMap	GBind[MAX_TRANSFORM_BUFSIZE_];
};

struct VS_INPUT_ANIMATION { // _LL_geometry00
	float4	Mat0		: MATRIX0;
	float4	Mat1		: MATRIX1;
	float4	Mat2		: MATRIX2;
	uint4	Parent		: INDEX;
	uint	VertexID	: SV_VertexID;
};

struct VS_OUTPUT_ANIMATION { // _LL_geometryAnimation
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
	uint4	Parent	: INDEX;
};

VS_OUTPUT_ANIMATION VS_Animation( VS_INPUT_ANIMATION In )
{
	VS_OUTPUT_ANIMATION	Out;

	float4	cmat0= In.Mat0;
	float4	cmat1= In.Mat1;
	float4	cmat2= In.Mat2;

	uint	id= GBind[ In.VertexID ].Remap;
	if( id != 0xffffffff ){
		// animation
		uint	offset= id * 3 + cFrame.x*3;
		Out.Mat0= GAnimation[ offset + 0 ] * cBlend.x;
		Out.Mat1= GAnimation[ offset + 1 ] * cBlend.x;
		Out.Mat2= GAnimation[ offset + 2 ] * cBlend.x;
	}else{
		// through
		Out.Mat0= In.Mat0;
		Out.Mat1= In.Mat1;
		Out.Mat2= In.Mat2;
	}
	Out.Parent= In.Parent;

	return	Out;
}


(2) 階層構造の解決

(1) の出力は _LL_geometry00 と同じものなので、これを入力として
Animation なしの場合と同じ Transform Shader に与えます。

Vertex			_LL_geometryAnimation
CBuffer			"GRoot"= _LL_rootWorld
ShaderResourceView	"GTree"= _LL_srv_geometryAnimation
StreamOut		_LL_geometryWorld
Draw	POINTLIST


(3) スキニングのためのマトリクス計算

それぞれの頂点が参照するノード個数分、静止状態で前計算した Bone の逆行列を
あらかじめ格納しておきます。これは BasePose に相当します。

この Matrix には Bone Matrix の参照用 id と、描画するオブジェクト自体が
存在する node の id を持たせておきます。

バッファ数を減らすためと管理しやすくするために、非 Animation データでも
使っていた GeometryMatrix ( _LL_geometry00 ) を流用します。
この node 用 Geometry Matrix の後ろに、追加で Bone 用 Matrix 領域を
確保しておきます。

_LL_geometry00 は index 部の .x に parent の node Geometry 番号を
格納していました。

Bone 用マトリクスは、.x に Bone Matrix の番号、.y に描画するオブジェクトの
node 番号を格納しています。

Buffer	_LL_geometry00
Usage	IMMUTABLE
Cpu 	0
Bind	VERTEX_BUFFER SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	INDEX:32x4UI	// .x= parent/bone id,  .y= world id
# node 0
 ~
# Primitive0 - Bone0
f -0.187506 -0.875848 0.444671 -7.197771
f -0.011216 0.454579 0.890635 1.248997
f -0.982199 0.162011 -0.095059 1.356605
i  6  26  0  1
 ~

ここで必要なのは Bone Matrix の部分だけです。
この値を Vertex (Stream) として入力し、アニメーション変換済みの
Bone Matrix に乗算します。

StreamOut	_LL_geometryWorldB
Vertex		_LL_geometry00	// offset 付き (Bone Matrix のみ入力)
ShaderResourceView "GOutT"= _LL_srv_geometryWorld
Draw	POINTLIST


struct VS_INPUT_BONE {
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
	uint4	Parent	: INDEX;
};

struct VS_OUTPUT_BONE {
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
};


VS_OUTPUT_BONE VS_Bone( VS_INPUT_BONE In )
{
	VS_OUTPUT_BONE	Out;

	uint	boneid= In.Parent.x;
	uint	worldid= In.Parent.y;

	float4	rmat0= In.Mat0;
	float4	rmat1= In.Mat1;
	float4	rmat2= In.Mat2;

	M34_MATRIX	mp;
	mp= mul34(
			GOutT[ boneid*3 + 0 ],
			GOutT[ boneid*3 + 1 ],
			GOutT[ boneid*3 + 2 ],
			rmat0,
			rmat1,
			rmat2
			);

	// worldid の乗算を行うと動的な変化に対応できるけどしていない
	Out.Mat0= mp.mat[0];
	Out.Mat1= mp.mat[1];
	Out.Mat2= mp.mat[2];

	return	Out;
}


今見ると、無理に Transform Shader を共有しようと思わなければ
もっと簡略化できそうですね。

関連エントリ
Direct3D10 GPU だけでジオメトリ計算 (1)



アニメーションから描画までの一連の演算を GPU のみで行ってみます。
少々古いネタで恐縮ですが、実際に 1年くらい前に作成した描画パスです。

特徴はまじめに描画エンジンに組み込んだこと。
Maya 等のツールから出力したデータを、画面に描画するまでの一連の作業に対応できます。
やってる内容はたいしたものではないものの、実作業ではどんなデータが来るかわかりません。
さまざまな状況への対応を考えると、やることは意外に複雑です。

例えば Animation は任意の Model と bind 可能で、各 node と対応する順番も任意、
存在しない node は無視し、Animation しないノードと共存できる必要もあります。
Bone 構造を持ったデータでも Animation を Bind せずに描画する状況も考えられます。

欠点はレンダリング回数が増えたために遅くて実用にならなかったことです。
他にもいろいろ理由があるのですが、、今までお蔵入りでした。


●考え方

・Animation なし

(1) Buffer 上の Geometry を元に各ノードの world matrix を算出します。
(2) (1) の結果をもとに実際の Primitive 描画を行います。


・Animation あり

(1) 任意 frame の Animation 値を、node 対応付けしながら取り出します。
(2) (1) の出力を入力と見なして world matrix の算出します。
(3) node 毎に bone が参照している matrix と、前計算した逆行列を乗算します。
(4) 頂点毎に必要なノードを参照し、blend しながら描画します。


●Animation なしの場合

(1) TransformShader

あらかじめ各 node 毎の変換 Matrix を Buffer に格納しておき、
描画時に world matrix に変換します。

Matrix は stream 入力し、変換した結果もそのまま Stream Output します。
ただし各ノードは親の影響を受けるため、他の Matrix を参照する必要があります。
そのため全く同じ Geometry Matrix のバッファを

・Vertex (StreamInput)
・ShaderResourceView

の両方に入力します。
現在の node は Stream (Vertex) で参照し、階層をたどる場合に
ShaderResourceView を使います。

Matrix は 4x3 で、空いた 4要素に親の index 番号を格納しています。

// 各 node の matrix。あらかじめ用意しておく。書き換えない
Buffer	_LL_geometry00
Usage	IMMUTABLE
Cpu 	0
Bind	VERTEX_BUFFER SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	INDEX:32x4UI	// .x= 親の index 番号、 .yzw= 未使用
# node 0
f  1.0  0.0  0.0  0.0
f  0.0  1.0  0.0  0.0
f  0.0  0.0  1.0  0.0
i  99999  0  0  1	// 99999 = 親無し
# node 1
f  1.0  0.0  0.0  0.0
f  0.0  1.0  0.0  0.0
f  0.0  0.0  1.0  0.0
i  0  0  0  1
 ~

必要な node の数だけ matrix が並びます。

セットアップは下記の通り。
"GRoot" や "GTree" は Shader 内のシンボル名で、それぞれ _LL_rootWorld と
_LL_srv_geometry00 を割り当てています。

// 描画時の Shader Setup
Vertex			_LL_geometry00
CBuffer			"GRoot"= _LL_rootWorld
ShaderResourceView	"GTree"= _LL_srv_geometry00
StreamOut		_LL_geometryWorld
Draw	POINTLIST

その他のバッファ定義

// Root の Transform 値。アプリケーションから渡す描画位置
Buffer	_LL_rootWorld
Usage	DEFAULT
Cpu	0
Bind	CONSTANT_BUFFER
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F

// ResourceView
ResourceView	_LL_srv_geometry00
Link	_LL_geometry00
Format	32x4F BUFFER
Elemet	4

// 出力用
Buffer	_LL_geometryWorld
Usage	DEFAULT
Cpu	0
Bind	VERTEX_BUFFER STREAM_OUTPUT SHADER_RESOURCE
Format
	MATRIX:32x4F
	MATRIX:32x4F
	MATRIX:32x4F

問題は、各ノードが親の影響を再帰的に受けること。
相互参照が発生するため 1pass では完了しません。
ここでは index を元に毎回 root までループして計算し尽くしています。
無駄が発生しますがとりあえず一回で終わります。

// Transform Shader

struct VS_INPUT_TRANSFORM {	// _LL_geometry00
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
	uint4	Parent	: INDEX;
};

struct VS_OUTPUT_TRANSFORM {	// _LL_geometryWorld
	float4	Mat0	: MATRIX0;
	float4	Mat1	: MATRIX1;
	float4	Mat2	: MATRIX2;
};

VS_OUTPUT_TRANSFORM VS_Transform( VS_INPUT_TRANSFORM In )
{
	VS_OUTPUT_TRANSFORM	Out;

	uint	parent= In.Parent.x;
	float4	cmat0= In.Mat0;
	float4	cmat1= In.Mat1;
	float4	cmat2= In.Mat2;

	// 親まで計算する
	for(; parent < 0xffff ;){
		M34_MATRIX	mp;
		mp= mul34(
				GTree[ parent ].M[ 0 ],
				GTree[ parent ].M[ 1 ],
				GTree[ parent ].M[ 2 ],
				cmat0,
				cmat1,
				cmat2
				);
		cmat0= mp.mat[0];
		cmat1= mp.mat[1];
		cmat2= mp.mat[2];
		parent= GTree[ parent ].Parent.x;
	}

	// 最後に root を乗算
	M34_MATRIX	mp2;
	mp2= mul34(
			GRoot[ 0 ],
			GRoot[ 1 ],
			GRoot[ 2 ],
			cmat0,
			cmat1,
			cmat2
			);

	Out.Mat0= mp2.mat[0];
	Out.Mat1= mp2.mat[1];
	Out.Mat2= mp2.mat[2];

	return	Out;
}


(2) 描画

上で求めた _LL_geometryWorld を元にモデルデータの描画を行います。
頂点毎の index で _LL_geometryWorld を参照してもいいし、
オフセットを付けて空いている Stream に入れ、
1回だけのインスタンシングでパラメータを受け取ることも出来ます。

インスタンシング描画命令を使うとオフセットを渡せるので、
ジオメトリ番号を渡すためだけにバッファを書き換える必要がなくなります。



NVIDIA の CUDA と同じように AMD (ATI) では AMD Stream SDK が用意されています。

AMD Pioneers Stream Computing on Graphics Processor Units
AMD Stream SDK

XP のみ対応となっているようで Vista では動作しませんでした。
RADEON + Vista で Folding@Home が動作しない理由もこの辺でしょうか。 (2008-08-19 追記を参照してください)
インストール自体は可能でドキュメントは読むことが出来ました。

CUDA は C言語 の拡張で、Cg と同じように専用コンパイラを用いた高級言語が
使われています。内部の詳細は出来る限り見えないように隠されています。
対する AMD Stream SDK は R600 (RADEON HD2000/3000) の詳細な資料が付属しており
ハードウエアから GPU の ISA までより詳しく内部構造を理解できるようになっています。

資料を見ると、GPGPU よりと思われる G80 系の GeForce と違い、
従来のグラフィック向け GPU 色をそのまま強く残しているように見えます。
プログラムの実行もシェーダーパイプラインをほぼなぞる形で実行されており、
メモリアクセスも頂点やテクスチャのフェッチと変わらないようです。

ネイティブコードは VLIW なので、これをそのまま人間が手で書いてパイプライン
最適化を行うのは困難です。
そのため、よりわかりやすくハードウエアを抽象化した
CAL (Compute Abstraction Layer) が用意されています。

CAL で用いられる言語もアセンブラですが、ハード依存を無くした比較的シンプルな
命令セットになっているようです。
この命令は IL (Intermediate Language) と呼ばれています。

IL でプログラムを用意しておけば、ドライバが実行時に GPU にあわせて
ネイティブな GPU 命令にコンパイルしてくれます。

この仕組みは GPU としてはごく当たり前の動作です。
例えば Direct3D の Shader は下記の手順で実行されています。

 HLSL → Direct3D IL → Driver 内蔵 Compiler → ネイティブコード

もともと Shader も D3D で定義された汎用の中間コードを、さらにコンパイルして
実行しているわけです。
IL 自体 ShaderModel 4.0 の HLSL がはき出すコードによく似ています。
実際 Shader とほとんど同じもので、HLSL で記述することもできるようです。

グラフィック向け Shader と異なる点としては
・OpenGL/DirectX といったグラフィック用 API を使わなくて良いこと。
 描画とか画面とか複雑な初期化がいらない。
・double 演算など専用の拡張命令が使えること
・オフセットを利用してメモリ書き込み位置をある程度指定出来ること
等でしょうか。

CAL SDK の他に Brook plus SDK が付属しており、Stream プロセッサ向けの
上位言語を使うこともできるようです。

素の GPU にかなり近いこともありますが、比較的低いレベルで抽象化し
さまざまな上位言語に対応する方針であること、など
CUDA との方針の違いがよくわかります。

2008-08-19 追記:
コメントで指摘がありましたが、Folding@home は RADEON + Vista で動きます。
log file をよく見たら Nvidia と誤認識されており、ビデオカードを頻繁に
入れ替えていたのが原因だったようです。
すみません、OS は全く関係なくただの勘違いでした。

UAC 設定や管理者権限で実行したかどうかによりますが、
C:\Program Files (x86)\Folding@home\Folding@home-gpu
だけではだめで
C:\Users\<USER>\AppData\Roaming\Folding@home-gpu
のファイルもすべて消してから Folding@home の GPU2 client (6.20) を
入れ直したら動作するようになりました。

また Vista 対応 CAL runtime も入るとのことで、SDK も試せるかもしれません。
こちらはまだ未確認です。それらしき dll は Roaming 側に入っていました。


MYCOM SIGGRAPH 2008 - NVIDIAが公開、DirectX 11世代の次世代GPUについて

DirectX11 への流れは思ったよりもずっと速いのかもしれません。
直前の Direct3D9 が長かったのでなおさらです。

API セットを一新した Direct3D8 はシェーダーへの流れを加速化し、
GPU の新たな可能性が明らかになりました。
D3D8 の欠点など小規模な改良修正を施し、将来を見据えて先の先の仕様まで
盛り込んだ D3D9 が出たのはわずか 2年後。
この後 D3D10 が出るまで 4年以上、長期にわたり D3D9 が使われ続けています。

汎用化の流れから再び仕様を完全に覆した D3D10 が登場しました。
それも今年の末でおよそ 2年。
足りない部分が明らかとなり、再びフィードバックの時期が来たのかもしれません。
この流れだと 11 はそれほど大幅な仕様変更ではなく、概念的には D3D10 を継承し、
比較的長期間使われるものになるのではないでしょうか。


上記 MYCOM JOURNAL の記事を見ると、パイプラインには新たに HullShader、
Tessellator、DomainShader が追加されています。

従来マルチパスレンダリングは、貧弱なピクセルパイプラインを補うのが目的でした。
その後 PixelShader に傾倒した高機能化が行われ、D3D9 ShaderModel3.0 で
この流れはほぼ一段落しています。

Direct3D10 ではむしろ StreamOutput を使ったジオメトリのためのマルチパスが
必要となりつつあります。
ジオメトリの場合は頂点数の増減など CPU へのフィードバックは難しく、
Index が展開されてしまう欠点もあります。

 (いっそ GPU 側だけで Draw 発行までできたらいいのですが、、
  Larrabee なら出来るのかもしれません。)

Direct3D 11 におけるパイプライン構成要素(HS、TS、DS)の追加は、
このようなジオメトリに対するマルチパス化要求とその問題点を
スマートに解決してくれるものと期待しています。


D3D10 のテクスチャは汎用的なバッファの一種でピクセルフォーマットが
拡張されています。

特に整数型の直行性が高くなり、固定少数として扱うかどうか、符号付きと
みなすかどうかといったバリエーションが増えています。
また Texture Array が追加されたため、従来のテクスチャフォーマットよりも
次元が増えました。

DirectX SDK のマニュアルでは、Direct3D 10 用の DDS フォーマット拡張を
定義しています。
残念ながらこの解説は不完全で、このドキュメントを見ても厳密な DDS のヘッダ
構造がわかりませんでした。

DirectX SDK の texconv10 コマンドを使うと D3D10 用のテクスチャを生成する
ことができます。このコマンドでヘッダの違いを調べてみました。
以下 DirectX SDK Aug2008 x64 を使用しています。


● ヘッダサイズの疑問

DDS テクスチャのヘッダは先頭の dwMagic と構造体を合わせてちょうど 128byte です。
Programming Guide for DDS によるとヘッダブロックは次のように定義されています。

In Direct3D 10:
  DWORD             dwMagic;  // 4byte
  DDS_HEADER        header;   // 124byte  = 0x7c
  DDS_HEADER_DXT10  header10; // 20byte

In Direct3D 9:
  DWORD             dwMagic;  // 4byte
  DDSURFACEDESC2    header;   // 124byte  = 0x7c

sozeof(DDS_HEADER) == sizeof(DDSURFACEDESC2) == 124byte で内容は互換性が
あります。

Direct3D10 で追加された DDS_HEADER_DXT10 は 5要素の 32bit UINT でできており
20byte と少々中途半端な大きさです。ヘッダサイズのアライメント崩れてしまう
のでこのような構造にするとは考えられにくいのが正直なところです。
例えば R32G32B32A32_FLOAT 型のテクスチャを読み書きする場合でも、ヘッダを
含めると SSE の直接アクセスに制限が生じることになります。

DDS_HEADER(DDSURFACEDESC2) の最後、DDS_PIXELFORMAT の後ろがちょうど
20byte あるので、もしここに格納されるのならつじつまが合います。

ところが実際に texconv10 で D3D10 専用形式に変換してみると、
ぴったりファイルサイズが 20byte 増えています。
128byte 目以降に追加の DDS_HEADER_DXT10 が入っていました。

よって DDS_HEADER_DXT10 の追加ブロックはマニュアルのヘッダ構造が正解です。
Direct3D 10 用 DDS はヘッダが 20byte 増えて 148byte になります。


● ヘッダ区別の方法

DDS ファイルを開いたときに、Direct3D 10 の拡張情報が含まれているかどうか
判断する必要があります。先頭 128byte 部分はほぼ完全な互換性があり、
追加情報を読むべきかどうかの手段が明確にされていないようです。

基本的に D3D9 形式で表現できるテクスチャは D3D9 ヘッダのみ格納するようです。
例えば次のように dds 変換した場合

(1) texconv   -ft dds white.bmp -m 1 -sx _dx9   -f a8r8g8b8
(2) texconv10 -ft dds white.bmp -m 1 -sx _unorm -f r8g8b8a8_unorm
(3) texconv10 -ft dds white.bmp -m 1 -sx _sint  -f r8g8b8a8_sint

出力
(1) white_dx9.dds   262272byte
(2) white_unorm.DDS 262272byte
(3) white_sint.DDS  262292byte

同じ texconv10 を使っても、D3D9 形式と互換性のある (2) と D3D10 専用の (3)
ではファイルサイズに 20byte の差が生じます。

このとき (2) の DDS_PIXELFORMAT は DDPF_RGB|DDPF_ALPHAPIXELS となり
Mask にも一通り正しい値が入りました。

(3) の DDS_PIXELFORMAT は DDPF_FOURCC で、dwFourCC に 0x30315844 = 'DX10'
が入りそれ以外はゼロです。

よって、D3D10 拡張 DDS の場合は dwFourCC を見て、'DX10' の場合のみ追加
の D3D10 ヘッダを参照すればいいようです。

ここで悩んだのは、(2) のテクスチャにも 128byte 目以降に追加のヘッダ情報が
格納されているように見えること。
当初 dwFourCC != 'DX10' の場合でも DDS_HEADER_DXT10 が挿入される場合が
あるのではないかと疑ったのですが、ファイルサイズを見るとデータ領域と
判断して良さそうです。データが壊れているのかもしれません。

その後いろいろ試したけど、やはり texconv10 ではデータが壊れてしまう問題が
生じるようです。x86 bin でもだめ。
March 2008 の texconv10 だと正しい値が取れています。要調査。



濁点・半濁点の後付変換に対応しました。
単独で文字としての入力は出来ませんが「は」+「゛」=「ば」のように
直前の文字に追加で合成できるようになりました。
その後「゜」で「ぱ」にも置換できます。

ctrlswapmini lite v1.02

2タッチで一度動き出せば安定しますが、
起動直後やトグル入力だと、まだ入力モードが安定しないことがあるようです。

トグル入力で全角半角の境界でたまに改行が割り込んでしまうのは、
未確定バッファの確定の判断を間違えることがあるからです。

まだキーバッファにコマンドがたまっている可能性があるので、IME の状態を
参照してもうまくいきません。今現在の状態であって、送信すべきキーが処理
されるタイミングでの結果をあらわしていないからです。

以前の ctrlswapmini では、この誤差に対して、確定するけど改行しないキー操作を
使っていました。Advanced Wnn はこの操作が使えなかったのでただの改行に
置き換えているのが原因です。
送信したキーストロークから IME バッファ状態を測する必要があるかもしれません。


関連エントリ
EMONSTER lite (S12HT) 対応 ctrlswapmini lite v1.01 更新


新 masafumi's Dialy さんによると DirectX SDK August 2008 が出ている
そうなので入れました。

とりあえずマニュアルとか。リリースノートに無いところ

マニュアルでの DXGI の扱いが変わっているようです。
以前は Direct3D 10 のカテゴリの一部だったのが、Direct3D 10/9 と並列な
位置に移動しています。

その他 Primitive Topology、Stream Output あたりにも手が入っている感じ。

Linking Static and Dynamic Libraries に d3d10sdklayers.dll の項目が増えてます。

個人的に気になった変更は stop 命令。
今までマニュアルに載っているのになぜか使えなかった、HLSL の stop 命令が
削除されていました。
やはり clip 命令 ( clip( -1 ) 等) が正式な手法なのでしょうか。



標準の IME Advanced Wnn でも動作するようになりました。
今のところ使えるのは 2タッチのみ。
「IME制御」にチェックが必要です。

ctrlswapmini lite v1.01

自動起動に失敗するバグも直しました。
v1.00 をアンインストールしてから入れ直す必要があります。



金曜日、使ったあと液晶を閉じてそのまま放置。
月曜日、電源が入って起動しました。
バッテリー残量 20% 程度。
生きてました。

901 はスリープ状態でかなり持ちます。
前使ってた EeePC 4G-X (701) だと一晩も無理。

最近はシャットダウンやめてサスペンド(スリープ)のまま運用してます。
起動も速くてちょうど PDA のように使えます。

使ったあとの充電は必要だけど、休止状態がなくても困らなくなりました。
ちなみにまだ Vista


EMOBILE の EMONSTER lite (S12HT) に乗り換えたので、
Bluetooth 経由のネット接続も速くなりました。

EM・ONEα S01SH2 + Bluetooth (1.2) だと 300Kbps 前後だったのが
EMONSTER lite S12HT + Bluetooth (2.0)で 1Mbps 程度出ています。

プロトコルのせいかプロファイルのせいかわかりませんが、
Bluetooth PAN になって接続も速くなりました。

先にインターネット共有を起動する手間はあるものの、
PC 側ですぐつながりすぐ切れるのは
ノート側のバッテリーを節約できてる気がして気持ちがよいです。

EM・ONEα + Bluetooth Dialup 接続のときは、切断に時間がかかって
しばらく固まることがあったので。



EMONSTER lite S12HT に対応した ctrlswapmini lite を作ってみました。
従来の ctrlswapmini 同様テンキーのトグル入力や 2タッチ(ポケベル) 入力が
できるようになります。
キーマップに互換性があるのが特徴で、ctrlswapmini 用のデータが使えます。

ctrlswapmini lite v1.00

トグル入力は単体でも可能ですが、ctrlswapmini を使うと大文字小文字変換や
単体の改行入力、テンキーだけでコピー&ペースト等が出来るようになります。


ただし EMONSTER lite (S12HT) ではいくつか制限があります。

(1) MS-IME でしか動作しません (Advanced Wnn ではだめ)
(2) 文字キーが独立していないので、トグル入力では対応したキーマップでないと
 文字種切り替えが出来なくなります。(2タッチでは大丈夫)
(3) 一部記号などがキーマップと異なっている可能性があります。


(1) MS-IME

 標準の Advanced Wnn ではうまく動作しません。
 スライドを閉じた状態をシミュレートしてもだめで、文字種切り替えのキー制御に
 互換性が無いようです。

 MS-IME に切り換えるためには付属の reg ファイルを書き込む必要があります。
 また MS-IME そのままだとテンキー (カーソルキー) で変換操作できないので、
 imekeyset5 を使って phone style を登録しておく必要があります。
 詳しくはマニュアルを参照してください。

ctrlswapmini lite マニュアル


(2) 文字キー

 [*] キーもカスタマイズ対象なので、そのままでは文字種切り替えできなくなります。
 キーマップをカスタマイズして、英数のみ、数字のみのキーマップを切り換えられる
 ようにすれば解決できるかもしれません。

 2タッチ(ポケベル) 入力では、文字種切り換えの概念が不要なので、特に問題無く
 英数かな共に入力することが出来ます。

 数値モードが無いので、ダイヤル時は画面上のキーパッドを使用してください。


ほぼ同様のキーを備える HTC HT1100 でも同じように使用できるかもしれませんが
未確認です。


W-ZERO3[es] 系では動作しないので、従来の ctrlswapmini を使ってください。
WindowsMobile のテンキーコードを発行する端末なら、S12HT 以外でも同様に動作
する可能性があります。


関連リンク
imekeyset5
ctrlswapmini

関連エントリ
WindowsMobile キーボードと S12HT の TouchFLO
EMONSTER lite S12HT の文字入力を MS-IME に切り替える
EMONSTER lite S12HT と文字入力


英語配列対応の touchkeysip 用データを作ってみました。

eckeyboardsip v1.00

EMONSTER lite S12HT はキーボードを英語配列と認識するため、touchkeysip の
データで一部記号で表記と入力される文字が異なっていました。
eckeyboardsip は日本語キーボード用と英語キーボード用、両方のデータを
同梱しています。

日本で販売されている WindowsMobile 端末には、日本語キーボードと認識する
ものと英語キーボードと認識するものと 2種類あります。

詳しくはこちらのエントリを参照してください。


EMONSTER lite (S12HT) の場合いくつか注意点があります。

 (1) 内部でキーボードを英語配列と見なしている
 (2) 標準 Advanced Wnn では、touchkeysip で [1]~[9],[0] のキーを押しても
   かな や英数のトグル入力になってしまう。

(1) は英語配列対応の script データを使うことで解決できます。
(2) は、スライドキーボードを開いているときのみ有効なので、閉じた状態では
 問題が起こりません。または MS-IME に切り換えることで対処可能です。


関連エントリ
WindowsMobile キーボードと S12HT の TouchFLO
EMONSTER lite S12HT の文字入力を MS-IME に切り替える
EMONSTER lite S12HT と文字入力



EMONSTER lite はテンキーが付いているものの、ソフトキーや OK ボタン
がなく、様々な場面で画面のタップが必要となります。
EMONSTER lite (S12HT)

テンキー部分だけでウィンドウ操作出来るよう、下記のように割り当ててみました。

┌──┬──┬──┐
│SOFT│ ↑ │SOFT│
├──┼──┼──┤
│ ← │決定│ → │
├──┼──┼──┤
│TASK│ ↓ │ OK │
├──┼──┼──┤
│ * │ 0 │ # │
└──┴──┴──┘

↓ [#]+[0]で切り替わる ↑

┌──┬──┬──┐
│ 1 │ 2 │ 3 │
├──┼──┼──┤
│ 4 │ 5 │ 6 │
├──┼──┼──┤
│ 7 │ 8 │ 9 │
├──┼──┼──┤
│ * │ 0 │ # │
└──┴──┴──┘

文字操作はできないので、[#] + [0] で切り換えます。
詳しくはこちら
説明

ダウンロード
emlite v1.00


WindowsMobile 端末には、キーボードを英語配列と認識するものと
日本語配列と認識するものの 2種類あるようです。

この違いは主に、外付けキーボードを繋いだ場合や、キー入力をシミュレートする
ツールで問題となります。touchkeysip での文字入力もその一つです。

想定しているキーボードと内部で認識しているキーボードの配列が異なっている場合、
キーの刻印と入力される文字にずれが生じます。

Bluetooth keyboard を販売している Reudo のページに、機種による配列の違いが
まとめられています。

Rboard for Keitai RBK-2000シリーズ

内蔵の QWERY キーボードを持っている日本向け端末は、日本語配列を採用している
可能性が高いようです。(100% ではない)
逆に QWERTY キーボードを持っていない端末は、単体での利用では特に影響が
ないためか、英語配列のものが多いようです。

おそらく日本語配列にするメリットは変換や漢字などのキーを認識できることで、
英語配列のメリットはカスタマイズする(変更する)コストが低いことだと考えられます。

ローマ字入力では問題ないものの、JISかな入力を利用するソフトだとこの違いが
致命的となります。特に ctrlswapmini では 一時かな モードを多用しているので
英語配列の機種ではうまく動作しないようです。
逆に日本語キーボード配列を採用している端末では、ある程度は動作する可能性が
残っているといえます。

一時かなモードは、W-ZERO3[es] 系の端末がテンキー入力で使用している特殊な
キーストロークです。
IME 自体はローマ字入力モードでありながら、送られてきたキーをその場限りで
JISかな入力と見なすことができます。

KEYDOWN, KEYUP のそれぞれ両方を、VK_KANA の DOWN/UP で囲みます。

KANA DOWN
KEY DOWN
KANA UP
KANA DOWN
KEY UP
KANA UP

この場合の KEY DOWN, KEY UP は JISかなモードの入力と見なされます。
この動作は便利なのですが WindowsMobile でしか使用できず
PC の IME では機能しませんでした。


● TouchFLO

EMONSTER lite S12HT には、TouchFLO と呼ばれる特殊なユーザーインターフェースが
搭載されています。
どの画面でも呼び出すことが出来、指だけで操作できるため便利そうではあるものの
メニューの内容が固定でカスタマイズできませんでした。

このメニューの内容は下記のレジストリを書き換えることで変更できるようです。

HKEY_LOCAL_MACHINE\Software\HTC\Biotouch
 ActionScreen
	新電子メール
	新規 SMS
	新規 MMS
	新しい予定
	新しい仕事
	新しいメモ
	新しい連絡先
 APLauncher
	電子メール
	Internet Explorer
	コミュニケーションマネージャ
	SMS/MMS
	タスク
	予定表
 MediaHubMini
	ミュージック
	フォト
	ビデオ

実際に APLauncher の "\Windows\iexplorer.exe" を
"\Program Files\NetFront Browser v3.5\NFBrowser.exe" に書き換えて、
NetFront を登録することが出来ました。


関連エントリ
EMONSTER lite S12HT の文字入力を MS-IME に切り替える
EMONSTER lite S12HT と文字入力
EMONSTER lite S12HT メニューや通信など


●大きさ

s12ht

小さいけど そのうち出るらしい Touch Diamond には負ける
S12HT 102x51x11.35 120g
Diamond 107x55x15.8 110g

テンキーは付いているものの、ソフトキー も OK ボタンも無いため
操作には画面タップが必要となります。


●画面

320x240 QVGA で、320 dot 側 (縦) が 5.2cm (5.2x3.9cm)
ちょうど EM・ONE の縦 (480dot) と同じ長さ (9.0x5.4cm)


●メニュー

メニューが複数入っています。

・普通のスタートメニュー
  ウィンドウズキー

・TouchFLO
  画面下のメニューバーを上に持ち上げる感じにスライド

・クイックリスト
  終話ボタン長押し

・クイックタスク
  テンキースライド

・クイックメニュー
  Today 画面右上から、タスクメニュー

・ホーム画面
  Today に表示されているメニュー


●通信

EM・ONE で契約した データプランの SIM でも通信可能
 → emb を選ぶ

タイトルバーのアンテナマークやアイコンが正しく表示されないことがあるけど、
接続自体は問題無さそう。

接続→接続→詳細設定→ネットワークの選択
  プルダウンメニューで EMnet から emb に変更する

ネット接続を手動でやるなら
  設定→接続→接続→既存の接続を管理→ポップアップメニューから接続
  ブラウザやインターネット共有でも可能

切断は CommManager
  設定→接続→CommManager →データ接続をタップ


●PC から接続 (インターネットの共有)

EM・ONE と違い、PC 側でモデムとしてダイヤルアップ設定を行うわけでは
ないようです。インターネットの共有を使います。

プログラム→インターネットの共有→接続
  PCとの接続方法は、USB または Bluetooth PAN を選択できる
  ここでも接続先を選択可能 → emb 等

S12HT 側で 接続 したら、PC 側から Bluetooth PAN で繋ぎます。

Vista の場合、ネットワークのプロパティから
  ネットワーク接続の管理→ Bluetooth ネットワークの接続
あらかじめペアリング等の設定が必要。

一応 EeePC 901 内蔵 Bluetooth + Vista の環境で接続できました。

Bluetooth 経由でも EM・ONE より高速です。


●ソフトの動作確認

touchkeysip
  問題無く動作します。ただし英語キーボード配列のキーコードが必要なので、
  一部の記号は修正が必要となるようです。
  (Today 画面には一切 plugin を入れていません。ホーム画面も外しています)

ChiRaKS
  きちんと動作しました。EM・ONE ではアクセラレータノ関係か描画に問題が
  ありましたが、EMONSTER lite S12HT では大丈夫です。


● ctrlswapmini や em1key に関して

EMONSTER lite S12HT は、キーボードを英語配列と見なしているようです。
その場合次の問題があります。

・キー配列が異なるため記号部分のキーコード修正が必要となる
・Advanced Wnn はテンキー入力専用なので、MS-IME に切り換えておく必要あり
・MS-IME が JISかな入力モードにならない

特に日本語入力のカスタマイズでは、JISかな入力の操作をシミュレートしている
ためうまく動作しないようです。

文字入力と関係ない単なるキーコードの置換のためなら em1key は利用できるかも
しれません。

em1key
ctrlswapmini


関連エントリ
EMONSTER lite S12HT の文字入力を MS-IME に切り替える
EMONSTER lite S12HT と文字入力



EMONSTER lite (S12HT) 標準の IME は Advanced Wnn です。
どうやら テンキーのトグル押し→仮名変換 専用に作られているらしく
Bluetooth 等の外部キーボードを繋いだ場合に日本語入力できませんでした。

症状について 詳しくはこちら

そこで、Advanced Wnn を使わずに MS-IME で日本語入力を行う方法を調べてみました。
下記のようにレジストリを書き換える必要があります。
(レジストリを書き換えは必ず自己責任で)

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\e0010411]
"Keyboard Layout"="00000411"
"Ime File"="imjp31.dll"
"Layout Text"="Microsoft IME3.1(JPN)"

修正後、リセットまたは電源を入れ直すと MS-IME になります。

これで Bluetooth Keyboard を使っても、日本語入力の取りこぼしがなくなりました。
ローマ字入力で文字入力も漢字変換も出来ます。
その代わりテンキーで数字以外の文字を入力出来なくなります。

元に戻すにはレジストリの値を復元してください。
初期状態、Advanced Wnn の時の値は下記の通りです。

[HKEY_LOCAL_MACHINE\System\CurrentControlSet\Control\Layouts\e0010411]
"Ime File"="M5ImeMgr.dll"
"Layout Text"="Keytouch Multiplay"
"Keyboard Layout"="00000411"

割り切って、ソフトウエアキーボード & Bluetooth キーボード中心で使うなら
これもありかもしれません。
元々キーが少ないのでテンキーをカスタマイズに使えるし。


関連エントリ
EMONSTER lite S12HT と文字入力



先日 EMONSTER lite S12HT を購入しました。
EMOBILE の WindowsMobile 端末です。

EMONSTER lite (S12HT)

無線LAN 無し、QWERTY キーボード無し、GPS 無し、加速センサー無し
その代わり小さく薄く、比較的入手しやすい価格帯です。
スライドテンキー付き。画面タッチによる操作 TouchFLO も可能。


●キーコード

テンキーのコードは WindowsMobile の winuserm.h に定義されている値で、
いわば標準。キーに対して 1つのコードが割り当てられています。

0~9  VK_T0~VK_T9  '0'~'9'
*     VK_TSTAR      VK_F8
#     VK_TPOUND     VK_F9

通話  VK_TTALK      VK_F3
終話  VK_TEND       VK_F4

決して ZERO3 es 系のような、トグル入力を無理矢理再現したり、入力モード
によって異なるコード列が送られてきたりする複雑なものではありません。
テンキー入力の状態と入力文字の制御は、IME など別のところが受け持っているようです。


●IME

IME は Advanced Wnn で予測変換付き。
設定画面は次の操作で出てきます。

設定→個人用→入力→入力方法
  入力方法を「ひらがな/カタカナ」か「ローマ字/かな」に切り替えてから [オプション]

または [*] キーの長押しから「オプション」を選択

単語登録や予測入力を無効にすることが出来ます。


●テンキートグル入力

テンキーの操作は カーソルキー と 決定キー の他、
[1]~[9],[0],[*],[#],[C] だけで行います。
キーが少ないため [*] [#] はいくつかの機能を兼用しています。

確定済み状態
 [*] 文字種切り替え
 [#] 記号入力 (一覧表示)

入力候補がある状態
 [*] 濁点・半濁点
 [#] 逆トグル

長押し
 [0]~[9] 数字入力
 [*]   メニュー表示
 [#]   マナーモード切り替え

よって数字入力モード [12] でも '*' や '#' の直接入力は出来ません。

自動送りは無さそうです。

変換は「↑」

トグル入力時のカーソル位置は文字の右側につくタイプですが、
→ キー補正が無いようです。

同じ文字の入力を繰り返すとき区切りとして間に [→] キーを入れますが、
このときカーソを右に移動するキーコードも発行されます。

通常の文字入力では、常に IME 変換バッファの末尾にカーソルがあるため
カーソルの右移動も無視されるため問題となりません。

また英字入力時も必ず 1文字だけの IME バッファが活用されるので、
カーソル移動が無視されるため問題になりません。

唯一問題となるのは、日本語入力時にカーソル位置を左に動かして
文字の挿入状態で同じキーの文字を複数連続で打ちたい場合です。

ちなみに一般的な携帯ではカーソルが文字の左側に付くので、→ でカーソルを
送ると確定になります。

改行の単独入力は出来ないようです。


●タッチ入力

タッチパネルの反応は鈍め。
TouchFLO があるため指での操作に合わせて調整されているのか、
または付属の保護シートが堅いせいかもしれません。


● Bluetooth キーボード

USB Host は無いですが、Bluetooth によるキーボード接続は可能です。
RBK-2000BT2 で試してみました。

IME が On の場合、ローマ字入力を取りこぼしてまともに日本語入力出来ません。
たとえば素早く [k][a] と入力しても 'k' が落ちて「あ」が入ります。
ゆっくり1文字単位で [k]、[a] を入力するとやっと「か」が入ります。
IME の文字バッファが 1文字分しかない状態に似ています。

さらに RBK-2000BT2 の数字キー [1]~[9],[0] でもトグル入力になってしまい
直接数値入力が出来ませんでした。

IME を off にすると、上記のような取りこぼしもなくキータイプに合わせて
快適に英数字入力できるようになります。
ちなみに配列は英語キーボードなので、RBK-2000BT2 ではキー刻印通りに入力出来ます。

やはり IME レベルでテンキーのトグル入力処理が行われているようです。
そしてこの IME (Advanced Wnn) はテンキー入力専用に作られているらしく、
直接のキーボード入力には向いていません。

強制的に MS-IME に切り替える方法があれば解決するかもしれません。
MS-IME らしきファイルやレジストリは存在していました。

続き
EMONSTER lite S12HT の文字入力を MS-IME に切り替える


Program Files も Symbolic link で置き換えました。
やり方は前回の winsxs と同じです。
C:\Program Files にそのままアプリケーションを install しても
C: ドライブを圧迫することがありません。

セキュリティ系ソフトはさすがに Symbolic Link を拒否するらしく、
実在の path を指定する必要があります。

VisualStudio を install してみます。
追加で Windows\Microsoft.NET を Symbolic Link にします。
他のアプリが起動していなければ movefile を使わなくても可能です。
コマンドプロンプトをメニューの「管理者として実行」で起動します。

 cd C:\Windows
 robocopy Microsoft.NET D:\Windows\Microsoft.NET /E /COPYALL /SEC
 ren Microsoft.NET Microsoft.NET.moved
 mklink /d Microsoft.NET D:\Windows\Microsoft.NET

下記の 3フォルダが D: ドライブを指し示すようになりました。

 C:\Program Files → D:\Program Files
 C:\Windows\winsxs → D:\Windows\winsxs
 C:\Windows\Microsoft.NET → D:\Windows\Microsoft.NET

C: ドライブをほとんど消費することなく VisualStudio をインストールできます。
VisualC++ 2008 Express Edition 英語版を導入した結果。

インストール前
 C: free 1.76GB
 D: free 5.03GB

インストール後
 C: free 1.72GB
 D: free 4.57GB

XP の時より空き容量が増えました。
でもあまりやりすぎると最初から D: に OS インストールしたのと変わらないので
ほどほどに。


関連エントリ
EeePC 901 に WindowsVista
EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (4)


Vista 使っています。
C: ドライブの容量が限界です。速度の方は問題なし。

EeeUser に Vista の Symbolic Link を使って、最も容量を消費している
システムフォルダを別ドライブに逃がす方法が載っていました。

Move Vista's Side by Side Directory

Symbolic Link を張り替えるだけですが、OS 起動中はすでに dll 等が
読み込まれているため移動することが出来ません。
movefile コマンドを利用して、Windows 起動のタイミングでファイル操作を
行うように予約するのがポイントのようです。あらかじめダミーのリンクを
作成してうまくフォルダを置き換えています。

おそらくこの方法を使えば、Program Files を Symbolic Link に置き換えることも
出来るでしょう。

なお winsxs の取り扱いは非常に危険で、失敗すると確実に問題が起こります。
この辺は注意事項をよく読んで自己責任で試す必要があります。

実際に手順通りやってみました。

(1) movefile コマンドを入れる
(2) ダミーのリンクを作っておく
(3) winsxs のパーミッションを書き換える
(4) 起動時に winsxs をリンクに置き換えるように予約する
   この段階ではまだ元のフォルダを指し示しているだけ
(5) 再起動
(6) winsxs を別ドライブ D: にコピーする
(7) リンクを張り直して、コピー先の D: ドライブを参照するように置き換える
(8) 再起動
(9) これで元のフォルダを消せるはず

OS は無事起動し (8) まではとりあえず完了。
1.4GB ほどの削減になるはずですが、すべてのファイルを削除できず。
150GB ほどオープン中で消せないファイルが残りました。
これは何らかのアクセスが行われている証拠なので、置き換えが失敗している
可能性があります。

ただ D: を指している Symbolic Link を消すと、Explorer でもエラーが出る
ようになるため Link 版 winsxs へのアクセスもきちんと行われているようです。


容量削減したはずが、思ったように C: ドライブの空きが増えない現象でしばらく
悩みました。原因は C:\ に残った 500MB 近い pagefile.sys でした。

仮想メモリは "なし" に設定しています。
タイムスタンプが更新されておらずアクセス痕跡がなかったので、
設定前に作られたファイルが残っているだけのようです。
削除しましたが問題は今のところ発生していません。

これで C: ドライブの空きが 1.7GB まで増えました。

関連エントリ
EeePC 901 に WindowsVista
EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (4)
EeePC 901 に WindowsVista (5)




2008/07/21
Atom と 64bit

CPU Atom には 無印、N、Z と 3種類あり、それぞれ用途が分かれているようです。
このうち EM64T (Intel 64) 対応なのは無印のみ。N270 採用の EeePC 901 でも
使えませんでした。SSE3,SSSE3 には対応しています。

                                     x64
Diamondvill nettop  無印 Atom 230    ○
Diamondvill netbook N    Atom N270   × EeePC901,Aspire one,MSI U100
Silverhorne MID     Z    Atom Z500~ × Z520=D4,工人舎SC

Wikipedia List of Intel Atom microprocessors

下記のドキュメントの Datasheet を見ると Intel Atom Processor 200
Series Datasheet のみ Intel 64 architecture 対応と書かれています。
Intel Atom Processor Technical Documents

Acer Aspire one の spec には Atom N270 に「CPU(64bit対応)」と載っています。
日本エイサー Aspire one

過去のニュース記事などを検索してみると、Diamondvill = Intel 64、
または N2xx シリーズも 64 対応しているかのように書かれているものがいくつか
あったので、そのせいかもしれません。(自分も)

関連エントリ
EeePC 901 に WindowsVista


Vista に関して

・EeePC 901 では Aero が使えるので動作は十分速い。XP よりは低速

・容量が足りなくてアップデートできないので実用には問題あり。

・Vista インストールは時間がかかる
  特に「インストールの最終処理の実行中」の状態で
  ハングアップしたのではないかと勘違いするくらい。
  この画面でぴくりとも動かないまま 1時間46分。

・削りすぎて MS-IME で日本語入力出来なくなったけど ATOK2008 入れれば使用可能

・Vista は Symbolic Link が使えるので C: ドライブの任意のフォルダをそのまま
 D: に逃がすことが出来る。

・RAMDISK は Gavotte Ramdisk が使える。(関連)
 2GB 以下の RAM でメインメモリから確保する場合は、特別な操作もレジストリ
 設定とかも不要で簡単でした。

・起動時に ACPI のエラーダイアログが毎回 2つ出る
 AsTray で解像度変更が出来ない。WLAN/Bluetooth/Camera 等の切り替えは可能。

・バッテリーは意外に持つ
 Aero glass + 電源プラン バランス + wlan + 画面輝度下から 3番目
 の状態で、インストール作業や再起動などを繰り返しつつ 4時間 45分。
 通常の利用ならたぶんもっと持ちそう。


Symbolic Link は便利です。たとえば次のように実行すると、以後 c:\home の
中身は d: ドライブ (d:\var\home) に保存されます。

(1) コマンドプロンプトを管理者権限で起動 (右ボタンメニューで選ぶ)
(2) コマンド上で mklink /d c:\home d:\var\home

Microsoft SDKs のように C:\Program Files に入ってしまったファイルを
D: に移動する場合にも使えるでしょう。


OS に関係なく EeePC 901 はかなりバッテリーが持つ印象です。
直前まで使っていた EeePC 4G では、サスペンド状態でうっかり一晩放置して
しまうとバッテリーが空でした。901 は朝になっても起動します。
容量もそんなに減ってなかったので最初驚いたほど。

いろいろ利点の多い 901 なのに、それでも普段持ち歩きたくなるのは
EeePC 4G-X (701) の方だったりします。


関連エントリ
EeePC 901 に WindowsVista
EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (4)
EeePC 901 に WindowsVista (5)



容量削って 4GB SSD に Vista 入れてみました。

eeepc vista

敢えて使うメリットはないし XP より遅いしバッテリーも持たないけど
普通に使える Vista PC になりました。

WindowsVista SP1 Bussiness でのスコア

評価:                      2.7

プロセッサ:                3.0
メモリ(RAM):               4.5
グラフィックス:            4.1
ゲーム用グラフィックス:    2.7
プライマリハードディスク:  4.5

前回より SSD のスコアが向上しています。
現在の空き 930MB / 3.72GB

XP の時と同じように RAMDISK を設定してみました。
Vista なので ERAM ではなく Gavotte Ramdisk
参考ページ
PC Watch 32bit Windowsの管理外領域をRAM Diskに使う

(1) RAM 2GB から確保するため特に設定なしに、展開後そのまま
 ramdisk.exe を管理者権限で実行します。(右ボタンメニューから選ぶ)

(2) Install Ramdisk を押す

(3) パラメータ設定して [OK] を押す
 容量設定 (例 512M)
 ドライブレター設定 (例 R:)


関連エントリ
EeePC 901 に WindowsVista
EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (4)
EeePC 901 に WindowsVista (5)


EeePC 901 に WindowsVista を入れてみました。
GMA950 なのでエアログラス出ます。

eeepcvista

とりあえず SP1 未適用でのスコア

評価:                      2.7

プロセッサ:                3.0
メモリ(RAM):               4.5
グラフィックス:            4.1
ゲーム用グラフィックス:    2.7
プライマリハードディスク:  4.2


Vista Bussiness
RAM は 2GB に増設済み。
SSD 8GB 側にインストール。

Atom は EM64T (Intel64) 対応だと思ってましたが EeePC 901 では
使えないのでしょうか。
Vista x64 のインストーラでもエラーになったため 32bit 版を入れています。

インストール時に
・少なくとも 6068MB の空きが必要
・推奨 11364MB
とおこられたのでまずは 8GB 側 SSD へ。

インストール直後の空き容量は下記の通り
 空き 1.84GB / 合計 7.50GB

チップセットドライバや LAN/WLAN ドライバは付属 CD-ROM のもの。
VGAドライバは intel サイトから 945GM Vista 用 winvista_1583.exe
をダウンロードして適用。
bluetooth やサウンドは標準で認識しています。

初期動作は極めて低速で、インストールだけ何時間もかかっています。
プロセッサは余裕があるものの 8GB SSD のアクセスがボトルネックと
なっているようです。

VGA ドライバが入ってエアログラス表示になったらましになりました。
表示速度や単純な操作のレスポンスは十分ですが、アップデートなど
ディスクアクセスが伴う処理は非常に重くかなり低速です。

vLite 使ったら容量が減ったので、4GB 側にも入れてみます。



EeePC 901 に WindowsVista (2)
EeePC 901 に WindowsVista (3)
EeePC 901 に WindowsVista (4)
EeePC 901 に WindowsVista (5)


超えました。

Folding@Home Client statistics by OS

OS Type             Current TFLOPS*   Active CPUs    Total CPUs
Windows             199               209518         2096062
Mac OS X/PowerPC    7                 8278           117514
Mac OS X/Intel      27                8852           54620
Linux               72                42255          319308
GPU                 1008              9168           20261
PLAYSTATIONR3       1374              48739          562786
Total               2687              326810         3170551

Last updated at Thu, 17 Jul 2008 06:04:12 


関連エントリ
GPU で Folding@home
GPU で Folding@home (3)


2008/07/15
Eee PC 901 その2

内蔵 Bluetooth はマウスと EM・ONE のダイヤルアップ接続に使用。
VGP-BMS30
出っ張りなしでワイヤレスマウスが使えるようになりました。

Bluetooth stack は まだ評価したことがない
WIDCOMM Bluetooth Software 5.1.0 でした。
一応今までと同じようにペアリング出来ることを確認。
自作ソフトも動作しました。


キーボード配列の変更は、以前こちらに書いた レジストリ設定を
そのまま使っています。[ひらカタ] を 変換キー にしています。


固定の D: ドライブが 8GB あるため、アプリケーションのインストールは
比較的容易です。ただし必ず C: に入ってしまうコンポーネントもあります。

以前 VisualStudio 2008 Professional を EeePC 4G-X に install したときは
C: ドライブに 1.6GB の空きが必要でした。
今回は VisualC++ 2008 Express Edition にしました。
少しでも容量を食わないよう英語版。

途中のインストールオプションをすべて無視し、インストール先を D: に
変更した状態で必要容量は下記の通りです。

C: 733 MB
D: 238 MB

C: ドライブに入るのは .NET Framework ~3.5 と Microsoft SDKs
この 2つがかなりの容量を占めています。
前回 は Microsoft SDK を手動で移動しました。

C: ドライブの空き容量の変化

1.44GB インストール前
918MB VisualC++2008 Express Edition を D: にインストール後
730MB DirectX SDK June2008 を D: に install 後

関連エントリ
Eee PC 901
Eee PC に VisualStudio 2008 を入れてみた
Eee PC 4G 買いました
Toshiba bluetooth stack と Bluesoleil 対応


2008/07/12
Eee PC 901

今日発売の新しい EeePC 901 買ってみました。
ASUS Eee PC 901
Atom プロセッサ搭載の PC は初めてです。

以前の EeePC 4G-X (700) と比べて本体が厚くなりました。
キーボード側だけでなく液晶側も厚みが増しており、
角が取れて全体的に丸みがかっています。
薄くスマートだった 4G と比べるとだいぶ印象が異なります。
本体も以前より重くなっています。

EeePC 4G で個人的に不満だった下記の点が一気に解消されています。
・画面解像度
・SSD の容量
・バッテリー寿命
・Bluetooth 内蔵

画面解像度は待望の縦 600ドットです。
これでインストーラやダイアログがはみ出て見えなくなったり、
ボタンが押せなくなったりすることもないでしょう。

内蔵 SSD は 12GB ですが、システムの C: ドライブは 4GB のままです。
C: の空き容量は従来通り若干苦労しそうです。
ただ最初から XP の SP3 が入っており、ページングファイルも無しに
設定されていました。

8GB の D: ドライブ側は Program Files フォルダのみ作られており
ほとんど空いています。アプリケーションはこちらに入れられるため
当分は SD カードを頼る必要もなさそうです。

EeePC 4G ではシステム系のアプリも SD にインストールしていたので
かばん中でカードが抜けたりしていないか心配でした。

Bluetooth も 4G では小型アダプタを USB ポートに指しっぱなしに
していたので、内蔵化は素直に嬉しいところです。
最初は Bluetooth が off になっていてアダプタが見つからないと
いわれます。Fn + F2 か EeePC Tray Utility で有効にしておく
必要があります。

バッテリー寿命には期待大です。
まだ実際に運用していないのでどれだけ持つかわかりませんが、
EeePC 4G では 1日持たないので AC アダプタを持ち歩いていました。


全体的にみて、EeePC 4G と比べて購入後すぐ使える普通の PC に進化した印象です。
最初にそれほど手を入れなくても、
調べたり設定変更を駆使したりメモリや SD を増設しなくても、
そのままでも十分使えそうです。

・画面が広くなった
  ダイアログなどがはみ出たときは、Tray Utility を使って上下
  スクロールモードに切り替える、といった専用の知識なしで使えます。

・RAM が増えた
  最初から 1GB (最大 2GB) なので、増設しなくてもページングファイル
  なしで大丈夫そうです。

・内蔵 SSD に余裕が出来た
  SD 運用スタイルを構築しなくても済みそう。

・バッテリー寿命が大幅に増えた
  4G ではバッテリーが持たない上に予備 AC アダプタが入手しづらく
  苦労しました。


その他気がついたことなど

デフォルトが classic スタートメニュー

CPU Atom は HT が有効になっているので、single core ですが
タスクマネージャーでは 2 cpu に見えます。

キーボードも端子類の配列レイアウトも EeePC 4G と同じなので
乗り換えの違和感は全くないです。

SD カードスロットはダミーカード入り。

関連エントリ
Eee PC 4G 買いました



データの追加と更新

GeForceGTX280     (240sp) Vista x64 177.41 = 1時間 45分 (105)
GeForceGTX260     (192sp) Vista x64 177.41 = 2時間  2分 (122)
GeForce8800GTX    (128sp) XP x86    175.16 = 2時間 42分 (162)
GeForce8800GTS640 ( 96sp) XP x86    175.16 = 5時間 12分 (312) 新
GeForce9600GT     ( 64sp) XP x86    175.16 = 4時間 10分 (250)
RADEON HD4870    (800spu) XP x86     8.6   = 2時間 33分 (153) 修正


関連エントリ
GPU で Folding@Home (2)


GPU で Folding@Home」で触れた処理時間を
もう少し調べてみました。

Folding@home
GPU2 client 6.12 beta8
複数の PC で走らせておいて、logfile から 2回以上演算結果の平均をとったもの。
データサイズ 25000 のデータのみ。

GeForceGTX280     (240sp) Vista x64 177.41 = 1時間 45分
GeForceGTX260     (192sp) Vista x64 177.41 = 2時間  2分
GeForce8800GTX    (128sp) XP x86    175.16 = 2時間 42分
GeForce9600GT     ( 64sp) XP x86    175.16 = 4時間 10分

8800/GTX260 は複数の異なるスペックの PC で走らせましたが
ほぼ一定の時間で終了しました。
PC 本体の性能が異なっていても大きな影響はないようです。
OS が違うともう少し差が生じるかもしれません。

まだ得られたデータが1回分だけなので正確ではないかもしれませんが
一応 RADEMON も。

RADEON HD4870     (800spu) XP x86   8.6    = 2時間 52分
RADEON HD4870     (800spu) XP x86   8.6    = 2時間 33分


関連エントリ
GPU で Folding@Home



ATI (AMD) RADEON HD4870 にほんの少しだけ触ることが出来ました。

普通の GPU として描画を試しただけですが、
結果は・・予想よりもずっと速い。

ゲームやベンチマークできちんと調べたわけではないのですが、
GTX200 クラスなのは間違いないようです。
走らせるプログラムや条件次第ではあるものの
もとから GeForce が苦手とする機能もあるので
今後 4800 が普及するとさらに状況が変わってくるかもしれません。

Direct3D10.1 / SM4.1 も動くし、GS を活用できるし、
280 のほぼ半分という価格差を考えるとかなり魅力的ですね。

AMD のドライバダインロードのリストに 4800 シリーズが無い点は要注意。
3870 とか選んで、CATALYST 8.6~ を入ればいいようです。


気がついたら GPU だけでも 1PETA FLOPS 目前

OS Type 	     Current TFLOPS* 	Active CPUs 	Total CPUs
Windows              200                210773          2081016
Mac OS X/PowerPC     7                  8411            117132
Mac OS X/Intel       27                 8860            53468
Linux                74                 43812           316280
GPU                  902                8199            17284
PLAYSTATIONR3        1332               47241           553464
Total                2542               327296          3138644

Last updated at Sat, 05 Jul 2008 06:04:04 


NVIDIA の新しい GeForce ドライバは Folding@Home に対応しています。
GTX280/260、8800GTX、9600GT で実際に走らせてみました。

ダウンロードするクライアントは次のページにある V6 Beta GPU2 です。
Folding@home DownloadWinOther

GTX280/260 (177.41) の場合 Vista x64 でも動作しましたが、
8800/9600 (175.19) の場合は起動するもののうまく進行しませんでした。
XP x86 では大丈夫です。

・GTX280 (177.41 + Vista x64)
・GTX260 (177.41 + Vista x64)
・8800GTX (175.19 + XP x86)
・9600GT (175.19 + XP x86)

速度は非常に速いです。
走らせた PC のスペックがばらばらで、またデータによって異なるので
おおざっぱですが 25000 のデータで
GTX280 2時間かからず、GTX260 2時間10分程度、8800GTX 2時間 40分くらい。
9600 はもっとかかっています。
これらの PC は他の作業しながらのデータなので、
あんまり当てにならないかもしれません。

期待の RADEON 4870 は試せる PC がなかったのでまだ未調査です。

関連エントリ
Folding@Home 1PFLOPS 達成?
Folding@Home PS3で 1PETA FLOPS



頼んで試してもらいました。
とりあえず GeForce8800GTX と比べると、GTX 280 は
GeometryShader の動作もかなり速くなっており比較にならないほど。
改良されているのは事実のようです。

が、それでも 2世代前の RADEON 2900XT にすら完敗。

2900 は ATI 最初の 10.0 (4.0) GPU で、3800系から 10.1 (4.1) です。
今度出る 4800系が GTX 280 対抗と考えられるため、
Geometry Shader に限定すれば RADEON の方がまだまだ優位であると
いえそうです。

それにしても 8800 の GeometryShader は本当に遅かったようです。


NVIDIA GeForce GTX 280 を入手してもらいました。
でかいと思ったけど、カード自体は GeForce8800GTX とほぼ同じ大きさでした。

電源は 6pin + 8pin 必須でそれなりの電源容量が必要です。
6+8pin は 以前 RADEON 2900XT を使っていたときと一緒。

仕事が忙しすぎて全く触る機会がないものの、NZONE にあった
GTX 200 Tech Demo の Medusa の起動を確認。
リアルタイムで見ることができました。
時間がほしい。

NZONE NVIDIA Demo: Medusa



GeForce 8800 Ultra 以来、久々に
新しいハイエンド GPU が出ました。

NVIDIAの1TFLOPS GPU「GeForce GTX 280」がついに登場

10.0 世代 ShaderModel 4.0 ではあるものの、気になったのはここ。

>Geometry Shaderのスループットを強化

GeForce は頂点を追加した時の GS の実行速度はかなり遅かったので、
これが RADEON 並になっているのならそろそろ買い換えてもいいかなと。

GS を積極的に使いたくても使えないジレンマから
やっと脱却できるかなと期待しています。

NVIDIA GeForce GTX 280



すっかりチェックするの忘れていました。
DirectX SDK June 2008 を導入しました。

まず SDK のインストーラがなんか違う。
いつもの解凍画面が出ずにすぐ起動し、インストールが速くなっている印象。


変更点はそれほど多くないようですが、一通りマニュアルをチェックしました。
以下ざっと見て気がついた "マニュアル" の変更点です。


以前こちらのエントリでも書いた
Direct3D 10 DXGI_FORMAT の機能対応一覧
相当のものがマニュアルに追加されたようです。

DirectX Graphics : Direct3DD 10 : Programming Guide : DXGI Overview
の下に次のページが追加されています。
・Hardware Support for Direct3D 10 Formats
・Hardware Support for Direct3D 10.1 Formats


DirectX Graphics : HLSL : Reference : Shader Models
  : Shader Model 4 : Texture Object
わかりにくそうだったところに修正が入って説明が増えているようです。


DirectX Graphics : HLSL : Reference : Language Syntax : Variables
  : Data Types : Struct
「Interpolation Modifiers Introduced in Shader Model 4」
のミスが修正されています。やっと本来の形になりました。
関連記事はこちら
Direct3D 10 Shader4.0 ピクセル補間モード



以前コメントで em1key + oyayubiwm が Vista ATOK2008 で動作しないと
報告をいただきました。

ATOK2008 を購入してみたので取りあえず動くようにしました。
v1.32 をダウンロードし、em1keypc.exe ではなく付属の em1keypc_atok.bat を
実行してください。
もし自動起動に設定されれている場合は、いったん解除してから
設定し直してください。

em1keypc v1.32

現在 WindowsVista x64 + ATOK2008 で動作を確認しています。


具体的な修正は下記の通り。

(1) em1keypc v1.31 + WindowsVista x64 + ATOK2008 では、
 IME を On にしても親指シフト状態に切り替わりませんでした。

(2) ただし Ctrl+0 による手動切り替えではきちんと親指シフト入力モードに
 なるので、プログラム自体は動作しています。
 IME の入力モードの取得に失敗しているようです。

(3) デフォルトでは TSF を優先して見に行くため、TSF 判定を切ると
 モード切替を受け取ることができました。

(4) 起動時の -m オプションで TSF 優先を解除できるようにしました。
 em1keypc_atok.bat は -m オプションを付けているだけです。


関連エントリ
em1keypc 64bit Windows でも 親指シフト



ワイヤードで、本体の GC コネクタに繋ぐようです。
USB じゃなかった。

ファミリートレーナー



DHARMA TACTICAL KEYBOARD 【DRTCKB91UBK】

全キー 30g の軽量タッチかつ USB 接続で Ctrl/Capslock と
ZenHan / ESC 入れ替え可能な Realforce でした。

買いました。

当初キータッチの軽さが気になるかと思ったけど、大丈夫。
個人差だと思うけど自分的には問題なし、むしろ軽くて良いです。

店頭で触り比べたときは、標準タイプの 45g のほうがしっかりと押した
感じがあって良さそうに感じました。人差し指だけで押してるとそう。
実際はタイプしてるとしっかり底打ちがあってしっくりきます。


[ CapsLock ] と [ Ctrl ]
[ Zen/Han ] と [ Esc ]

を dip switch で切り替えできます。
両方交換するには、裏面 dip switch の 1 と 2 番をどちらも on にするだけ。
USB ケーブルを抜いた状態で操作せよとのこと。


CapsLock と Ctrl はキーの大きさが違うので、わざわざ換えのキーパーツ
まで付いて来て見た目も交換できる仕様です。
見た目だけ両方 [ Ctrl ] キーにすることも可能。

キー引き抜きよう工具が付いてましたが、キートップ側面のざらざらで
つめが削れてしまい、うまく使いこなせませんでした。
結局マイナスドライバとかで引っこ抜いた。


ハード的にキーを押せなくするキーストッパーが 3個入ってます。
主に Win キーを無効にするために使うようです。
入れ替え後の CapsLock (vi の敵) も無効にしたかったけどうまく入らず断念。

3個あるので、今まで使ってた手持ちの RealForce 91UBK にも入れてみました。
使えます。


キーの刻印はかな無しで、Realforce より文字が大きくはっきりした印象。
Win キーのみ Realforce と形状が異なっており、キートップの傾斜が
ありません。
その代わり触って区別できるようなくぼみが付いています。


やはりキー交換できるのが良いです。
これを Realforce の標準機能にして欲しいくらい。

レジストリや設定ソフトなど、ソフトウエアでも交換できますが、
あまり設定したくない場合があります。
例えば一時的に ノートPC につないで外付けキーボードとして使う場合。
ノートだと Esc 位置など配列が一定でなく、キーを入れ替えないことも
あるからです。


関連エントリ
シグマA・P・O 静電容量無接点方式 キーボード



ゲーマー向けキーボードと書かれてますが
これはもしかして東プレ RealForce 。

シグマA・P・O、静電容量無接点方式のゲーマー向けキーボード
DHARMA TACTICAL KEYBOARD 【DRTCKB91UBK】

しかも Ctrl CapsLock や 半/全 ESC キーの入れ替え可能。
ほんとにキー入れ替え可能なリアルフォースだったら、これ買います。

Topre Realforce



halmako さんに送っていただいたので久しぶりに更新しました。
HTC S11HT EMONSTER 3DM caps
Direct3D Mobile DeviceCaps 一覧

CPU 専用の独自のドライバではなくリファレンスが使われています。

ただ元のプログラム自体 WM5 時代に作成したので、WM6 で
D3D が更新されていたりすると古い API だけ見に行ってる可能性があります。
この辺はぜんぜん追いかけていませんでした。

ところで WM/PocketPC は登場時からずっと OS の上限で 16bit FrameBuffer
のままです。
PocketPC 一覧

ワンセグやデジカメに解像度が 854x480 だったりと、携帯電話の性能は
かなりあがっています。
ものによってはスペックに 26万色液晶とか書かれていたりするので、
内部データは 16bit よりも高そうです。

1677万色表示のものもありました。
FOMA SH905i

表示可能な色数はスマートフォンの方がだいぶ少なくなっている可能性があります。

よく見ると EM・ONE や ZERO3 の仕様には 65536色と書かれているようです。
EMOBILE EM・ONEα
SHARP Advanced W-ZERO3[es]


Vista SP1 + March2008 で 10.1 が動くようになりました。

以前は動かなかった D3D10_DRIVER_TYPE_REFERENCE で起動します。
また D3D10.0 GPU の場合は D3D10_FEATURE_LEVEL_10_0 さえ指定しておけば
D3D10_DRIVER_TYPE_HARDWARE が使えました。

よって開発側としては D3D10CreateDevice1() 等の 10.1 API に乗り換え、
GPU に応じて FEATURE LEVEL を切り替えるだけでよさそうです。

10.0 GPU の場合個々の API や State がどう影響してどう制限されるのか
まだわからないので、その辺は実際に使ってみてからになるでしょう。
取りあえず一安心。


関連エントリ
DirectX 10.1 S3 Chrome 400
DirectX 10.1 RADEON HD3800 シリーズ

追記:

March2008 の SDK で
dxsdkvar.h を include しているとエラーが出ます。

中身を見ると見慣れない構文で、新しいコンパイラの機能なのか、、
どちらかといえばバージョン管理ツールのキーワード置換に
失敗しているような感じ。


2008/03/08
DirectX March 2008

Runtime が来たようです。

DirectX End-User Runtimes (March 2008)


追記

DirectX Software Development Kit (March 2008)

SDKもありました。Direct3D 10.1 RTM


そろそろソースコードも UTF-8 で統一したいと常々思っていました。
VisualC++ の場合 BOM (ef bb bf) があれば UTF-8 とみなしてくれます。

コンパイラおよびリンカでの Unicode のサポート

バイナリには記述したコードのまま格納されるわけではなく、
必要に応じて ShiftJIS や UTF-16 に変換されます。

関連エントリ
_T() と TEXT() の違いやソースの文字コード

逆に UTF-8 のままデータを記述することが難しいのと、
BOM が付くと他のコンパイラでエラーになることがあるようです。

"表示" を utf-8 でコンパイルしてみる

  SJIS = 95 5c 8e a6
  UTF8 = e8 a1 a8 e7 a4 ba
  UTF16= 8868 793a

VC2008: utf8+bom  = 95 5c 8e a6  (SJISに変換されている)
VC2008: utf8      = e8 a1 a8 e7 a4 ba
CW    : utf8+bom  = error
CW    : utf8      = e8 a1 a8 e7 a4 ba
gcc4.1: utf8+bom  = error
gcc4.1: utf8      = e8 a1 a8 e7 a4 ba

VC bom 無しはたまたまうまくいってますが、Shift JIS 判定ありなので
問題が出ます。(warning C4819 になる事も)

例えば "引\n" を UTF-8 記述すると、バイト列では

 引       \  n
 e5 bc 95 5c 6e

ShiftJIS でも意味のあるコードなので、'\' 'n' が変換されず
文字として残ります。

常に日本語 (cp932) とみなすこの動作は、Windows のシステムロケールを
見ているようです。VisualStudio は英語版を使っているし、option の
"International Settings" にある Language を
"Same as Microsoft Windows" でなく English にしても変化無し。

Vista で コントロールパネル→地域と言語のオプション→管理
「Unicode対応ではないプログラムの言語」を「英語」に切り替えると
コードが素通りし、"引\n" の \n が改行に変換されるようになりました。

でも他のアプリに影響が出るので、このまま使うのは問題ありです。

gcc では「 -finput-charset=cset 」「 -fexec-charset=cset 」の
オプションがあって、それぞれ個別に指定できるようです。
例えば utf8 と sjis にすると VC とほぼ同じ挙動となりました。
でも BOM はだめ。


久しぶりに新しい GPU 出てますね。しかも 10.1 対応。
PC Watch S3、DirectX 10.1対応GPU「Chrome 400」

Windows Vista SP1 の方は一応 d3d10_1core.dll も追加されていて
なんとなく動きそうに見えますが、実際に走らせると E_NOTIMPL で
エラーになります。

おそらく March SDK 待ちだと思います。
でも3月はもうすぐだ。


過去エントリ
DirectX 10.1 RADEON HD3800 シリーズ


2008/02/19
電池切れ1

CASIO の電波時計 WAVE CEPTOR DQD-1000 を長年愛用しています。
目覚ましだけでなく温度計も付いてるし時間も狂わないし。

唯一の難点は、電池切れ警告が無いことです。
でもこれかなり致命的だったりします。


(1) 設定した時間にアラームが鳴り始めて EL バックライトも点灯

(2) 電力消費量の急激な増加に伴い電圧降下

(3) 電池容量が少ないと、電圧降下に耐えられなくて瞬時にリセットされる

(4) もちろんアラーム音は即座に止まるし時間も 12:00 に戻る
  電池容量が少なくても時計としてはまだ動作可能

(5) そのうち電波受信して勝手に正常な時刻に戻る

(6) アラームが鳴らなかったのに、時計としては正しい時刻を指しているので
  朝起きられなかった原因がわからない。


数年前、前回電池切れのときも全く同じミスをしました。
成長していない・・。



プロバイダのサービス終了に伴い、これまで代表で使っていた
メールアドレスが使用できなくなりました。

各種ソフトウエアのドキュメントに書いてあるアドレスでは
今後メールが届かなくなりますのでどうぞご了承ください。

webページに掲載してある方は修正いたしました。
またフォームからの送信もこれまでどおり大丈夫です。

10年以上使ってきたメールサービスでした。
ご迷惑をおかけいたします。
よろしくお願いします。



一応動きました。

EeePC wbalancege

・EeePC 4G-X
・RAM 2GB に増設済み (512MB は RAMDISK)
・CPU Clock は 630MHz のまま
・Google Earth の cache は RAMDISK に割り当て
・使用した Bluetooth アダプタは BT-MicroEDR2

「建物の3D表示」(3Dモデル) ありでも GoogleEarth 単体だと
思ったより速くスムーズに動きます。

WbalanceGE 併用だと非常に厳しいです。
建物が多かったりアップになるとかなりのコマ落ちに。
上のキャプチャの状態では歩くのもやっと。
建物の3D表示 が無ければ大丈夫です。
WbalanceGE の描画はもっと軽量化した方が良いのかも(たぶん重すぎ)。

バランスWiiボード で地球を歩く WbalanceGE v1.10


内蔵ドライブは 4GB、C: ドライブの空きも少なくそのままでは無理です。

VC のみの最小構成にして SDHCカードに入れます。
容量は EeePC 付属の 4GB SDHC カードで十分でした。
RAM も標準の 512MB のまま。増設なしです。
VisualStudio 2008 は英語版を使いました。

VisualStudio 2008 のインストーラは、インストール先にリムーバブルディスクを
選択することができません。内蔵 SD もはじかれてしまいだめです。
いろいろ試したけどあきらめました。

仕方なく外付けの USB HDD にインストールしてから、フォルダごと SD カードに
コピーすることにします。


(1) 容量確認
  まずこの辺を参考にして、C: を 1.6GB 程度空けておきます。
4Gamer Eee PC発売記念(?) この小さいマシンでゲームを動かしてみよう
    ――その1:Windows XPを頑張って小さくしてみる


  RAM 512MB ですが、以下の手順は仮想メモリを切った状態で行っています。
  (ページングファイルなし)

(2) タスクトレイの「ハードウエアの安全な取り外し」から D: を取り外す。
  これで再起動するまで内蔵 SD カードリーダーは使用できなくなります。

(3) 外付け USB HDD を取り付ける。
  E: で認識されました。(環境依存、違っていたら読み替えてください)

  マイコンピュータのプロパティ>管理>ディスクの管理
  外付け USB HDD のドライブ (E:) を選択して右ボタンメニューから
   「ドライブ文字とパスの変更」
  ドライブ文字を D: に変更します。

(4) USB HDD (D:) へ VisualStudio 2008 をインストール
  画面を 800x600 に切り替えてからインストーラ起動。
  インストール先は
   D:\Program Files\Microsoft Visual Studio 9.0
  必ず Custom を選びます。

(5) パッケージ選択
  いらないものを全部削ります。VC のみ。
  最低限コンパイルできればよしとします。

  Language Tools の Visual C++ 以外は全部外します。
  さらに Visual C++ の中の
    × Smart Device Programmablity
  と、ソースコードもチェックを外しておきます。
    × Visual C++ Run-Time Libraries \ Visual C++ CRT Source Code
    × Visual C++ Class & Template Libraries \ ATL MFC Source Code

(6) インストール実行
  これだけ削ってインストール先も D: を指定したはずなのに、
  C: を 1.6GB も消費するといわれます。

  インストール先を指定できるのは VisualStudio 本体のみで、
  付随するコンポーネントの類は C: に入れられてしまうようです。

  ぎりぎりだけどそのまま進めます。
  この数値は多少多めに表示されているのか 220MB ほど残りました。

(7) インストーラ終了
  もちろんドキュメントは入れません。探し物はオンラインで。
  インストーラの最初の画面に戻ったら Exit

(8) SDK の移動
  C: にインストールされたものは .NET Framework 3.x や Windows SDK でした。
  特に Windows SDK が 450MB と巨大なので移動します。

   C:\Program Files\Microsoft SDKs

  これをそのまま D: に移動しました。

   D:\Program Files\Microsoft SDKs

  C: は 670MB ほどの空きになりました。

(9) 再起動
  (3) と同じ手順で USB HDD のドライブ文字を E: に戻します。
  再起動して再び D: が内蔵カードリーダーになります。

(10) SDカードに移動
  HDD 上の E:\Program Files を丸ごと SD の D:\Program Files に
  移動します。

(11) SDK の設定
  Windows SDK の場所を変更したのでその設定。
  環境変数 WindowsSdkDir の値は、vsvars32.bat の
  :GetWindowsSdkDirHelper 辺りを見ると次のレジストリを見ています。

  レジストリ HKLM
    \SOFTWARE\Microsoft\Microsoft SDKs\Windows

  上記レジストリ以下 CurrentInstallFolder に登録されているパスをすべて
  C:\ から D:\ に変更します。

  これだけではうまくいかなかったので、結局 VisualStudio 2008 の
  Tools → Options → Project and Solutions → VC++ Directories
  から Executable files、Include files、Library Files の
  $(WindowsSdkDir) を全部 D:\ から始まる実パスに置き換えてしまいました。

コンパイルできるようになりました。
SD カードは 1GB 少々 (NTFS) しか使ってないので、もっとインストール
時のオプションを増やしても大丈夫かもしれません。


ついでに DirectX SDK も入れました。
こちらは何もしなくてもインストール先にリムーバブルディスクを選べます。
ランタイムを入れると C: も多少消費します。

(1) DirectX SDK November 2007
  インストーラを起動します。
  unzip の展開先を聞いてくるので必ず、D:\TEMP など C: 以外の
  パスに書き換えてください。
  USB HDD がまだつながっているなら、そちらの方が高速です。

(2) インストール先指定
  展開が終わるとインストーラが起動するので、今度はインストール先を
  変更します。ドライブ名を C: から D: にするだけ。

  インストール内容を選びます。容量を食いそうなサンプルは外しておきました。
   × DirectX Samples and Source Code


コンパイル前に、環境変数 TEMP と TMP を、SD カードなど C: 以外のパスに
設定しておいてください。D:\TEMP など。

これで一通り開発環境ができました。
SD カード上でコンパイルも OK。


発売日 25日に Eee PC 買いました。店頭で。
開店直後に飛び込みました。

店頭に実機が1台ありましたが、なぜかデフラグ実行後の画面。
SSD なのに!

その後注文したものの、在庫の箱が見つからないらしく店員総出で
店内の棚から倉庫から探し回り、15分ほど待たされました。
発売日なのに。


本体は小さいゆえに思ったより若干重く感じます。それでも 1kg 未満。
付属の AC アダプタもコネクタ一体型で小さいものでした。

パームレスト部が狭いので、手の置き場所にはちょっと困るかもしれません。
机の上だとキーが遠いけど、完全に手を乗せるだけのスペースはなし。

ところでこのキーボードに見覚えがあります。
以前 EM・ONE で愛用していた ELECOM TK-UP84CP
物理的な大きさ、形状、配列がそっくりです。
emobile EM・ONE USBキーボードの改造

キーの刻印と配列は若干違っていて、スペースバーの右が [変換] ではなく
[ひらカタ] になっています。自分は [変換] の方を使うので、下記のように
入れ替えました。

キー入れ替え reg ファイル (Caps Lock → Control 、[ひらカタ] → [変換])
[HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\Keyboard Layout]
"Scancode Map"=hex:00,00,00,00,00,00,00,00,\
  04,00,00,00,\
  1d,00,3a,00,\
  79,00,70,00,\
  70,00,79,00,\
  00,00,00,00

画面解像度は 800x480 で狭いですが、EeePC Tray Utility でいつでも
800x600 (上下スクロール) と切り替えられるようになっています。
同じ解像度でも WindowsMobile よりずっと情報量が多いのは不思議です。

他に気になるのはディスク容量とバッテリー寿命くらいでしょうか。

だけど SSD なのでアクセス音が皆無。
電源を入れると無音で立ち上がるところがかなり新鮮です。

起動したまま揺らしても走ってもたぶん大丈夫。
ポケットに Wiiリモコン を入れて、ログを取りながら一度本気走りを
してみたいです。(これがやりたかった)

ゼロスピンドルとはいっても冷却用ファンなど機械可動部はまだあります。
動作時のディスクアクセスが問題なくても、本体のつくりが耐衝撃
構造かどうかはまた別の問題なのでご注意ください。


取りあえず標準バッテリー 1200mAh(へたり気味)で
連続待ち受け時間はおよそ 7時間10分 (430分) でした。

単純に容量の比率だけで求めると
 大容量バッテリー 2000mAh = 約12時間弱
 スーパー大容量バッテリー 3400mAh = 約20時間

現在 スーパー大容量バッテリー 3400mAh を使用しており
夜充電して、昼間は 完全に待ち受け状態のモデムとして 1日持っています。

当分は、昨日買ったばかりの某ノートPC のモデムとして活用しようと思ってます。
EMOBILE EM・ONE を Bluetooth モデムにする

本当は Bluetooth 接続時以外は HSDPA も停止できれば
もう少しバッテリーの持ちも良くなるのかもしれません。

MachiukeIdle v1.00

なおマニュアルにも書いていますが、ZERO3 系ではおそらく動作しません。
BattUserIdle / ACUserIdle に値を書き込んでも 0 のままで、
無効となっているためです。


Bluetooth 環境強化中です。
いつでも Bluetooth 経由でダイヤルアップできるよう、EM・ONE を
Bluetooth 待ち受け状態のまま待機させておくソフトを作ってみました。

MachiukeIdle v1.00

IDLE 状態にして画面を消し、バッテリーをセーブします。
またかばんの中でも誤動作しないようにキーロックをかけています。

何らかの操作を行っても、5秒間操作しないときは再び IDLE状態みなし画面を消します。

Bluetooth は HSDPA よりも遅いので注意。だいたい 280Kbps 前後。
EMOBILE の回線速度を最大まで活用できませんが、無線で気軽にネット
接続できるのは便利です。

問題の連続待ち受け時間は現在調査中です。結構時間がかかりそう。

通信時はバッテリーをだいぶ消費するので、やはり運用するなら大容量
バッテリーは欲しくなります。


電源周りの設定は下記のレジストリを使っています。

HKEY_LOCAL_MACHINE
      System\CurrentControlSet\Control\Power\Timeouts

key
    BattSuspendTimeout
    ACSuspendTimeout
    BattUserIdle
    ACUserIdle

すべて DWORD で秒数です。0 を入れると Timeout 無しになります。

 ~Timeout が設定画面で変更できる、自動電源OFFの秒数相当
 ~UserIdle が、自動で画面OFFするまでの秒数


・キーボードがつながる
・マウスがつながる
・携帯電話をモデムにしてネット接続できる
・オーディオアダプタがつながって音楽再生
・PDA の同期ができる(ActiveSync)
・WiiリモコンやバランスWiiボードがつながる
・PDA や携帯電話のファイル転送ができる

その他試していないけど

・ヘッドセットがつながる
・GPSユニットがつながる

などなど。

早い話、USBでできることのワイヤレス版、と思えばほぼイメージに近いです。

ワイヤレスマウスやキーボードも、それぞれ専用のレシーバーを使う
必要がなくなります。PCに内蔵されていればそれで済むし、
アダプタをつける場合も1個でできます。

さらに A2DP では Bluetooth 自体が PC 上の音源として認識されます。
USB 音源のようなもので、対応受信機さえあれば PC に音源が無くても
ヘッドホンやスピーカーが鳴らせます。


欠点は接続時にペアリングが必要なこと。
 ケーブル抜き差しだけで済むUSBよりも最初に若干手間がかかります。

それと通信速度が遅いこと。
 ストレージ系など大容量のデータ転送は苦手です。

また対応機器の選択の幅が狭く、それぞれ結構な値段がすること。

そして bluetooth stack によって対応プロファイルの違いがあって、
結果として使えたり使えなかったり、相性の問題が生じてしまうことでしょうか。
操作方法もソフトによって異なっています。


これまで EM・ONE のダイヤルアップ接続と Keyboard くらいにしか
使っていませんでしたが、bluetooth のプログラム作ったり調べたり
していたらすっかりはまってました。

 ノートPC(Windows)
 マウス
 外部キーボード
 ネット回線 (EM・ONE)
 ヘッドホン
 ゲームコントローラ (Wiiリモコン等)

が全部無線でつながってしまいました。PCから伸びているケーブルは無し!
(それぞれバッテリーが持つ間だけ)


USB の Bluetooth アダプタは3種類試しましたが、基本的には Windows XP
でも Vista でも標準のドライバで使うことができました。x64 でも大丈夫です。

ただし Windows 標準の bluetooth stack では A2DP 等のオーディオ系
プロファイルが使えず、必要な場合はアダプタ付属の bluetooth stack や
他のソフトに頼ることになります。

このときアダプタ付属の bluetooth stack は、Vista や x64 未対応の
場合もあるため注意が必要です。

また API の違いもあるので、すべてに対応する場合プログラム側の工夫も
必要でした。プログラムによっては bluetooth stack の種類に依存する
可能性があります。
Toshiba bluetooth stack と Bluesoleil 対応


結局 Bluesoleil 5 を購入しました。Windows の stack と異なり
A2DP は使えるようになったものの、代わりに bluetooth による
WM 端末の ActiveSync 接続が使えなくなりました。悩ましいところです。

まとめ
・bluetooth stack によってプロファイルが異なる
・bluetooth stack によって API が異なる
・bluetooth stack によって OS に対応していないことがある


Windows XP SP2 (x86 32bit) と Windows XP SP2 (x64) で動作確認しました。
どちらも Windows 標準の bluetooth stack で、アダプタ付属のドライバを
使用せずに認識できました。

Windows bluetooth stack の場合、通信時に何らかの理由で timeout すると
WriteFile() に切り替わってしまう問題があったので修正しました。


ここ数日一番悩んだ問題が、使っていると突然 バランスWiiボードの 通信が
切れてしまうというもの。電池交換しても変わらず、プログラム側の負荷が
高いせいかと、かなり悩んだのですが・・。

ふと切れた直後にボードの電源ランプが点滅していることを発見。
比較的長時間点滅が続くので、どうやら sync 待ち状態っぽい。

さらに左下、電池ボックス上の特定の一点に力をかけると点滅が始ることを
突き止めた。
sync ボタンが押されてしまっているらしい。

壊してしまったのかと分解してみると、sync ボタンは基板から電池ボックス
まで長い棒が伸びている。これ、垂直に押さなくても軽く倒しただけでも
スイッチが入るらしい。

どうも圧力で電池ボックス周辺がゆがんで、sync ボタンのスイッチが倒れて
押されているようだ。

電池ボックスの sync ボタンの穴を削って、干渉しないように広げたら
再発しなくなりました。


他のボードでは全く発生しないので、個体差か単に酷使しすぎてへたった
だけだと思います。


Toshiba bluetooth stack と Bluesoleil に対応できました。
より多くの Bluetooth アダプタ(ドライバ) で動作するようになりました。

WbalanceGE v1.20 (GoogleEarth を歩く)
WBHealthMeter v1.10 (バランスWiiボード 体重計)

あらかじめ接続してから上記プログラムを起動する必要あり。
ペアリングと接続はそれぞれ、個別の接続管理画面で行います。

●Toshiba bluetooth stack
・Bluetooth 設定で[新しい接続]を押す
  必要に応じて バランスWiiボード の Sync ボタンを押す。

・一度登録されたら、以後は Nintendo RVL_WBC-01 のアイコンを選んで
 メニューから[接続]するだけ。このときも Sync ボタンを押す必要あり。

●Bluesoleil
・バランスWiiボードの Sync を押して、検索画面でアイコンが表示されるのを待つ。
 バランスWiiボードのランプ点滅が止まったら Sync を押しておく。

・名前が確定したら、メニューから接続(Connect)を選ぶ
 やはり接続時も Sync ボタンを押しておく必要あり。

●Windows 標準
・これまでどおり、プログラム上から「バランスWiiボード登録」で可能。
 コントロールパネルから登録しても OK

コマンドの送信が原因でした。他の bluetooth stack では
HidD_SetOutputReport() が使えないようです。Toshiba 以外はエラーも
返らないので工夫が要ります。

まとめると下記のようになります。

WindowsVista bluetooth stack
 ○ HidD_SetOutputReport
 × WriteFile  (送信できない、エラーにならない)

Toshiba bluetooth stack v5.10.15
 × HidD_SetOutputReport (送信できない、エラーになる)
 ○ WriteFile

Bluesoleil v2.6.0.1 070402 (BT-MicroEDR2 付属)
 HID の認識でエラーのため列挙できない

Bluesoleil v5.0.5 64bit
 × HidD_SetOutputReport (送信できない、エラーにならない)
 ○ WriteFile

判定手順
 1. HidD_SetOutputReport() を使い、0x15 等の return のあるコマンドを送る
 2. もし 1. がエラーになったら WriteFile を選択する
 3. 結果が来たらそのまま、一定期間経っても結果がこなければ WriteFile を選択する

今回実験した組み合わせ
 Vista x86 + Princeton PTM-UBT3S + 付属 Toshiba stack
 Vista x86 + Princeton PTM-UBT3S + Windows stack
 Vista x64 + Planex BT-Mini2EDR + Windows stack
 Vista x64 + Planex BT-Mini2EDR + Bluesoleil 5
 Vista x64 + Planex BT-MicroEDR2 + Bluesoleil 2/5


関連エントリ
バランスWiiボードを使ったまじめな体重計 WBHealthMeter 1.00
バランスWiiボード で地球を歩く WbalanceGE v1.10


体重測定のみに特化した、まじめな体重計を作ってみました。

WBHealthMeter v1.00 (バランスWiiボード 体重計)

アナログ針つき。

WBHealthMeter

●そのまま使う

 測定した体重値を常時リアルタイム表示します。
 アナログ針はデジタル表示よりもレスポンスが良いです。

 BMI と体重の対応表をリアルタイムに更新するので、
 特に身長を設定しなくても、自分の BMI 値がわかります。


●バランスボードのボタンを押してから乗る

 値の変動が収まったときの数値を今回の体重値とみなしてログに記録します。
 一般のデジタル体重計に近い動作です。


画面には過去8件分だけ表示しますが、ファイル上は特に制限無くすべての
結果書き込まれています。


追記 (2020/09/30): GitHub: WBHealthMeter


方向転換時の判定にミスがあったので更新しました。

WbalanceGE v1.10 (GoogleEarth を歩く)

その他バグ修正と、方向転換時のパラメータも調整しています。

○補足など

上空からははっきり見えても、自分視点だと地面はかなりぼけぼけです。
メニューの「Camera切替」かスペースキーで上空視点になるので、
迷ったら切り替えてみてください。

比較的狭くて小さ目の建物が多いところ、地面のペイントが多いところがお勧め。

移動速度は歩幅の設定で調整可能です。カーソルキーでも変更できます。

残念ながら GoogleEarth には建物への当たり判定がありません。
地面の高低差には追従します。