Hello everybody. I'm learning D3D12, so sorry if my question is kind of stupid. I'm having some troubles with a structured buffer. In general I want to implement particles using a compute shader. But my structured buffer doesn't work.
In the beggining I had a vertex buffer of points. Then I appled GS and I received billboards. It works. Now I want to use a structured buffer instead of a vertex buffer. When I try to use it a debug layer doesn't give me any information. I don't understand what I do wrong.
It is a pipeline with a vertex buffer.
[spoiler]
Input layout
D3D12_INPUT_ELEMENT_DESC inputElementDesc[] =
{
{ "POSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
{ "PREVPOSITION", 0, DXGI_FORMAT_R32G32B32A32_FLOAT, 0, D3D12_APPEND_ALIGNED_ELEMENT, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 }
};
Root signature:
D3D12_DESCRIPTOR_RANGE ranges[1];
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 2, 0);
D3D12_ROOT_PARAMETER rootParameters[1];
rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_GEOMETRY);
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
rootSignatureDesc.Init(_countof(rootParameters), &rootParameters[0], 0, nullptr, flags);
VS
#include "ParticlesRenderCommon.inl"
void VSMain(in VSInput In, out VSOutput Out)
{
Out.CurrPosition = In.CurrPosition;
Out.PrevPosition = In.PrevPosition;
}
GS
#include "ParticlesRenderCommon.inl"
[maxvertexcount(1)]
void GSMain(point VSOutput In[1], inout PointStream<GSOutput> OutStream)
{
GSOutput output;
output.Position = mul(ViewProjectionMatrix, In[0].CurrPosition);
OutStream.Append(output);
OutStream.RestartStrip();
}
PS
#include "ParticlesRenderCommon.inl"
void PSMain(in GSOutput In, out float4 Color : SV_TARGET)
{
Color = float4(0.2f, 0.8f, 0.4f, 0.8f);
}
Common.inl
struct VSInput
{
float4 CurrPosition : POSITION;
float4 PrevPosition : PREVPOSITION;
};
struct VSOutput
{
float4 CurrPosition : SV_POSITION;
float4 PrevPosition : PREVPOSITION;
};
struct GSOutput
{
float4 Position : SV_POSITION;
};
cbuffer MatrixPerFrame : register(b0)
{
float4x4 ViewProjectionMatrix;
};
cbuffer CameraVectors : register(b1)
{
float4 CamUp;
float4 CamRight;
};
CommandList
commandList->SetPipelineState(mParticlesRenderPSO);
commandList->SetGraphicsRootSignature(mRenderer->ParticlesRenderRootSignature());
commandList->SetDescriptorHeaps(1, &mParticlesCBVHeap);
commandList->SetGraphicsRootDescriptorTable(0, mParticlesCBVHeap->GetGPUDescriptorHandleForHeapStart());
commandList->RSSetViewports(1, &mViewport);
commandList->RSSetScissorRects(1, &mScissorRect);
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
commandList->IASetVertexBuffers(0, 1, &mParticlesBufferView);
commandList->DrawInstanced(mRenderNbOfParticles, 1, 0, 0);
And it produce a good result:
[/spoiler]
It is a pipeline with a structured buffer.
[spoiler]
Input Layout is null.
RootSignature:
D3D12_DESCRIPTOR_RANGE ranges[2];
ranges[0].Init(D3D12_DESCRIPTOR_RANGE_TYPE_CBV, 2, 0);
ranges[1].Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 1, 0);
D3D12_ROOT_PARAMETER rootParameters[2];
rootParameters[0].InitAsDescriptorTable(1, &ranges[0], D3D12_SHADER_VISIBILITY_GEOMETRY);
rootParameters[1].InitAsDescriptorTable(1, &ranges[1], D3D12_SHADER_VISIBILITY_VERTEX);
D3D12_ROOT_SIGNATURE_DESC rootSignatureDesc;
D3D12_ROOT_SIGNATURE_FLAGS flags = D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT;
rootSignatureDesc.Init(_countof(rootParameters), &rootParameters[0], 0, nullptr, flags);
Create a structured buffer
const UINT64 sizeUploadBuffer = mParticles.size() * sizeof(ParticleVertex);
mParticlesUAVBuffer = mRenderer->Device()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_DEFAULT),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(particlesSizeInBytes, D3D12_RESOURCE_FLAG_ALLOW_UNORDERE_ACCESS),
D3D12_RESOURCE_STATE_COPY_DEST,
nullptr);
mParticlesUAVBufferUpload = mRenderer->Device()->CreateCommittedResource(
&CD3DX12_HEAP_PROPERTIES(D3D12_HEAP_TYPE_UPLOAD),
D3D12_HEAP_FLAG_NONE,
&CD3DX12_RESOURCE_DESC::Buffer(sizeUploadBuffer),
D3D12_RESOURCE_STATE_GENERIC_READ,
nullptr);
D3D12_SUBRESOURCE_DATA particlesData = {};
particlesData.pData = mParticles.data();
particlesData.RowPitch = sizeUploadBuffer;
particlesData.SlicePitch = particlesData.RowPitch;
UpdateSubresources<1>(mRenderer->CommandList(), mParticlesUAVBuffer, mParticlesUAVBufferUpload, 0, 0, 1, &particlesData);
mRenderer->CommandList()->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mParticlesUAVBuffer, D3D12_RESOURCE_STATE_COPY_DEST, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
srvDesc.Format = DXGI_UNKNOWN;
srvDesc.ViewDimension = D3D12_SRV_DIMENSION_BUFFER;
srvDesc.Buffer.FirstElement = 0;
srvDesc.Buffer.NumElements = mParticles.size();
srvDesc.Buffer.StructureByteStride = sizeof(ParticleVertex);
srvDesc.Buffer.Flags = D3D12_BUFFER_SRV_FLAG_NONE;
CD3DX12_CPU_DESCRIPTOR_HANDLE srvHandle(mParticlesCBVHeap->GetCPUDescriptorHandleForHeapStart(), 2, mRenderer->Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));
mRenderer->Device()->CreateShaderResourceView(mParticlesUAVBuffer, &srvDesc, srvHandle);
Common.inl
struct VSInput
{
float4 CurrPosition : POSITION;
float4 PrevPosition : PREVPOSITION;
};
struct VSOutput
{
float4 CurrPosition : SV_POSITION;
float4 PrevPosition : PREVPOSITION;
};
struct GSOutput
{
float4 Position : SV_POSITION;
};
struct Particle
{
float4 CurrPosition;
float4 PrevPosition;
};
struct TestVSInput
{
uint id : SV_VertexID;
};
StructuredBuffer<Particle> Particles : register(t0);
cbuffer MatrixPerFrame : register(b0)
{
float4x4 ViewProjectionMatrix;
};
cbuffer CameraVectors : register(b1)
{
float4 CamUp;
float4 CamRight;
};
VS
#include "ParticlesRenderCommon.inl"
void VSMain(in TestVSInput In, out VSOutput Out)
{
Particle particle = Particles[In.id];
Out.CurrPosition = particle.CurrPosition;
Out.PrevPosition = particle.PrevPosition;
}
GS is same.
PS is same.
CommandList:
CD3DX12_GPU_DESCRIPTOR_HANDLE srvHandle(mParticlesCBVHeap->GetGPUDescriptorHandleForHeapStart(), 2, mRenderer->Device()->GetDescriptorHandleIncrementSize(D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV));
commandList->SetPipelineState(mParticlesRenderPSO);
commandList->SetGraphicsRootSignature(mRenderer->ParticlesRenderRootSignature());
commandList->SetDescriptorHeaps(1, &mParticlesCBVHeap);
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mParticlesUAVBuffer, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE, D3D12_RESOURCE_STATE_UNORDERED_ACCESS));
commandList->SetGraphicsRootDescriptorTable(0, mParticlesCBVHeap->GetGPUDescriptorHandleForHeapStart());
commandList->SetGraphicsRootDescriptorTable(1, srvHandle);
commandList->RSSetViewports(1, &mViewport);
commandList->RSSetScissorRects(1, &mScissorRect);
commandList->IASetPrimitiveTopology(D3D_PRIMITIVE_TOPOLOGY_POINTLIST);
commandList->IASetVertexBuffers(0, 0, nullptr);
commandList->DrawInstanced(mRenderNbOfParticles, 1, 0, 0);
commandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mParticlesUAVBuffer, D3D12_RESOURCE_STATE_UNORDERED_ACCESS, D3D12_RESOURCE_STATE_NON_PIXEL_SHADER_RESOURCE));
It is a result of these manipulations
[/spoiler]
Do you have any idea of what I'm doing wrong?