Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.1 ) |
- 名前:PSPv1.5 日時:2018/10/19 21:18
↓のようなのを書いてみました。CPU負荷ではなくノーウェイトFPSでの比較ですが、「あだけ」と「全角(半角も
混じっていますが)だけ」とでほとんど同じでした。140くらい。
フォントって最初の描画は重いがそこでデータを作って2ループ目からはそれを使うのでそこそこ早い、という
認識なので、メインループに入る前にこっそりごっそり描画しておけばいいのかなとか思っています。
(そこまでやったことはありませんが)
#include "DxLib.h"
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{
ChangeWindowMode(TRUE);
SetGraphMode(1280, 720, 32);
SetWaitVSyncFlag(FALSE);
if (DxLib_Init() < 0) return -1;
SetDrawScreen(DX_SCREEN_BACK);
TCHAR str1[] = TEXT("、。,.・:;?!゛゜´`¨^ ̄_ヽヾゝゞ〃仝々〆〇ー―‐/\〜‖|…‥\n" \
"‘’“”()〔〕[]{}〈〉《》「」『』【】+−±×÷=≠<>≦≧∞∴\n" \
"♂♀°′″℃¥$¢£%#&*@§☆★○●◎◇◆□■△▲▽▼※〒→←↑↓〓\n" \
"∈∋⊆⊇⊂⊃∪∩∧∨¬⇒⇔∀∃∠⊥⌒∂∇≡≒≪≫√∽∝∵∫∬ʼn♯♭♪\n" \
"ΑΒΓΔΕΖΗΘΙΚΛΜΝΞΟΠΡΣΤΥΦΧΨΩαβγδεζηθ\n" \
"ικλμνξοπρστυφχψωАБВГДЕЁЖЗИЙКЛМНО\n" \
"ПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдеёжзийклмн\n" \
"опрстуфхцчшщъыьэюя\n" \
"─│┌┐┘└├┬┤┴┼━┃┏┓┛┗┣┳┫┻╋┠┯┨┷┿┝┰┥┸╂\n" \
"。「」、・ヲァィゥェォャュョッーアイウエオカキクケコサシスセソタチツテトナニヌネノハヒフヘホマミムメモヤユヨラリルレロワン゙゚\n" \
"@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]_`\n" \
"abcdefghijklmnopqrstu ~∞gョх\n" \
"援括窮欠合紫潤焉゚∫島煤縺ロ∠凵諱ソ∪");
int l = strlenDx(str1);
TCHAR str2[500], buf[64];
for (int i = 0; i < l; i++)
str2[i] = (str1[i] == _T('\n')) ? _T('\n') : _T('あ');
str2[l] = _T('\0');
unsigned int c = 0;
char KeyBuf[256];
while (ProcessMessage() == 0)
{
GetHitKeyStateAll(KeyBuf);
ClearDrawScreen();
for (int i = 0; i < 192; i++)
{
if (KeyBuf[KEY_INPUT_LSHIFT]) // Lシフトキーで全角+半角
DrawString(0, 20 + i * 2, str1, GetColor((c & 2) ? 255 : 0, (c & 4) ? 255 : 0, (c & 1) ? 255 : 0));
if (KeyBuf[KEY_INPUT_LCONTROL]) // Lコントロールキーで あ のみ
DrawString(0, 20 + i * 2, str2, GetColor((c & 2) ? 255 : 0, (c & 4) ? 255 : 0, (c & 1) ? 255 : 0));
c++;
}
float fFPS = GetFPS();
sprintfDx(buf, TEXT("L-Shift:全角文字(+半角カナ) L-Control:「あ」のみ %d fps"), (int)fFPS);
DrawString(0, 0, buf, GetColor(255, 255, 255));
ScreenFlip();
}
return DxLib_End();
}
|
Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.2 ) |
- 名前:sereparu 日時:2018/10/20 10:34
PSPv1.5さん
検証用のソースまでご用意いただき、誠にありがとうございます。
PSPv1.5さんのソースを実行してみたところ、PSPv1.5さんのおっしゃる通り
「あ」だけの場合も、全角記号の場合も、処理が重くなることなく、FPSも140くらいで安定していました。
自分のソースもほぼ同じものだったので、何が違うか一つずつ比較してみたところ
SetGraphModeの画面の解像度の引数を変えると、全角記号の表示で処理が重くなる(FPSが0になる)ことが分かりました。
PSPv1.5さんのソースでは「SetGraphMode(1280, 720, 32);」となっていますが
自分のソースでは「SetGraphMode(960, 540, 32);」と設定していました。
PSPv1.5さんのソースの「SetGraphMode(1280, 720, 32);」の画面の解像度の部分を
色々変更してみたところ、以下のような結果になりました。
(○…全角記号の表示で処理が重くならなかった、×…全角記号の表示で処理が重くなった)
SetGraphMode(640, 480, 32); → ×
SetGraphMode(800, 600, 32); → ×
SetGraphMode(1024, 768, 32); → ○
SetGraphMode(1280, 1024, 32); → ○
SetGraphMode(1280, 720, 32); → ○
SetGraphMode(1920, 1080, 32); → ○
現在、解像度が最大1920×1080のデスクトップPC用のモニターを使っていますが
試しに解像度が最大1280×800のノートPCで同じソースを実行してみたところ
ノートPCの方では、どの解像度にしても「あ」だけの場合も、全角記号の場合もFPSは20くらいでした。
そのため、使用しているモニターの性能に依存する問題なのではないかと思います。
そうなると、プログラム側で修正するのが難しいかもしれません。
もう少し何か方法がないか調べてみます。
|
Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.3 ) |
- 名前:PSPv1.5 日時:2018/10/20 12:45
No.1に書いたソースのSetGraphMode(w, h, bpp)のwとhを変えて試してみました。
すると
■NG (FPS=0 ... 1コマ描くのに5秒以上かかる)
1600 x 384 ドット数:614400
640 x 962 ドット数:615680
1280 x 481 ドット数:615680
1600 x 385 ドット数:616000
800 x 770 ドット数:616000
960 x 642 ドット数:616320
640 x 963 ドット数:616320
800 x 771 ドット数:616800
1028 x 600 ドット数:616800
■OK (FPS = 140程度)
1280 x 482 ドット数:616960
640 x 964 ドット数:616960
960 x 643 ドット数:617280
1600 x 386 ドット数:617600
1920 x 322 ドット数:618240
1600 x 390 ドット数:624000
という結果でした。つまり、バックバッファの縦と横のドット数をかけた数値が
616800まではNG、616960から普通の速度、という感じです。
また、str1[]の中身を半分くらいまでにすると、上記NGだった組み合わせのうち、
FPS=140程度になるものもあります。
ちょっと調べてみましたが、
SetFontCacheCharNum(int n);
int GetFontCacheCharNum(); // デフォルトは0が返ってくるので最初どれだけ確保されているのかは取得できない
という関数が存在します。
今回は 435文字+あ+英数字+αで500もないので、SetFontCacheCharNum(2048); のようにすると
(VRAMが十分確保できるPCなら)640x480でもOKでした。
推測ですが、バックバッファサイズに応じたキャッシュサイズを最初に作る仕様なのかもしれませんね。
(GetFontCacheCharNum() はそれを返してほしいところですが…)
|
Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.4 ) |
- 名前:yumetodo 日時:2018/10/20 13:47
そもそもDrawStringToHandleを使うようにするとどうなりますか?
|
Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.5 ) |
- 名前:sereparu 日時:2018/10/20 15:31
PSPv1.5さん、yumetodoさん
迅速なご回答、誠にありがとうございます。
PSPv1.5さんのおっしゃる通り、「SetFontCacheCharNum(2048);」を指定したところ
どの解像度でも全角記号を描画しても処理落ちが発生しなくなりました。
過去ログをよく調べたら同じような回答が既に存在しました。
過去ログの調査不足でした。申し訳ありません。
ttp://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=3307
ttp://dxlib.o.oo7.jp/cgi/patiobbs/patio.cgi?mode=view&no=3949
>yumetodoさん
CreateFontToHandleでフォントサイズの小さいフォントハンドルを作成して
DrawStringToHandleで全角記号を描画した場合は、処理落ちが発生しませんでした。
ただ、今回の場合、フォントサイズを15以上に設定すると処理落ちが発生しました。
「SetFontCacheCharNum(2048);」を指定しても、フォントサイズを巨大(150など)にした場合は
コンソールに「テクスチャに画像を転送するためのメモリの確保に失敗しました」とエラーが出力され
描画自体できなくなります。
使用する文字の種類、解像度、フォントサイズなどに合わせて
ちょうど良いキャッシュサイズを自動で設定できる機能があったら良いのに、と思いました。
何か良い方法がないか、もう少し考えてみます。
|
Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.6 ) |
- 名前:管理人 日時:2018/10/23 01:37
|
Re: DrawStringで大量の文字列を描画すると処理が重くなる ( No.7 ) |
- 名前:sereparu(解決) 日時:2018/10/27 00:13
管理人さん
ライブラリの更新、誠にありがとうございます。
とりあえず、一度に大量の文字を表示しない、フォントサイズを大きくしすぎないよう
気を付けて使用することにします。
今回はテスト用に大量の文字を表示したため発生した現象であり
通常は問題ないと思いますので、解決とさせていただきます。
ありがとうございました。
|
|