Problems with a structured buffer in DX12

Started by
4 comments, last by obfuscate 7 years ago

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:

sWSPXKe.png

[/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

s6Z1wG1.png

[/spoiler]

Do you have any idea of what I'm doing wrong?

Advertisement

Have you tried using PIX For Windows to debug your lack of particles?

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

Have you tried using PIX For Windows to debug your lack of particles?

Nope. If I try to use PIX and capture frame, PIX will crash.

You mentioned having used the Debug Layer, but does this include using the "GPU-Based Validation" feature added in a recent SDK?

Information on enabling it here: https://msdn.microsoft.com/en-us/library/windows/desktop/mt490477

Adam Miles - Principal Software Development Engineer - Microsoft Xbox Advanced Technology Group

You mentioned having used the Debug Layer, but does this include using the "GPU-Based Validation" feature added in a recent SDK?

I included this feature and received an error in an output

[spoiler]

D3D12 ERROR: GPU-BASED VALIDATION: Draw, Incompatible resource state: Resource: 0x00000267AD2F6A60:'Unnamed ID3D12Resource Object', Subresource Index: [0], Descriptor heap index to DescriptorTableStart: [2], Descriptor heap index FromTableStart: [0], Binding Type In Descriptor: SRV, Resource State: D3D12_RESOURCE_STATE_UNORDERED_ACCESS(0x8), Index of Descriptor Range: 0, Shader Stage: VERTEX, Root Parameter Index: [1], Draw Index: [1], Shader Code: ...\Data\Shaders\HLSL\Particles\ParticlesRender.vs(5,2-38), Asm Instruction Range: [0x5c-0x87], Asm Operand Index: [3], Command List: 0x00000267ACC7F3D0:'Unnamed ID3D12GraphicsCommandList Object', SRV/UAV/CBV Descriptor Heap: 0x00000267AD764A30:'Unnamed ID3D12DescriptorHeap Object', Sampler Descriptor Heap: <not set>, Pipeline State: 0x00000267AD6E4830:'Unnamed ID3D12PipelineState Object', [ EXECUTION ERROR #942: GPU_BASED_VALIDATION_INCOMPATIBLE_RESOURCE_STATE]
[/spoiler]
I tryed to change a descriptor range in a root signature from SRV to UAV. After this the error was gone, but result didn't change.
Also I tryed to use another resource barrier for a UAV buffer (non_pixel_shader) and I received same result (the error was gone, a final image was without changes).

This topic is closed to new replies.

Advertisement