Direct3D виртуальный адрес GPU - PullRequest
0 голосов

Существует код, который создает постоянный буфер для загрузки некоторых данных в память графического процессора:

    void BoxApp::BuildConstantBuffers()
    {

        mObjectCB = std::make_unique<UploadBuffer<ObjectConstants>>(md3dDevice.Get(), 1, true);

        UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));

        D3D12_GPU_VIRTUAL_ADDRESS cbAddress = mObjectCB->Resource()->GetGPUVirtualAddress();

    D3D12_CONSTANT_BUFFER_VIEW_DESC cbvDesc; 

    cbvDesc.BufferLocation = cbAddress; 

    cbvDesc.SizeInBytes = objCBByteSize; 

    md3dDevice->CreateConstantBufferView( 
        &cbvDesc,
        mCbvHeap->GetCPUDescriptorHandleForHeapStart());

} 

Где UploadBuffer:

template<typename T>
class UploadBuffer
{
public:

    UploadBuffer(ID3D12Device* device, UINT elementCount, bool isConstantBuffer) : 
        mIsConstantBuffer(isConstantBuffer)
    {
        mElementByteSize = sizeof(T);

        if(isConstantBuffer)
            mElementByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(T));

        ThrowIfFailed(device->CreateCommittedResource(
            &CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
            D3D12_HEAP_FLAG_NONE,
            &CD3DX12_RESOURCE_DESC::Buffer(mElementByteSize*elementCount),
            D3D12_RESOURCE_STATE_GENERIC_READ,
            nullptr,
            IID_PPV_ARGS(&mUploadBuffer)));

        ThrowIfFailed(mUploadBuffer->Map(0, nullptr, reinterpret_cast<void**>(&mMappedData)));


    }
}

CreateConstantBufferView использует два адреса в памяти: 1) начало кучи, 2) адрес памяти виртуального графического процессора в поле BufferLocation

Где буфер (постоянный объект) будет создан физически? Почему этот метод использует два разных адреса?

1 Ответ

1 голос
/ 28 июня 2019

Адрес ЦП используется, когда ЦП обращается к памяти.В случае данных в D3D12_HEAP_TYPE_UPLOAD этот адрес используется для записи данных в ресурс, потому что он находится в некой «разделяемой памяти», к которой могут обращаться как CPU, так и GPU.Адрес ЦП - это адрес виртуальной памяти, сопоставленный с правильным физическим местоположением для требуемого типа доступа.

Адрес графического процессора используется, когда графический процессор обращается к памяти, обычно, когда он используется входным ассемблером.для геометрии (VB / IB) или внутри кучи сэмплера / дескриптора текстуры.Для D3D12_HEAP_TYPE_DEFAULT память доступна только для графического процессора, поэтому адрес процессора на самом деле отсутствует.GPU также может напрямую считывать ресурс D3D12_HEAP_TYPE_UPLOAD.Адрес графического процессора - это виртуальный адрес, характерный для архитектуры памяти графического процессора.

Для систем с унифицированной архитектурой памяти (UMA), таких как Xbox One, адреса процессора и графического процессора часто совпадают с адресом виртуальной памяти.

Вы загружаете данные в ресурс D3D12_HEAP_TYPE_DEFAULT, сначала копируя их в объект D3D12_HEAP_TYPE_UPLOAD через Map в ЦП, затем вы должны выполнить команду списка командв графическом процессоре для фактического копирования данных оттуда в ресурс D3D12_HEAP_TYPE_DEFAULT.

В случае констант они обычно находятся в кучах D3D12_HEAP_TYPE_UPLOAD.Хотя вы также можете использовать VB и IB в этих кучах, они действительно полезны только для ресурсов стиля «динамического использования», которые обновляются в каждом кадре.На большинстве архитектур с графическим процессором их быстрее получить в виде ресурса «статического использования» в D3D12_HEAP_TYPE_DEFAULT.Поскольку константы обычно меняют каждый кадр, не имеет смысла помещать их в D3D12_HEAP_TYPE_DEFAULT.

Помните, что вы, разработчик приложения, несете ответственность за синхронизацию CPU / GPU через заборы, поэтому вам необходимоубедитесь, что вы не меняете память на процессоре, пока он все еще нужен графическому процессору.За исключением очень простых случаев (как в этом примере , где он в основном создает один ресурс постоянного буфера на кадр фрейма буфера), вам обычно нужен какой-то линейный диспетчер памяти для констант.Для примера см. GraphicsMemory в DirectX Tool Kit для DX12 .

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

...