Directx 如何在Direct3d11中从顶点缓冲区读取顶点

Directx 如何在Direct3d11中从顶点缓冲区读取顶点,directx,buffer,direct3d,vertex,Directx,Buffer,Direct3d,Vertex,我有一个关于顶点缓冲区的问题。如何从D3D11中的顶点缓冲区读取顶点?我想得到一个特定顶点的位置来进行计算,如果这个方法是错误的,人们会怎么做呢?以下代码(显然)不起作用 谢谢。以下代码仅获取映射资源的地址,在取消映射之前您没有阅读任何内容 vert = (VERTEX*) ms.pData; 如果要从映射的资源中读取数据,请首先分配足够的内存,然后使用memcpy复制数据,我不知道您的顶点结构,因此我假设vert为void*,您可以自己转换它 vert = new BYTE[ms.Depth

我有一个关于顶点缓冲区的问题。如何从D3D11中的顶点缓冲区读取顶点?我想得到一个特定顶点的位置来进行计算,如果这个方法是错误的,人们会怎么做呢?以下代码(显然)不起作用


谢谢。

以下代码仅获取映射资源的地址,在取消映射之前您没有阅读任何内容

vert = (VERTEX*) ms.pData;
如果要从映射的资源中读取数据,请首先分配足够的内存,然后使用memcpy复制数据,我不知道您的顶点结构,因此我假设vert为void*,您可以自己转换它

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

代码错误的地方:

  • 您要求GPU为您提供其内存地址(
    Map()
  • 存储此地址(
    运算符=()
  • 然后说:“谢谢,我不再需要它了”(
    Unmap()
取消映射后,您无法真正说出指针现在指向的位置。它可以指向已经分配了其他东西的内存位置,或者指向你女朋友笔记本电脑的内存(只是开玩笑而已=)。 您必须复制数据(全部或部分),而不是位于
Map()
Unmap()
之间的指针:使用memcopy、
进行
循环或任何操作。把它放在数组中,
std::vector
,BST,所有东西

新来者在这里可能犯的典型错误:

  • 不检查
    HRESULT
    方法的返回值。如果map失败,它可以返回它喜欢的任何指针。取消引用这样的指针会导致未定义的行为。因此,最好检查任何DirectX函数的返回值
  • 不检查D3D11调试输出。它可以用通俗易懂的英语(显然比我的英语好=)清楚地说出哪里错了,该做什么。所以,您几乎可以立即修复该错误
  • 您只能在具有CPU访问标志的情况下读取,这意味着您还必须设置使用率fag
  • 我们通常如何读取缓冲区:

    • 我们不使用暂存缓冲区进行渲染/计算:它很慢
    • 相反,我们从主缓冲区(非暂存且CPU不可读)复制到暂存缓冲区(or),然后将数据复制到系统内存(
      memcopy()
    • 我们在发布版本中不会做太多,这会影响性能
    • 暂存缓冲区在现实生活中有两种主要用途:调试(查看缓冲区是否包含错误数据并修复算法中的某些错误)和读取最终的非像素数据(例如,如果您在计算着色器中计算科学数据)
    • 在大多数情况下,通过良好地设计代码,可以完全避免暂存缓冲区。假设CPUGPU只有一种连接方式:CPU->GPU

      • Drop的回答很有帮助。我想我不能读取缓冲区的原因是因为我之前没有将CPU访问标志设置为D3D11。这里

        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;
        
        我同意这是性能下降,我想这样做,只是为了能够调试这些值


        谢谢你

        谢谢你的解释。作为DirectX中的新手,我没有意识到,我可以把最终的变换矩阵与顶点相乘,以获得其在C++代码中的位置,即在着色器之外。这就是我想要的,所以使用管道中的输出流是一种严重的过度使用。谢谢你的解释!复制内存后,如何实际访问顶点?
            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;