Поделиться через


Копирование и доступ к данным ресурсов (Direct3D 10)

Больше не нужно думать о ресурсах как созданных в памяти видео или системной памяти. Следует ли среде выполнения управлять памятью. Благодаря архитектуре новой модели драйвера WDDM (Windows Display Driver Model), приложения теперь создают ресурсы Direct3D 10 с различными флагами использования , чтобы указать, как приложение намерено использовать данные ресурса. Новая модель драйвера виртуализирует память, используемую ресурсами, и это становится ответственностью операционной системы, драйвера или диспетчера памяти — разместить ресурсы в наиболее производительной области памяти с учетом предполагаемого использования.

По умолчанию подразумевается, что ресурсы будут доступны для GPU. Конечно, при этом бывают случаи, когда данные ресурсов должны быть доступны центральному процессору. Копирование данных ресурсов вокруг, чтобы соответствующий процессор смог получить доступ к нему, не влияя на производительность, требует некоторых знаний о том, как работают методы API.

Копирование данных ресурса

Ресурсы создаются в памяти при выполнении вызова Create Direct3D. Их можно создавать в видеопамяти, системной памяти или любом другом виде памяти. Так как модель драйвера WDDM виртуализирует эту память, приложения больше не должны отслеживать тип ресурсов памяти.

В идеале все ресурсы будут находиться в видеопамяти, чтобы графический процессор может иметь немедленный доступ к ним. Однако иногда необходимо, чтобы ЦП считывал данные ресурсов, или чтобы ГП получал доступ к данным ресурсов, записанным ЦП. Direct3D 10 обрабатывает эти различные сценарии, запрашивая приложение указать использование, а затем предлагает несколько методов для копирования данных ресурсов при необходимости.

В зависимости от того, как был создан ресурс, не всегда можно напрямую получить доступ к базовым данным. Это может означать, что данные ресурса должны быть скопированы из исходного ресурса в другой ресурс, доступный соответствующим обработчиком. С точки зрения Direct3D 10 ресурсы по умолчанию можно получить непосредственно с помощью GPU, динамические и промежуточные ресурсы можно напрямую получить через ЦП.

После создания ресурса его нельзя изменить. Вместо этого скопируйте содержимое одного ресурса в другой ресурс, созданный с другим использованием. Direct3D 10 предоставляет эту функциональность с тремя разными методами. Первые два метода (ID3D10Device::CopyResource и ID3D10Device::CopySubresourceRegion) предназначены для копирования данных ресурсов из одного ресурса в другой. Третий метод (ID3D10Device::UpdateSubresource) предназначен для копирования данных из памяти в ресурс.

Существует два основных типа ресурсов: сопоставимые и не сопоставленные. Ресурсы, созданные с динамическим или промежуточным использованием, сопоставляются, а ресурсы, созданные с использованием по умолчанию или неизменяемыми, не сопоставляются.

Копирование данных между ресурсами, которые нельзя сопоставить, происходит очень быстро, поскольку это наиболее распространенный случай, и он был оптимизирован для эффективной работы. Так как эти ресурсы не доступны напрямую ЦП, они оптимизированы так, чтобы GPU могли быстро управлять ими.

Копирование данных между сопоставимыми ресурсами является более проблематичным, так как производительность будет зависеть от использования ресурса, с которым был создан ресурс. Например, GPU может считывать динамический ресурс довольно быстро, но не может записывать в него, а также не может читать или записывать напрямую в промежуточные ресурсы.

Приложения, которые хотят скопировать данные из ресурса с использованием по умолчанию в ресурс с промежуточным использованием (чтобы ЦП считывал данные , т. е. проблема обратного чтения GPU) должна делать это с осторожностью. Для получения дополнительной информации об этом последнем случае см. раздел «Доступ к данным ресурсов».

Доступ к данным ресурса

Для доступа к ресурсу требуется сопоставление ресурса; Сопоставление по сути означает, что приложение пытается предоставить ЦП доступ к памяти. Процесс сопоставления ресурса, чтобы ЦП мог получить доступ к базовой памяти, может привести к некоторым узким местам производительности, поэтому необходимо внимательно подходить к тому, как и когда выполнять эту задачу.

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

Выполнение операции карты в неправильное время может привести к серьезному снижению производительности, заставив GPU и ЦП синхронизироваться друг с другом. Эта синхронизация произойдет, если приложение захочет получить доступ к ресурсу до того, как GPU завершит копирование в ресурс, который может сопоставить ЦП.

ЦП может считывать только ресурсы, созданные с помощью флага D3D10_USAGE_STAGING. Так как ресурсы, созданные с этим флагом, нельзя использовать как выходные данные конвейера, если процессор хочет считать данные из ресурса, созданного GPU, данные должны быть скопированы в ресурс, созданный с флагом стадии. Это можно сделать с помощью методов ID3D10Device::CopyResource или ID3D10Device::CopySubresourceRegion для копирования содержимого одного ресурса в другой. Затем приложение может получить доступ к этому ресурсу, вызвав соответствующий метод Map. Если доступ к ресурсу больше не нужен, приложение должно вызвать соответствующий метод Unmap. Например, ID3D10Texture2D::Map и ID3D10Texture2D::Unmap. Различные методы Map возвращают определенные значения в зависимости от входных флагов. Дополнительные сведения см.в разделе"Примечания карты".

Заметка

Когда приложение вызывает метод Map, он получает указатель на данные ресурса для доступа. Среда выполнения гарантирует, что указатель имеет определенное выравнивание на основании уровня возможностей . Для D3D_FEATURE_LEVEL_10_0 и более поздних версий указатель соответствует 16 байтам. Для уровня ниже D3D_FEATURE_LEVEL_10_0указатель выравнивается на 4 байта. 16-байтовое выравнивание позволяет приложению выполнять SSE-оптимизированные операции с данными нативно, без повторного выравнивания или копирования.

 

Рекомендации по производительности

Лучше всего рассматривать компьютер как компьютер, работающий как параллельная архитектура с двумя основными типами процессоров: один или несколько ЦП и один или несколько GPU. Как и в любой параллельной архитектуре, оптимальная производительность достигается, когда каждый процессор планируется с достаточной работой, чтобы предотвратить его простой, и когда работа одного процессора не ожидает работы другого.

Худший сценарий параллелизма GPU и ЦП — это необходимость заставлять один процессор ожидать результатов работы, выполненной другим. Direct3D 10 пытается устранить эту нагрузку, сделав методы ID3D10Device::CopyResource и ID3D10Device::CopySubresourceRegion асинхронными; копирование может не быть завершено к моменту завершения работы метода. Преимущество этого в том, что приложение не несет затрату на производительность при фактическом копировании данных до тех пор, пока процессор не обращается к данным, то есть при вызове Map. ** Вызов метода Map после фактического копирования данных не приводит к потере производительности. С другой стороны, если метод Map вызывается перед копированием данных, произойдет затор в конвейере.

Асинхронные вызовы в Direct3D 10 (которые являются подавляющей частью методов и особенно вызовов отрисовки), хранятся в том, что называется буфером команд. Этот буфер является внутренним для графического драйвера и используется для пакетных вызовов базового оборудования, чтобы дорогостоящий переход с пользовательского режима в режим ядра в Microsoft Windows происходит как можно реже.

Буфер команд очищается, что приводит к переключении режима пользователя или ядра в одной из четырех ситуаций, которые приведены ниже.

  1. вызывается.
  2. вызывается ID3D10Device::Flush.
  3. Буфер команд заполнен; его размер является динамическим и управляется операционной системой и графическим драйвером.
  4. Процессору требуется доступ к результатам команды, ожидающей выполнения в буфере команд.

Из четырех описанных выше ситуаций число четыре является наиболее важным для производительности. Если приложение выполнит вызов ID3D10Device::CopyResource или ID3D10Device::CopySubresourceRegion, этот вызов помещается в командный буфер. Если приложение затем попытается мапировать промежуточный ресурс, который был целью вызова копирования до того, как буфер команд был очищен, произойдет затор в конвейере, так как не только вызов метода Copy должен быть выполнен, но и все остальные команды в буфере команд также должны быть выполнены. Это приведет к синхронизации GPU и ЦП, так как ЦП будет ожидать доступа к промежуточному ресурсу, пока GPU освобождает буфер команд и в конечном итоге заполнит ресурс, необходимый ЦП. После завершения копирования GPU, ЦП начнет получать доступ к промежуточному ресурсу, но в это время GPU будет бездействовать.

Это часто происходит во время выполнения, что значительно снижает производительность. Поэтому сопоставление ресурсов, созданных с использованием по умолчанию, должно выполняться с осторожностью. Приложение должно ждать достаточно долго, чтобы буфер команд был очищен и все эти команды завершили выполнение, прежде чем пытаться сопоставлять соответствующий промежуточный ресурс. Сколько времени должно ожидать приложение? По крайней мере два кадра, так как это позволит максимально использовать параллелизм между ЦП и GPU. Способ работы GPU заключается в том, что в то время как приложение обрабатывает кадр N, отправляя вызовы в буфер команд, GPU занят выполнение вызовов из предыдущего кадра N-1.

Таким образом, если приложение хочет сопоставить ресурс, который находится в видеопамяти, и вызывает ID3D10Device::CopyResource или ID3D10Device::CopySubresourceRegion в кадре N, этот вызов фактически начнет выполняться в кадре N+1, когда приложение отправляет вызовы для следующего кадра. Копия должна быть завершена, когда приложение обрабатывает кадр N+2.

Рамка Состояние GPU/ЦП
N
  • Проблемы в работе ЦП при отрисовке текущего кадра.
N+1
  • Gpu, выполняющий вызовы, отправленные из ЦП во время кадра N.
  • Проблемы с ЦП при рендеринге вызовов для текущего кадра.
N+2
  • GPU завершил выполнение вызовов, отправленных из ЦП во время кадра N. Результаты готовы.
  • GPU, выполняющий вызовы, отправляемые из ЦП во время кадра N+1.
  • Проблемы с ЦП вызывают отрисовку текущего кадра.
N+3
  • GPU завершил выполнение вызовов, отправленных из ЦП во время кадра N+1. Результаты готовы.
  • GPU, выполняющий вызовы, отправленные из ЦП во время кадра N+2.
  • Проблемы с ЦП выполнения вызовов текущего кадра.
N+4 ...

 

ресурсы (Direct3D 10)