Отправка данных текстуры через буферы

Отправка 2D-или трехмерных текстурных данных аналогична отправке 1D-данных, за исключением того, что приложениям необходимо уделять больше внимания выравниванию данных, связанным с шагом строки. Буферы можно использовать ортогонически и одновременно из нескольких частей графического конвейера и очень гибки.

Отправка данных текстуры с помощью буферов

Приложения должны передавать данные через ID3D12GraphicsCommandList::CopyTextureRegion или ID3D12GraphicsCommandList::CopyBufferRegion. Данные текстуры гораздо чаще станут большими, доступ к ним многократно и воспользоваться улучшенными преимуществами совместного использования кэша нелинейных макетов памяти, чем другие данные ресурсов. Если буферы используются в D3D12, приложения имеют полный контроль над размещением данных и согласованием, связанными с копированием данных ресурсов, при условии, что требования к выравниванию памяти выполнены.

В примере показано, где приложение просто преобразует данные из 2D в 1D, прежде чем помещает его в буфер. Для сценария mipmap 2D приложение может либо расположено каждый вложенный ресурс дискретно и быстро использовать алгоритм 1D-подраспределения, либо использовать более сложный метод распределения вложенной памяти для минимизации использования видеопамяти. Предполагается, что первый метод будет использоваться чаще, так как это проще. Второй способ может быть полезен при упаковке данных на диск или по сети. В любом случае приложение должно по-прежнему вызывать API копирования для каждого подресурса.

// Prepare a pBitmap in memory, with bitmapWidth, bitmapHeight, and pixel format of DXGI_FORMAT_B8G8R8A8_UNORM. 
//
// Sub-allocate from the buffer for texture data.
//

D3D12_SUBRESOURCE_FOOTPRINT pitchedDesc = { 0 };
pitchedDesc.Format = DXGI_FORMAT_B8G8R8A8_UNORM;
pitchedDesc.Width = bitmapWidth;
pitchedDesc.Height = bitmapHeight;
pitchedDesc.Depth = 1;
pitchedDesc.RowPitch = Align(bitmapWidth * sizeof(DWORD), D3D12_TEXTURE_DATA_PITCH_ALIGNMENT);

//
// Note that the helper function UpdateSubresource in D3DX12.h, and ID3D12Device::GetCopyableFootprints 
// can help applications fill out D3D12_SUBRESOURCE_FOOTPRINT and D3D12_PLACED_SUBRESOURCE_FOOTPRINT structures.
//
// Refer to the D3D12 Code example for the previous section "Uploading Different Types of Resources"
// for the code for SuballocateFromBuffer.
//

SuballocateFromBuffer(
    pitchedDesc.Height * pitchedDesc.RowPitch,
    D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT
    );

D3D12_PLACED_SUBRESOURCE_FOOTPRINT placedTexture2D = { 0 };
placedTexture2D.Offset = m_pDataCur – m_pDataBegin;
placedTexture2D.Footprint = pitchedDesc;

//
// Copy texture data from DWORD* pBitmap->pixels to the buffer
//

for (UINT y = 0; y < bitmapHeight; y++)
{
  UINT8 *pScan = m_pDataBegin + placedTexture2D.Offset + y * pitchedDesc.RowPitch;
  memcpy( pScan, &(pBitmap->pixels[y * bitmapWidth]), sizeof(DWORD) * bitmapWidth );
}

//
// Create default texture2D resource.
//

D3D12_RESOURCE_DESC  textureDesc { ... };

CComPtr<ID3D12Resource> texture2D;
d3dDevice->CreateCommittedResource( 
        &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT), 
        D3D12_HEAP_FLAG_NONE, &textureDesc, 
        D3D12_RESOURCE_STATE_COPY_DEST, 
        nullptr, 
        IID_PPV_ARGS(&texture2D) );

//
// Copy heap data to texture2D.
//

commandList->CopyTextureRegion( 
        &CD3DX12_TEXTURE_COPY_LOCATION( texture2D, 0 ), 
        0, 0, 0, 
        &CD3DX12_TEXTURE_COPY_LOCATION( m_spUploadHeap, placedTexture2D ), 
        nullptr );

Обратите внимание на использование вспомогательных структур CD3DX12_HEAP_PROPERTIES и CD3DX12_TEXTURE_COPY_LOCATION, а также методы CreateCommittedResource и CopyTextureRegion.

Копирование

Методы D3D12 позволяют приложениям заменять обновления D3D11 UpdateSubresource, CopySubresourceRegion и исходные данные ресурсов. Один трехмерный подресурс для данных текстуры с основной строкой может находиться в буферных ресурсах. CopyTextureRegion может копировать эти данные текстуры из буфера в ресурс текстуры с неизвестным макетом текстуры и наоборот. Приложения должны предпочитать этот тип метода для заполнения часто используемых ресурсов GPU, создавая большие буферы в куче UPLOAD, создавая часто доступные ресурсы GPU в куче DEFAULT, которая не имеет доступа к ЦП. Такой метод эффективно поддерживает дискретные GPU и их большие объемы недоступной памяти ЦП без обычного нарушения архитектуры UMA.

Обратите внимание на следующие две константы:

const UINT D3D12_TEXTURE_DATA_PITCH_ALIGNMENT = 256;
const UINT D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT = 512;

Сопоставление и отмена сопоставления

Сопоставление и unmap можно вызывать несколькими потоками безопасно. Первый вызов map выделяет диапазон виртуальных адресов ЦП для ресурса. Последний вызов unmap освобождает диапазон виртуальных адресов ЦП. Виртуальный адрес ЦП обычно возвращается приложению.

Каждый раз, когда данные передаются между ЦП и GPU через ресурсы в кучах обратного чтения, map и Unmap должны использоваться для поддержки всех систем D3D12. Максимальное максимальное повышение эффективности диапазонов в системах, требующих диапазонов (см. D3D12_RANGE).

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

Метод D3D11 с помощью Map (с набором параметров DISCARD) для переименования ресурсов не поддерживается в D3D12. Приложения должны реализовать переименование ресурсов. Все вызовы Map неявно NO_OVERWRITE и многопоточных. Перед доступом к данным с ЦП необходимо убедиться, что любая соответствующая работа GPU, содержащаяся в списках команд, завершена. Вызовы D3D12 к Map неявно очищают буферы команд и не блокируют ожидание завершения работы GPU. В результате сопоставление и unmap могут быть оптимизированы в некоторых сценариях.

Выравнивание буфера

Ограничения выравнивания буфера:

  • Линейное копирование подресурсов должно быть выровнено по 512 байтам (с шагом строки, выровненным по D3D12_TEXTURE_DATA_PITCH_ALIGNMENT байтам).
  • Операции чтения констант должны быть кратными 256 байтами с начала кучи (т. е. только из адресов, которые выровнены по 256 байтам).
  • Операции чтения данных индекса должны иметь несколько размеров типа данных индекса (т. е. только с адресов, которые естественно выровнены по данным).
  • Данные ID3D12GraphicsCommandList::ExecuteIndirect должны быть от смещения, кратные 4 (т. е. только из адресов, которые выровнены по DWORD).