通过 DirectX 11 渲染正方形

Rendering squares via DirectX 11

简介

我正在尝试以最有效的方式在 DirectX 11 中渲染正方形。每个方块都有一个颜色 (float3) 和一个位置 (float3)。正方形的典型数量约为 500 万。

我尝试了 3 种方法:

  1. 渲染原始数据
  2. 使用几何着色器
  3. 使用实例渲染

原始数据意味着,每个正方形在顶点缓冲区中表示为 4 个顶点,在索引缓冲区中表示为两个三角形。

几何着色器和实例化渲染意味着每个正方形在顶点缓冲区中只有一个顶点。

我的 5M 正方形结果(在 nvidia GTX960M 上)是:

我预计几何着色器不是最有效的方法。另一方面,令我惊讶的是实例化渲染比原始数据慢。顶点着色器中的计算完全相同。它只是与存储在常量缓冲区中的变换矩阵相乘+ Shift 变量的加法。

原始数据输入

struct VSInput{
    float3 Position : POSITION0;
    float3 Colot : COLOR0;
    float2 Shift : TEXCOORD0;// This is xy deviation from square center 
};

实例化渲染输入

struct VSInputPerVertex{
    float2 Shift : TEXCOORD0;    
};

struct VSInputPerInstance{
    float3 Position : POSITION0;
    float3 Colot : COLOR0;       
};

备注

对于更大的模型(20M 平方),实例化渲染更有效(显然是因为内存流量)。

问题

为什么实例渲染比原始数据渲染慢(在 5M 正方形的情况下)?有没有另一种有效的方法来完成这个渲染任务?我错过了什么吗?

编辑

StructuredBuffer 方法

一种可能的解决方案是按照@galop1n 的建议使用StructuredBuffer(有关详细信息,请参阅他的回答)。

我的结果(在 nvidia GTX960M 上)5M 方块

观察

每个实例的小顶点数通常是未充分利用硬件的好方法。我建议您使用该变体,它应该在每个供应商上都能提供良好的性能。

VSSetShaderResourceViews(0,1,&quadData);
SetPrimitiveTopology(TRIANGLE);
Draw( 6 *  quadCount, 0);

在顶点着色器中,您有

struct Quad {
    float3 pos;
    float3 color;
};
StructuredBuffer<Quad> quads : register(t0);

并在顶点着色器中重建四边形:

// shift for each vertex
static const float2 shifts[6] = { float2(-1,-1), ..., float2(1,1) };
void main( uint vtx : SV_VertexID, out YourStuff yourStuff) {
    Quad quad = quads[vtx/6];
    float2 offs = shifts[vtx%6];
}

然后像往常一样重建顶点和变换。你必须注意,因为你绕过了输入组装阶段,如果你想将颜色作为 rgba8 发送,你需要使用一个 uint 并手动解压。如果要绘制数百万个四边形,带宽使用率会降低。