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.
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:
It is a pipeline with a structured buffer.
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
Do you have any idea of what I'm doing wrong?