Стратегия рендеринга для оконной системы в XNA (производительность RenderTarget)

В настоящее время я создаю оконную систему для игр XNA с нуля. Я занимаюсь разработкой в ​​первую очередь для Windows, но кто знает, какие платформы я могу поддерживать в будущем. Не стесняйтесь отвечать, если вы знаете это для родного Direct3D, так как семантика производительности должна быть схожей. Если возможно, подумайте, что изменится, если целевой платформой будет X-Box 360.

Я делаю хорошие успехи, но сейчас я не уверен, как именно сделать окна. Я придумал четыре подхода:

  • Просто визуализируйте все элементы управления прямо на экране. Это то, что я делаю сейчас. Элементы управления могут быть анимированы путем наложения между состояниями, если они не являются полупрозрачными. Я не нашел хорошего способа анимации между произвольным числом состояний (предположим, что кнопка в данный момент анимируется от нажатия кнопки вверх до нажатия кнопки вниз и от мыши до мыши, а затем отключается. плавно переходить из своего последнего состояния в новое состояние. При таком подходе это работает только в том случае, если одна анимация воспроизводится после завершения последней, или у вас будут скачки анимации.

  • Рендеринг каждого окна верхнего уровня и всех элементов управления в цель рендеринга, а затем использовать его для отображения окон верхнего уровня с полупрозрачностью на экране. Это делает полупрозрачность на работе верхнего уровня и простой в управлении, но ничего не меняет с анимацией.

  • Визуализируйте каждый элемент управления в цель визуализации, которая обновляется только тогда, когда элемент управления становится грязным (то есть должен анимироваться или текст был изменен). Таким образом, будет работать полупрозрачность для каждого элемента управления.

  • Как и предыдущий, но в дополнение к решению проблемы анимации есть вторая цель рендеринга для каждого элемента управления. Всякий раз, когда анимация запускается, меняйте цели рендеринга, чтобы у нас было состояние при запуске анимации, и смешайте его с состоянием назначения в другой цели рендеринга. Это не должно увеличивать накладные расходы по сравнению с предыдущим подходом, у нас просто было вдвое больше целей рендеринга, из которых в любом данном кадре будет отображаться только одна (максимум). Но тут возникает проблема: чтобы это работало, мне нужно, чтобы "старая" цель рендеринга сохранила свое содержимое. Это должно работать с хорошей производительностью в Windows, но, по-видимому, серьезно сказывается на производительности X-Box 360. С другой стороны, бит "сохранить" необходим только при активной анимации.

И вот идут актуальные вопросы. Все, что разъясняет, приветствуется. Что касается вопросов производительности, помните, что это будет просто оконная система игры - игра может использовать множество целей рендеринга и также высосать производительность, и, вероятно, намного больше, чем оконная система. Предположим, что у нас может быть пять окон верхнего уровня с 20-40 элементами управления на экране в худшем случае.

  • Какой из этих подходов вы бы порекомендовали и почему? Не стесняйтесь, конечно, добавить еще один подход.
  • Есть ли влияние на производительность, когда, скажем, доступно только 200 или 400 целей рендеринга, при условии, что только 20 из них рендерится в каждый кадр?
  • Действительно ли влияние PreserveContents на производительность на X-Box 360 так сильно? Насколько это плохо в Windows?
  • Свойство RenderTarget2D.RenderTargetUsage может быть записано в. Является ли переключение во время выполнения хорошей идеей, чтобы включить PreserveContents только при необходимости?
  • Вы (как игрок) не возражаете против того, чтобы управляющая анимация прыгала в определенных ситуациях, например при наведении курсора на кнопку, перемещении мыши, а затем снова, так что анимация "normal->hover" воспроизводится дважды с самого начала, потому что она медленнее чем ты?

3 ответа

Если вы разрабатываете для Xbox 360, вы должны быть осторожны с целями рендеринга. Xbox 360 имеет специальную память (10 МБ) для хранения целей рендеринга, включая ту, которая используется для рендеринга на экране.

Пока вы не превышаете 10 МБ, переключение с одной цели рендеринга на другую не оказывает никакого влияния, даже с PreserveContents, поскольку все цели рендеринга хранятся в этой специальной памяти.

Однако, когда у вас есть более 10 МБ целей рендеринга с PreserveContents, этот атрибут должен эмулироваться путем постоянного переключения цели рендеринга назад и из обычной памяти.

Таким образом, количество целей рендеринга не так важно, как их общий размер. Вы можете узнать размер цели рендеринга с помощью этой формулы:

size (bits) = width  x height x color data size (bits)

Размер цветных данных на Xbox 360 составляет 32 бита, поэтому, например, если пользователь вашей библиотеки разрабатывает свою игру в HD без единой цели рендеринга, кроме основной, он будет использовать:

3,515625MB = 29491200 bits = 1280 x 760 x 32 bits

Кроме того, вы должны избегать создания целей рендеринга динамически. Это стоило слишком дорого. Вы должны создать пул статических целей рендеринга, размещенных в начале игры, и ваши GUI-компоненты запрашивают их.

  • Если вы хотите этот уровень контроля с анимациями (то есть, когда несколько элементов одновременно работают с одним и тем же элементом управления), то вам придется делать несколько проходов. Так что либо включите такую ​​вещь в шейдере и сделайте несколько проходов с шейдером, либо выполните стандартный цикл Render->Resolve->Rerender.
  • Действительно, есть хит производительности, создающий так много целей визуализации. Создавать такое количество не очень хорошая идея. Вам лучше иметь меньшее количество целей рендеринга большего размера и написать несколько элементов управления для этой цели.
  • Прошло много лет с тех пор, как я сделал какие-то 360 dev (bugger:(), но, насколько я помню, это не так уж и здорово. Я бы избежал этого варианта, если бы в этом не было крайней необходимости. Надеюсь, кто-то с более современным опытом может помочь здесь.
  • Это может работать во время выполнения, но может потребовать немало работы за кулисами. Я не ожидаю, что это будет работать слишком хорошо. Я уверен, что это нормально, если вы не делаете это в середине цикла рендеринга.
  • Я думаю, что скачкообразные анимации определенно отстой. По моему мнению:)

Xbox360 имеет 10 МБ специальной памяти, используемой для текущей цели рендеринга. Но остальное сказать о том, как это работает, не совсем точно. Какая бы цель рендеринга ни использовалась, она занимает 10 МБ пространства. В противном случае вы можете иметь столько целей рендера, сколько захотите. Если ваша цель рендеринга больше 10 МБ (например, 1280x720 с некоторым мультисэмплингом АА), тогда xbox360 использует метод, называемый предикатным тайлингом: http://msdn.microsoft.com/en-us/library/bb464139.aspx

Я хорошо пишу систему управления окнами. Я рендерил виджеты в цель рендеринга, затем рендерил цель виджета в цель окна, цель окна в буфер резервного копирования. Это позволяет мне легко добавлять полосы прокрутки и визуализировать только часть цели визуализации виджета в цель визуализации окна. Если есть лучший способ справиться с прокруткой содержимого окна, дайте мне знать. Не уверен, что это лучший по производительности.

Другие вопросы по тегам