通过 DirectX 11 渲染正方形
Rendering squares via DirectX 11
简介
我正在尝试以最有效的方式在 DirectX 11 中渲染正方形。每个方块都有一个颜色 (float3) 和一个位置 (float3)。正方形的典型数量约为 500 万。
我尝试了 3 种方法:
- 渲染原始数据
- 使用几何着色器
- 使用实例渲染
原始数据意味着,每个正方形在顶点缓冲区中表示为 4 个顶点,在索引缓冲区中表示为两个三角形。
几何着色器和实例化渲染意味着每个正方形在顶点缓冲区中只有一个顶点。
我的 5M 正方形结果(在 nvidia GTX960M 上)是:
- 几何着色器 22 FPS
- 实例化渲染 30 FPS
- 原始数据渲染41 FPS
我预计几何着色器不是最有效的方法。另一方面,令我惊讶的是实例化渲染比原始数据慢。顶点着色器中的计算完全相同。它只是与存储在常量缓冲区中的变换矩阵相乘+ 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 方块
- StructuredBuffer 48 FPS
观察
- 有时我观察到 StructuredBuffer 方法在 30 FPS - 55 FPS(100 帧的累计数)之间振荡。好像有点不稳定。中值为 48 FPS。我没有使用以前的方法观察到这一点。
- 考虑绘制调用和 StructuredBuffer 大小之间的平衡。当我使用具有 1K - 4K 点 的缓冲区时,我达到了 最快的 行为,适用于较小的模型。当我尝试渲染 5M 正方形模型时,我有大量的绘制调用并且效率不高(30 FPS)。我观察到的 5M 方块的最佳行为是每个缓冲区 16K 点。每个缓冲区 32K 和 8K 点似乎是较慢的设置。
每个实例的小顶点数通常是未充分利用硬件的好方法。我建议您使用该变体,它应该在每个供应商上都能提供良好的性能。
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 并手动解压。如果要绘制数百万个四边形,带宽使用率会降低。
简介
我正在尝试以最有效的方式在 DirectX 11 中渲染正方形。每个方块都有一个颜色 (float3) 和一个位置 (float3)。正方形的典型数量约为 500 万。
我尝试了 3 种方法:
- 渲染原始数据
- 使用几何着色器
- 使用实例渲染
原始数据意味着,每个正方形在顶点缓冲区中表示为 4 个顶点,在索引缓冲区中表示为两个三角形。
几何着色器和实例化渲染意味着每个正方形在顶点缓冲区中只有一个顶点。
我的 5M 正方形结果(在 nvidia GTX960M 上)是:
- 几何着色器 22 FPS
- 实例化渲染 30 FPS
- 原始数据渲染41 FPS
我预计几何着色器不是最有效的方法。另一方面,令我惊讶的是实例化渲染比原始数据慢。顶点着色器中的计算完全相同。它只是与存储在常量缓冲区中的变换矩阵相乘+ 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 方块
- StructuredBuffer 48 FPS
观察
- 有时我观察到 StructuredBuffer 方法在 30 FPS - 55 FPS(100 帧的累计数)之间振荡。好像有点不稳定。中值为 48 FPS。我没有使用以前的方法观察到这一点。
- 考虑绘制调用和 StructuredBuffer 大小之间的平衡。当我使用具有 1K - 4K 点 的缓冲区时,我达到了 最快的 行为,适用于较小的模型。当我尝试渲染 5M 正方形模型时,我有大量的绘制调用并且效率不高(30 FPS)。我观察到的 5M 方块的最佳行为是每个缓冲区 16K 点。每个缓冲区 32K 和 8K 点似乎是较慢的设置。
每个实例的小顶点数通常是未充分利用硬件的好方法。我建议您使用该变体,它应该在每个供应商上都能提供良好的性能。
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 并手动解压。如果要绘制数百万个四边形,带宽使用率会降低。