<p>Are you sure the buffer isn't just defined as a host visible buffer? If you allocate it in CPU space it might have to transfer it a lot, I use ByteAddressBuffer a lot and it's not <em>that</em> slow for me. So maybe it's just not properly allocated.</p>

CC BY-SA 4.0
2023-10-04T12:42:21.157Z
Hi! Thanks for the answer. The buffer is allocated at the default heap (`D3D12_HEAP_TYPE_DEFAULT`). For reference: `D3D12_RESOURCE_DIMENSION_BUFFER`, `Width = elements * elementSize`, `D3D12_TEXTURE_LAYOUT_ROW_MAJOR` and `DXGI_FORMAT_UNKNOWN`... If I did not forget anything, since it's been a while. Still haven't figured this one out though! Also note that the slowdown only occurs under D3D, not under Vulkan (since afair host visible is Vk terminology).
Carsten
CC BY-SA 4.0
2023-10-03T19:22:04.197Z
2023-10-03T19:22:04.197Z
N Nielsbishere B
<p>I am currently experimenting with unbounded descriptor arrays and ultimately want to use bindless descriptors. I wrote a test application, that draws 100.000 simple object instances, where the transform for each object is pulled from a buffer array.</p>
<pre><code>#pragma pack_matrix(row_major)

struct VertexData 
{
    float4 Position : SV_POSITION;
}; 

struct VertexInput
{
    float3 Position : POSITION;
};

struct CameraData
{
    float4x4 ViewProjection;
};

struct InstanceData
{
    float4x4 Transform;
};

ConstantBuffer&lt;CameraData&gt; camera : register(b0, space0);
StructuredBuffer&lt;InstanceData&gt; instanceBuffer[] : register(t0, space1);

VertexData main(in VertexInput input, uint id : SV_InstanceID)
{
    VertexData vertex;

    InstanceData instance = instanceBuffer[id].Load(0);
    float4 position = mul(float4(input.Position, 1.0), instance.Transform);
    vertex.Position = mul(position, camera.ViewProjection);
 
    return vertex;
}
</code></pre>
<p>I am using DXC to compile this shader to both, SPIR-V and DXIL. Under Vulkan, the draw call takes roughly 2ms, however under D3D, it takes around 10ms. I tried eliminating the buffer access by hashing the instance id and generating the transform for each object this way and (as expected) the draw calls were equally fast. I then tried using a <code>ByteAddressBuffer</code> instead of a <code>StructuredBuffer</code> and it did not show any difference in Vulkan (which is expected, since <a href="https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#constant-texture-structured-byte-buffers" rel="nofollow noreferrer">they are essentially the same in SPIR-V</a>), but in D3D performance dropped even further to around 40ms per draw call. Now I am wondering what could cause such behavior. I tried <a href="https://godbolt.org/z/1j5WofcWs" rel="nofollow noreferrer">looking at the IL</a>, but I can't really tell how this compares to each other.</p>
<p>What could cause this discrepancy? Is there any way to profile this? All debuggers I tried just showed me the GPU times, which I mentioned above, but not more. Also some NSight Graphics features are not supported on my GPU (1080 Ti), so I could not test this compeltely.</p>

<vulkan><directx12><buffers>
What causes buffer access to be significantly slower in DXIL than SPIR-V?
Carsten
# What causes buffer access to be significantly slower in DXIL than SPIR-V?

(Asked by: username_0 on 2022-08-20)

I am currently experimenting with unbounded descriptor arrays and ultimately want to use bindless descriptors. I wrote a test application, that draws 100.000 simple object instances, where the transform for each object is pulled from a buffer array.

```
#pragma pack_matrix(row_major)

struct VertexData 
{
    float4 Position : SV_POSITION;
}; 

struct VertexInput
{
    float3 Position : POSITION;
};

struct CameraData
{
    float4x4 ViewProjection;
};

struct InstanceData
{
    float4x4 Transform;
};

ConstantBuffer<CameraData> camera : register(b0, space0);
StructuredBuffer<InstanceData> instanceBuffer[] : register(t0, space1);

VertexData main(in VertexInput input, uint id : SV_InstanceID)
{
    VertexData vertex;

    InstanceData instance = instanceBuffer[id].Load(0);
    float4 position = mul(float4(input.Position, 1.0), instance.Transform);
    vertex.Position = mul(position, camera.ViewProjection);
 
    return vertex;
}

```

I am using DXC to compile this shader to both, SPIR-V and DXIL. Under Vulkan, the draw call takes roughly 2ms, however under D3D, it takes around 10ms. I tried eliminating the buffer access by hashing the instance id and generating the transform for each object this way and (as expected) the draw calls were equally fast. I then tried using a `ByteAddressBuffer` instead of a `StructuredBuffer` and it did not show any difference in Vulkan (which is expected, since [they are essentially the same in SPIR-V](https://github.com/microsoft/DirectXShaderCompiler/blob/main/docs/SPIR-V.rst#constant-texture-structured-byte-buffers)), but in D3D performance dropped even further to around 40ms per draw call. Now I am wondering what could cause such behavior. I tried [looking at the IL](https://godbolt.org/z/1j5WofcWs), but I can't really tell how this compares to each other.

What could cause this discrepancy? Is there any way to profile this? All debuggers I tried just showed me the GPU times, which I mentioned above, but not more. Also some NSight Graphics features are not supported on my GPU (1080 Ti), so I could not test this compeltely.

**Tags:** vulkan, directx12, buffers


---

## 1 answers

### Answer by username_1 on 2023-10-03. Score: 1

Are you sure the buffer isn't just defined as a host visible buffer? If you allocate it in CPU space it might have to transfer it a lot, I use ByteAddressBuffer a lot and it's not *that* slow for me. So maybe it's just not properly allocated.

> **Comments:**
> **username_0**: Hi! Thanks for the answer. The buffer is allocated at the default heap (`D3D12_HEAP_TYPE_DEFAULT`). For reference: `D3D12_RESOURCE_DIMENSION_BUFFER`, `Width = elements * elementSize`, `D3D12_TEXTURE_LAYOUT_ROW_MAJOR` and `DXGI_FORMAT_UNKNOWN`... If I did not forget anything, since it's been a while. Still haven't figured this one out though! Also note that the slowdown only occurs under D3D, not under Vulkan (since afair host visible is Vk terminology).  

---

