2011年12月27日火曜日

アライメント

主にJavaを触っているのだが、よく考えればメモリー管理はよろしくやってくれるわけで・・・。
アドレスも見れないし見る必要がないコンセプトなのでいいやと思いつつも、何故かC++版を
書いてみたい衝動に駆られ、久しぶりにC/C++コンパイラーを起動した。
すぐに終わるだろうと考えていたが、環境がUbuntu-64bit(Android-Gingerbread以上)なことを
すっかり忘れていたため、予想外に時間が掛かってしまった。
C/C++関連は32bitOSにどっぷりと慣れていたからなぁ・・・。

// アライメントの計算
uintptr_t alignment(uintptr_t rawAddress, size_t align){
    align--;
    return (rawAddress + align) & ~align;
}

void* allocateAligned(size_t size, size_t align){
    // 2の羃乗でない場合はアサート
    assert(((align - 1) & align) == 0);
    // 実際に確保するサイズ(actual_size = request_size + (align - 1) + offset_size)
    size_t actualSize = size + (align - 1) + sizeof(void*);
    // アラインされていないメモリ確保
    void* pRawAddress = malloc(actualSize);
    if(pRawAddress == NULL)
        return NULL;
    // オフセットアドレスに生アドレスを書き込む
    uintptr_t rawAddress = reinterpret_cast<uintptr_t>(pRawAddress);
    uintptr_t alignedAddress = alignment(rawAddress + sizeof(void*), align);
    ptrdiff_t offsetAddress = alignedAddress - sizeof(void*);
    void** ppOffsetAddress = reinterpret_cast<void**>(offsetAddress);
    *ppOffsetAddress = pRawAddress;
    // アラインされたアドレスへのポインタを返す
    return reinterpret_cast<void*>(alignedAddress);
}

void Allocator::freeAligned(void* p){
    assert(p != NULL);
    uintptr_t alignedAddress = reinterpret_cast<uintptr_t>(p);
    uintptr_t offsetAddress = alignedAddress - sizeof(void*);
    void** ppOffsetAddress = reinterpret_cast<void**>(offsetAddress);
    // アラインされていないアドレスへのポインタで解放
    free(*ppOffsetAddress);
}

64bitなのでポインターサイズは8bytes。
32bitなら気にせず unsigend int で済ましても問題がなかったところ。
uintptr_t、ptrdiff_t、size_t が環境によって自動的に変わるため、これを利用すればいい。

※オフセット値を2bytesで保持していたが、アドレスを直接持つように変更

2011年11月18日金曜日

replicaisland

今更ながら replicaisland
以前、仕事のヘルプでGLSurfaceViewを扱うAndroidアプリに触れる機会があったのですが
当時は疑問に思っていたことがソースを見て解消できました。
オープンソースって凄いですね。

何を疑問としていたかといえば、AndroidのライフサイクルとGLSurfaceViewです。

・ Backキー押し下げによる終了
・ Homeキー押し下げからの再スタート
   例えばランチャーアイコン、RecentryList
・ 電源キー押し下げによるサスペンド・レジューム

EGLContextが破棄されるタイミングでVRAMの内容もフラッシュされるため
一般的なゲームコンソールなどとは異なり、Android特有の制御をしてあげないとダメと。

当然といえばそれまでですけど、Androidの経験が少ないと癖のある制御に違和感を覚えますね。

で、深く追うつもりはなかったのですが、ついついエンジン部分も。
・UI、GL、ゲームのスレッド3本制御
・レンダリングキュー
・GLSurfaceViewのカスタマイズ
・GCを発生させにくい設計

これは大変勉強になりました。
その他、ゲームという括りを外しても入力周りはかなり参考になります。