2013-07-01 2 views
3

У меня вопрос о буферах вершин. Как читать вершины из буфера вершин в D3D11? Я хочу получить конкретную позицию вершины для вычислений, если этот подход ошибочен, как это сделать? Следующий код не работает (очевидно).Как читать вершины из буфера вершин в Direct3d11

VERTEX* vert; 
D3D11_MAPPED_SUBRESOURCE ms; 
devcon->Map(pVBufferSphere, NULL, D3D11_MAP_READ, NULL, &ms); 
vert = (VERTEX*) ms.pData; 
devcon->Unmap(pVBufferSphere, NULL); 

Thanks.

ответ

2

Следующий код получает только адрес отображаемого ресурса, вы ничего не читали перед тем, как распаковать.

vert = (VERTEX*) ms.pData; 

Если вы хотите, чтобы прочитать данные из отображенного ресурса, первый выделить достаточно памяти, а затем использовать тетср, чтобы скопировать данные, я не знаю структуру VERTEX, так что я полагаю, верт недействительна *, вы можете преобразовать его самостоятельно

vert = new BYTE[ms.DepthPitch]; 
memcpy(vert, ms.pData, ms.DepthPitch]; 
+0

Спасибо за объяснение! –

5

Где ваш код не так:

  • Вы просят ГПУ дать вам адрес в памяти (Map()),
  • Хранение этого адреса (operator=()),
  • Затем, сказав: «Спасибо, мне это больше не нужно» (Unmap()).

После этого вы не можете сказать, где именно указывает ваш указатель. Он может указывать на место памяти, где уже выделено другое вещество или память вашего ноутбука вашей подруги (просто шучу =)). Необходимо скопировать данные (все или ее часть), а не указатель между Map()Unmap(): используйте memcopy, for loop, anything. Поместите его в массив, std::vector, BST, все.

Типичные ошибки, которые новички могут Сделанные здесь:

  1. Не проверять HRESULT возвращаемого значения ID3D11DeviceContext::Map метода. Если карта не удалась, она может вернуть любой желаемый указатель. Выделение такого указателя приводит к неопределенному поведению. Поэтому лучше проверить возвращаемое значение функции DirectX.
  2. Не проверять выходные данные D3D11. Он может четко сказать, что не так, и что делать на простом английском языке (явно лучше, чем мой английский =)). Таким образом, вы можете исправить ошибку почти мгновенно.
  3. Вы можете прочитать только от ID3D11Buffer, если это было created с D3D11_CPU_ACCESS_READ Значок доступа к ЦП, что означает, что вы также должны установить D3D11_USAGE_STAGING использование fag.

Как мы читать обычно работают на жидком буфере:

  • Мы не использует промежуточные буферы для визуализации/вычислений: это медленно.
  • Вместо этого мы копируем из основного буфера (не являющегося промежуточным и нечитаемым процессором) для промежуточной установки (ID3D11DeviceContext::CopyResource() или ID3D11DeviceContext::CopySubresourceRegion()), а затем копируем данные в системную память (memcopy()).
  • Мы не делаем этого слишком много в выпусках, это повредит производительности.
  • Существует два основных режима использования буферов промежуточного уровня: отладка (см., Если буфер содержит неправильные данные и исправление некоторой ошибки в алгоритме) и чтение окончательных непиксельных данных (например, если вы вычисляете научные данные в Compute shader).
  • В большинстве случаев вы можете избежать создания буферов на основе хорошо продуманного кода. Думайте, что CPU < -> GPU был подключен только одним способом: CPU-> GPU.
+0

Спасибо за объяснение. Поскольку новичок в directx in не понимал, я мог просто умножить окончательную матрицу преобразования с вершиной, чтобы получить ее позицию в коде C++, то есть вне шейдера. Это все, что я хотел, поэтому использование выходного потока из конвейера было серьезным излишеством. –

1

Ответ на вопрос был полезен. Я понял, что причина, по которой я не смог прочитать буфер, состоял в том, что раньше у меня не было CPU_ACCESS_FLAG, установленного в D3D11_CPU_ACCESS_READ. Здесь

D3D11_BUFFER_DESC bufferDesc; 
ZeroMemory(&bufferDesc, sizeof(bufferDesc)); 
bufferDesc.ByteWidth = iNumElements * sizeof(T); 
bufferDesc.Usage = D3D11_USAGE_DEFAULT; 
bufferDesc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; 
bufferDesc.BindFlags = D3D11_BIND_UNORDERED_ACCESS | D3D11_BIND_SHADER_RESOURCE ; 
bufferDesc.MiscFlags = D3D11_RESOURCE_MISC_BUFFER_STRUCTURED; 
bufferDesc.StructureByteStride = sizeof(T); 

А потом читать данные, которые я сделал

const ID3D11Device& device = *DXUTGetD3D11Device(); 
    ID3D11DeviceContext& deviceContext = *DXUTGetD3D11DeviceContext(); 
    D3D11_MAPPED_SUBRESOURCE ms; 
    HRESULT hr = deviceContext.Map(g_pParticles, 0, D3D11_MAP_READ, 0, &ms);  

    Particle* p = (Particle*)malloc(sizeof(Particle*) * g_iNumParticles); 
    ZeroMemory(p, sizeof(Particle*) * g_iNumParticles); 
    memccpy(p, ms.pData, 0, sizeof(ms.pData)); 
    deviceContext.Unmap(g_pParticles, 0); 

    delete[] p; 

Я согласен, что это снижение производительности, я хотел бы сделать это, просто чтобы иметь возможность отладки значения!

В любом случае, спасибо! =)

Смежные вопросы