Jump to content
  • Advertisement
Sign in to follow this  
obfuscate

DX12 Problems with a structured buffer in DX12

This topic is 514 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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?

Share this post


Link to post
Share on other sites
Advertisement

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.

Share this post


Link to post
Share on other sites

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).

Share this post


Link to post
Share on other sites
Sign in to follow this  

  • Advertisement
×

Important Information

By using GameDev.net, you agree to our community Guidelines, Terms of Use, and Privacy Policy.

We are the game development community.

Whether you are an indie, hobbyist, AAA developer, or just trying to learn, GameDev.net is the place for you to learn, share, and connect with the games industry. Learn more About Us or sign up!

Sign me up!