Почему я получаю плохую производительность с SDL2 и SDL_RenderCopy внутри двойного цикла for для всех пикселей?

Я программирую игру raycasting, используя SDL2. При рисовании пола мне нужно вызывать SDL_RenderCopy попиксельно. Это приводит к узкому месту, из-за которого частота кадров падает ниже 10 кадров в секунду. Я ищу повышения производительности, но не могу найти.

Вот приблизительный обзор падения производительности:

int main() {
  while(true) {
        for(x=0; x<800; x++) {
            for(y=0; y<600; y++) {
                SDL_Rect src = { 0, 0, 1, 1 };
                SDL_Rect dst = { x, y, 1, 1 };
                SDL_RenderCopy(ren, tx, &src, &dst); // this drops the framerate below 10
            }
        }
        SDL_RenderPresent(ren);
    }
 }

person Marius Anderie    schedule 09.08.2014    source источник
comment
Возможно, вам потребуется выполнить профилирование, чтобы точно определить область узкого места. Кажется, для каждого цикла for вы создаете массивы и выделяете память. Вы делаете это 600 раз для каждого внешнего цикла for. Возможно ли повторно использовать один и тот же массив снова и снова вместо создания новых массивов. Если вы можете повторно использовать свой массив, это гарантирует, что ЦП будет извлекать данные из одной и той же области памяти, а не искать их во всей памяти.   -  person Juniar    schedule 09.08.2014
comment
У вас действительно есть отдельная текстура для каждого пикселя? Вы действительно не должны этого делать.   -  person Fsmv    schedule 11.08.2014
comment
@Fsmv, почему ты так думаешь? У него только одна текстура — tx он просто рендерит ее попиксельно, хотя и не совсем понимает, почему.   -  person Zammalad    schedule 20.08.2014
comment
@Zammalad, ты прав, мой плохой. Наверное, я не очень внимательно читал его код и подумал, что это единственная причина, по которой кто-то будет вызывать RenderCopy 800*600 раз с прямоугольниками 1x1. Однако действительно странно копировать каждый пиксель по отдельности.   -  person Fsmv    schedule 20.08.2014


Ответы (2)


Вероятно, вам следует использовать потоковую передачу текстур для этого. По сути, вы создадите SDL_Texture типа SDL_TEXTUREACCESS_STREAMING, а затем в каждом кадре вы «блокируете» текстуру, обновляете требуемые пиксели, а затем снова «разблокируете» текстуру. Затем текстура визуализируется одним вызовом SDL_RenderCopy.

Кроме того, вызов SDL_RenderCopy 480 000 раз за кадр всегда будет убивать вашу частоту кадров.

person Zammalad    schedule 11.08.2014
comment
Нужно ли вообще использовать текстуру для этих ручных пиксельных операций? Не быстрее ли временно использовать SDL_Surface? Кроме того, вам больше не нужно вызывать SDL_RenderCopy, так как пиксели интегрируются при разблокировке текстуры, не так ли? - person Timmos; 23.08.2015
comment
Не уверен, что понимаю, что ты имеешь в виду @Timmos - person Zammalad; 23.08.2015
comment
Разве SDL_Surface не будет более эффективным для всех этих операций с пикселями, чем SDL_Texture? - person Timmos; 25.08.2015
comment
@ Тиммос Я так не думаю, хотя могу ошибаться. Но если предположить, что OP использует SDL2, то есть то, что он помечен, тогда SDL_Texture имеет аппаратное ускорение, тогда как SDL_Surface будет использовать программный рендеринг (если только вы не создаете новую текстуру в каждом кадре из модифицированной поверхности, что в любом случае не так эффективно). Используя SDL_Texture в режиме пропаривания, у вас есть доступ к пикселям, и вам нужно создать их только один раз, а также использовать аппаратное ускорение. - person Zammalad; 25.08.2015
comment
И официальный пример: hg.libsdl.org/SDL/file/e12c38730512 /test/teststreaming.c - person Ciro Santilli 新疆再教育营六四事件ۍ 08.04.2016

Вы вызываете SDL_RenderCopy() в каждом кадре, поэтому 600 * 800 = 480 000 раз! Падение производительности — это нормально.

person frkk    schedule 13.05.2015