Форум программистов, компьютерный форум, киберфорум
C/C++: WinAPI
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.60/5: Рейтинг темы: голосов - 5, средняя оценка - 4.60
2 / 2 / 0
Регистрация: 14.08.2016
Сообщений: 40

"Разрыв кадра" лечится(?) двойным вызовом BitBlt O_o

31.05.2020, 00:27. Показов 1146. Ответов 10

Студворк — интернет-сервис помощи студентам
Несколько дней пытаюсь понять почему при задержке основного цикла > 10мс на глаз видно т.н. "разрыв кадра"? И вот игрался и заметил одну особенность, если 2 раза подряд и более вызвать функцию BitBlt, то проблема если и не исчезает то становится едва заметной. Как это вообще объяснить?

Если что вот код программы:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
#include"Include\Engine.h"
 
Object oTri;
Vector posFIX = {0,0,2}, posFLOAT = {0,0,30};
 
double startTimeALL = 0, startTimeDraw = 0, max_Draw = 0, max_Update = 0, max_ALL = 0;
double    dtTimeALL = 0,    dtTimeDraw = 0;
 
float delay_ms = 20;
float fi = 0;
 
void INIT() 
{   
    oTri = CreateTriangle(2, 2);
 
    float FovY = 90;
    float aspect  = float(mmHEIGHT)/mmWIDTH;
    matProjection = matProj(aspect,1,1000,FovY*toRAD);
    matViewPos    = matView(mmWIDTH,mmHEIGHT);
 
     matProjectionViewPos =   matProjection*matViewPos;
    invmProjectionViewPos = -(matProjection*matViewPos);
}
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
    if(!InitInstance(hInstance, nCmdShow)) return GetLastError();
    
    SetResolution(1000, 500);
 
    INIT();
    while(!mmENDPROG) 
    {   
        startTimeALL = clock();
 
        startTimeDraw = clock();
            KeysState();
            MouseState();
            if(hitESC) mmENDPROG = true;
            if(hitTAB) mmFLAG[2]++, mmFLAG[2] %= 4;
 
            MSG msg;
            mmWHEEL = 0;
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            if(msFORW) delay_ms += 1;
            if(msBACK) delay_ms -= 1;
            
            ClearPixels();
 
                fi += pi/36;    if(fi >= pi*2) fi = 0;
 
                posFIX.x  = cos(fi)*3;
                posFLOAT += (posFIX-posFLOAT)*0.2;
 
                Position(&oTri, posFLOAT);
                ModifyObject(&oTri);    
                DrawObject(&oTri);
 
            UpdatePixels();
 
                StreamText << "BitBlt * "<<mmFLAG[2]+1<<"\t(Press 'TAB' to change)";    Text(10, 20);
 
                StreamText << "delay_ms = "<<delay_ms<<"\t('Mouse Wheel' to change)";   Text(10, 250);
 
                StreamText << "dtTimeDraw = "<<dtTimeDraw;                              Text(10, 320);
                StreamText << "dtTimeALL = "<<dtTimeALL;                                Text(10, 340);
                StreamText << "max_Draw = "<<max_Draw<<"\t(Press 'SPACE' to clear)";    Text(10, 380);
                StreamText << "max_ALL  = "<<max_ALL;                                   Text(10, 400);
                StreamText << "FPS = "<<int(1000/dtTimeALL);                            Text(10, 470);
 
            ClearKeys();
 
            if(mmFLAG[2] == 0)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 1)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 2)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 3)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
        dtTimeDraw = clock() - startTimeDraw;           
        
 
        // если код выше выполнился быстрее чем delay_ms, то ждем оставшиеся [мс] до delay_ms
        while(clock() - startTimeALL < delay_ms);   
 
 
        dtTimeALL = clock() - startTimeALL;
 
        if(dtTimeDraw   > max_Draw)     max_Draw    = dtTimeDraw;
        if(dtTimeALL    > max_ALL)      max_ALL     = dtTimeALL;
        if(hitSPACE)    max_Draw = max_ALL = 0;
    }
    ReleaseInstance();
    return 0;
}
Можете сами проверить .ехе (во вложении)
На моем ноуте с 60Гц монитором "разрыв" виден на delay_ms = 20;
Вложения
Тип файла: zip Engine.zip (54.0 Кб, 1 просмотров)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
31.05.2020, 00:27
Ответы с готовыми решениями:

Низкая скорость копирования изображения вызовом функции bitblt
Привет. Имеется набор иерархически упорядоченных классов - графических объектов, например объект-контейнер-примитив-кнопка, либо...

Разрыв кадра в играх
Доброго времени суток. Проблема - разрыв кадра в играх, особенно заметно при вращении камерой. Суть в том, что у меня есть два знакомых,...

Разрыв кадра в играх
Доброго времени суток. Проблема - разрыв кадра в играх, особенно заметно при вращении камерой. Суть в том, что у меня есть два знакомых,...

10
 Аватар для GoodWeather
886 / 588 / 179
Регистрация: 28.02.2017
Сообщений: 2,359
Записей в блоге: 1
31.05.2020, 02:49
Что-то непонятное... Что собою представляет сей некий device?
Что за странные ClearPixels() и UpdatePixels()?
Как обрабатываются WM_PAINT и WM_ERASEBKGND?
0
2 / 2 / 0
Регистрация: 14.08.2016
Сообщений: 40
31.05.2020, 13:43  [ТС]
Цитата Сообщение от GoodWeather Посмотреть сообщение
Что-то непонятное... Что собою представляет сей некий device?
Что за странные ClearPixels() и UpdatePixels()?
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
const std::string APPTITLE = "Engine";
 
HWND                window;
HDC                 device, buffer;
BITMAPINFOHEADER    bih;            // информация о картинке
HBITMAP             hBmp;           
DWORD              *pBmp;           // буфер с выводимыми пикселями
HGDIOBJ             hOld;
 
HFONT               hFont;
 
 
 
DWORD ScreenBuffer[2000][2000];     // инициализируем экранный  буффер с запасом
float  DepthBuffer[2000][2000];     // инициализируем глубинный буффер с запасом
//==========================================================================================
//                                  Глобальные переменные
//==========================================================================================
bool  mmENDPROG = false;
int   mmWIDTH;
int   mmHEIGHT;
short mmWHEEL;
int   mmFLAG[10];
float mmVALUE[10];
//==========================================================================================
//                          Очистка, обновление и вывод пикселей
//==========================================================================================
void ClearPixels()
{
    for(int j = 0; j<mmHEIGHT; j++) for(int i = 0; i<mmWIDTH; i++) ScreenBuffer[i][j] = 0, DepthBuffer[i][j] = 999999;
}
void UpdatePixels()
{
    for(int j = 0; j<mmHEIGHT; j++) for(int i = 0; i<mmWIDTH; i++) pBmp[j*mmWIDTH + i] = ScreenBuffer[i][j];
}
void RenderScene()
{
    BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);                                 //Рисуем пиксели
}
//==========================================================================================
//                                  Инициализация окна
//==========================================================================================
void SetResolution(int WIDTH, int HEIGHT)
{
    mmWIDTH  = WIDTH;
    mmHEIGHT = HEIGHT;
 
    memset(&bih, 0, sizeof bih);            // Очищаем заголовок изображения
    bih.biSize          = sizeof bih;       // Заполняем его своими параметрами
    bih.biPlanes        = 1;
    bih.biBitCount      = 32;               // 32 бита на пиксель (R=8 G=8 B=8) + 8 бит на альфа канал (32-битный канал у видеопамяти) 
    bih.biCompression   = BI_RGB;           // Простой формат
    bih.biWidth         = mmWIDTH;
    bih.biHeight        = -mmHEIGHT;
 
    hBmp   = CreateDIBSection(NULL, (PBITMAPINFO)&bih, DIB_RGB_COLORS, (PVOID *)&pBmp, NULL, NULL); // Создаём изображение
    SelectObject(buffer, hBmp);
 
    RECT WindowRect;           
    RECT ClientRect;
    GetClientRect(window, &ClientRect);
    GetWindowRect(window, &WindowRect);
    int  sx = GetSystemMetrics(SM_CXSCREEN);// ширина монитра в пикселях (с текущем разрешением)
    int  sy = GetSystemMetrics(SM_CYSCREEN);// высота монитра в пикселях (с текущем разрешением)
    int  width  = mmWIDTH  + ((WindowRect.right  - WindowRect.left) - ClientRect.right);
    int  height = mmHEIGHT + ((WindowRect.bottom - WindowRect.top)  - ClientRect.bottom);
    SetWindowPos(window, 0, sx/2-width/2, sy/2-height/2, width, height, 0);  
}
LRESULT CALLBACK WinProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) 
{
    switch (message) 
    {
    case WM_DESTROY:
        mmENDPROG = true;
        PostQuitMessage(0);
        break;
    case WM_MOUSEWHEEL:
        mmWHEEL = ((wParam >> 16) & 0xffff);
        break;
    }
    return DefWindowProc(hWnd, message, wParam, lParam);
}
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow) 
{
    WNDCLASSEX wc;
    wc.cbSize = sizeof(WNDCLASSEX);
    wc.style = CS_HREDRAW | CS_VREDRAW;
    wc.lpfnWndProc = (WNDPROC)WinProc;
    wc.cbClsExtra = 0;
    wc.cbWndExtra = 0;
    wc.hInstance = hInstance;
    wc.hIcon = NULL;
    wc.hCursor = LoadCursor(NULL, IDC_ARROW);
    wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
    wc.lpszMenuName = NULL;
    wc.lpszClassName = APPTITLE.c_str();
    wc.hIconSm = NULL;
    RegisterClassEx(&wc);
    
    window = CreateWindow(APPTITLE.c_str(), APPTITLE.c_str(), WS_OVERLAPPEDWINDOW, 111,111, 333,333, NULL, NULL, hInstance, NULL);
    if(window == 0) return 0;
 
    ShowWindow(window, nCmdShow);
    UpdateWindow(window);
 
    device = GetDC(window);
    buffer = CreateCompatibleDC(device);    // Создаём контекст
 
    
    SetBkMode(buffer, TRANSPARENT);
    hFont  = CreateFont(20, 0, 0, 0, 0, ANSI_CHARSET, 0, 0, 0, 0, 0, 0, 0, "Consolas");
    hOld   = SelectObject(buffer, hFont);   // При завершении программы возвращаем объект
 
    return 1;
}
void ReleaseInstance()
{
    SelectObject(buffer, hOld);             // hOld содержит объект до первого вызова SelectObject в нашей программе
    DeleteDC(buffer);
    DeleteObject(hBmp);
    DeleteObject(hFont);
    ReleaseDC(window, device);
}
Цитата Сообщение от GoodWeather Посмотреть сообщение
Как обрабатываются WM_PAINT и WM_ERASEBKGND?
Никаким. Очистка экрана происходит просто заполнением в буфер пикселей нужным цветом каждый кадр. WM_PAINT хз зачем его обрабатывать, так все устраивает.
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
31.05.2020, 14:31
Цитата Сообщение от isrepeat Посмотреть сообщение
так все устраивает.
Цитата Сообщение от isrepeat Посмотреть сообщение
Несколько дней пытаюсь понять
- значит, не всё

Remarks
The GetDC function retrieves a common, class, or private DC depending on the class style of the specified window. For class and private DCs, GetDC leaves the previously assigned attributes unchanged. However, for common DCs, GetDC assigns default attributes to the DC each time it is retrieved. For example, the default font is System, which is a bitmap font. Because of this, the handle to a common DC returned by GetDC does not tell you what font, color, or brush was used when the window was drawn. To determine the font, call GetTextFace.

Note that the handle to the DC can only be used by a single thread at any one time.

After painting with a common DC, the ReleaseDC function must be called to release the DC. Class and private DCs do not have to be released. ReleaseDC must be called from the same thread that called GetDC. The number of DCs is limited only by available memory.
что-то мне подсказывает, что HDC окна нельзя вот так держать всё время существования приложения.
Правильно так: в WM_PAINT контекст создаётся вызовом BeginPaint и освобождается EndPaint

обработчик WM_ERASEBKGND делается неактивным, если не требуется встроенная очистка фона окна (для избежания мерцания)

DWORD ScreenBuffer[2000][2000]; // инициализируем экранный буффер с запасом
float DepthBuffer[2000][2000]; // инициализируем глубинный буффер с запасом
а это чудо заменяй на вектор и выставляй актуальный размер тогда, когда это требуется
0
2 / 2 / 0
Регистрация: 14.08.2016
Сообщений: 40
31.05.2020, 16:29  [ТС]
Цитата Сообщение от Алексей1153 Посмотреть сообщение
что-то мне подсказывает, что HDC окна нельзя вот так держать всё время существования приложения
Добавил GetDC в начале итерации и ReleaseDC в конце - никаких изменений.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
    if(!InitInstance(hInstance, nCmdShow)) return GetLastError();
    
    SetResolution(1000, 500);
 
    INIT();
    while(!mmENDPROG) 
    {       
        device = GetDC(window); //***********************************************************
 
        startTimeALL = clock();
 
        startTimeDraw = clock();
            KeysState();
            MouseState();
            if(hitESC) mmENDPROG = true;
            if(hitTAB) mmFLAG[2]++, mmFLAG[2] %= 4;
 
            MSG msg;
            mmWHEEL = 0;
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            if(msFORW) delay_ms += 1;
            if(msBACK) delay_ms -= 1;
            
            ClearPixels();
 
                fi += pi/36;    if(fi >= pi*2) fi = 0;
 
                posFIX.x  = cos(fi)*3;
                posFLOAT += (posFIX-posFLOAT)*0.2;
 
                Position(&oTri, posFLOAT);
                ModifyObject(&oTri);    
                DrawObject(&oTri);
 
            UpdatePixels();
 
                StreamText << "BitBlt * "<<mmFLAG[2]+1<<"\t(Press 'TAB' to change)";    Text(10, 20);
 
                StreamText << "delay_ms = "<<delay_ms<<"\t('Mouse Wheel' to change)";   Text(10, 250);
 
                StreamText << "dtTimeDraw = "<<dtTimeDraw;                              Text(10, 320);
                StreamText << "dtTimeALL = "<<dtTimeALL;                                Text(10, 340);
                StreamText << "max_Draw = "<<max_Draw<<"\t(Press 'SPACE' to clear)";    Text(10, 380);
                StreamText << "max_ALL  = "<<max_ALL;                                   Text(10, 400);
                StreamText << "FPS = "<<int(1000/dtTimeALL);                            Text(10, 470);
 
            ClearKeys();        
 
            if(mmFLAG[2] == 0)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 1)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 2)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 3)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
            
        dtTimeDraw = clock() - startTimeDraw;           
        
 
        // если код выше выполнился быстрее чем delay_ms, то ждем оставшиеся [мс] до delay_ms
        while(clock() - startTimeALL < delay_ms);   
 
 
        dtTimeALL = clock() - startTimeALL;
 
        if(dtTimeDraw   > max_Draw)     max_Draw    = dtTimeDraw;
        if(dtTimeALL    > max_ALL)      max_ALL     = dtTimeALL;
        if(hitSPACE)    max_Draw = max_ALL = 0;
 
        ReleaseDC(window, device);  //***********************************************************
    }
    ReleaseInstance();
    return 0;
}
Цитата Сообщение от Алексей1153 Посмотреть сообщение
Правильно так: в WM_PAINT контекст создаётся вызовом BeginPaint и освобождается EndPaint
Ну WM_PAINT высылается по происшествию какого-либо события. Мне же надо каждую итерацию цикла выводить пиксели.
BeginPaint и EndPaint как везде пишут целесообразно пользоваться во время обработки WM_PAINT, иначе нужно пользоваться GetDC - ReleaseDC.

Цитата Сообщение от Алексей1153 Посмотреть сообщение
а это чудо заменяй на вектор и выставляй актуальный размер тогда, когда это требуется
Обращению к стеку на порядок быстрее(если не больше) чем обращение к оперативной памяти.
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
31.05.2020, 16:52
isrepeat, глобальная переменная - это будет не стек. Можешь убедиться: объяви эти массивы внутри функции InitInstance - программа упадёт из-за нехватки стека (вот это будет именно стек!)

Даже если это был стек - про быстродействие - это тоже ещё надо доказать. И заметишь ли ты это быстродействие вообще

Цитата Сообщение от isrepeat Посмотреть сообщение
Ну WM_PAINT высылается по происшествию какого-либо события
да, нужно периодически делать InvalidateRect окна. Пиксели можешь рендерить как угодно часто (лишь бы железо позволяло), а отображать их часто нет смысла. Либо это нужно делать из другого потока и с двойной буферизвцией

Если хочется космические FPS - используй какой-нибудь OpenGL или DirectX
1
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
31.05.2020, 17:03
Цитата Сообщение от isrepeat Посмотреть сообщение
Ну WM_PAINT высылается по происшествию какого-либо события. Мне же надо каждую итерацию цикла выводить пиксели.
А почему это всё у тебя делается в WinMain вперемешку с циклом сообщений?
Это надо делать в отдельном потоке, и чтоб в нём не было ничего лишнего, кроме отрисовки.
0
2 / 2 / 0
Регистрация: 14.08.2016
Сообщений: 40
31.05.2020, 19:05  [ТС]
isrepeat, глобальная переменная - это будет не стек. Можешь убедиться: объяви эти массивы внутри функции InitInstance - программа упадёт из-за нехватки стека (вот это будет именно стек!)
Хм...действительно.

Добавлено через 15 минут
Даже если это был стек - про быстродействие - это тоже ещё надо доказать. И заметишь ли ты это быстродействие вообще
С одной стороны я проверил в консоли такой вот код:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
#include "stdafx.h"
#include <iostream>
#include <ctime>
using namespace std;
 
#define WIDTH  1234
#define HEIGHT 567
 
float   array_1[WIDTH][HEIGHT];
double  tempTime, dt_1, dt_2, dt_3;
 
 
int main(int argc, char* argv[])
{
    srand(time(0));
    float   array_2[WIDTH][HEIGHT];
    float **array_3 = new float*[WIDTH];    for(int i = 0; i<WIDTH; i++) array_3[i] = new float[HEIGHT];
 
    //for(int k = 1; k <= 10; k++)
    while(1)
    {
        tempTime = clock();
        for(int i = 0; i<WIDTH; i++) for(int j = 0; j<HEIGHT; j++)  array_1[i][j] = rand() % 123467;
        dt_1 = clock() - tempTime;
 
        tempTime = clock();
        for(int i = 0; i<WIDTH; i++) for(int j = 0; j<HEIGHT; j++)  array_2[i][j] = rand() % 123467;
        dt_2 = clock() - tempTime;
 
        tempTime = clock();
        for(int i = 0; i<WIDTH; i++) for(int j = 0; j<HEIGHT; j++)  array_3[i][j] = rand() % 123467;
        dt_3 = clock() - tempTime;
 
        cout << "(Global)  dt_1 = "<< dt_1 << endl;
        cout << "(Stack)   dt_2 = "<< dt_2 << endl;
        cout << "(Pointer) dt_3 = "<< dt_3 << endl;
 
        cout << endl;
        cout << endl;
        system("pause");
        cout << endl;
    }
 
    for(int i = 0; i<WIDTH; i++)
        delete[] array_3[i];
    delete[] array_3;
 
    return 0;
}
И тут различий практически нет. время выполнения в среднем у всех одинаковое что в Debug что в Release.

Но с другой стороны в моей программе проверил время записи в "стековый массив" и в динамический.
Во время Debug что там что там уходит около 4[мс], но в релизе на первый уходит около 0 [мс], а на второй все те же 4 [мс].

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) 
{
    if(!InitInstance(hInstance, nCmdShow)) return GetLastError();
    
    SetResolution(1000, 500);
 
    INIT();
    while(!mmENDPROG) 
    {       
        device = GetDC(window); //***********************************************************
 
        startTimeALL = clock();
 
        startTimeDraw = clock();
            KeysState();
            MouseState();
            if(hitESC) mmENDPROG = true;
            if(hitTAB) mmFLAG[2]++, mmFLAG[2] %= 4;
 
            MSG msg;
            mmWHEEL = 0;
            if(PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
            {
                TranslateMessage(&msg);
                DispatchMessage(&msg);
            }
            if(msFORW) delay_ms += 1;
            if(msBACK) delay_ms -= 1;
            
            ClearPixels();
 
                fi += pi/36;    if(fi >= pi*2) fi = 0;
 
                posFIX.x  = cos(fi)*3;
                posFLOAT += (posFIX-posFLOAT)*0.2;
 
                Position(&oTri, posFLOAT);
                ModifyObject(&oTri);    
                DrawObject(&oTri);
 
            timePTR   = clock();
            for(int j = 0; j<mmHEIGHT; j++) for(int i = 0; i<mmWIDTH; i++) pBmp[j*mmWIDTH + i] = ScreenBuffer[i][j];
            dtPTR     = clock() - timePTR;
 
            timeSTACK = clock();
            for(int j = 0; j<mmHEIGHT; j++) for(int i = 0; i<mmWIDTH; i++) ScreenBuffer[i][j] = ScreenBuffer[i][j] + 1;
            dtSTACK   = clock() - timeSTACK;
 
                StreamText << "BitBlt * "<<mmFLAG[2]+1<<"\t(Press 'TAB' to change)";    Text(10, 20);
 
                StreamText << "delay_ms = "<<delay_ms<<"\t('Mouse Wheel' to change)";   Text(10, 220);
 
                StreamText << "dtPTR   = "<<dtPTR;                                      Text(10, 250);
                StreamText << "dtSTACK = "<<dtSTACK;                                    Text(10, 270);
 
                StreamText << "dtTimeDraw = "<<dtTimeDraw;                              Text(10, 320);
                StreamText << "dtTimeALL = "<<dtTimeALL;                                Text(10, 340);
                StreamText << "max_Draw = "<<max_Draw<<"\t(Press 'SPACE' to clear)";    Text(10, 380);
                StreamText << "max_ALL  = "<<max_ALL;                                   Text(10, 400);
                StreamText << "FPS = "<<int(1000/dtTimeALL);                            Text(10, 470);
 
            ClearKeys();        
 
            if(mmFLAG[2] == 0)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 1)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 2)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
 
            if(mmFLAG[2] == 3)  BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY),
                                BitBlt(device, 0, 0, mmWIDTH, mmHEIGHT, buffer, 0, 0, SRCCOPY);
            
        dtTimeDraw = clock() - startTimeDraw;           
        
 
        // если код выше выполнился быстрее чем delay_ms, то ждем оставшиеся [мс] до delay_ms
        while(clock() - startTimeALL < delay_ms);   
 
 
        dtTimeALL = clock() - startTimeALL;
 
        if(dtTimeDraw   > max_Draw)     max_Draw    = dtTimeDraw;
        if(dtTimeALL    > max_ALL)      max_ALL     = dtTimeALL;
        if(hitSPACE)    max_Draw = max_ALL = 0;
 
        ReleaseDC(window, device);  //***********************************************************
    }
    ReleaseInstance();
    return 0;
}
А почему это всё у тебя делается в WinMain вперемешку с циклом сообщений?
Это надо делать в отдельном потоке, и чтоб в нём не было ничего лишнего, кроме отрисовки.
В потоке делать отрисовку? Не слишком жирно будет, с учетом того что отрисовка может доходить до 15мс+.
А вот если Вы про обработку сообщений в потоке, то да, понимаю что надо но пока и так сойдет.
0
6772 / 4565 / 1844
Регистрация: 07.05.2019
Сообщений: 13,726
31.05.2020, 19:08
Цитата Сообщение от isrepeat Посмотреть сообщение
В потоке делать отрисовку? Не слишком жирно будет, с учетом того что отрисовка может доходить до 15мс+.
А вот если Вы про обработку сообщений в потоке, то да, понимаю что надо но пока и так сойдет.
Нет, я именно про отрисовку.
Делать долгую отрисовку в цикле сообщений, это не то, чтобы слишком "жирно", скорее - слишком тупо.
1
2 / 2 / 0
Регистрация: 14.08.2016
Сообщений: 40
31.05.2020, 19:20  [ТС]
Цитата Сообщение от oleg-m1973 Посмотреть сообщение
Делать долгую отрисовку в цикле сообщений, это не то, чтобы слишком "жирно", скорее - слишком тупо.
Ааа ну всмысле что сейчас у меня реализовано так, что обработка следующего сообщения начнется через время равное отрисовке кадра (а нужно чтоб это происходило параллельно). Логично.
0
фрилансер
 Аватар для Алексей1153
6465 / 5678 / 1131
Регистрация: 11.10.2019
Сообщений: 15,118
31.05.2020, 19:51
isrepeat, не надо заниматься преждевременной тонкой оптимизацией - всё равно не получится. Используй вектор - это экономия времени разработки и нервов, защита от некоторых ошибок управления памятью.

пусть твой проект сначала заработает хотя бы на 1 фпс, но правильно. Вот потом начнёшь профилировать и производить оптимизацию

но с большой вероятностью вектор так и останется вектором, время жрётся обычно не его наличием, а совсем другими местами алгоритма
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
31.05.2020, 19:51
Помогаю со студенческими работами здесь

Разрыв кадра при не ограниченом фпс
Доброго времени суток, столкнулся с такой проблемой и не как не могу определить в чем же прична, имееться проц amd 5600x и видеокарточка...

Разрыв кадра. Бегущая горизонтальная полоса снизу вверх
Доброго времени суток, господа. После смены видеокарты с 1060 6gb на Aorus 3070(в остальном конфиг не менялся), случилась такая проблема. ...

Object Inspector O_o
Привет всем! Народ, уже часов 18 сижу за компом не могу найти компонент который имеет все возможности Object Inspector`a мне не нужно чтобы...

direct.h not found o_O
Невезучий я какой-то... Точнее, везучий на странные ошибки. Вот такой еррор- fatal error C1083: Cannot open include file:...

Активация windows O_o
Че за дурдом? Ща загрузил комп и он требует активацию windows 7. У меня она лицензия, лет наверно 5 уже. Че за дела?


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
11
Ответ Создать тему
Новые блоги и статьи
Программный отбор значения справочника
Maks 21.03.2026
Процедура ВодителиНачалоВыбора(Элемент, ДанныеВыбора, ВыборДобавлением, СтандартнаяОбработка) / / Отключаем стандартную обработку (стандартное открытие формы выбора без фильтров) . . .
Переходник USB-CAN-GPIO
Eddy_Em 20.03.2026
Достаточно давно на работе возникла необходимость в переходнике CAN-USB с гальваноразвязкой, оный и был разработан. Однако, все меня терзала совесть, что аж 48-ногий МК используется так тупо: просто. . .
Оттенки серого
Argus19 18.03.2026
Оттенки серого Нашёл в интернете 3 прекрасных модуля: Модуль класса открытия диалога открытия/ сохранения файла на Win32 API; Модуль класса быстрого перекодирования цветного изображения в оттенки. . .
SDL3 для Desktop (MinGW): Рисуем цветные прямоугольники с помощью рисовальщика SDL3 на Си и C++
8Observer8 17.03.2026
Содержание блога Финальные проекты на Си и на C++: finish-rectangles-sdl3-c. zip finish-rectangles-sdl3-cpp. zip
Символические и жёсткие ссылки в Linux.
algri14 15.03.2026
Существует два типа ссылок — символические и жёсткие. Ссылка в Linux — это запись в каталоге, которая может указывать либо на inode «файла-ИСТОЧНИКА», тогда это будет «жёсткая ссылка» (hard link),. . .
[Owen Logic] Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора
ФедосеевПавел 14.03.2026
Поддержание уровня воды в резервуаре количеством включённых насосов: моделирование и выбор регулятора ВВЕДЕНИЕ Выполняя задание на управление насосной группой заполнения резервуара,. . .
делаю науч статью по влиянию грибов на сукцессию
anaschu 13.03.2026
прикрепляю статью
SDL3 для Desktop (MinGW): Создаём пустое окно с нуля для 2D-графики на SDL3, Си и C++
8Observer8 10.03.2026
Содержание блога Финальные проекты на Си и на C++: hello-sdl3-c. zip hello-sdl3-cpp. zip Результат:
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru